-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
102 changed files
with
3,381 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/.idea/caches | ||
/.idea/libraries | ||
/.idea/modules.xml | ||
/.idea/workspace.xml | ||
/.idea/navEditor.xml | ||
/.idea/assetWizardSettings.xml | ||
/captures | ||
*.iml | ||
.externalNativeBuild | ||
|
||
.kotlintest | ||
|
||
/local.properties | ||
.gradle | ||
build/ | ||
bin/ | ||
|
||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
Cadabra is the A/B testing library that simplifies objects creation | ||
at the different application layers. | ||
|
||
Cadabra either takes the external A/B test configuration, or makes the decision based on supplied end-user id. | ||
|
||
To publish use `gw uploadArchives --no-daemon --no-parallel` | ||
|
||
[](https://app.bitrise.io/app/5781b73059466ba5) | ||
|
||
[](https://www.codacy.com/app/fo2/cadabra?utm_source=github.com&utm_medium=referral&utm_content=fo2rist/cadabra&utm_campaign=Badge_Grade) | ||
|
||
[](https://codecov.io/gh/fo2rist/cadabra) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// Top-level build file where you can add configuration options common to all sub-projects/modules. | ||
|
||
buildscript { | ||
ext.kotlin_version = '1.3.31' | ||
repositories { | ||
google() | ||
jcenter() | ||
mavenCentral() | ||
} | ||
dependencies { | ||
// NOTE: Do not place your application dependencies here; they belong | ||
// in the individual module build.gradle files | ||
classpath 'com.android.tools.build:gradle:3.4.1' | ||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" | ||
|
||
// for google-services plugin | ||
classpath 'com.google.gms:google-services:4.2.0' | ||
|
||
// for jacoco aggregator plugin | ||
classpath "com.vanniktech:gradle-android-junit-jacoco-plugin:0.15.0" | ||
// for maven publisher plugin | ||
classpath 'com.vanniktech:gradle-maven-publish-plugin:0.8.0' | ||
} | ||
} | ||
|
||
allprojects { | ||
repositories { | ||
google() | ||
jcenter() | ||
mavenCentral() | ||
} | ||
|
||
buildscript { | ||
repositories { | ||
mavenCentral() | ||
} | ||
} | ||
|
||
configurations.all { | ||
resolutionStrategy { | ||
//Force appcompat 28 before migration for Firebase 18+ and AndroidX | ||
force 'com.android.support:appcompat-v7:28.0.0' | ||
force 'com.android.support:support-v4:28.0.0' | ||
force 'com.android.support:support-annotations:28.0.0' | ||
} | ||
} | ||
} | ||
|
||
//adds report aggregation tasks such as jacocoTestReport & jacocoTestReport<FLAVOR><BUILD_TYPE> | ||
apply plugin: "com.vanniktech.android.junit.jacoco" | ||
junitJacoco { | ||
jacocoVersion = "0.8.4" | ||
includeNoLocationClasses = true | ||
} | ||
|
||
task clean(type: Delete) { | ||
delete rootProject.buildDir | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
apply plugin: 'com.android.library' | ||
apply plugin: 'kotlin-android' | ||
apply plugin: "com.vanniktech.maven.publish" | ||
|
||
android { | ||
compileSdkVersion 28 | ||
buildToolsVersion = '28.0.3' | ||
|
||
defaultConfig { | ||
minSdkVersion 15 | ||
targetSdkVersion 28 | ||
versionCode 1 | ||
versionName "0.0.1" | ||
|
||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" | ||
} | ||
compileOptions { | ||
sourceCompatibility = JavaVersion.VERSION_1_8 | ||
targetCompatibility = JavaVersion.VERSION_1_8 | ||
} | ||
|
||
testOptions { | ||
unitTests { | ||
includeAndroidResources = true | ||
all { | ||
useJUnitPlatform() | ||
testLogging { | ||
events 'PASSED', 'FAILED', 'SKIPPED' | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
dependencies { | ||
implementation fileTree(dir: 'libs', include: ['*.jar']) | ||
api project(path: ':cadabra-core') | ||
|
||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" | ||
implementation 'com.android.support:appcompat-v7:28.0.0' | ||
|
||
//Kotlintest | ||
testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version" | ||
testImplementation 'io.kotlintest:kotlintest-runner-junit5:3.3.2' | ||
|
||
//JUnit5 (Required for kotlintest and spek) | ||
testImplementation "org.junit.jupiter:junit-jupiter-api:5.4.2" | ||
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.4.2" | ||
//Robolectric | ||
testImplementation 'org.robolectric:robolectric:4.3' | ||
testImplementation 'junit:junit:4.12' | ||
//vintage engine is required for Robolectic tests which need JUnit4 | ||
testRuntimeOnly "org.junit.vintage:junit-vintage-engine:5.4.2" | ||
|
||
//Mockito | ||
testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.1.0" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# region Maven publishing | ||
POM_ARTIFACT_ID=cadabra-android | ||
# endregion |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||
package="com.fo2rist.cadabra.android"/> |
59 changes: 59 additions & 0 deletions
59
cadabra-android/src/main/java/com/fo2rist/cadabra/android/CadabraAndroid.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package com.fo2rist.cadabra.android | ||
|
||
import android.content.Context | ||
import com.fo2rist.cadabra.Cadabra | ||
import com.fo2rist.cadabra.CadabraConfig | ||
import com.fo2rist.cadabra.Variant | ||
import com.fo2rist.cadabra.android.CadabraAndroid.Companion.initialize | ||
import com.fo2rist.cadabra.android.exceptions.NotInitializedException | ||
import kotlin.reflect.KClass | ||
|
||
/** | ||
* Android-specific cadabra extension that supports resources injection. | ||
* Usage: | ||
* - register/start experiments with [Cadabra.config] | ||
* - initialize context with [initialize] | ||
* - access resources associated with experiment via [getExperimentContext], see [VariantResources] for details | ||
* @see [Cadabra] for experiment registration details | ||
*/ | ||
interface CadabraAndroid : Cadabra { | ||
|
||
/** | ||
* Get Android resources accessor for active experiment variant. | ||
* @throws IllegalStateException if was not initialized via [initialize]. | ||
*/ | ||
fun getExperimentContext(variantClass: KClass<out Variant>): ExperimentContext | ||
|
||
/** | ||
* Get Android resources accessor for active experiment variant. | ||
* @throws NotInitializedException if was not initialized via [initialize]. | ||
*/ | ||
fun getExperimentContext(variantClass: Class<out Variant>): ExperimentContext | ||
|
||
companion object { | ||
|
||
private val _instance = CadabraAndroidImpl() | ||
|
||
/** | ||
* Entry point CadabraAndroid experiment variants usage. | ||
*/ | ||
val instance: CadabraAndroid | ||
get() = _instance | ||
|
||
/** | ||
* Entry point for Cadabra configuration. | ||
* Same as [Cadabra.config]. | ||
*/ | ||
val config: CadabraConfig | ||
get() = _instance | ||
|
||
/** | ||
* Initialize Cadabra for resources access. | ||
* Initialization is required prior resources usage but not required to register and access experiments. | ||
* [Context.getApplicationContext] will be used by Cadabra as the context. | ||
*/ | ||
fun initialize(context: Context) { | ||
_instance.initialize(context) | ||
} | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
cadabra-android/src/main/java/com/fo2rist/cadabra/android/CadabraAndroidImpl.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package com.fo2rist.cadabra.android | ||
|
||
import android.content.Context | ||
import com.fo2rist.cadabra.Cadabra | ||
import com.fo2rist.cadabra.CadabraConfig | ||
import com.fo2rist.cadabra.Variant | ||
import com.fo2rist.cadabra.android.exceptions.NotInitializedException | ||
import kotlin.reflect.KClass | ||
|
||
internal class CadabraAndroidImpl : CadabraAndroid, Cadabra by Cadabra.instance, CadabraConfig by Cadabra.config { | ||
|
||
private lateinit var appContext: Context | ||
|
||
fun initialize(context: Context) { | ||
if (::appContext.isInitialized) { | ||
return | ||
} | ||
|
||
appContext = context.applicationContext | ||
} | ||
|
||
override fun getExperimentContext(variantClass: KClass<out Variant>): ExperimentContext { | ||
return getExperimentContext(variantClass.java) | ||
} | ||
|
||
override fun getExperimentContext(variantClass: Class<out Variant>): ExperimentContext { | ||
checkInitialized() | ||
|
||
val variant = getExperimentVariant(variantClass) | ||
return ExperimentContext(variant, VariantResourcesImpl(appContext, variant)) | ||
} | ||
|
||
/** | ||
* @throws NotInitializedException if the value is null. | ||
*/ | ||
private fun checkInitialized() { | ||
if (!::appContext.isInitialized) { | ||
throw NotInitializedException() | ||
} | ||
} | ||
} | ||
|
32 changes: 32 additions & 0 deletions
32
cadabra-android/src/main/java/com/fo2rist/cadabra/android/ExperimentConfigFactory.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package com.fo2rist.cadabra.android | ||
|
||
import com.fo2rist.cadabra.ExperimentsConfig | ||
import org.json.JSONObject | ||
|
||
/** | ||
* Create config from json. | ||
* Format example: | ||
* ``` | ||
* { | ||
* "ExperimentId": "VariantName", | ||
* ... | ||
* } | ||
* ``` | ||
* @throws org.json.JSONException if the parse fails. | ||
*/ | ||
fun configFromJson(json: String): ExperimentsConfig { | ||
if (json.isEmpty()) { | ||
return ExperimentsConfig.create() | ||
} | ||
|
||
val jsonObject = JSONObject(json) | ||
|
||
val keys = jsonObject.keys() | ||
val configPairs = Array<Pair<String, String>>(jsonObject.length()) { | ||
val experimentId = keys.next() | ||
experimentId to jsonObject.getString(experimentId) | ||
} | ||
|
||
@Suppress("SpreadOperator") | ||
return ExperimentsConfig.create(*configPairs) | ||
} |
14 changes: 14 additions & 0 deletions
14
cadabra-android/src/main/java/com/fo2rist/cadabra/android/ExperimentContext.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package com.fo2rist.cadabra.android | ||
|
||
import com.fo2rist.cadabra.Variant | ||
|
||
/** | ||
* Full context of experiment state as it's resolved for current session/user. | ||
*/ | ||
class ExperimentContext( | ||
/** | ||
* Active variant to be applied by the app. | ||
*/ | ||
val variant: Variant, | ||
resources: VariantResources | ||
) : VariantResources by resources |
15 changes: 15 additions & 0 deletions
15
cadabra-android/src/main/java/com/fo2rist/cadabra/android/ResourceNamesGenerator.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package com.fo2rist.cadabra.android | ||
|
||
/** | ||
* Generates names for resources by base resource name and given variant. | ||
*/ | ||
internal class ResourceNamesGenerator { | ||
|
||
/** | ||
* Generate resource name to use by base name current variant. | ||
* E.g. For "string_a" and variant "A" should give "string_a", for "string_a" and variant "B" should give "string_b" | ||
*/ | ||
fun generateResourceName(baseResourceName: String, variantName: String): String { | ||
return baseResourceName.replaceAfterLast("_", variantName.toLowerCase()) | ||
} | ||
} |
Oops, something went wrong.