diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index fc6a9345c..b974f554c 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,4 +1,4 @@ -name: SDK Distribute +name: Distribute PushOk on: pull_request: @@ -14,11 +14,19 @@ jobs: if: github.event.pull_request.merged == true || (github.event_name == 'push' && startsWith(github.ref, 'refs/heads/release/')) runs-on: ubuntu-latest steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Get last 3 commit messages + run: | + commits=$(git log -3 --pretty=format:"%s") + echo "commits=$commits" >> $GITHUB_ENV + - name: trigger build & send to FAD uses: benc-uk/workflow-dispatch@v1 - with: + with: workflow: 61033697 repo: mindbox-cloud/android-app ref: develop token: ${{ secrets.GITHUBACCESSTOKEN }} - + inputs: '{"branch": "${{ github.head_ref }}", "commits": "${{ env.commits }}"}' \ No newline at end of file diff --git a/build.gradle b/build.gradle index 7f1808258..5b83a14c4 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,5 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = "1.8.21" repositories { google() mavenCentral() @@ -8,13 +7,7 @@ buildscript { maven { url("https://developer.huawei.com/repo/") } } dependencies { - classpath "com.android.tools.build:gradle:7.4.2" - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath "org.jetbrains.dokka:dokka-gradle-plugin:0.10.1" - classpath 'com.google.gms:google-services:4.3.10' - classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' - classpath 'com.huawei.agconnect:agcp:1.6.0.300' - + classpath libs.bundles.buildscript.plugins // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } @@ -31,7 +24,4 @@ allprojects { task clean(type: Delete) { delete rootProject.buildDir -} - - -apply from: 'dependencies.gradle' \ No newline at end of file +} \ No newline at end of file diff --git a/dependencies.gradle b/dependencies.gradle deleted file mode 100644 index a9fcd7876..000000000 --- a/dependencies.gradle +++ /dev/null @@ -1,41 +0,0 @@ -ext { - sdkDependencies = [ - kotlin_stdlib: "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version", - androidx_core_ktx: 'androidx.core:core-ktx:1.7.0', - androidx_annotations: 'androidx.annotation:annotation:1.3.0', - firebase_bom: 'com.google.firebase:firebase-bom:32.7.2', - firebase_messaging: 'com.google.firebase:firebase-messaging', - gms_play_services_basement: 'com.google.android.gms:play-services-basement:18.0.0', - gms_play_services_base: 'com.google.android.gms:play-services-base:18.0.1', - gms_play_services_ads_identifier: 'com.google.android.gms:play-services-ads-identifier:18.0.1', - kotlinx_coroutines_core: 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2', - kotlinx_coroutines_android: 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0', - volley: 'com.android.volley:volley:1.2.1', - gson: 'com.google.code.gson:gson:2.8.9', - room: 'androidx.room:room-runtime:2.5.1', - room_ktx: 'androidx.room:room-ktx:2.5.1', - room_compiler: 'androidx.room:room-compiler:2.5.1', - work_manager: 'androidx.work:work-runtime-ktx:2.7.1', - androidx_lifecycle: 'androidx.lifecycle:lifecycle-process:2.3.1', - hms_push: 'com.huawei.hms:push:6.11.0.300', - hms_ads_identifier: 'com.huawei.hms:ads-identifier:3.4.39.302', - koin: 'io.insert-koin:koin-android:3.2.2', - koin_test: 'io.insert-koin:koin-test:3.2.2', - koin_junit4: 'io.insert-koin:koin-test-junit4:3.2.2', - constraint_layout: 'androidx.constraintlayout:constraintlayout:2.1.4', - threetenapb: 'com.jakewharton.threetenabp:threetenabp:1.4.6' - ] - - testDependencies = [ - junit: 'junit:junit:4.13.2', - androidx_junit: 'androidx.test.ext:junit:1.1.3', - espresso: 'androidx.test.espresso:espresso-core:3.4.0', - kotlinx_coroutines_test: 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.2', - turbine: 'app.cash.turbine:turbine:0.12.1', - mockk: 'io.mockk:mockk:1.13.3', - mockk_android: 'io.mockk:mockk-android:1.13.3', - mockk_agent: 'io.mockk:mockk-agent:1.13.3', - robolectric: 'org.robolectric:robolectric:4.11', - test_core: 'androidx.test:core:1.5.0' - ] -} \ No newline at end of file diff --git a/example/app/build.gradle b/example/app/build.gradle index 616f8bf35..b8ab04921 100644 --- a/example/app/build.gradle +++ b/example/app/build.gradle @@ -55,7 +55,7 @@ dependencies { //Mindbox - implementation 'cloud.mindbox:mobile-sdk:2.11.0' + implementation 'cloud.mindbox:mobile-sdk:2.11.1' implementation 'cloud.mindbox:mindbox-firebase' implementation 'cloud.mindbox:mindbox-huawei' diff --git a/gradle.properties b/gradle.properties index b60b65600..f5a415db7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -20,4 +20,4 @@ android.enableJetifier=true # Kotlin code style for this project: "official" or "obsolete": kotlin.code.style=official # SDK version property -SDK_VERSION_NAME=2.11.0 \ No newline at end of file +SDK_VERSION_NAME=2.11.1 \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 000000000..6051ba2b9 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,106 @@ +[versions] +compile_sdk = "34" +build_tools = "34.0.0" +min_sdk = "19" +target_sdk = "34" + +firebase_bom = "32.7.2" +hms_push = "6.11.0.300" +room = "2.5.1" +kotlin = "1.8.21" +gradle_plugin = "7.4.2" +gms_play_services_basement = "18.0.0" +gms_play_services_base = "18.0.1" +gms_play_services_ads_identifier = "18.0.1" +google_services = "4.3.10" +hms_ads_identifier = "3.4.39.302" +kotlinx_coroutines_core = "1.4.2" +kotlinx_coroutines_android = "1.5.0" +volley = "1.2.1" +gson = "2.8.9" +work_manager = "2.7.1" +androidx_lifecycle = "2.3.1" +androidx_core_ktx = "1.7.0" +androidx_annotations = "1.3.0" +constraint_layout = "2.1.4" +threetenapb = "1.4.6" +glide = "4.15.1" + +junit = "4.13.2" +androidx_junit = "1.1.3" +espresso = "3.4.0" +mockk = "1.13.3" +robolectric = "4.11" +test_core = "1.5.0" +turbine = "0.12.1" +kotlinx_coroutines_test = "1.4.2" + +agcp = "1.6.0.300" +maven_plugin = "2.1" + +[bundles] +buildscript-plugins = [ + "android_tools_build_gradle", + "kotlin_gradle_plugin", + "google_services", + "maven_plugin", + "agcp" +] + +test = [ + "junit", + "mockk", + "robolectric", + "test_core", + "turbine", + "kotlinx_coroutines_test" +] + +androidTest = [ + "androidx_junit", + "espresso" +] + +[libraries] +kotlin_stdlib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib", version.ref = "kotlin" } +androidx_core_ktx = { group = "androidx.core", name = "core-ktx", version.ref = "androidx_core_ktx" } +androidx_annotations = { group = "androidx.annotation", name = "annotation", version.ref = "androidx_annotations" } +firebase_bom = { group = "com.google.firebase", name = "firebase-bom", version.ref = "firebase_bom" } +firebase_messaging = { group = "com.google.firebase", name = "firebase-messaging" } +gms_play_services_basement = { group = "com.google.android.gms", name = "play-services-basement", version.ref = "gms_play_services_basement" } +gms_play_services_base = { group = "com.google.android.gms", name = "play-services-base", version.ref = "gms_play_services_base" } +gms_play_services_ads_identifier = { group = "com.google.android.gms", name = "play-services-ads-identifier", version.ref = "gms_play_services_ads_identifier" } +kotlinx_coroutines_core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "kotlinx_coroutines_core" } +kotlinx_coroutines_android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "kotlinx_coroutines_android" } +volley = { group = "com.android.volley", name = "volley", version.ref = "volley" } +gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" } +room_runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" } +room_ktx = { group = "androidx.room", name = "room-ktx", version.ref = "room" } +room_compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" } +work_manager = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "work_manager" } +androidx_lifecycle = { group = "androidx.lifecycle", name = "lifecycle-process", version.ref = "androidx_lifecycle" } +hms_push = { group = "com.huawei.hms", name = "push", version.ref = "hms_push" } +hms_ads_identifier = { group = "com.huawei.hms", name = "ads-identifier", version.ref = "hms_ads_identifier" } +constraint_layout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraint_layout" } +threetenabp = { group = "com.jakewharton.threetenabp", name = "threetenabp", version.ref = "threetenapb" } +glide = { group = "com.github.bumptech.glide", name = "glide", version.ref = "glide" } +glide_compiler = { group = "com.github.bumptech.glide", name = "compiler", version.ref = "glide" } + +# Test libraries +junit = { group = "junit", name = "junit", version.ref = "junit" } +androidx_junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx_junit" } +espresso = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espresso" } +mockk = { group = "io.mockk", name = "mockk", version.ref = "mockk" } +mockk_android = { group = "io.mockk", name = "mockk-android", version.ref = "mockk" } +mockk_agent = { group = "io.mockk", name = "mockk-agent", version.ref = "mockk" } +robolectric = { group = "org.robolectric", name = "robolectric", version.ref = "robolectric" } +test_core = { group = "androidx.test", name = "core", version.ref = "test_core" } +turbine = { group = "app.cash.turbine", name = "turbine", version.ref = "turbine" } +kotlinx_coroutines_test = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-test", version.ref = "kotlinx_coroutines_test" } + +# Buildscript plugins +android_tools_build_gradle = { module = "com.android.tools.build:gradle", version.ref = "gradle_plugin" } +kotlin_gradle_plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } +google_services = { module = "com.google.gms:google-services", version.ref = "google_services" } +maven_plugin = { module = "com.github.dcendents:android-maven-gradle-plugin", version.ref = "maven_plugin" } +agcp = { module = "com.huawei.agconnect:agcp", version.ref = "agcp" } \ No newline at end of file diff --git a/mindbox-firebase/build.gradle b/mindbox-firebase/build.gradle index f8d72a994..311e35821 100644 --- a/mindbox-firebase/build.gradle +++ b/mindbox-firebase/build.gradle @@ -12,23 +12,23 @@ android { dependencies { implementation project(path: ':sdk') - implementation sdkDependencies.androidx_core_ktx - implementation sdkDependencies.kotlinx_coroutines_core + // Implementation dependencies + implementation libs.androidx.core.ktx + implementation libs.kotlinx.coroutines.core - implementation sdkDependencies.gson + // GSON + implementation libs.gson // Firebase messaging - implementation platform(sdkDependencies.firebase_bom) - implementation sdkDependencies.firebase_messaging - implementation sdkDependencies.gms_play_services_base - implementation sdkDependencies.gms_play_services_basement + implementation platform(libs.firebase.bom) + implementation libs.firebase.messaging + implementation libs.gms.play.services.base + implementation libs.gms.play.services.basement // Ads - implementation sdkDependencies.gms_play_services_ads_identifier - testImplementation testDependencies.junit - testImplementation testDependencies.mockk - testImplementation testDependencies.mockk_android - testImplementation testDependencies.mockk_agent - testImplementation testDependencies.test_core + implementation libs.gms.play.services.ads.identifier + + // Test dependencies + testImplementation libs.bundles.test } \ No newline at end of file diff --git a/mindbox-huawei/build.gradle b/mindbox-huawei/build.gradle index fc0ddfd56..5b87dde74 100644 --- a/mindbox-huawei/build.gradle +++ b/mindbox-huawei/build.gradle @@ -12,14 +12,18 @@ android { dependencies { implementation project(path: ':sdk') - implementation sdkDependencies.kotlinx_coroutines_core - implementation sdkDependencies.hms_push - implementation sdkDependencies.hms_ads_identifier - implementation sdkDependencies.gson - implementation sdkDependencies.androidx_annotations - testImplementation testDependencies.junit - testImplementation testDependencies.mockk - testImplementation testDependencies.mockk_android - testImplementation testDependencies.mockk_agent - testImplementation testDependencies.test_core + // Implementation dependencies + implementation libs.kotlinx.coroutines.core + + // HMS + implementation libs.hms.push + implementation libs.hms.ads.identifier + + // GSON + implementation libs.gson + implementation libs.androidx.annotations + + // Test dependencies + testImplementation libs.bundles.test + } \ No newline at end of file diff --git a/modulesCommon.gradle b/modulesCommon.gradle index c7aae3e3a..123f07feb 100644 --- a/modulesCommon.gradle +++ b/modulesCommon.gradle @@ -1,19 +1,18 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' -apply plugin: 'org.jetbrains.dokka' apply plugin: 'signing' apply plugin: 'maven-publish' group = 'com.github.mindbox-cloud' android { - compileSdkVersion 34 - buildToolsVersion "34.0.0" + compileSdkVersion libs.versions.compile.sdk.get().toInteger() + buildToolsVersion libs.versions.build.tools.get() defaultConfig { - minSdkVersion 19 - targetSdkVersion 34 + minSdkVersion libs.versions.min.sdk.get().toInteger() + targetSdkVersion libs.versions.target.sdk.get().toInteger() versionCode 1 multiDexEnabled true versionName '"' + SDK_VERSION_NAME + '"' @@ -44,11 +43,6 @@ android { jvmTarget = '1.8' } - dokka { - outputFormat = 'javadoc' - outputDirectory = "$buildDir/dokka" - } - task androidSourcesJar(type: Jar) { archiveClassifier.set('sources') from android.sourceSets.main.java.srcDirs diff --git a/sdk/build.gradle b/sdk/build.gradle index d111126c0..4cb9f6365 100644 --- a/sdk/build.gradle +++ b/sdk/build.gradle @@ -34,47 +34,41 @@ android { dependencies { - implementation sdkDependencies.kotlin_stdlib - implementation sdkDependencies.androidx_core_ktx - testImplementation testDependencies.junit - androidTestImplementation testDependencies.androidx_junit - androidTestImplementation testDependencies.espresso - testImplementation testDependencies.kotlinx_coroutines_test - testImplementation testDependencies.turbine - - testImplementation testDependencies.robolectric - testImplementation testDependencies.mockk - testImplementation testDependencies.mockk_android - testImplementation testDependencies.mockk_agent - testImplementation testDependencies.test_core + // Implementation dependencies + implementation libs.kotlin.stdlib + implementation libs.androidx.core.ktx // ConstraintLayout - implementation sdkDependencies.constraint_layout + implementation libs.constraint.layout - // coroutines - implementation sdkDependencies.kotlinx_coroutines_core - implementation sdkDependencies.kotlinx_coroutines_android + // Coroutines + implementation libs.kotlinx.coroutines.core + implementation libs.kotlinx.coroutines.android - //network - implementation sdkDependencies.volley - implementation sdkDependencies.gson + // Network + implementation libs.volley + implementation libs.gson - // DB - implementation sdkDependencies.room - implementation sdkDependencies.room_ktx - kapt sdkDependencies.room_compiler + // Database + implementation libs.room.runtime + implementation libs.room.ktx + kapt libs.room.compiler - //work manager - implementation sdkDependencies.work_manager + // Work Manager + implementation libs.work.manager // Handle app lifecycle - implementation sdkDependencies.androidx_lifecycle - implementation sdkDependencies.threetenapb + implementation libs.androidx.lifecycle + implementation libs.threetenabp + + // Glide + implementation libs.glide + kapt libs.glide.compiler - testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.5' + // Test dependencies + testImplementation libs.bundles.test - implementation 'com.github.bumptech.glide:glide:4.15.1' - kapt 'com.github.bumptech.glide:compiler:4.15.1' + // Android Test dependencies + androidTestImplementation libs.bundles.androidTest } \ No newline at end of file diff --git a/sdk/src/androidTest/java/cloud/mindbox/mobile_sdk/DeviceUuidRepeatedUnitTest.kt b/sdk/src/androidTest/java/cloud/mindbox/mobile_sdk/DeviceUuidRepeatedUnitTest.kt index 31d23b08b..5873ad7da 100644 --- a/sdk/src/androidTest/java/cloud/mindbox/mobile_sdk/DeviceUuidRepeatedUnitTest.kt +++ b/sdk/src/androidTest/java/cloud/mindbox/mobile_sdk/DeviceUuidRepeatedUnitTest.kt @@ -1,7 +1,6 @@ package cloud.mindbox.mobile_sdk import androidx.test.platform.app.InstrumentationRegistry -import cloud.mindbox.mobile_sdk.models.isUuid import org.junit.AfterClass import org.junit.Assert import org.junit.BeforeClass diff --git a/sdk/src/androidTest/java/cloud/mindbox/mobile_sdk/DeviceUuidSingleUnitTest.kt b/sdk/src/androidTest/java/cloud/mindbox/mobile_sdk/DeviceUuidSingleUnitTest.kt index f81a6f6ac..9cf401cd5 100644 --- a/sdk/src/androidTest/java/cloud/mindbox/mobile_sdk/DeviceUuidSingleUnitTest.kt +++ b/sdk/src/androidTest/java/cloud/mindbox/mobile_sdk/DeviceUuidSingleUnitTest.kt @@ -1,7 +1,6 @@ package cloud.mindbox.mobile_sdk import androidx.test.platform.app.InstrumentationRegistry -import cloud.mindbox.mobile_sdk.models.isUuid import org.junit.After import org.junit.Assert import org.junit.Test diff --git a/sdk/src/androidTest/java/cloud/mindbox/mobile_sdk/FmsTokenRepeatedUnitTest.kt b/sdk/src/androidTest/java/cloud/mindbox/mobile_sdk/FmsTokenRepeatedUnitTest.kt index 19a9c6593..8d7357df9 100644 --- a/sdk/src/androidTest/java/cloud/mindbox/mobile_sdk/FmsTokenRepeatedUnitTest.kt +++ b/sdk/src/androidTest/java/cloud/mindbox/mobile_sdk/FmsTokenRepeatedUnitTest.kt @@ -1,7 +1,6 @@ package cloud.mindbox.mobile_sdk import androidx.test.platform.app.InstrumentationRegistry -import cloud.mindbox.mobile_sdk.models.isUuid import org.junit.AfterClass import org.junit.Assert import org.junit.BeforeClass diff --git a/sdk/src/androidTest/java/cloud/mindbox/mobile_sdk/FmsTokenSingleUnitTest.kt b/sdk/src/androidTest/java/cloud/mindbox/mobile_sdk/FmsTokenSingleUnitTest.kt index 666a9c758..55c89b243 100644 --- a/sdk/src/androidTest/java/cloud/mindbox/mobile_sdk/FmsTokenSingleUnitTest.kt +++ b/sdk/src/androidTest/java/cloud/mindbox/mobile_sdk/FmsTokenSingleUnitTest.kt @@ -1,7 +1,6 @@ package cloud.mindbox.mobile_sdk import androidx.test.platform.app.InstrumentationRegistry -import cloud.mindbox.mobile_sdk.models.isUuid import org.junit.After import org.junit.Assert import org.junit.Test diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/Extensions.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/Extensions.kt index eb8d97cf2..6e6173cbb 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/Extensions.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/Extensions.kt @@ -23,8 +23,13 @@ import cloud.mindbox.mobile_sdk.inapp.domain.models.InAppType import cloud.mindbox.mobile_sdk.inapp.domain.models.SessionDelay import cloud.mindbox.mobile_sdk.logger.MindboxLoggerImpl import cloud.mindbox.mobile_sdk.utils.LoggingExceptionHandler +import cloud.mindbox.mobile_sdk.utils.loggingRunCatching import com.android.volley.VolleyError import com.android.volley.toolbox.HttpHeaderParser +import com.google.gson.Gson +import com.google.gson.JsonElement +import com.google.gson.JsonObject +import com.google.gson.reflect.TypeToken import org.threeten.bp.Instant import org.threeten.bp.LocalDateTime import org.threeten.bp.ZoneOffset @@ -32,6 +37,7 @@ import org.threeten.bp.ZonedDateTime import org.threeten.bp.format.DateTimeFormatter import java.nio.charset.Charset import java.util.Queue +import java.util.UUID import kotlin.math.roundToInt import kotlin.time.Duration.Companion.days import kotlin.time.Duration.Companion.hours @@ -217,7 +223,7 @@ internal fun verifyMainThreadExecution(methodName: String) { } } -fun String.parseTimeSpanToMillis(): Long { +internal fun String.parseTimeSpanToMillis(): Long { val regex = """(-)?(\d+\.)?([01]?\d|2[0-3]):([0-5]?\d):([0-5]?\d)(\.\d{1,7})?""".toRegex() val matchResult = regex.matchEntire(this) ?: throw IllegalArgumentException("Invalid timeSpan format") @@ -231,3 +237,23 @@ fun String.parseTimeSpanToMillis(): Long { return if (sign == "-") duration.inWholeMilliseconds * -1 else duration.inWholeMilliseconds } + +internal fun String.isUuid(): Boolean { + return loggingRunCatching(false) { + UUID.fromString(this) + true + } +} + +internal inline fun Gson.fromJson(json: JsonElement?): Result = runCatching { + fromJson(json, object : TypeToken() {}.type) +} + +internal fun JsonObject.getOrNull(memberName: String?): JsonElement? = runCatching { + this.get(memberName) +}.getOrNull() + +internal inline fun Result.getOrNull(runIfNull: (Throwable) -> Unit): T? = getOrElse { + runIfNull(it) + null +} \ No newline at end of file diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/InitializeLock.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/InitializeLock.kt index 09015fe89..314b57ce9 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/InitializeLock.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/InitializeLock.kt @@ -2,18 +2,18 @@ package cloud.mindbox.mobile_sdk import androidx.annotation.WorkerThread import cloud.mindbox.mobile_sdk.logger.mindboxLogI +import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.Job -import java.util.concurrent.CountDownLatch internal object InitializeLock { - private val map: MutableMap = mutableMapOf( - State.SAVE_MINDBOX_CONFIG to CountDownLatch(1), - State.APP_STARTED to CountDownLatch(1) + private val map: MutableMap> = mutableMapOf( + State.SAVE_MINDBOX_CONFIG to CompletableDeferred(), + State.APP_STARTED to CompletableDeferred() ) @WorkerThread - internal fun await(state: State) { + internal suspend fun await(state: State) { State.values().filter { state >= it } .sortedBy { it.ordinal } .mapNotNull { map[it] } @@ -23,13 +23,13 @@ internal object InitializeLock { } internal fun complete(state: State) { - map[state]?.countDown() + map[state]?.complete(Unit) mindboxLogI("State $state completed") } internal fun reset(state: State) { - map[state]?.countDown() - map[state] = CountDownLatch(1) + map[state]?.complete(Unit) + map[state] = CompletableDeferred() mindboxLogI("State $state is reset") } diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/Mindbox.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/Mindbox.kt index 95348a05c..95a3b8f1a 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/Mindbox.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/Mindbox.kt @@ -100,6 +100,8 @@ object Mindbox : MindboxLog { private var firstInitCall: Boolean = true + private val migrationManager: MigrationManager by mindboxInject { migrationManager } + /** * Allows you to specify additional components for message handling * when calling the [handleRemoteMessage] function. @@ -495,6 +497,7 @@ object Mindbox : MindboxLog { } initScope.launch { + migrationManager.migrateAll() val checkResult = checkConfig(configuration) val validatedConfiguration = validateConfiguration(configuration) DbManager.saveConfigurations(Configuration(configuration)) @@ -1047,7 +1050,6 @@ object Mindbox : MindboxLog { SharedPreferencesManager.with(context) DbManager.init(context) setPushServiceHandler(context, pushServices) - MigrationManager(context).migrateAll() } private fun asyncOperation( diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/SdkValidation.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/SdkValidation.kt index a1ef9e4e2..c7789103c 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/SdkValidation.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/SdkValidation.kt @@ -1,7 +1,6 @@ package cloud.mindbox.mobile_sdk import androidx.core.util.PatternsCompat -import cloud.mindbox.mobile_sdk.models.isUuid import cloud.mindbox.mobile_sdk.utils.LoggingExceptionHandler internal object SdkValidation { diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/di/modules/DataModule.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/di/modules/DataModule.kt index 70f247f8f..1643fb23b 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/di/modules/DataModule.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/di/modules/DataModule.kt @@ -25,10 +25,7 @@ import cloud.mindbox.mobile_sdk.managers.RequestPermissionManagerImpl import cloud.mindbox.mobile_sdk.models.TreeTargetingDto import cloud.mindbox.mobile_sdk.models.operation.response.FrequencyDto import cloud.mindbox.mobile_sdk.monitoring.data.validators.MonitoringValidator -import cloud.mindbox.mobile_sdk.utils.Constants -import cloud.mindbox.mobile_sdk.utils.PushPermissionActionDto -import cloud.mindbox.mobile_sdk.utils.RedirectUrlActionDto -import cloud.mindbox.mobile_sdk.utils.RuntimeTypeAdapterFactory +import cloud.mindbox.mobile_sdk.utils.* import com.google.gson.Gson import com.google.gson.GsonBuilder @@ -152,7 +149,11 @@ internal fun DataModule( } override val mobileConfigSerializationManager: MobileConfigSerializationManager - get() = MobileConfigSerializationManagerImpl(gson = gson) + get() = MobileConfigSerializationManagerImpl( + gson = gson.newBuilder() + .registerTypeAdapter(String::class.java, StrictStringAdapter()) + .create() + ) override val inAppGeoRepository: InAppGeoRepository by lazy { InAppGeoRepositoryImpl( @@ -236,6 +237,9 @@ internal fun DataModule( get() = FrequencyDataFiller() override val frequencyValidator: FrequencyValidator get() = FrequencyValidator() + override val migrationManager: MigrationManager by lazy { + MigrationManager(appContext) + } override val gson: Gson by lazy { GsonBuilder().registerTypeAdapterFactory( diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/di/modules/MindboxModule.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/di/modules/MindboxModule.kt index 13b6996f3..8cbe0ebad 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/di/modules/MindboxModule.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/di/modules/MindboxModule.kt @@ -3,7 +3,6 @@ package cloud.mindbox.mobile_sdk.di.modules import android.app.Application import cloud.mindbox.mobile_sdk.abtests.CustomerAbMixer import cloud.mindbox.mobile_sdk.abtests.InAppABTestLogic -import cloud.mindbox.mobile_sdk.inapp.data.managers.data_filler.DataManager import cloud.mindbox.mobile_sdk.inapp.data.managers.SessionStorageManager import cloud.mindbox.mobile_sdk.inapp.data.managers.data_filler.* import cloud.mindbox.mobile_sdk.inapp.data.mapper.InAppMapper @@ -27,6 +26,7 @@ import cloud.mindbox.mobile_sdk.monitoring.data.room.dao.MonitoringDao import cloud.mindbox.mobile_sdk.monitoring.data.validators.MonitoringValidator import cloud.mindbox.mobile_sdk.monitoring.domain.interfaces.* import cloud.mindbox.mobile_sdk.network.MindboxServiceGenerator +import cloud.mindbox.mobile_sdk.utils.MigrationManager import com.android.volley.RequestQueue import com.google.gson.Gson @@ -104,6 +104,7 @@ internal interface DataModule : MindboxModule { val inAppConfigTtlValidator: InAppConfigTtlValidator val frequencyDataFiller: FrequencyDataFiller val frequencyValidator: FrequencyValidator + val migrationManager: MigrationManager } internal interface MonitoringModule : MindboxModule { diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/inapp/data/managers/MobileConfigSerializationManagerImpl.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/inapp/data/managers/MobileConfigSerializationManagerImpl.kt index 9c0767fe0..f4bcbeaff 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/inapp/data/managers/MobileConfigSerializationManagerImpl.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/inapp/data/managers/MobileConfigSerializationManagerImpl.kt @@ -1,24 +1,24 @@ package cloud.mindbox.mobile_sdk.inapp.data.managers +import cloud.mindbox.mobile_sdk.fromJson +import cloud.mindbox.mobile_sdk.getOrNull import cloud.mindbox.mobile_sdk.inapp.data.dto.* -import cloud.mindbox.mobile_sdk.inapp.data.dto.BackgroundDto -import cloud.mindbox.mobile_sdk.inapp.data.dto.FormBlankDto -import cloud.mindbox.mobile_sdk.inapp.data.dto.PayloadBlankDto -import cloud.mindbox.mobile_sdk.inapp.data.dto.PayloadDto import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.managers.MobileConfigSerializationManager import cloud.mindbox.mobile_sdk.logger.MindboxLoggerImpl import cloud.mindbox.mobile_sdk.logger.mindboxLogE import cloud.mindbox.mobile_sdk.models.TreeTargetingDto -import cloud.mindbox.mobile_sdk.models.operation.response.FormDto -import cloud.mindbox.mobile_sdk.models.operation.response.FrequencyDto -import cloud.mindbox.mobile_sdk.models.operation.response.InAppConfigResponseBlank +import cloud.mindbox.mobile_sdk.models.operation.response.* +import cloud.mindbox.mobile_sdk.models.operation.response.InAppConfigResponseBlank.InAppDtoBlank +import cloud.mindbox.mobile_sdk.models.operation.response.SettingsDtoBlank.OperationDtoBlank +import cloud.mindbox.mobile_sdk.models.operation.response.SettingsDtoBlank.TtlDtoBlank import com.google.gson.Gson +import com.google.gson.JsonElement import com.google.gson.JsonObject +import com.google.gson.JsonParser internal class MobileConfigSerializationManagerImpl(private val gson: Gson) : MobileConfigSerializationManager { - override fun deserializeToInAppTargetingDto(inAppTreeTargeting: JsonObject?): TreeTargetingDto? { val result = runCatching { gson.fromJson(inAppTreeTargeting, TreeTargetingDto::class.java) @@ -47,17 +47,75 @@ internal class MobileConfigSerializationManagerImpl(private val gson: Gson) : } override fun deserializeToConfigDtoBlank(inAppConfig: String): InAppConfigResponseBlank? { - val result = runCatching { - gson.fromJson(inAppConfig, InAppConfigResponseBlank::class.java) + val jsonObject = runCatching { + JsonParser.parseString(inAppConfig).asJsonObject + }.getOrElse { + mindboxLogE("Failed to parse inAppConfig json", it) + return null } - result.exceptionOrNull()?.let { error -> - MindboxLoggerImpl.e( - parent = this@MobileConfigSerializationManagerImpl, - message = "Failed to parse inAppConfig: $inAppConfig", - exception = error - ) + + val inApps = jsonObject.getOrNull("inapps")?.let { deserializeInApps(it) } + val settings = jsonObject.getOrNull("settings")?.let { deserializeSettings(it) } + val abtests = jsonObject.getOrNull("abtests")?.let { deserializeAbtests(it) } + val monitoring = jsonObject.getOrNull("monitoring")?.let { deserializeMonitoring(it) } + + return InAppConfigResponseBlank(inApps, monitoring, settings, abtests) + } + + internal fun deserializeMonitoring(json: JsonElement?): MonitoringDto? = runCatching { + MonitoringDto(logs = json!! + .asJsonObject.get("logs") + .asJsonArray.mapNotNull { log -> + runCatching { + gson.fromJson(log, LogRequestDtoBlank::class.java)?.copy() + }.getOrNull { + mindboxLogE("Failed to parse logs block", it) + } + }) + }.getOrNull { + mindboxLogE("Failed to parse monitoring block", it) + } + + internal fun deserializeInApps(json: JsonElement?): List? = + gson.fromJson>(json) + .getOrNull { + mindboxLogE("Failed to parse inapps block", it) + } + + internal fun deserializeSettings(json: JsonElement?): SettingsDtoBlank? = runCatching { + json?.let { + val operations = json.asJsonObject.get("operations")?.let { operationsJson -> + runCatching { + operationsJson.asJsonObject.entrySet().associate { (key, value) -> + key to runCatching { + gson.fromJson(value, OperationDtoBlank::class.java)?.copy() + }.getOrNull { + mindboxLogE("Failed to parse operation $key", it) + } + }.filterValues { it != null } + }.getOrNull { + mindboxLogE("Failed to parse operations block", it) + } + } + + val ttl = runCatching { + gson.fromJson(json.asJsonObject.get("ttl"), TtlDtoBlank::class.java)?.copy() + }.getOrNull { + mindboxLogE("Failed to parse ttl block", it) + } + + SettingsDtoBlank(operations, ttl) } - return result.getOrNull() + }.getOrNull { + mindboxLogE("Failed to parse settings block", it) + } + + internal fun deserializeAbtests(json: JsonElement?): List? = runCatching { + json?.asJsonArray?.map { abtest -> + gson.fromJson(abtest).getOrThrow()!! + }?.map { it.copy() } + }.getOrNull { + mindboxLogE("Failed to parse abtests block", it) } override fun deserializeToInAppFormDto(inAppForm: JsonObject?): FormDto? { diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/inapp/data/mapper/InAppMapper.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/inapp/data/mapper/InAppMapper.kt index c8a5a9f23..44f02fbaf 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/inapp/data/mapper/InAppMapper.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/inapp/data/mapper/InAppMapper.kt @@ -68,10 +68,10 @@ internal class InAppMapper { logRequestDtoBlank: LogRequestDtoBlank, ): LogRequestDto { return LogRequestDto( - requestId = logRequestDtoBlank.requestId!!, - deviceId = logRequestDtoBlank.deviceId!!, - from = logRequestDtoBlank.from!!, - to = logRequestDtoBlank.to!! + requestId = logRequestDtoBlank.requestId, + deviceId = logRequestDtoBlank.deviceId, + from = logRequestDtoBlank.from, + to = logRequestDtoBlank.to ) } @@ -306,7 +306,7 @@ internal class InAppMapper { id = dto.id, minVersion = dto.sdkVersion?.minVersion, maxVersion = dto.sdkVersion?.maxVersion, - salt = dto.salt!!, + salt = dto.salt, variants = dto.variants?.map { variantDto -> ABTest.Variant( id = variantDto.id, @@ -367,19 +367,19 @@ internal class InAppMapper { is TreeTargetingDto.CityNodeDto -> TreeTargeting.CityNode( type = TreeTargetingDto.CityNodeDto.CITY_JSON_NAME, kind = if (treeTargetingDto.kind == "positive") Kind.POSITIVE else Kind.NEGATIVE, - ids = treeTargetingDto.ids as List + ids = treeTargetingDto.ids!!.map { it.toString() } ) is TreeTargetingDto.CountryNodeDto -> TreeTargeting.CountryNode( type = TreeTargetingDto.CountryNodeDto.COUNTRY_JSON_NAME, kind = if (treeTargetingDto.kind == "positive") Kind.POSITIVE else Kind.NEGATIVE, - ids = treeTargetingDto.ids as List + ids = treeTargetingDto.ids!!.map { it.toString() } ) is TreeTargetingDto.RegionNodeDto -> TreeTargeting.RegionNode( type = TreeTargetingDto.RegionNodeDto.REGION_JSON_NAME, kind = if (treeTargetingDto.kind == "positive") Kind.POSITIVE else Kind.NEGATIVE, - ids = treeTargetingDto.ids as List + ids = treeTargetingDto.ids!!.map { it.toString() } ) is TreeTargetingDto.ViewProductCategoryNodeDto -> ViewProductCategoryNode( @@ -469,7 +469,7 @@ internal class InAppMapper { } fun mapToTtlDto(inAppTtlDtoBlank: SettingsDtoBlank.TtlDtoBlank) = TtlDto( - inApps = inAppTtlDtoBlank.inApps!! + inApps = inAppTtlDtoBlank.inApps ) private fun getTargetingProductSegmentationsList(targeting: TreeTargeting): List { diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/inapp/data/repositories/MobileConfigRepositoryImpl.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/inapp/data/repositories/MobileConfigRepositoryImpl.kt index 0b1021634..843954483 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/inapp/data/repositories/MobileConfigRepositoryImpl.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/inapp/data/repositories/MobileConfigRepositoryImpl.kt @@ -149,7 +149,7 @@ internal class MobileConfigRepositoryImpl( operationNameValidator.isValid(name) && operationValidator.isValid(operation) }?.map { (name, operation) -> - name!! to OperationDto(operation!!.systemName!!) + name!! to OperationDto(operation!!.systemName) }?.toMap() ?: emptyMap() diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/inapp/data/validators/ABTestValidator.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/inapp/data/validators/ABTestValidator.kt index c714f2e7f..e6b4fbce4 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/inapp/data/validators/ABTestValidator.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/inapp/data/validators/ABTestValidator.kt @@ -24,7 +24,7 @@ internal class ABTestValidator(private val sdkVersionValidator: SdkVersionValida return false } - if (item.salt.isNullOrBlank()) { + if (item.salt.isBlank()) { mindboxLogW("In abtest ${item.id} 'salt' field is invalid. All abtests will not be used.") return false } diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/inapp/data/validators/TtlParametersValidator.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/inapp/data/validators/TtlParametersValidator.kt index 02242d01b..a04f79177 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/inapp/data/validators/TtlParametersValidator.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/inapp/data/validators/TtlParametersValidator.kt @@ -7,6 +7,6 @@ import cloud.mindbox.mobile_sdk.utils.loggingRunCatching internal class TtlParametersValidator : Validator { override fun isValid(item: SettingsDtoBlank.TtlDtoBlank): Boolean = loggingRunCatching(false) { - item.inApps!!.parseTimeSpanToMillis() >= 0 + item.inApps.parseTimeSpanToMillis() >= 0 } } \ No newline at end of file diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/inapp/domain/InAppProcessingManagerImpl.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/inapp/domain/InAppProcessingManagerImpl.kt index 990f3ef7d..81b84c2b4 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/inapp/domain/InAppProcessingManagerImpl.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/inapp/domain/InAppProcessingManagerImpl.kt @@ -147,8 +147,8 @@ internal class InAppProcessingManagerImpl( private fun handleCustomerSegmentationErrorLog(error: CustomerSegmentationError) { val volleyError = error.cause as? VolleyError - volleyError?.let { error -> - if ((error.networkResponse?.statusCode == 400) && (error.getErrorResponseBodyData() + volleyError?.let { + if ((volleyError.networkResponse?.statusCode == 400) && (volleyError.getErrorResponseBodyData() .contains(RESPONSE_STATUS_CUSTOMER_SEGMENTS_REQUIRE_CUSTOMER)) ) { mindboxLogI("Cannot check customer segment. It's a new customer") diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/models/Extentions.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/models/Extentions.kt deleted file mode 100644 index 79fd60137..000000000 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/models/Extentions.kt +++ /dev/null @@ -1,14 +0,0 @@ -package cloud.mindbox.mobile_sdk.models - -import java.util.UUID - -internal fun String.isUuid() = if (this.isNotBlank()) { - try { - UUID.fromString(this) - true - } catch (e: Exception) { - false - } -} else { - false -} \ No newline at end of file diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/models/TreeTargetingDto.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/models/TreeTargetingDto.kt index 3583fcf3e..4884d6cdc 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/models/TreeTargetingDto.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/models/TreeTargetingDto.kt @@ -61,7 +61,7 @@ internal sealed class TreeTargetingDto { @SerializedName("kind") val kind: String?, @SerializedName("ids") - val ids: List?, + val ids: List?, ) : TreeTargetingDto() { companion object { const val COUNTRY_JSON_NAME = "country" @@ -74,7 +74,7 @@ internal sealed class TreeTargetingDto { @SerializedName("kind") val kind: String?, @SerializedName("ids") - val ids: List?, + val ids: List?, ) : TreeTargetingDto() { companion object { const val CITY_JSON_NAME = "city" @@ -87,7 +87,7 @@ internal sealed class TreeTargetingDto { @SerializedName("kind") val kind: String?, @SerializedName("ids") - val ids: List?, + val ids: List?, ) : TreeTargetingDto() { companion object { const val REGION_JSON_NAME = "region" diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/models/operation/response/ABTestDto.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/models/operation/response/ABTestDto.kt index fe23923c3..6c59e0c4a 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/models/operation/response/ABTestDto.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/models/operation/response/ABTestDto.kt @@ -8,7 +8,7 @@ internal data class ABTestDto( @SerializedName("sdkVersion") val sdkVersion: SdkVersion?, @SerializedName("salt") - val salt: String?, + val salt: String, @SerializedName("variants") val variants: List?, ) { diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/models/operation/response/InAppConfigResponse.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/models/operation/response/InAppConfigResponse.kt index bd0dbde27..583157857 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/models/operation/response/InAppConfigResponse.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/models/operation/response/InAppConfigResponse.kt @@ -26,12 +26,12 @@ internal data class SettingsDtoBlank( { internal data class OperationDtoBlank( @SerializedName("systemName") - val systemName: String? + val systemName: String ) internal data class TtlDtoBlank( @SerializedName("inapps") - val inApps: String? + val inApps: String ) } @@ -128,13 +128,13 @@ internal data class MonitoringDto( internal data class LogRequestDtoBlank( @SerializedName("requestId") - val requestId: String?, + val requestId: String, @SerializedName("deviceUUID") - val deviceId: String?, + val deviceId: String, @SerializedName("from") - val from: String?, + val from: String, @SerializedName("to") - val to: String?, + val to: String, ) internal data class InAppConfigResponseBlank( diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/utils/MigrationManager.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/utils/MigrationManager.kt index 39fd319b1..983752a99 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/utils/MigrationManager.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/utils/MigrationManager.kt @@ -8,22 +8,33 @@ import cloud.mindbox.mobile_sdk.managers.SharedPreferencesManager import cloud.mindbox.mobile_sdk.repository.MindboxPreferences import com.google.gson.Gson import com.google.gson.reflect.TypeToken +import kotlinx.coroutines.Job import kotlinx.coroutines.launch +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock internal class MigrationManager(val context: Context) { + private val migrationMutex = Mutex() + private val migrationJobs = mutableListOf() - fun migrateAll() { + suspend fun migrateAll() { listOf( version282(), version290() ).filter { it.isNeeded } .onEach { migration -> - loggingRunCatching { - mindboxLogI("Run migration '${migration.description}'") - migration.run() + val job = Mindbox.mindboxScope.launch { + migrationMutex.withLock { + if (migration.isNeeded) { + mindboxLogI("Run migration '${migration.description}'") + migration.run() + } + } } + migrationJobs.add(job) }.also { + migrationJobs.forEach { it.join() } if (MindboxPreferences.versionCode != Constants.SDK_VERSION_CODE) { mindboxLogE("Migrations failed, reset memory") MindboxPreferences.softReset() @@ -36,7 +47,7 @@ internal class MigrationManager(val context: Context) { val description: String val isNeeded: Boolean - fun run() + suspend fun run() } private fun version290() = object : Migration { @@ -45,7 +56,7 @@ internal class MigrationManager(val context: Context) { override val isNeeded: Boolean get() = MindboxPreferences.shownInAppIds != "" - override fun run() { + override suspend fun run() { val gson = Gson() val oldShownInApps = LoggingExceptionHandler.runCatching>(HashSet()) { gson.fromJson( @@ -75,11 +86,9 @@ internal class MigrationManager(val context: Context) { && !MindboxPreferences.isFirstInitialize && MindboxPreferences.isPushTokenNeedUpdated - override fun run() { - Mindbox.mindboxScope.launch { + override suspend fun run() { MindboxPreferences.isPushTokenNeedUpdated = false Mindbox.updateAppInfo(context) - } } } } \ No newline at end of file diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/utils/StrictStringAdapter.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/utils/StrictStringAdapter.kt new file mode 100644 index 000000000..ea76cb871 --- /dev/null +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/utils/StrictStringAdapter.kt @@ -0,0 +1,28 @@ +package cloud.mindbox.mobile_sdk.utils + +import com.google.gson.JsonSyntaxException +import com.google.gson.TypeAdapter +import com.google.gson.stream.JsonReader +import com.google.gson.stream.JsonToken +import com.google.gson.stream.JsonWriter +import java.io.IOException + +class StrictStringAdapter : TypeAdapter() { + @Throws(IOException::class) + override fun read(reader: JsonReader): String? { + return when (reader.peek()) { + JsonToken.NULL -> { + reader.nextNull() + null + } + + JsonToken.STRING -> reader.nextString() + else -> throw JsonSyntaxException("Expected STRING but was " + reader.peek()) + } + } + + @Throws(IOException::class) + override fun write(out: JsonWriter, value: String?) { + out.value(value) + } +} \ No newline at end of file diff --git a/sdk/src/test/java/cloud/mindbox/mobile_sdk/ExtensionsTest.kt b/sdk/src/test/java/cloud/mindbox/mobile_sdk/ExtensionsTest.kt index 1504ea620..552145ff2 100644 --- a/sdk/src/test/java/cloud/mindbox/mobile_sdk/ExtensionsTest.kt +++ b/sdk/src/test/java/cloud/mindbox/mobile_sdk/ExtensionsTest.kt @@ -148,4 +148,35 @@ internal class ExtensionsTest { val error = VolleyError(networkResponse) assertEquals(responseBodyData, error.getErrorResponseBodyData()) } + + @Test + fun `isUuid returns true for valid UUID`() { + val validUuid = "123e4567-e89b-12d3-a456-426614174000" + assertTrue(validUuid.isUuid()) + } + + @Test + fun `isUuid returns false for invalid UUID`() { + val invalidUuid = "123-e89b-12d3-426614174000" + assertFalse(invalidUuid.isUuid()) + } + + @Test + fun `isUuid returns false for empty string`() { + val emptyString = "" + assertFalse(emptyString.isUuid()) + } + + @Test + fun `isUuid returns false for blank string`() { + val blankString = " " + assertFalse(blankString.isUuid()) + } + + @Test + fun `isUuid returns false when UUID string is too long`() { + val longUuid = "123e4567-e89b-12d3-a456-426614174000-extra-uuid" + assertFalse(longUuid.isUuid()) + } + } \ No newline at end of file diff --git a/sdk/src/test/java/cloud/mindbox/mobile_sdk/InitializeLockTest.kt b/sdk/src/test/java/cloud/mindbox/mobile_sdk/InitializeLockTest.kt new file mode 100644 index 000000000..7138fe769 --- /dev/null +++ b/sdk/src/test/java/cloud/mindbox/mobile_sdk/InitializeLockTest.kt @@ -0,0 +1,138 @@ +package cloud.mindbox.mobile_sdk + +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.advanceTimeBy +import kotlinx.coroutines.test.advanceUntilIdle +import kotlinx.coroutines.test.runTest +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test + +@OptIn(ExperimentalCoroutinesApi::class) +class InitializeLockTest { + + @Before + fun setUp() { + InitializeLock.reset(InitializeLock.State.SAVE_MINDBOX_CONFIG) + InitializeLock.reset(InitializeLock.State.APP_STARTED) + } + + @Test + fun `test complete and await SAVE_MINDBOX_CONFIG`() = runTest { + val job = launch { + InitializeLock.await(InitializeLock.State.SAVE_MINDBOX_CONFIG) + } + + advanceTimeBy(100) + assertTrue(job.isActive) + InitializeLock.complete(InitializeLock.State.SAVE_MINDBOX_CONFIG) + advanceUntilIdle() + + assertTrue(job.isCompleted) + } + + @Test + fun `test complete and await APP_STARTED`() = runTest { + val job = launch { + InitializeLock.await(InitializeLock.State.APP_STARTED) + } + advanceTimeBy(100) + assertTrue(job.isActive) + InitializeLock.complete(InitializeLock.State.SAVE_MINDBOX_CONFIG) + assertTrue(job.isActive) + InitializeLock.complete(InitializeLock.State.APP_STARTED) + advanceUntilIdle() + + assertTrue(job.isCompleted) + } + + @Test + fun `test reset and await APP_STARTED`() = runTest { + val job = launch { + InitializeLock.await(InitializeLock.State.APP_STARTED) + } + advanceTimeBy(100) + assertTrue(job.isActive) + InitializeLock.complete(InitializeLock.State.SAVE_MINDBOX_CONFIG) + InitializeLock.reset(InitializeLock.State.APP_STARTED) + advanceUntilIdle() + + assertTrue(job.isCompleted) + } + + @Test + fun `test coroutine doesnt complete without change state`() = runTest { + val job = launch { + InitializeLock.await(InitializeLock.State.SAVE_MINDBOX_CONFIG) + } + advanceTimeBy(1000) + assertTrue(job.isActive) + job.cancel() + } + + @Test + fun `test coroutine doesnt complete without change state for APP_STARTED`() = runTest { + val job = launch { + InitializeLock.complete(InitializeLock.State.SAVE_MINDBOX_CONFIG) + InitializeLock.await(InitializeLock.State.APP_STARTED) + } + advanceTimeBy(1000) + + assertTrue(job.isActive) + job.cancel() + } + + @Test + fun `test coroutine complete when reset status SAVE_MINDBOX_CONFIG`() = runTest { + val job = launch { + InitializeLock.await(InitializeLock.State.SAVE_MINDBOX_CONFIG) + } + advanceTimeBy(100) + assertTrue(job.isActive) + InitializeLock.reset(InitializeLock.State.SAVE_MINDBOX_CONFIG) + job.join() + + assertTrue(job.isCompleted) + } + + @Test + fun `test multiple completes for the same state`() = runTest { + val job = launch { + InitializeLock.await(InitializeLock.State.SAVE_MINDBOX_CONFIG) + } + advanceTimeBy(100) + InitializeLock.complete(InitializeLock.State.SAVE_MINDBOX_CONFIG) + InitializeLock.complete(InitializeLock.State.SAVE_MINDBOX_CONFIG) + + advanceUntilIdle() + assertTrue(job.isCompleted) + } + + @Test + fun `test coroutine is cancelled before state completion`() = runTest { + val job = launch { + InitializeLock.await(InitializeLock.State.SAVE_MINDBOX_CONFIG) + } + advanceTimeBy(100) + job.cancel() + assertTrue(job.isCancelled) + + InitializeLock.complete(InitializeLock.State.SAVE_MINDBOX_CONFIG) + assertTrue(job.isCancelled) + } + + @Test + fun `test coroutine when states already completed`() = runTest { + launch { + InitializeLock.complete(InitializeLock.State.SAVE_MINDBOX_CONFIG) + } + advanceTimeBy(100) + val job = launch { + InitializeLock.await(InitializeLock.State.SAVE_MINDBOX_CONFIG) + } + + job.join() + assertTrue(job.isCompleted) + } +} \ No newline at end of file diff --git a/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/InAppValidatorTest.kt b/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/InAppValidatorTest.kt index 789194de0..c715f74de 100644 --- a/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/InAppValidatorTest.kt +++ b/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/InAppValidatorTest.kt @@ -1322,7 +1322,7 @@ internal class InAppValidatorTest { InAppStub.getInAppDto() .copy( targeting = InAppStub.getTargetingCountryNodeDto() - .copy(type = null, kind = "positive", ids = listOf("123", "456")), + .copy(type = null, kind = "positive", ids = listOf(123, 456)), form = InAppStub.getInAppDto().form?.copy( variants = listOf( InAppStub.getModalWindowDto() @@ -1341,7 +1341,7 @@ internal class InAppValidatorTest { InAppStub.getInAppDto() .copy( targeting = (InAppStub.getTargetingCountryNodeDto() - .copy(type = "country", kind = null, ids = listOf("123", "456"))), + .copy(type = "country", kind = null, ids = listOf(123, 456))), form = InAppStub.getInAppDto().form?.copy( variants = listOf( InAppStub.getModalWindowDto() @@ -1398,7 +1398,7 @@ internal class InAppValidatorTest { InAppStub.getInAppDto() .copy( targeting = (InAppStub.getTargetingCountryNodeDto() - .copy(type = "country", kind = "negative", ids = listOf("123", "456"))), + .copy(type = "country", kind = "negative", ids = listOf(123, 456))), form = InAppStub.getInAppDto().form?.copy( variants = listOf( InAppStub.getModalWindowDto() @@ -1417,7 +1417,7 @@ internal class InAppValidatorTest { InAppStub.getInAppDto() .copy( targeting = (InAppStub.getTargetingCountryNodeDto() - .copy(type = "country", kind = "positive", ids = listOf("123", "456"))), + .copy(type = "country", kind = "positive", ids = listOf(123, 456))), form = InAppStub.getInAppDto().form?.copy( variants = listOf( InAppStub.getModalWindowDto() @@ -1436,7 +1436,7 @@ internal class InAppValidatorTest { InAppStub.getInAppDto() .copy( targeting = InAppStub.getTargetingCityNodeDto() - .copy(type = null, kind = "positive", ids = listOf("123", "456")), + .copy(type = null, kind = "positive", ids = listOf(123, 456)), form = InAppStub.getInAppDto().form?.copy( variants = listOf( InAppStub.getModalWindowDto() @@ -1455,7 +1455,7 @@ internal class InAppValidatorTest { InAppStub.getInAppDto() .copy( targeting = (InAppStub.getTargetingCityNodeDto() - .copy(type = "country", kind = null, ids = listOf("123", "456"))), + .copy(type = "country", kind = null, ids = listOf(123, 456))), form = InAppStub.getInAppDto().form?.copy( variants = listOf( InAppStub.getModalWindowDto() @@ -1512,7 +1512,7 @@ internal class InAppValidatorTest { InAppStub.getInAppDto() .copy( targeting = (InAppStub.getTargetingCityNodeDto() - .copy(type = "country", kind = "negative", ids = listOf("123", "456"))), + .copy(type = "country", kind = "negative", ids = listOf(123, 456))), form = InAppStub.getInAppDto().form?.copy( variants = listOf( InAppStub.getModalWindowDto() @@ -1531,7 +1531,7 @@ internal class InAppValidatorTest { InAppStub.getInAppDto() .copy( targeting = (InAppStub.getTargetingCityNodeDto() - .copy(type = "country", kind = "positive", ids = listOf("123", "456"))), + .copy(type = "country", kind = "positive", ids = listOf(123, 456))), form = InAppStub.getInAppDto().form?.copy( variants = listOf( InAppStub.getModalWindowDto() @@ -1550,7 +1550,7 @@ internal class InAppValidatorTest { InAppStub.getInAppDto() .copy( targeting = InAppStub.getTargetingRegionNodeDto() - .copy(type = null, kind = "positive", ids = listOf("123", "456")), + .copy(type = null, kind = "positive", ids = listOf(123, 456)), form = InAppStub.getInAppDto().form?.copy( variants = listOf( InAppStub.getModalWindowDto() @@ -1569,7 +1569,7 @@ internal class InAppValidatorTest { InAppStub.getInAppDto() .copy( targeting = (InAppStub.getTargetingRegionNodeDto() - .copy(type = "country", kind = null, ids = listOf("123", "456"))), + .copy(type = "country", kind = null, ids = listOf(123, 456))), form = InAppStub.getInAppDto().form?.copy( variants = listOf( InAppStub.getModalWindowDto() @@ -1626,7 +1626,7 @@ internal class InAppValidatorTest { InAppStub.getInAppDto() .copy( targeting = (InAppStub.getTargetingRegionNodeDto() - .copy(type = "country", kind = "negative", ids = listOf("123", "456"))), + .copy(type = "country", kind = "negative", ids = listOf(123, 456))), form = InAppStub.getInAppDto().form?.copy( variants = listOf( InAppStub.getModalWindowDto() @@ -1645,7 +1645,7 @@ internal class InAppValidatorTest { InAppStub.getInAppDto() .copy( targeting = (InAppStub.getTargetingRegionNodeDto() - .copy(type = "country", kind = "positive", ids = listOf("123", "456"))), + .copy(type = "country", kind = "positive", ids = listOf(123, 456))), form = InAppStub.getInAppDto().form?.copy( variants = listOf( InAppStub.getModalWindowDto() diff --git a/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/managers/MobileConfigSerializationManagerImplTest.kt b/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/managers/MobileConfigSerializationManagerImplTest.kt deleted file mode 100644 index b564f2e0d..000000000 --- a/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/managers/MobileConfigSerializationManagerImplTest.kt +++ /dev/null @@ -1,80 +0,0 @@ -package cloud.mindbox.mobile_sdk.inapp.data.managers - -import cloud.mindbox.mobile_sdk.models.InAppStub -import cloud.mindbox.mobile_sdk.models.operation.response.ABTestDto -import cloud.mindbox.mobile_sdk.models.operation.response.SdkVersion -import com.google.gson.Gson -import com.google.gson.JsonObject -import org.junit.Assert.assertEquals -import org.junit.Assert.assertNull -import org.junit.Test - -class MobileConfigSerializationManagerImplTest { - - private val manager by lazy { - MobileConfigSerializationManagerImpl(Gson()) - } - - @Test - fun `deserialize config abtests`() { - val json = getJson() - - val expected = listOf( - ABTestDto( - id = "0ec6be6b-421f-464b-9ee4-348a5292a5fd", - salt = "c0e2682c-3d0f-4291-9308-9e48a16eb3c8", - sdkVersion = SdkVersion( - minVersion = 6, - maxVersion = null, - ), - variants = listOf( - ABTestDto.VariantDto( - id = "3162b011-b30f-4300-a72b-bd5cac0d6607", - modulus = ABTestDto.VariantDto.ModulusDto( - lower = 0, - upper = 50, - ), - objects = listOf( - ABTestDto.VariantDto.ObjectsDto( - type = "inapps", - kind = "concrete", - inapps = listOf( - "655f5ffa-de86-4224-a0bf-229fe208ed0d", - "b33ca779-3c99-481f-ad46-91282b0caf04" - ) - ) - ), - ), - ABTestDto.VariantDto( - id = "dbc39dce-db4f-4dc9-9133-378df018233b", - modulus = ABTestDto.VariantDto.ModulusDto( - lower = 50, - upper = 100, - ), - objects = listOf( - ABTestDto.VariantDto.ObjectsDto( - type = "inapps", - kind = "all", - inapps = null - ) - ) - ) - ) - ) - ) - - - val config = manager.deserializeToConfigDtoBlank(json)!! - - assertNull(config.inApps) - assertNull(config.monitoring) - assertNull(config.settings) - - assertEquals(expected, config.abtests) - } - - private fun getJson(): String { - return javaClass.classLoader!!.getResourceAsStream("abtests.json")!!.bufferedReader() - .use { it.readText() } - } -} \ No newline at end of file diff --git a/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/managers/serialization/AbtestsMobileConfigSerializationManagerTest.kt b/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/managers/serialization/AbtestsMobileConfigSerializationManagerTest.kt new file mode 100644 index 000000000..686080c66 --- /dev/null +++ b/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/managers/serialization/AbtestsMobileConfigSerializationManagerTest.kt @@ -0,0 +1,83 @@ +package cloud.mindbox.mobile_sdk.inapp.data.managers.serialization + +import android.app.Application +import cloud.mindbox.mobile_sdk.di.MindboxDI +import cloud.mindbox.mobile_sdk.di.mindboxInject +import cloud.mindbox.mobile_sdk.inapp.data.managers.MobileConfigSerializationManagerImpl +import io.mockk.every +import io.mockk.mockk +import org.junit.Assert.* +import org.junit.Before +import org.junit.Test + + +class AbtestsMobileConfigSerializationManagerTest { + + private val manager: MobileConfigSerializationManagerImpl by mindboxInject { + mobileConfigSerializationManager as MobileConfigSerializationManagerImpl + } + + private val context = mockk(relaxed = true) { + every { applicationContext } returns this + } + + @Before + fun onTestStart() { + MindboxDI.init(context) + } + + @Test + fun `test ABTestsConfig should parse successfully`() { + val json = getJson("ConfigParsing/ABTests/ABTestsConfig.json") + val config = manager.deserializeAbtests(json)!! + + assertEquals(2, config.size) + + config.forEach { abTest -> + assertNotNull(abTest.salt) + assertNotNull(abTest.sdkVersion) + assertNotNull(abTest.variants) + } + } + + @Test + fun `test ABTestsConfig with IdError should throw decoding error`() { + val json = getJson("ConfigParsing/ABTests/ABTestsIdConfigError.json") + val config = manager.deserializeAbtests(json) + + assertNull(config) + } + + @Test + fun `test ABTestsConfig with IdTypeError should throw decoding error`() { + val json = getJson("ConfigParsing/ABTests/ABTestsIdConfigTypeError.json") + val config = manager.deserializeAbtests(json) + // Type of `id` is Int instead of String + assertNull(config) + } + + @Test + fun `test ABTestsConfig with SdkVersionError should set to Null corrupted data`() { + val json = getJson("ConfigParsing/ABTests/ABTestsSdkVersionConfigError.json") + val config = manager.deserializeAbtests(json)!! + + config.forEach { abTest -> + if (abTest.id == "94CD824A-59AA-4937-9E0E-089895A0DB6F") { + assertNull(abTest.sdkVersion) + } else { + assertNotNull(abTest.sdkVersion) + } + assertNotNull(abTest.salt) + assertNotNull(abTest.variants) + } + } + + @Test + fun `test ABTestsConfig with SdkVersionTypeError should throw decoding error`() { + val json = getJson("ConfigParsing/ABTests/ABTestsSdkVersionConfigTypeError.json") + val config = manager.deserializeAbtests(json) + // Type of `sdkVersion` is Int instead of SdkVersion + assertNull(config) + } +} + diff --git a/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/managers/serialization/ConfigSerializationManagerTest.kt b/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/managers/serialization/ConfigSerializationManagerTest.kt new file mode 100644 index 000000000..7cfea3adf --- /dev/null +++ b/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/managers/serialization/ConfigSerializationManagerTest.kt @@ -0,0 +1,223 @@ +package cloud.mindbox.mobile_sdk.inapp.data.managers.serialization + +import android.app.Application +import cloud.mindbox.mobile_sdk.di.MindboxDI +import cloud.mindbox.mobile_sdk.di.mindboxInject +import cloud.mindbox.mobile_sdk.inapp.data.managers.MobileConfigSerializationManagerImpl +import cloud.mindbox.mobile_sdk.logger.mindboxLogE +import io.mockk.every +import io.mockk.mockk +import io.mockk.mockkStatic +import io.mockk.verify +import org.junit.Assert.assertNotNull +import org.junit.Assert.assertNull +import org.junit.Before +import org.junit.Test + +internal class ConfigSerializationManagerTest { + + private val manager: MobileConfigSerializationManagerImpl by mindboxInject { + mobileConfigSerializationManager as MobileConfigSerializationManagerImpl + } + + private val context = mockk(relaxed = true) { + every { applicationContext } returns this + } + + @Before + fun onTestStart() { + MindboxDI.init(context) + } + + @Test + fun config_shouldParseSuccessfully() { + // Correct config + val json = getJson("ConfigParsing/Config/ConfigWithSettingsABTestsMonitoringInapps.json") + val config = manager.deserializeToConfigDtoBlank(json.toString())!! + + assertNotNull(config.inApps) + assertNotNull(config.abtests) + assertNotNull(config.settings) + assertNotNull(config.monitoring) + } + + @Test + fun config_withSettingsError_shouldSetSettingsToNull() { + // Key is `settingsTest` instead of `settings` + val json = getJson("ConfigParsing/Config/ConfigSettingsError.json") + val config = manager.deserializeToConfigDtoBlank(json.toString())!! + + assertNull(config.settings) + assertNotNull(config.inApps) + assertNotNull(config.abtests) + assertNotNull(config.monitoring) + } + + @Test + fun config_withSettingsTypeError_shouldSetSettingsToNull() { + // Type of `settings` is Int instead of Settings + val json = getJson("ConfigParsing/Config/ConfigSettingsTypeError.json") + val config = manager.deserializeToConfigDtoBlank(json.toString())!! + + assertNull(config.settings) + assertNotNull(config.inApps) + assertNotNull(config.abtests) + assertNotNull(config.monitoring) + } + + @Test + fun config_withMonitoringError_shouldSetMonitoringToNull() { + // Key is `monitoringTest` instead of `monitoring` + val json = getJson("ConfigParsing/Config/ConfigMonitoringError.json") + val config = manager.deserializeToConfigDtoBlank(json.toString())!! + + assertNull(config.monitoring) + assertNotNull(config.settings) + assertNotNull(config.inApps) + assertNotNull(config.abtests) + } + + @Test + fun config_withMonitoringTypeError_shouldSetMonitoringToNull() { + // Type of `monitoring` is Int instead of Monitoring + val json = getJson("ConfigParsing/Config/ConfigMonitoringTypeError.json") + val config = manager.deserializeToConfigDtoBlank(json.toString())!! + + assertNull(config.monitoring) + assertNotNull(config.settings) + assertNotNull(config.inApps) + assertNotNull(config.abtests) + } + + @Test + fun config_withABTestsError_shouldSetABTestsToNull() { + // Key is `abtestsTest` instead of `abtests` + val json = getJson("ConfigParsing/Config/ConfigABTestsError.json") + val config = manager.deserializeToConfigDtoBlank(json.toString())!! + + assertNull(config.abtests) + assertNotNull(config.monitoring) + assertNotNull(config.settings) + assertNotNull(config.inApps) + } + + @Test + fun config_withABTestsTypeError_shouldSetABTestsToNull() { + // Type of `abtests` is Int instead of [ABTest] + val json = getJson("ConfigParsing/Config/ConfigABTestsTypeError.json") + val config = manager.deserializeToConfigDtoBlank(json.toString())!! + + assertNull(config.abtests) + assertNotNull(config.monitoring) + assertNotNull(config.settings) + assertNotNull(config.inApps) + } + + @Test + fun config_withInAppsError_shouldSetInAppsToNull() { + // Key is `inappsTest` instead of `inapps` + val json = getJson("ConfigParsing/Config/ConfigInAppsError.json") + val config = manager.deserializeToConfigDtoBlank(json.toString())!! + + assertNull(config.inApps) + assertNotNull(config.abtests) + assertNotNull(config.monitoring) + assertNotNull(config.settings) + } + + @Test + fun config_withInAppsTypeError_shouldSetInAppsToNull() { + // Type of `inapps` is Int instead of FailableDecodableArray + val json = getJson("ConfigParsing/Config/ConfigInAppsTypeError.json") + val config = manager.deserializeToConfigDtoBlank(json.toString())!! + + assertNull(config.inApps) + assertNotNull(config.abtests) + assertNotNull(config.monitoring) + assertNotNull(config.settings) + } + + @Test + fun config_withABTestsOneElementError_shouldSetABTestsToNull() { + // Key is `saltTest` instead of `salt` + val json = getJson("ConfigParsing/Config/ConfigABTestsOneElementError.json") + val config = manager.deserializeToConfigDtoBlank(json.toString())!! + + assertNull(config.abtests) + assertNotNull(config.monitoring) + assertNotNull(config.settings) + assertNotNull(config.inApps) + } + + @Test + fun config_withABTestsOneElementTypeError_shouldSetABTestsToNull() { + // Type of `variants` is Int instead of [ABTestVariant] + val json = getJson("ConfigParsing/Config/ConfigABTestsOneElementTypeError.json") + val config = manager.deserializeToConfigDtoBlank(json.toString())!! + + assertNull(config.abtests) + assertNotNull(config.monitoring) + assertNotNull(config.settings) + assertNotNull(config.inApps) + } + + @Test + fun `empty config`() { + // Key is `abtestsTest` instead of `abtests` + mockkStatic(::mindboxLogE) + val json = getJson("ConfigParsing/Config/EmptyConfigs/EmptyConfig.json") + val config = manager.deserializeToConfigDtoBlank(json.toString())!! + + assertNull(config.abtests) + assertNull(config.monitoring) + assertNull(config.settings) + assertNull(config.inApps) + + verify(exactly = 0) { mindboxLogE(any(), any()) } + } + + @Test + fun `no monitoring in config`() { + // Key is `abtestsTest` instead of `abtests` + mockkStatic(::mindboxLogE) + val json = getJson("ConfigParsing/Config/EmptyConfigs/NoMonitoring.json") + val config = manager.deserializeToConfigDtoBlank(json.toString())!! + + assertNull(config.monitoring) + assertNotNull(config.abtests) + assertNotNull(config.settings) + assertNotNull(config.inApps) + + verify(exactly = 0) { mindboxLogE(any(), any()) } + } + + @Test + fun `empty monitoring in config`() { + // Key is `abtestsTest` instead of `abtests` + mockkStatic(::mindboxLogE) + val json = getJson("ConfigParsing/Config/EmptyConfigs/EmptyMonitoring.json") + val config = manager.deserializeToConfigDtoBlank(json.toString())!! + + assertNull(config.abtests) + assertNull(config.monitoring) + assertNull(config.settings) + assertNull(config.inApps) + + verify(exactly = 0) { mindboxLogE(any(), any()) } + } + + @Test + fun `empty monitoring logs in config`() { + // Key is `abtestsTest` instead of `abtests` + mockkStatic(::mindboxLogE) + val json = getJson("ConfigParsing/Config/EmptyConfigs/EmptyLogsMonitoring.json") + val config = manager.deserializeToConfigDtoBlank(json.toString())!! + + assertNull(config.abtests) + assertNull(config.monitoring) + assertNull(config.settings) + assertNull(config.inApps) + + verify(exactly = 0) { mindboxLogE(any(), any()) } + } +} \ No newline at end of file diff --git a/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/managers/serialization/JsonTestUtils.kt b/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/managers/serialization/JsonTestUtils.kt new file mode 100644 index 000000000..743c83281 --- /dev/null +++ b/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/managers/serialization/JsonTestUtils.kt @@ -0,0 +1,10 @@ +package cloud.mindbox.mobile_sdk.inapp.data.managers.serialization + +import com.google.gson.JsonElement +import com.google.gson.JsonParser + +fun Any.getJson(path: String): JsonElement { + return javaClass.classLoader!!.getResourceAsStream(path)!!.bufferedReader() + .use { it.readText() } + .let { JsonParser.parseString(it) } +} diff --git a/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/managers/MobileConfigSerializationManagerTest.kt b/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/managers/serialization/MobileConfigSerializationManagerTest.kt similarity index 98% rename from sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/managers/MobileConfigSerializationManagerTest.kt rename to sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/managers/serialization/MobileConfigSerializationManagerTest.kt index f67dac558..c462319e3 100644 --- a/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/managers/MobileConfigSerializationManagerTest.kt +++ b/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/managers/serialization/MobileConfigSerializationManagerTest.kt @@ -1,6 +1,7 @@ -package cloud.mindbox.mobile_sdk.inapp.data.managers +package cloud.mindbox.mobile_sdk.inapp.data.managers.serialization import cloud.mindbox.mobile_sdk.di.modules.DataModule +import cloud.mindbox.mobile_sdk.inapp.data.managers.MobileConfigSerializationManagerImpl import cloud.mindbox.mobile_sdk.inapp.domain.interfaces.managers.MobileConfigSerializationManager import cloud.mindbox.mobile_sdk.models.InAppStub import cloud.mindbox.mobile_sdk.models.TreeTargetingDto @@ -136,7 +137,7 @@ internal class MobileConfigSerializationManagerTest { @Test fun `deserialize to in app targeting city dto success`() { val expectedResult = InAppStub.getTargetingCityNodeDto() - .copy(type = "city", kind = "positive", listOf("123")) + .copy(type = "city", kind = "positive", listOf(123)) val actualResult = mobileConfigSerializationManager.deserializeToInAppTargetingDto(JsonObject().apply { addProperty("${'$'}type", "city") @@ -151,7 +152,7 @@ internal class MobileConfigSerializationManagerTest { @Test fun `deserialize to in app targeting country dto success`() { val expectedResult = InAppStub.getTargetingCountryNodeDto() - .copy(type = "country", kind = "positive", listOf("123")) + .copy(type = "country", kind = "positive", listOf(123)) val actualResult = mobileConfigSerializationManager.deserializeToInAppTargetingDto(JsonObject().apply { addProperty("${'$'}type", "country") @@ -167,7 +168,7 @@ internal class MobileConfigSerializationManagerTest { @Test fun `deserialize to in app targeting region dto success`() { val expectedResult = InAppStub.getTargetingRegionNodeDto() - .copy(type = "region", kind = "positive", listOf("123")) + .copy(type = "region", kind = "positive", listOf(123)) val actualResult = mobileConfigSerializationManager.deserializeToInAppTargetingDto(JsonObject().apply { addProperty("${'$'}type", "region") diff --git a/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/managers/serialization/MonitoringMobileConfigSerializationManagerTest.kt b/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/managers/serialization/MonitoringMobileConfigSerializationManagerTest.kt new file mode 100644 index 000000000..c639caa04 --- /dev/null +++ b/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/managers/serialization/MonitoringMobileConfigSerializationManagerTest.kt @@ -0,0 +1,110 @@ +package cloud.mindbox.mobile_sdk.inapp.data.managers.serialization + +import android.app.Application +import cloud.mindbox.mobile_sdk.di.MindboxDI +import cloud.mindbox.mobile_sdk.di.mindboxInject +import cloud.mindbox.mobile_sdk.inapp.data.managers.MobileConfigSerializationManagerImpl +import cloud.mindbox.mobile_sdk.logger.MindboxLoggerImpl +import io.mockk.every +import io.mockk.mockk +import io.mockk.mockkObject +import io.mockk.verify +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Before +import org.junit.Test + + +class MonitoringMobileConfigSerializationManagerTest { + + private val manager: MobileConfigSerializationManagerImpl by mindboxInject { + mobileConfigSerializationManager as MobileConfigSerializationManagerImpl + } + + private val context = mockk(relaxed = true) { + every { applicationContext } returns this + } + + @Before + fun onTestStart() { + MindboxDI.init(context) + } + + @Test + fun monitoringConfig_shouldParseSuccessfully() { + // Correct config + val json = getJson("ConfigParsing/Monitoring/MonitoringConfig.json") + val config = manager.deserializeMonitoring(json)!! + + assertEquals(2, config.logs?.size) + } + + @Test + fun monitoringConfig_withLogsError_shouldSetMonitoringToNull() { + // Key is `logsTests` instead of `logs` + val json = getJson("ConfigParsing/Monitoring/MonitoringLogsError.json") + val config = manager.deserializeMonitoring(json) + + assertNull(config?.logs) + } + + @Test + fun monitoringConfig_withLogsTypeError_shouldSetMonitoringToNull() { + // Type of `logs` is Int instead of + val json = getJson("ConfigParsing/Monitoring/MonitoringLogsTypeError.json") + val config = manager.deserializeMonitoring(json) + + assertNull(config?.logs) + } + + @Test + fun monitoringConfig_withLogsOneElementError_shouldParseSuccessfullyRemainsElements() { + // Type of `requestId` is Int instead of String + val json = getJson("ConfigParsing/Monitoring/MonitoringLogsOneElementError.json") + val config = manager.deserializeMonitoring(json) + + assertEquals(1, config?.logs?.size) + } + + @Test + fun monitoringConfig_withLogsOneElementTypeError_shouldParseSuccessfullyRemainsElements() { + // Type of `requestId` is Int instead of String + mockkObject(MindboxLoggerImpl) + val json = getJson("ConfigParsing/Monitoring/MonitoringLogsOneElementTypeError.json") + val config = manager.deserializeMonitoring(json)!! + + assertEquals(1, config.logs?.size) + verify(exactly = 1) { MindboxLoggerImpl.e(any(),"Failed to parse logs block", any()) } + } + + @Test + fun monitoringConfig_withLogsTwoElementsError_shouldParseSuccessfullyRemainsElements() { + // Key is `request` instead `requestId` and key is `device` instead of `deviceUUID` + mockkObject(MindboxLoggerImpl) + + val json = getJson("ConfigParsing/Monitoring/MonitoringLogsTwoElementsError.json") + val config = manager.deserializeMonitoring(json)!! + + assertEquals(0, config.logs?.size) + verify(exactly = 2) { MindboxLoggerImpl.e(any(),"Failed to parse logs block", any()) } + } + + @Test + fun monitoringConfig_withLogsTwoElementsTypeError_shouldParseSuccessfullyRemainsElements() { + // Type of `requestId` is Int instead of String and type of `from` is Object instead of `String` + val json = getJson("ConfigParsing/Monitoring/MonitoringLogsTwoElementsTypeError.json") + val config = manager.deserializeMonitoring(json)!! + + assertEquals(0, config.logs?.size) + } + + @Test + fun monitoringConfig_withLogsTwoElementsMixedError_shouldParseSuccessfullyRemainsElements() { + // Type of `requestId` is Int instead of String and key is `fromTest` instead of `from` + val json = getJson("ConfigParsing/Monitoring/MonitoringLogsElementsMixedError.json") + val config = manager.deserializeMonitoring(json) + + assertEquals(0, config?.logs?.size) + } +} + diff --git a/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/managers/serialization/SettingsMobileConfigSerializationManagerTest.kt b/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/managers/serialization/SettingsMobileConfigSerializationManagerTest.kt new file mode 100644 index 000000000..3f00f7362 --- /dev/null +++ b/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/managers/serialization/SettingsMobileConfigSerializationManagerTest.kt @@ -0,0 +1,446 @@ +package cloud.mindbox.mobile_sdk.inapp.data.managers.serialization + +import android.app.Application +import cloud.mindbox.mobile_sdk.di.MindboxDI +import cloud.mindbox.mobile_sdk.di.mindboxInject +import cloud.mindbox.mobile_sdk.inapp.data.managers.MobileConfigSerializationManagerImpl +import cloud.mindbox.mobile_sdk.models.operation.response.ABTestDto +import cloud.mindbox.mobile_sdk.models.operation.response.SdkVersion +import com.google.gson.Gson +import io.mockk.every +import io.mockk.mockk +import org.junit.Assert.* +import org.junit.Before +import org.junit.Test + +class SettingsMobileConfigSerializationManagerTest { + + private val manager: MobileConfigSerializationManagerImpl by mindboxInject { + mobileConfigSerializationManager as MobileConfigSerializationManagerImpl + } + + private val context = mockk(relaxed = true) { + every { applicationContext } returns this + } + + @Before + fun onTestStart() { + MindboxDI.init(context) + } + + @Test + fun `deserialize config abtests`() { + val json = getJson("abtests.json") + + val expected = listOf( + ABTestDto( + id = "0ec6be6b-421f-464b-9ee4-348a5292a5fd", + salt = "c0e2682c-3d0f-4291-9308-9e48a16eb3c8", + sdkVersion = SdkVersion( + minVersion = 6, + maxVersion = null, + ), + variants = listOf( + ABTestDto.VariantDto( + id = "3162b011-b30f-4300-a72b-bd5cac0d6607", + modulus = ABTestDto.VariantDto.ModulusDto( + lower = 0, + upper = 50, + ), + objects = listOf( + ABTestDto.VariantDto.ObjectsDto( + type = "inapps", + kind = "concrete", + inapps = listOf( + "655f5ffa-de86-4224-a0bf-229fe208ed0d", + "b33ca779-3c99-481f-ad46-91282b0caf04" + ) + ) + ), + ), + ABTestDto.VariantDto( + id = "dbc39dce-db4f-4dc9-9133-378df018233b", + modulus = ABTestDto.VariantDto.ModulusDto( + lower = 50, + upper = 100, + ), + objects = listOf( + ABTestDto.VariantDto.ObjectsDto( + type = "inapps", + kind = "all", + inapps = null + ) + ) + ) + ) + ) + ) + + val config = manager.deserializeToConfigDtoBlank(json.toString())!! + + assertNull(config.inApps) + assertNull(config.monitoring) + assertNull(config.settings) + + assertEquals(expected, config.abtests) + } + + @Test + fun `deserialize config all`() { + val json = getJson("ConfigParsing/ConfigWithSettingsABTestsMonitoringInapps.json") + val config = manager.deserializeToConfigDtoBlank(json.toString())!! + + assertNotNull(config.inApps) + assertEquals(4, config.inApps!!.size) + + assertNotNull(config.monitoring) + assertEquals(2, config.monitoring!!.logs!!.size) + + assertNotNull(config.settings) + assertEquals(3, config.settings!!.operations!!.size) + + assertNotNull(config.abtests) + assertEquals(2, config.abtests!!.size) + } + + @Test + fun settings_config_shouldParseSuccessfully() { + val json = getJson("ConfigParsing/Settings/SettingsConfig.json") + val config = manager.deserializeSettings(json)!! + + assertNotNull(config.operations) + assertNotNull(config.operations!!["viewProduct"]) + assertNotNull(config.operations["viewCategory"]) + assertNotNull(config.operations["setCart"]) + + assertNotNull(config.ttl) + assertNotNull(config.ttl?.inApps) + } + + // MARK: - Operations + + @Test + fun settings_config_withOperationsError_shouldSetOperationsToNull() { + val json = getJson("ConfigParsing/Settings/OperationsErrors/SettingsOperationsError.json") + val config = manager.deserializeSettings(json)!! + + assertNull( + "Operations must be `null` if the key `operations` is not found", + config.operations, + ) + assertNull(config.operations?.get("viewProduct")) + assertNull(config.operations?.get("viewCategory")) + assertNull(config.operations?.get("setCart")) + + assertNotNull("TTL must be successfully parsed", config.ttl) + assertNotNull("TTL must be successfully parsed", config.ttl?.inApps) + } + + @Test + fun settings_config_withOperationsTypeError_shouldSetOperationsToNull() { + val json = + getJson("ConfigParsing/Settings/OperationsErrors/SettingsOperationsTypeError.json") + val config = manager.deserializeSettings(json)!! + + assertNull( + "Operations must be `null` if the type of `operations` is not a `SettingsOperations`", + config.operations, + ) + assertNull(config.operations?.get("viewProduct")) + assertNull(config.operations?.get("viewCategory")) + assertNull(config.operations?.get("setCart")) + + assertNotNull("TTL must be successfully parsed", config.ttl) + assertNotNull("TTL must be successfully parsed", config.ttl?.inApps) + } + + @Test + fun settings_config_withOperationsViewProductError_shouldSetViewProductToNull() { + val json = + getJson("ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewProductError.json") + val config = manager.deserializeSettings(json)!! + + assertNotNull("Operations must be successfully parsed", config.operations) + assertNull( + "ViewProduct must be `null` if the key `viewProduct` is not found", + config.operations?.get("viewProduct"), + ) + assertNotNull(config.operations?.get("viewCategory")) + assertNotNull(config.operations?.get("setCart")) + + assertNotNull("TTL must be successfully parsed", config.ttl) + assertNotNull("TTL must be successfully parsed", config.ttl?.inApps) + } + + @Test + fun settings_config_withOperationsViewProductTypeError_shouldSetViewProductToNull() { + val json = + getJson("ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewProductTypeError.json") + val config = manager.deserializeSettings(json)!! + + assertNotNull("Operations must be successfully parsed", config.operations) + assertNull( + "ViewProduct must be `null` if the type of `viewProduct` is not an `Operation`", + config.operations?.get("viewProduct") + ) + assertNotNull(config.operations?.get("viewCategory")) + assertNotNull(config.operations?.get("setCart")) + + assertNotNull("TTL must be successfully parsed", config.ttl) + assertNotNull("TTL must be successfully parsed", config.ttl?.inApps) + } + + @Test + fun settings_config_withOperationsViewProductSystemNameError_shouldSetViewProductToNull() { + val json = + getJson("ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewProductSystemNameError.json") + val config = manager.deserializeSettings(json)!! + + assertNotNull("Operations must be successfully parsed", config.operations) + assertNull( + "ViewProduct must be `null` if the key `systemName` is not found", + config.operations?.get("viewProduct") + ) + assertNotNull(config.operations?.get("viewCategory")) + assertNotNull(config.operations?.get("setCart")) + + assertNotNull("TTL must be successfully parsed", config.ttl) + assertNotNull("TTL must be successfully parsed", config.ttl?.inApps) + } + + @Test + fun settings_config_withOperationsViewProductSystemNameTypeError_shouldSetViewProductToNull() { + val json = + getJson("ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewProductSystemNameTypeError.json") + val config = manager.deserializeSettings(json)!! + + assertNotNull("Operations must be successfully parsed", config.operations) + assertNull( + "ViewProduct must be `null` if the type of `systemName` is not a `String`", + config.operations?.get("viewProduct"), + ) + assertNotNull(config.operations?.get("viewCategory")) + assertNotNull(config.operations?.get("setCart")) + + assertNotNull("TTL must be successfully parsed", config.ttl) + assertNotNull("TTL must be successfully parsed", config.ttl?.inApps) + } + + @Test + fun settings_config_withAllOperationsWithErrors_shouldSetOperationsToNull() { + val json = + getJson("ConfigParsing/Settings/OperationsErrors/SettingsAllOperationsWithErrors.json") + val config = manager.deserializeSettings(json)!! + + assertNull(config.operations?.get("viewProduct")) + assertNull(config.operations?.get("viewCategory")) + assertNull(config.operations?.get("setCart")) + + assertNotNull("TTL must be successfully parsed", config.ttl) + assertNotNull("TTL must be successfully parsed", config.ttl?.inApps) + } + + @Test + fun settings_config_withAllOperationsWithTypeErrors_shouldSetOperationsToNull() { + val json = + getJson("ConfigParsing/Settings/OperationsErrors/SettingsAllOperationsWithTypeErrors.json") + val config = manager.deserializeSettings(json)!! + + assertEquals( + "Operations must be `null` if all three operations are `null`", + true, + config.operations?.isEmpty(), + ) + assertNull(config.operations?.get("viewProduct")) + assertNull(config.operations?.get("viewCategory")) + assertNull(config.operations?.get("setCart")) + + assertNotNull("TTL must be successfully parsed", config.ttl) + assertNotNull("TTL must be successfully parsed", config.ttl?.inApps) + } + + @Test + fun settings_config_withOperationsViewCategoryAndSetCartError_shouldSetViewCategoryAndSetCartToNull() { + val json = + getJson("ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewCategoryAndSetCartError.json") + val config = manager.deserializeSettings(json)!! + + assertNotNull("Operations must be successfully parsed", config.operations) + assertNotNull( + "ViewProduct must be successfully parsed", + config.operations?.get("viewProduct"), + ) + assertNull( + "ViewCategory must be `null` if the key `viewCategory` is not found", + config.operations?.get("viewCategory"), + ) + assertNull( + "setCart must be `null` if the key `setCart` is not found", + config.operations?.get("setCart"), + ) + + assertNotNull("TTL must be successfully parsed", config.ttl) + assertNotNull("TTL must be successfully parsed", config.ttl?.inApps) + } + + @Test + fun settings_config_withOperationsViewCategoryAndSetCartTypeError_shouldSetViewCategoryAndSetCartToNull() { + val json = + getJson("ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewCategoryAndSetCartTypeError.json") + val config = manager.deserializeSettings(json)!! + + assertNotNull("Operations must be successfully parsed", config.operations) + assertNotNull( + "ViewProduct must be successfully parsed", + config.operations?.get("viewProduct") + ) + assertNull( + "ViewCategory must be `null` if the type of `viewCategory` is not a `SettingsOperations`", + config.operations?.get("viewCategory"), + ) + assertNull( + "setCart must be `null` if the type `setCart` is not a `SettingsOperations`", + config.operations?.get("setCart"), + ) + + assertNotNull("TTL must be successfully parsed", config.ttl) + assertNotNull("TTL must be successfully parsed", config.ttl?.inApps) + } + + @Test + fun settings_config_withOperationsViewCategoryAndSetCartSystemNameError_shouldSetViewCategoryAndSetCartToNull() { + val json = + getJson("ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewCategoryAndSetCartSystemNameError.json") + val config = manager.deserializeSettings(json)!! + + assertNotNull("Operations must be successfully parsed", config.operations) + assertNotNull( + "ViewProduct must be successfully parsed", + config.operations?.get("viewProduct"), + ) + assertNull( + "ViewCategory must be `null` if the key `systemName` is not found", + config.operations?.get("viewCategory"), + ) + assertNull( + "setCart must be `null` if the key `systemName` is not found", + config.operations?.get("setCart"), + ) + + assertNotNull("TTL must be successfully parsed", config.ttl) + assertNotNull("TTL must be successfully parsed", config.ttl?.inApps) + } + + @Test + fun settings_config_withOperationsViewCategoryAndSetCartSystemNameTypeError_shouldSetViewCategoryAndSetCartToNull() { + val json = + getJson("ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewCategoryAndSetCartSystemNameTypeError.json") + val config = manager.deserializeSettings(json)!! + + assertNotNull("Operations must be successfully parsed", config.operations) + assertNotNull( + "ViewProduct must be successfully parsed", + config.operations?.get("viewProduct"), + ) + assertNull( + "ViewCategory must be `null` if the type of `systemName` is not a `String`", + config.operations?.get("viewCategory"), + ) + assertNull( + "setCart must be `null` if the type `systemName` is not a `String`", + config.operations?.get("setCart"), + ) + + assertNotNull("TTL must be successfully parsed", config.ttl) + assertNotNull("TTL must be successfully parsed", config.ttl?.inApps) + } + + @Test + fun settings_config_withOperationsViewCategoryAndSetCartSystemNameMixedError_shouldSetViewCategoryAndSetCartToNull() { + val json = + getJson("ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewCategoryAndSetCartSystemNameMixedError.json") + val config = manager.deserializeSettings(json)!! + + assertNotNull("Operations must be successfully parsed", config.operations) + assertNotNull( + "ViewProduct must be successfully parsed", + config.operations?.get("viewProduct"), + ) + assertNull( + "ViewCategory must be `null` if the key `systemName` is not found", + config.operations?.get("viewCategory"), + ) + assertNull( + "setCart must be `null` if the type `systemName` is not a `String`", + config.operations?.get("setCart"), + ) + + assertNotNull("TTL must be successfully parsed", config.ttl) + assertNotNull("TTL must be successfully parsed", config.ttl?.inApps) + } + + // MARK: - TTL + + @Test + fun settings_config_withTtlError_shouldSetTtlToNull() { + val json = getJson("ConfigParsing/Settings/TtlErrors/SettingsTtlError.json") + val config = manager.deserializeSettings(json)!! + + assertNotNull("Operations must be successfully parsed", config.operations) + assertNotNull(config.operations?.get("viewProduct")) + assertNotNull(config.operations?.get("viewCategory")) + assertNotNull(config.operations?.get("setCart")) + + assertNull("TTL must be `null` if the key `ttl` is not found", config.ttl) + assertNull("TTL must be `null`", config.ttl?.inApps) + } + + @Test + fun settings_config_withTtlTypeError_shouldSetTtlToNull() { + val json = getJson("ConfigParsing/Settings/TtlErrors/SettingsTtlTypeError.json") + val config = manager.deserializeSettings(json)!! + + assertNotNull("Operations must be successfully parsed", config.operations) + assertNotNull(config.operations?.get("viewProduct")) + assertNotNull(config.operations?.get("viewCategory")) + assertNotNull(config.operations?.get("setCart")) + + assertNull( + "TTL must be `null` if the type of `inapps` is not a `TimeToLive`", + config.ttl, + ) + assertNull("TTL must be `null`", config.ttl?.inApps) + } + + @Test + fun settings_config_withTtlInappsError_shouldSetTtlToNull() { + val json = getJson("ConfigParsing/Settings/TtlErrors/SettingsTtlInappsError.json") + val config = manager.deserializeSettings(json)!! + + assertNotNull("Operations must be successfully parsed", config.operations) + assertNotNull(config.operations?.get("viewProduct")) + assertNotNull(config.operations?.get("viewCategory")) + assertNotNull(config.operations?.get("setCart")) + + assertNull("TTL must be `null` if the key `inapps` is not found", config.ttl) + assertNull("TTL must be `null`", config.ttl?.inApps) + } + + @Test + fun settings_config_withTtlInappsTypeError_shouldSetTtlToNull() { + val json = getJson("ConfigParsing/Settings/TtlErrors/SettingsTtlInappsTypeError.json") + val config = manager.deserializeSettings(json)!! + + assertNotNull("Operations must be successfully parsed", config.operations) + assertNotNull(config.operations?.get("viewProduct")) + assertNotNull(config.operations?.get("viewCategory")) + assertNotNull(config.operations?.get("setCart")) + + assertNull("TTL must be `null` if the key `inapps` is not a `String`", config.ttl) + assertNull( + "TTL must be `null` if the key `inapps` is not a `String`", + config.ttl?.inApps, + ) + } +} + diff --git a/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/mapper/InAppMapperTest.kt b/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/mapper/InAppMapperTest.kt new file mode 100644 index 000000000..b18cf0de7 --- /dev/null +++ b/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/mapper/InAppMapperTest.kt @@ -0,0 +1,74 @@ +package cloud.mindbox.mobile_sdk.inapp.data.mapper + +import cloud.mindbox.mobile_sdk.inapp.domain.models.TreeTargeting +import cloud.mindbox.mobile_sdk.models.TreeTargetingDto +import cloud.mindbox.mobile_sdk.models.operation.response.FrequencyDto +import cloud.mindbox.mobile_sdk.models.operation.response.InAppConfigResponse +import cloud.mindbox.mobile_sdk.models.operation.response.InAppDto +import org.junit.Assert.assertTrue +import org.junit.Test + +class InAppMapperTest { + + @Test + fun `mapToInAppConfig ids type to string`() { + val mapper = InAppMapper() + + val result = mapper.mapToInAppConfig( + InAppConfigResponse( + inApps = listOf( + InAppDto( + id = "id", + frequency = FrequencyDto.FrequencyOnceDto( + type = "once", + kind = "lifetime", + ), + sdkVersion = null, + targeting = TreeTargetingDto.UnionNodeDto( + type = "or", + nodes = listOf( + TreeTargetingDto.CountryNodeDto( + type = "country", + kind = "positive", + ids = listOf(1L, 2L, 3L), + ), + TreeTargetingDto.RegionNodeDto( + type = "region", + kind = "positive", + ids = listOf(4L, 5L, 6L), + ), + TreeTargetingDto.CityNodeDto( + type = "city", + kind = "positive", + ids = listOf(7L, 8L, 9L), + ), + ), + ), + form = null, + ) + ), + monitoring = null, + abtests = null, + settings = null, + ) + ) + + val targeting = result.inApps.first().targeting as TreeTargeting.UnionNode + + val country = targeting.nodes.first() as TreeTargeting.CountryNode + assertTrue(country.ids.contains("1")) + assertTrue(country.ids.contains("2")) + assertTrue(country.ids.contains("3")) + + val region = targeting.nodes[1] as TreeTargeting.RegionNode + assertTrue(region.ids.contains("4")) + assertTrue(region.ids.contains("5")) + assertTrue(region.ids.contains("6")) + + val city = targeting.nodes.last() as TreeTargeting.CityNode + assertTrue(city.ids.contains("7")) + assertTrue(city.ids.contains("8")) + assertTrue(city.ids.contains("9")) + } + +} \ No newline at end of file diff --git a/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/validators/ABTestValidatorTest.kt b/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/validators/ABTestValidatorTest.kt index 95166c1c3..4779b1404 100644 --- a/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/validators/ABTestValidatorTest.kt +++ b/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/validators/ABTestValidatorTest.kt @@ -123,7 +123,7 @@ internal class ABTestValidatorTest( variant2.copy(modulus = modulus.copy(lower = 60, upper = 40)), ) ) to false, - abtest.copy(salt = null) to false, + abtest.copy(salt = "") to false, abtest.copy(salt = "") to false, abtest.copy(id = "") to false, abtest.copy(sdkVersion = null) to false, diff --git a/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/validators/OperationValidatorTest.kt b/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/validators/OperationValidatorTest.kt index 0d60b30a6..ba98210f9 100644 --- a/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/validators/OperationValidatorTest.kt +++ b/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/validators/OperationValidatorTest.kt @@ -17,7 +17,6 @@ class OperationValidatorTest { @Test fun `operation is not valid`() { - assertFalse(validator.isValid(SettingsDtoBlank.OperationDtoBlank(systemName = null))) assertFalse(validator.isValid(SettingsDtoBlank.OperationDtoBlank(systemName = ""))) assertFalse(validator.isValid(SettingsDtoBlank.OperationDtoBlank(systemName = " "))) assertFalse(validator.isValid(SettingsDtoBlank.OperationDtoBlank(systemName = "\t"))) diff --git a/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/validators/TtlParametersValidatorTest.kt b/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/validators/TtlParametersValidatorTest.kt index 02ab6ac7a..633d5d752 100644 --- a/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/validators/TtlParametersValidatorTest.kt +++ b/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/data/validators/TtlParametersValidatorTest.kt @@ -57,13 +57,6 @@ class TtlParametersValidatorTest { assertTrue(validator.isValid(negativeValueTtl)) } - @Test - fun `isValid returns false for null value`() { - val nullTtl = SettingsDtoBlank.TtlDtoBlank(null) - - assertFalse(validator.isValid(nullTtl)) - } - @Test fun `isValid returns false when ttl is valid string`() { val nullTtl = SettingsDtoBlank.TtlDtoBlank("one day") diff --git a/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/presentation/InAppActionHandlerTest.kt b/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/presentation/InAppActionHandlerTest.kt index 23367d43e..cea8f6cd3 100644 --- a/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/presentation/InAppActionHandlerTest.kt +++ b/sdk/src/test/java/cloud/mindbox/mobile_sdk/inapp/presentation/InAppActionHandlerTest.kt @@ -50,6 +50,7 @@ class InAppActionHandlerTest { Assert.assertTrue(resultAction.payload == "test_payload") } + @Suppress("UNCHECKED_CAST") private fun callPrivateMethod( instance: Any, methodName: String, diff --git a/sdk/src/test/java/cloud/mindbox/mobile_sdk/monitoring/LogRequestStub.kt b/sdk/src/test/java/cloud/mindbox/mobile_sdk/monitoring/LogRequestStub.kt index 147ad5119..7322176a6 100644 --- a/sdk/src/test/java/cloud/mindbox/mobile_sdk/monitoring/LogRequestStub.kt +++ b/sdk/src/test/java/cloud/mindbox/mobile_sdk/monitoring/LogRequestStub.kt @@ -14,10 +14,10 @@ internal class LogRequestStub { ) fun getLogRequestDtoBlank(): LogRequestDtoBlank = LogRequestDtoBlank( - requestId = null, - deviceId = null, - from = null, - to = null + requestId = "", + deviceId = "", + from = "", + to = "" ) } } \ No newline at end of file diff --git a/sdk/src/test/java/cloud/mindbox/mobile_sdk/monitoring/MonitoringValidatorTest.kt b/sdk/src/test/java/cloud/mindbox/mobile_sdk/monitoring/MonitoringValidatorTest.kt index 15260ec45..81c736fec 100644 --- a/sdk/src/test/java/cloud/mindbox/mobile_sdk/monitoring/MonitoringValidatorTest.kt +++ b/sdk/src/test/java/cloud/mindbox/mobile_sdk/monitoring/MonitoringValidatorTest.kt @@ -37,7 +37,7 @@ internal class MonitoringValidatorTest { fun `monitoring validation requestId error null`() { assertFalse(monitoringValidator.validateLogRequestDtoBlank( LogRequestStub.getLogRequestDtoBlank() - .copy(requestId = null, deviceId = "abvc", from = "2023-01-15T00:00:00", to = "2023-01-30T00:00:00") + .copy(requestId = "", deviceId = "abvc", from = "2023-01-15T00:00:00", to = "2023-01-30T00:00:00") )) } @@ -45,7 +45,7 @@ internal class MonitoringValidatorTest { fun `monitoring validation deviceId error empty string`() { assertFalse(monitoringValidator.validateLogRequestDtoBlank( LogRequestStub.getLogRequestDtoBlank() - .copy(requestId = "asd", deviceId = "", from = "2023-01-15T00:00:00", to = "2023-01-30T00:00:00") + .copy(requestId = "", deviceId = "", from = "2023-01-15T00:00:00", to = "2023-01-30T00:00:00") )) } @@ -53,7 +53,7 @@ internal class MonitoringValidatorTest { fun `monitoring validation deviceId error null`() { assertFalse(monitoringValidator.validateLogRequestDtoBlank( LogRequestStub.getLogRequestDtoBlank() - .copy(requestId = "asd", deviceId = null, from = "2023-01-15T00:00:00", to = "2023-01-30T00:00:00") + .copy(requestId = "asd", deviceId = "", from = "2023-01-15T00:00:00", to = "2023-01-30T00:00:00") )) } @@ -69,7 +69,7 @@ internal class MonitoringValidatorTest { fun `monitoring validation from error null`() { assertFalse(monitoringValidator.validateLogRequestDtoBlank( LogRequestStub.getLogRequestDtoBlank() - .copy(requestId = "123", deviceId = "abvc", from = null, to = "2023-01-30T00:00:00") + .copy(requestId = "123", deviceId = "abvc", from = "", to = "2023-01-30T00:00:00") )) } @@ -93,7 +93,7 @@ internal class MonitoringValidatorTest { fun `monitoring validation to error null`() { assertFalse(monitoringValidator.validateLogRequestDtoBlank( LogRequestStub.getLogRequestDtoBlank() - .copy(requestId = "asd", deviceId = "abvc", from = "2023-01-15T00:00:00", to = null) + .copy(requestId = "asd", deviceId = "abvc", from = "2023-01-15T00:00:00", to = "") )) } diff --git a/sdk/src/test/java/cloud/mindbox/mobile_sdk/utils/MigrationManagerTest.kt b/sdk/src/test/java/cloud/mindbox/mobile_sdk/utils/MigrationManagerTest.kt index d559ac119..7150506cb 100644 --- a/sdk/src/test/java/cloud/mindbox/mobile_sdk/utils/MigrationManagerTest.kt +++ b/sdk/src/test/java/cloud/mindbox/mobile_sdk/utils/MigrationManagerTest.kt @@ -4,6 +4,8 @@ import cloud.mindbox.mobile_sdk.repository.MindboxPreferences import com.google.gson.Gson import com.google.gson.reflect.TypeToken import io.mockk.* +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test @@ -14,8 +16,9 @@ class MigrationManagerTest { mockkObject(MindboxPreferences) } + @OptIn(ExperimentalCoroutinesApi::class) @Test - fun `run method properly updates MindboxPreferences shownInApps`() { + fun `run method properly updates MindboxPreferences shownInApps`() = runTest { val gson: Gson = mockk() val oldShownInAppIds = setOf("app1", "app2") val oldShownInAppIdsString = Gson().toJson(oldShownInAppIds) @@ -42,11 +45,10 @@ class MigrationManagerTest { val mm = MigrationManager(mockk()) every { MindboxPreferences.versionCode } returns Constants.SDK_VERSION_CODE mm.migrateAll() - - verify(exactly = 1) { + coVerify(exactly = 1) { MindboxPreferences.shownInApps = expectedNewMapString } - verify(exactly = 1) { + coVerify(exactly = 1) { MindboxPreferences.shownInAppIds = "" } } diff --git a/sdk/src/test/java/cloud/mindbox/mobile_sdk/utils/NullableTypAdapterFactoryTest.kt b/sdk/src/test/java/cloud/mindbox/mobile_sdk/utils/NullableTypAdapterFactoryTest.kt new file mode 100644 index 000000000..7a0c9e73b --- /dev/null +++ b/sdk/src/test/java/cloud/mindbox/mobile_sdk/utils/NullableTypAdapterFactoryTest.kt @@ -0,0 +1,113 @@ +package cloud.mindbox.mobile_sdk.utils + +import com.google.gson.GsonBuilder +import com.google.gson.JsonParseException +import org.junit.Assert.* +import org.junit.Test + + +class NullableTypAdapterFactoryTest { + + private val gson by lazy { + GsonBuilder() + .registerTypeAdapter(String::class.java, StrictStringAdapter()) + .create() + } + + @Test + fun parse_null_when_nonnullable_type_is_null() { + val result = gson.fromJson( + """{ + "field1": null, + "field2": null + }""".trimIndent(), StubObject::class.java + ) + + assertNull(result.field1) + assertNull(result.field2) + + assertThrows(NullPointerException::class.java) { + result.copy() + } + } + + @Test + fun parse_success() { + val result = gson.fromJson( + """{ + "field1": "string1", + "field2": "string2" + }""".trimIndent(), StubObject::class.java + ) + + assertEquals(StubObject("string1", "string2"), result) + } + + @Test + fun parse_success_nullable() { + val result = gson.fromJson( + """{ + "field1": "string1", + "field2": null + }""".trimIndent(), StubObject::class.java + ) + + assertEquals(StubObject("string1", null), result) + } + + + @Test + fun parse_throw_error_when_json_corrupted() { + assertThrows(JsonParseException::class.java) { + gson.fromJson( + """{ + "field1": "string1" + "field2": "string2" + }""".trimIndent(), StubObject::class.java + ) + } + } + + @Test + fun throw_exception_when_parse_not_string_type_int() { + assertThrows(JsonParseException::class.java) { + gson.fromJson( + """{ + "field1": 123, + "field2": null + }""".trimIndent(), StubObject::class.java + ) + } + } + + @Test + fun throw_exception_when_parse_not_string_type_object() { + assertThrows(JsonParseException::class.java) { + gson.fromJson( + """{ + "field1": "123", + "field2": {} + }""".trimIndent(), StubObject::class.java + ) + } + } + + @Test + fun throw_exception_when_parse_not_string_type_array() { + assertThrows(JsonParseException::class.java) { + gson.fromJson( + """{ + "field1": [], + "field2": null + }""".trimIndent(), StubObject::class.java + ) + } + } + + + data class StubObject( + val field1: String, + val field2: String?, + ) + +} \ No newline at end of file diff --git a/sdk/src/test/resources/ConfigParsing/ABTests/ABTestsConfig.json b/sdk/src/test/resources/ConfigParsing/ABTests/ABTestsConfig.json new file mode 100644 index 000000000..2b050cc79 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/ABTests/ABTestsConfig.json @@ -0,0 +1,79 @@ +[ + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } +] diff --git a/sdk/src/test/resources/ConfigParsing/ABTests/ABTestsIdConfigError.json b/sdk/src/test/resources/ConfigParsing/ABTests/ABTestsIdConfigError.json new file mode 100644 index 000000000..313b66e07 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/ABTests/ABTestsIdConfigError.json @@ -0,0 +1,79 @@ +[ + { + "idTest": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } +] diff --git a/sdk/src/test/resources/ConfigParsing/ABTests/ABTestsIdConfigTypeError.json b/sdk/src/test/resources/ConfigParsing/ABTests/ABTestsIdConfigTypeError.json new file mode 100644 index 000000000..576624803 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/ABTests/ABTestsIdConfigTypeError.json @@ -0,0 +1,78 @@ +[ + { + "id": 1, + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } +] diff --git a/sdk/src/test/resources/ConfigParsing/ABTests/ABTestsSdkVersionConfigError.json b/sdk/src/test/resources/ConfigParsing/ABTests/ABTestsSdkVersionConfigError.json new file mode 100644 index 000000000..2d9725789 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/ABTests/ABTestsSdkVersionConfigError.json @@ -0,0 +1,79 @@ +[ + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + "sdkVersionTest": { + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } +] diff --git a/sdk/src/test/resources/ConfigParsing/ABTests/ABTestsSdkVersionConfigTypeError.json b/sdk/src/test/resources/ConfigParsing/ABTests/ABTestsSdkVersionConfigTypeError.json new file mode 100644 index 000000000..4013f2eda --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/ABTests/ABTestsSdkVersionConfigTypeError.json @@ -0,0 +1,75 @@ +[ + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + "sdkVersion": 1, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } +] diff --git a/sdk/src/test/resources/ConfigParsing/Config/ConfigABTestsError.json b/sdk/src/test/resources/ConfigParsing/Config/ConfigABTestsError.json new file mode 100644 index 000000000..da30d8f57 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Config/ConfigABTestsError.json @@ -0,0 +1,405 @@ +{ + "abtestsTest": [ + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } + ], + "inapps": [ + { + "id": "12345678-c777-4ac9-86b3-722c3e998cb6", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://www.akusherstvo.ru/images/uploadfoto/events/in-app/in-app-app300-2.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "bottom" + } + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 30, + "height": 30 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.05, + "right": 0.025, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "283d926e-7609-493b-8d1d-67e9a909847e", + "sdkVersion": { + "min": 9, + "max": null + }, + "frequency": { + "kind": "session", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "value": false, + "$type": "pushEnabled" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "тестовый пейлоад", + "$type": "pushPermission" + }, + "source": { + "value": "https://inapps-stable.mindbox.ru/media/default-push-modal-ru.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 18, + "height": 18 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.215, + "right": 0.0665, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "modal" + } + ] + } + }, + { + "id": "4c7ee36b-e439-452a-b76a-3908f30766db", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "", + "value": "https://www.forrestgerke.com/shop/apple-3x4-linoleum-block-print", + "$type": "redirectUrl" + }, + "source": { + "value": "https://images.squarespace-cdn.com/content/v1/524cb77be4b0bf732ffea906/1597867591991-JG1UEAX03TOY6EK76MEG/Apple+-+Product+Image.jpg", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "c68d2f2a-d3f6-40ef-b300-4597cced3453", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://mobpush-images.mindbox.ru/Mpush-test/223/c41cd63a-fffb-49f9-afcf-58e213ddd677.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [ + { + "color": "#9E3535", + "lineWidth": 5, + "size": { + "kind": "dp", + "width": 40, + "height": 40 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.7, + "right": 0, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + } + ], + "monitoring": { + "logs": [ + { + "requestId": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] + }, + "settings": { + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } + } +} diff --git a/sdk/src/test/resources/ConfigParsing/Config/ConfigABTestsOneElementError.json b/sdk/src/test/resources/ConfigParsing/Config/ConfigABTestsOneElementError.json new file mode 100644 index 000000000..d1c19f241 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Config/ConfigABTestsOneElementError.json @@ -0,0 +1,405 @@ +{ + "abtests": [ + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + "sdkVersion": { + "min": 7, + "max": null + }, + "saltTest": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } + ], + "inapps": [ + { + "id": "12345678-c777-4ac9-86b3-722c3e998cb6", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://www.akusherstvo.ru/images/uploadfoto/events/in-app/in-app-app300-2.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "bottom" + } + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 30, + "height": 30 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.05, + "right": 0.025, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "283d926e-7609-493b-8d1d-67e9a909847e", + "sdkVersion": { + "min": 9, + "max": null + }, + "frequency": { + "kind": "session", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "value": false, + "$type": "pushEnabled" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "тестовый пейлоад", + "$type": "pushPermission" + }, + "source": { + "value": "https://inapps-stable.mindbox.ru/media/default-push-modal-ru.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 18, + "height": 18 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.215, + "right": 0.0665, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "modal" + } + ] + } + }, + { + "id": "4c7ee36b-e439-452a-b76a-3908f30766db", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "", + "value": "https://www.forrestgerke.com/shop/apple-3x4-linoleum-block-print", + "$type": "redirectUrl" + }, + "source": { + "value": "https://images.squarespace-cdn.com/content/v1/524cb77be4b0bf732ffea906/1597867591991-JG1UEAX03TOY6EK76MEG/Apple+-+Product+Image.jpg", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "c68d2f2a-d3f6-40ef-b300-4597cced3453", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://mobpush-images.mindbox.ru/Mpush-test/223/c41cd63a-fffb-49f9-afcf-58e213ddd677.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [ + { + "color": "#9E3535", + "lineWidth": 5, + "size": { + "kind": "dp", + "width": 40, + "height": 40 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.7, + "right": 0, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + } + ], + "monitoring": { + "logs": [ + { + "requestId": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] + }, + "settings": { + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } + } +} diff --git a/sdk/src/test/resources/ConfigParsing/Config/ConfigABTestsOneElementTypeError.json b/sdk/src/test/resources/ConfigParsing/Config/ConfigABTestsOneElementTypeError.json new file mode 100644 index 000000000..084b59601 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Config/ConfigABTestsOneElementTypeError.json @@ -0,0 +1,376 @@ +{ + "abtests": [ + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": 1 + }, + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } + ], + "inapps": [ + { + "id": "12345678-c777-4ac9-86b3-722c3e998cb6", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://www.akusherstvo.ru/images/uploadfoto/events/in-app/in-app-app300-2.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "bottom" + } + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 30, + "height": 30 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.05, + "right": 0.025, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "283d926e-7609-493b-8d1d-67e9a909847e", + "sdkVersion": { + "min": 9, + "max": null + }, + "frequency": { + "kind": "session", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "value": false, + "$type": "pushEnabled" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "тестовый пейлоад", + "$type": "pushPermission" + }, + "source": { + "value": "https://inapps-stable.mindbox.ru/media/default-push-modal-ru.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 18, + "height": 18 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.215, + "right": 0.0665, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "modal" + } + ] + } + }, + { + "id": "4c7ee36b-e439-452a-b76a-3908f30766db", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "", + "value": "https://www.forrestgerke.com/shop/apple-3x4-linoleum-block-print", + "$type": "redirectUrl" + }, + "source": { + "value": "https://images.squarespace-cdn.com/content/v1/524cb77be4b0bf732ffea906/1597867591991-JG1UEAX03TOY6EK76MEG/Apple+-+Product+Image.jpg", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "c68d2f2a-d3f6-40ef-b300-4597cced3453", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://mobpush-images.mindbox.ru/Mpush-test/223/c41cd63a-fffb-49f9-afcf-58e213ddd677.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [ + { + "color": "#9E3535", + "lineWidth": 5, + "size": { + "kind": "dp", + "width": 40, + "height": 40 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.7, + "right": 0, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + } + ], + "monitoring": { + "logs": [ + { + "requestId": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] + }, + "settings": { + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } + } +} diff --git a/sdk/src/test/resources/ConfigParsing/Config/ConfigABTestsTypeError.json b/sdk/src/test/resources/ConfigParsing/Config/ConfigABTestsTypeError.json new file mode 100644 index 000000000..760413fc7 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Config/ConfigABTestsTypeError.json @@ -0,0 +1,328 @@ +{ + "abtests": 1, + "inapps": [ + { + "id": "12345678-c777-4ac9-86b3-722c3e998cb6", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://www.akusherstvo.ru/images/uploadfoto/events/in-app/in-app-app300-2.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "bottom" + } + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 30, + "height": 30 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.05, + "right": 0.025, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "283d926e-7609-493b-8d1d-67e9a909847e", + "sdkVersion": { + "min": 9, + "max": null + }, + "frequency": { + "kind": "session", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "value": false, + "$type": "pushEnabled" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "тестовый пейлоад", + "$type": "pushPermission" + }, + "source": { + "value": "https://inapps-stable.mindbox.ru/media/default-push-modal-ru.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 18, + "height": 18 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.215, + "right": 0.0665, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "modal" + } + ] + } + }, + { + "id": "4c7ee36b-e439-452a-b76a-3908f30766db", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "", + "value": "https://www.forrestgerke.com/shop/apple-3x4-linoleum-block-print", + "$type": "redirectUrl" + }, + "source": { + "value": "https://images.squarespace-cdn.com/content/v1/524cb77be4b0bf732ffea906/1597867591991-JG1UEAX03TOY6EK76MEG/Apple+-+Product+Image.jpg", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "c68d2f2a-d3f6-40ef-b300-4597cced3453", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://mobpush-images.mindbox.ru/Mpush-test/223/c41cd63a-fffb-49f9-afcf-58e213ddd677.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [ + { + "color": "#9E3535", + "lineWidth": 5, + "size": { + "kind": "dp", + "width": 40, + "height": 40 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.7, + "right": 0, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + } + ], + "monitoring": { + "logs": [ + { + "requestId": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] + }, + "settings": { + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } + } +} diff --git a/sdk/src/test/resources/ConfigParsing/Config/ConfigInAppsError.json b/sdk/src/test/resources/ConfigParsing/Config/ConfigInAppsError.json new file mode 100644 index 000000000..a6ec65a38 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Config/ConfigInAppsError.json @@ -0,0 +1,405 @@ +{ + "inappsTest": [ + { + "id": "12345678-c777-4ac9-86b3-722c3e998cb6", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://www.akusherstvo.ru/images/uploadfoto/events/in-app/in-app-app300-2.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "bottom" + } + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 30, + "height": 30 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.05, + "right": 0.025, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "283d926e-7609-493b-8d1d-67e9a909847e", + "sdkVersion": { + "min": 9, + "max": null + }, + "frequency": { + "kind": "session", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "value": false, + "$type": "pushEnabled" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "тестовый пейлоад", + "$type": "pushPermission" + }, + "source": { + "value": "https://inapps-stable.mindbox.ru/media/default-push-modal-ru.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 18, + "height": 18 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.215, + "right": 0.0665, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "modal" + } + ] + } + }, + { + "id": "4c7ee36b-e439-452a-b76a-3908f30766db", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "", + "value": "https://www.forrestgerke.com/shop/apple-3x4-linoleum-block-print", + "$type": "redirectUrl" + }, + "source": { + "value": "https://images.squarespace-cdn.com/content/v1/524cb77be4b0bf732ffea906/1597867591991-JG1UEAX03TOY6EK76MEG/Apple+-+Product+Image.jpg", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "c68d2f2a-d3f6-40ef-b300-4597cced3453", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://mobpush-images.mindbox.ru/Mpush-test/223/c41cd63a-fffb-49f9-afcf-58e213ddd677.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [ + { + "color": "#9E3535", + "lineWidth": 5, + "size": { + "kind": "dp", + "width": 40, + "height": 40 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.7, + "right": 0, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + } + ], + "monitoring": { + "logs": [ + { + "requestId": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] + }, + "settings": { + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } + }, + "abtests": [ + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } + ] +} diff --git a/sdk/src/test/resources/ConfigParsing/Config/ConfigInAppsTypeError.json b/sdk/src/test/resources/ConfigParsing/Config/ConfigInAppsTypeError.json new file mode 100644 index 000000000..877892ab3 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Config/ConfigInAppsTypeError.json @@ -0,0 +1,113 @@ +{ + "inapps": 1, + "monitoring": { + "logs": [ + { + "requestId": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] + }, + "settings": { + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } + }, + "abtests": [ + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } + ] +} diff --git a/sdk/src/test/resources/ConfigParsing/Config/ConfigMonitoringError.json b/sdk/src/test/resources/ConfigParsing/Config/ConfigMonitoringError.json new file mode 100644 index 000000000..dbe49607d --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Config/ConfigMonitoringError.json @@ -0,0 +1,405 @@ +{ + "monitoringTest": { + "logs": [ + { + "requestId": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] + }, + "inapps": [ + { + "id": "12345678-c777-4ac9-86b3-722c3e998cb6", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://www.akusherstvo.ru/images/uploadfoto/events/in-app/in-app-app300-2.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "bottom" + } + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 30, + "height": 30 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.05, + "right": 0.025, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "283d926e-7609-493b-8d1d-67e9a909847e", + "sdkVersion": { + "min": 9, + "max": null + }, + "frequency": { + "kind": "session", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "value": false, + "$type": "pushEnabled" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "тестовый пейлоад", + "$type": "pushPermission" + }, + "source": { + "value": "https://inapps-stable.mindbox.ru/media/default-push-modal-ru.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 18, + "height": 18 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.215, + "right": 0.0665, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "modal" + } + ] + } + }, + { + "id": "4c7ee36b-e439-452a-b76a-3908f30766db", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "", + "value": "https://www.forrestgerke.com/shop/apple-3x4-linoleum-block-print", + "$type": "redirectUrl" + }, + "source": { + "value": "https://images.squarespace-cdn.com/content/v1/524cb77be4b0bf732ffea906/1597867591991-JG1UEAX03TOY6EK76MEG/Apple+-+Product+Image.jpg", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "c68d2f2a-d3f6-40ef-b300-4597cced3453", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://mobpush-images.mindbox.ru/Mpush-test/223/c41cd63a-fffb-49f9-afcf-58e213ddd677.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [ + { + "color": "#9E3535", + "lineWidth": 5, + "size": { + "kind": "dp", + "width": 40, + "height": 40 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.7, + "right": 0, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + } + ], + "settings": { + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } + }, + "abtests": [ + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } + ] +} diff --git a/sdk/src/test/resources/ConfigParsing/Config/ConfigMonitoringTypeError.json b/sdk/src/test/resources/ConfigParsing/Config/ConfigMonitoringTypeError.json new file mode 100644 index 000000000..9debb65ee --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Config/ConfigMonitoringTypeError.json @@ -0,0 +1,390 @@ +{ + "monitoring": 1, + "inapps": [ + { + "id": "12345678-c777-4ac9-86b3-722c3e998cb6", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://www.akusherstvo.ru/images/uploadfoto/events/in-app/in-app-app300-2.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "bottom" + } + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 30, + "height": 30 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.05, + "right": 0.025, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "283d926e-7609-493b-8d1d-67e9a909847e", + "sdkVersion": { + "min": 9, + "max": null + }, + "frequency": { + "kind": "session", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "value": false, + "$type": "pushEnabled" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "тестовый пейлоад", + "$type": "pushPermission" + }, + "source": { + "value": "https://inapps-stable.mindbox.ru/media/default-push-modal-ru.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 18, + "height": 18 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.215, + "right": 0.0665, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "modal" + } + ] + } + }, + { + "id": "4c7ee36b-e439-452a-b76a-3908f30766db", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "", + "value": "https://www.forrestgerke.com/shop/apple-3x4-linoleum-block-print", + "$type": "redirectUrl" + }, + "source": { + "value": "https://images.squarespace-cdn.com/content/v1/524cb77be4b0bf732ffea906/1597867591991-JG1UEAX03TOY6EK76MEG/Apple+-+Product+Image.jpg", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "c68d2f2a-d3f6-40ef-b300-4597cced3453", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://mobpush-images.mindbox.ru/Mpush-test/223/c41cd63a-fffb-49f9-afcf-58e213ddd677.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [ + { + "color": "#9E3535", + "lineWidth": 5, + "size": { + "kind": "dp", + "width": 40, + "height": 40 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.7, + "right": 0, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + } + ], + "settings": { + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } + }, + "abtests": [ + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } + ] +} diff --git a/sdk/src/test/resources/ConfigParsing/Config/ConfigSettingsError.json b/sdk/src/test/resources/ConfigParsing/Config/ConfigSettingsError.json new file mode 100644 index 000000000..193bf6809 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Config/ConfigSettingsError.json @@ -0,0 +1,409 @@ +{ + + + "settingsTests": { + + + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } + }, + "inapps": [ + { + "id": "12345678-c777-4ac9-86b3-722c3e998cb6", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://www.akusherstvo.ru/images/uploadfoto/events/in-app/in-app-app300-2.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "bottom" + } + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 30, + "height": 30 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.05, + "right": 0.025, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "283d926e-7609-493b-8d1d-67e9a909847e", + "sdkVersion": { + "min": 9, + "max": null + }, + "frequency": { + "kind": "session", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "value": false, + "$type": "pushEnabled" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "тестовый пейлоад", + "$type": "pushPermission" + }, + "source": { + "value": "https://inapps-stable.mindbox.ru/media/default-push-modal-ru.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 18, + "height": 18 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.215, + "right": 0.0665, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "modal" + } + ] + } + }, + { + "id": "4c7ee36b-e439-452a-b76a-3908f30766db", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "", + "value": "https://www.forrestgerke.com/shop/apple-3x4-linoleum-block-print", + "$type": "redirectUrl" + }, + "source": { + "value": "https://images.squarespace-cdn.com/content/v1/524cb77be4b0bf732ffea906/1597867591991-JG1UEAX03TOY6EK76MEG/Apple+-+Product+Image.jpg", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "c68d2f2a-d3f6-40ef-b300-4597cced3453", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://mobpush-images.mindbox.ru/Mpush-test/223/c41cd63a-fffb-49f9-afcf-58e213ddd677.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [ + { + "color": "#9E3535", + "lineWidth": 5, + "size": { + "kind": "dp", + "width": 40, + "height": 40 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.7, + "right": 0, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + } + ], + "monitoring": { + "logs": [ + { + "requestId": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] + }, + "abtests": [ + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } + ] +} diff --git a/sdk/src/test/resources/ConfigParsing/Config/ConfigSettingsTypeError.json b/sdk/src/test/resources/ConfigParsing/Config/ConfigSettingsTypeError.json new file mode 100644 index 000000000..54e190a12 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Config/ConfigSettingsTypeError.json @@ -0,0 +1,394 @@ +{ + + + "settings": 1, + + + "inapps": [ + { + "id": "12345678-c777-4ac9-86b3-722c3e998cb6", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://www.akusherstvo.ru/images/uploadfoto/events/in-app/in-app-app300-2.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "bottom" + } + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 30, + "height": 30 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.05, + "right": 0.025, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "283d926e-7609-493b-8d1d-67e9a909847e", + "sdkVersion": { + "min": 9, + "max": null + }, + "frequency": { + "kind": "session", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "value": false, + "$type": "pushEnabled" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "тестовый пейлоад", + "$type": "pushPermission" + }, + "source": { + "value": "https://inapps-stable.mindbox.ru/media/default-push-modal-ru.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 18, + "height": 18 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.215, + "right": 0.0665, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "modal" + } + ] + } + }, + { + "id": "4c7ee36b-e439-452a-b76a-3908f30766db", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "", + "value": "https://www.forrestgerke.com/shop/apple-3x4-linoleum-block-print", + "$type": "redirectUrl" + }, + "source": { + "value": "https://images.squarespace-cdn.com/content/v1/524cb77be4b0bf732ffea906/1597867591991-JG1UEAX03TOY6EK76MEG/Apple+-+Product+Image.jpg", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "c68d2f2a-d3f6-40ef-b300-4597cced3453", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://mobpush-images.mindbox.ru/Mpush-test/223/c41cd63a-fffb-49f9-afcf-58e213ddd677.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [ + { + "color": "#9E3535", + "lineWidth": 5, + "size": { + "kind": "dp", + "width": 40, + "height": 40 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.7, + "right": 0, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + } + ], + "monitoring": { + "logs": [ + { + "requestId": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] + }, + "abtests": [ + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } + ] +} diff --git a/sdk/src/test/resources/ConfigParsing/Config/ConfigWithSettingsABTestsMonitoringInapps.json b/sdk/src/test/resources/ConfigParsing/Config/ConfigWithSettingsABTestsMonitoringInapps.json new file mode 100644 index 000000000..d55d8152f --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Config/ConfigWithSettingsABTestsMonitoringInapps.json @@ -0,0 +1,405 @@ +{ + "inapps": [ + { + "id": "12345678-c777-4ac9-86b3-722c3e998cb6", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://www.akusherstvo.ru/images/uploadfoto/events/in-app/in-app-app300-2.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "bottom" + } + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 30, + "height": 30 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.05, + "right": 0.025, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "283d926e-7609-493b-8d1d-67e9a909847e", + "sdkVersion": { + "min": 9, + "max": null + }, + "frequency": { + "kind": "session", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "value": false, + "$type": "pushEnabled" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "тестовый пейлоад", + "$type": "pushPermission" + }, + "source": { + "value": "https://inapps-stable.mindbox.ru/media/default-push-modal-ru.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 18, + "height": 18 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.215, + "right": 0.0665, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "modal" + } + ] + } + }, + { + "id": "4c7ee36b-e439-452a-b76a-3908f30766db", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "", + "value": "https://www.forrestgerke.com/shop/apple-3x4-linoleum-block-print", + "$type": "redirectUrl" + }, + "source": { + "value": "https://images.squarespace-cdn.com/content/v1/524cb77be4b0bf732ffea906/1597867591991-JG1UEAX03TOY6EK76MEG/Apple+-+Product+Image.jpg", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "c68d2f2a-d3f6-40ef-b300-4597cced3453", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://mobpush-images.mindbox.ru/Mpush-test/223/c41cd63a-fffb-49f9-afcf-58e213ddd677.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [ + { + "color": "#9E3535", + "lineWidth": 5, + "size": { + "kind": "dp", + "width": 40, + "height": 40 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.7, + "right": 0, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + } + ], + "monitoring": { + "logs": [ + { + "requestId": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] + }, + "settings": { + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } + }, + "abtests": [ + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/sdk/src/test/resources/ConfigParsing/Config/EmptyConfigs/EmptyConfig.json b/sdk/src/test/resources/ConfigParsing/Config/EmptyConfigs/EmptyConfig.json new file mode 100644 index 000000000..9e26dfeeb --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Config/EmptyConfigs/EmptyConfig.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/sdk/src/test/resources/ConfigParsing/Config/EmptyConfigs/EmptyLogsMonitoring.json b/sdk/src/test/resources/ConfigParsing/Config/EmptyConfigs/EmptyLogsMonitoring.json new file mode 100644 index 000000000..54e903be5 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Config/EmptyConfigs/EmptyLogsMonitoring.json @@ -0,0 +1,3 @@ +{ + "monitoring": {} +} \ No newline at end of file diff --git a/sdk/src/test/resources/ConfigParsing/Config/EmptyConfigs/EmptyMonitoring.json b/sdk/src/test/resources/ConfigParsing/Config/EmptyConfigs/EmptyMonitoring.json new file mode 100644 index 000000000..54e903be5 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Config/EmptyConfigs/EmptyMonitoring.json @@ -0,0 +1,3 @@ +{ + "monitoring": {} +} \ No newline at end of file diff --git a/sdk/src/test/resources/ConfigParsing/Config/EmptyConfigs/NoMonitoring.json b/sdk/src/test/resources/ConfigParsing/Config/EmptyConfigs/NoMonitoring.json new file mode 100644 index 000000000..d26fda9c6 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Config/EmptyConfigs/NoMonitoring.json @@ -0,0 +1,20 @@ +{ + "settings": { + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } + }, + "abtests": [], + "inapps": [] +} \ No newline at end of file diff --git a/sdk/src/test/resources/ConfigParsing/ConfigWithSettingsABTestsMonitoringInapps.json b/sdk/src/test/resources/ConfigParsing/ConfigWithSettingsABTestsMonitoringInapps.json new file mode 100644 index 000000000..d55d8152f --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/ConfigWithSettingsABTestsMonitoringInapps.json @@ -0,0 +1,405 @@ +{ + "inapps": [ + { + "id": "12345678-c777-4ac9-86b3-722c3e998cb6", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://www.akusherstvo.ru/images/uploadfoto/events/in-app/in-app-app300-2.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "bottom" + } + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 30, + "height": 30 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.05, + "right": 0.025, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "283d926e-7609-493b-8d1d-67e9a909847e", + "sdkVersion": { + "min": 9, + "max": null + }, + "frequency": { + "kind": "session", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "value": false, + "$type": "pushEnabled" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "тестовый пейлоад", + "$type": "pushPermission" + }, + "source": { + "value": "https://inapps-stable.mindbox.ru/media/default-push-modal-ru.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "elements": [ + { + "color": "#000000", + "lineWidth": 1, + "size": { + "kind": "dp", + "width": 18, + "height": 18 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.215, + "right": 0.0665, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "modal" + } + ] + } + }, + { + "id": "4c7ee36b-e439-452a-b76a-3908f30766db", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "", + "value": "https://www.forrestgerke.com/shop/apple-3x4-linoleum-block-print", + "$type": "redirectUrl" + }, + "source": { + "value": "https://images.squarespace-cdn.com/content/v1/524cb77be4b0bf732ffea906/1597867591991-JG1UEAX03TOY6EK76MEG/Apple+-+Product+Image.jpg", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + }, + { + "id": "c68d2f2a-d3f6-40ef-b300-4597cced3453", + "sdkVersion": { + "min": 8, + "max": null + }, + "frequency": { + "kind": "lifetime", + "$type": "once" + }, + "targeting": { + "nodes": [ + { + "$type": "true" + } + ], + "$type": "and" + }, + "form": { + "variants": [ + { + "content": { + "background": { + "layers": [ + { + "action": { + "intentPayload": "Some payload test", + "value": "", + "$type": "redirectUrl" + }, + "source": { + "value": "https://mobpush-images.mindbox.ru/Mpush-test/223/c41cd63a-fffb-49f9-afcf-58e213ddd677.png", + "$type": "url" + }, + "$type": "image" + } + ] + }, + "position": { + "margin": { + "kind": "dp", + "top": 0, + "right": 0, + "left": 0, + "bottom": 0 + }, + "gravity": { + "horizontal": "center", + "vertical": "top" + } + }, + "elements": [ + { + "color": "#9E3535", + "lineWidth": 5, + "size": { + "kind": "dp", + "width": 40, + "height": 40 + }, + "position": { + "margin": { + "kind": "proportion", + "top": 0.7, + "right": 0, + "left": 0, + "bottom": 0 + } + }, + "$type": "closeButton" + } + ] + }, + "imageUrl": "", + "redirectUrl": "", + "intentPayload": "", + "$type": "snackbar" + } + ] + } + } + ], + "monitoring": { + "logs": [ + { + "requestId": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] + }, + "settings": { + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } + }, + "abtests": [ + { + "id": "94CD824A-59AA-4937-9E0E-089895A0DB6F", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "7D4154FD-A6D4-4BBD-B058-7150FAC18AE1", + "variants": [ + { + "id": "80FD90DA-D5EB-47C0-82E0-2683EF4CB9C1", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["210adb81-c777-4ac9-86b3-722c3e998cb6"], + "$type": "inapps" + } + ] + }, + { + "id": "9B15D2FC-3C18-44E7-B804-18AA0248706A", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "concrete", + "inapps": ["c68d2f2a-d3f6-40ef-b300-4597cced3453"], + "$type": "inapps" + } + ] + } + ] + }, + { + "id": "ACD8FF4F-25A7-41F5-9322-A7AC9F2B4CFE", + "sdkVersion": { + "min": 7, + "max": null + }, + "salt": "00A8B15F-AA68-4545-A425-42238055460B", + "variants": [ + { + "id": "93719D17-8C46-482F-A220-2FA02647079D", + "modulus": { + "lower": 0, + "upper": 50 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + }, + { + "id": "AA7131D5-D77D-4847-AC77-676C224CD902", + "modulus": { + "lower": 50, + "upper": 100 + }, + "objects": [ + { + "kind": "all", + "inapps": null, + "$type": "inapps" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/sdk/src/test/resources/ConfigParsing/Monitoring/MonitoringConfig.json b/sdk/src/test/resources/ConfigParsing/Monitoring/MonitoringConfig.json new file mode 100644 index 000000000..a9136d529 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Monitoring/MonitoringConfig.json @@ -0,0 +1,16 @@ +{ + "logs": [ + { + "requestId": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] +} diff --git a/sdk/src/test/resources/ConfigParsing/Monitoring/MonitoringLogsElementsMixedError.json b/sdk/src/test/resources/ConfigParsing/Monitoring/MonitoringLogsElementsMixedError.json new file mode 100644 index 000000000..373fa1e75 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Monitoring/MonitoringLogsElementsMixedError.json @@ -0,0 +1,16 @@ +{ + "logs": [ + { + "requestId": 1, + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "fromTest": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] +} diff --git a/sdk/src/test/resources/ConfigParsing/Monitoring/MonitoringLogsError.json b/sdk/src/test/resources/ConfigParsing/Monitoring/MonitoringLogsError.json new file mode 100644 index 000000000..9213c9c13 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Monitoring/MonitoringLogsError.json @@ -0,0 +1,20 @@ +{ + + + "logsTests": [ + + + { + "requestId": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] +} diff --git a/sdk/src/test/resources/ConfigParsing/Monitoring/MonitoringLogsOneElementError.json b/sdk/src/test/resources/ConfigParsing/Monitoring/MonitoringLogsOneElementError.json new file mode 100644 index 000000000..e263115b2 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Monitoring/MonitoringLogsOneElementError.json @@ -0,0 +1,20 @@ +{ + "logs": [ + { + + + "request": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + + + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] +} diff --git a/sdk/src/test/resources/ConfigParsing/Monitoring/MonitoringLogsOneElementTypeError.json b/sdk/src/test/resources/ConfigParsing/Monitoring/MonitoringLogsOneElementTypeError.json new file mode 100644 index 000000000..083079863 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Monitoring/MonitoringLogsOneElementTypeError.json @@ -0,0 +1,20 @@ +{ + "logs": [ + { + + + "requestId": 1, + + + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] +} diff --git a/sdk/src/test/resources/ConfigParsing/Monitoring/MonitoringLogsTwoElementsError.json b/sdk/src/test/resources/ConfigParsing/Monitoring/MonitoringLogsTwoElementsError.json new file mode 100644 index 000000000..a9e929838 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Monitoring/MonitoringLogsTwoElementsError.json @@ -0,0 +1,16 @@ +{ + "logs": [ + { + "request": "bb978cd7-ce4c-4239-a5d2-4b7e5d4fb5b9", + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "device": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2023-02-10T00:00:00", + "to": "2023-03-01T20:30:00" + } + ] +} diff --git a/sdk/src/test/resources/ConfigParsing/Monitoring/MonitoringLogsTwoElementsTypeError.json b/sdk/src/test/resources/ConfigParsing/Monitoring/MonitoringLogsTwoElementsTypeError.json new file mode 100644 index 000000000..88baa9808 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Monitoring/MonitoringLogsTwoElementsTypeError.json @@ -0,0 +1,16 @@ +{ + "logs": [ + { + "requestId": 1, + "deviceUUID": "216e6225-3170-4089-a6f0-3d1ed8f64153", + "from": "2024-02-12T10:00:00", + "to": "2024-02-14T20:30:00" + }, + { + "requestId": "8e829a63-a5c3-4e1c-a772-41fd61f8f331", + "deviceUUID": "126e6225-3170-4089-a6f0-3d1ed8f64153", + "from": { }, + "to": "2023-03-01T20:30:00" + } + ] +} diff --git a/sdk/src/test/resources/ConfigParsing/Monitoring/MonitoringLogsTypeError.json b/sdk/src/test/resources/ConfigParsing/Monitoring/MonitoringLogsTypeError.json new file mode 100644 index 000000000..f48076ed7 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Monitoring/MonitoringLogsTypeError.json @@ -0,0 +1,7 @@ +{ + + + "logs": 1 + + +} diff --git a/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsAllOperationsWithErrors.json b/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsAllOperationsWithErrors.json new file mode 100644 index 000000000..6cf4a7f0d --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsAllOperationsWithErrors.json @@ -0,0 +1,16 @@ +{ + "operations": { + "viewProductTest": { + "systemName": "ViewProduct" + }, + "viewCategoryTest": { + "systemName": "ViewCategory" + }, + "setCartTest": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsAllOperationsWithTypeErrors.json b/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsAllOperationsWithTypeErrors.json new file mode 100644 index 000000000..9c0413e9d --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsAllOperationsWithTypeErrors.json @@ -0,0 +1,10 @@ +{ + "operations": { + "viewProduct": 1, + "viewCategory": 2, + "setCart": 2 + }, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsError.json b/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsError.json new file mode 100644 index 000000000..743ab67be --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsError.json @@ -0,0 +1,16 @@ +{ + "operationsTests": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsTypeError.json b/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsTypeError.json new file mode 100644 index 000000000..9538e9f95 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsTypeError.json @@ -0,0 +1,6 @@ +{ + "operations": 1, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewCategoryAndSetCartError.json b/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewCategoryAndSetCartError.json new file mode 100644 index 000000000..fc22f0c2e --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewCategoryAndSetCartError.json @@ -0,0 +1,16 @@ +{ + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategoryTest": { + "systemName": "ViewCategory" + }, + "setCartTest": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewCategoryAndSetCartSystemNameError.json b/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewCategoryAndSetCartSystemNameError.json new file mode 100644 index 000000000..283cefefe --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewCategoryAndSetCartSystemNameError.json @@ -0,0 +1,16 @@ +{ + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemNameTest": "ViewCategory" + }, + "setCart": { + "systemNameTest": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewCategoryAndSetCartSystemNameMixedError.json b/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewCategoryAndSetCartSystemNameMixedError.json new file mode 100644 index 000000000..b860aa34c --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewCategoryAndSetCartSystemNameMixedError.json @@ -0,0 +1,16 @@ +{ + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemNameTest": "ViewCategory" + }, + "setCart": { + "systemName": 123 + } + }, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewCategoryAndSetCartSystemNameTypeError.json b/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewCategoryAndSetCartSystemNameTypeError.json new file mode 100644 index 000000000..45d6acb04 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewCategoryAndSetCartSystemNameTypeError.json @@ -0,0 +1,16 @@ +{ + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": 123 + }, + "setCart": { + "systemName": 321 + } + }, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewCategoryAndSetCartTypeError.json b/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewCategoryAndSetCartTypeError.json new file mode 100644 index 000000000..ae9a4492c --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewCategoryAndSetCartTypeError.json @@ -0,0 +1,12 @@ +{ + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": 1, + "setCart": 2 + }, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewProductError.json b/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewProductError.json new file mode 100644 index 000000000..b65031cc5 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewProductError.json @@ -0,0 +1,16 @@ +{ + "operations": { + "viewProductTest": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewProductSystemNameError.json b/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewProductSystemNameError.json new file mode 100644 index 000000000..299359b31 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewProductSystemNameError.json @@ -0,0 +1,16 @@ +{ + "operations": { + "viewProduct": { + "systemNameTest": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewProductSystemNameTypeError.json b/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewProductSystemNameTypeError.json new file mode 100644 index 000000000..c0aac36cc --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewProductSystemNameTypeError.json @@ -0,0 +1,16 @@ +{ + "operations": { + "viewProduct": { + "systemName": 123 + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewProductTypeError.json b/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewProductTypeError.json new file mode 100644 index 000000000..39426daec --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Settings/OperationsErrors/SettingsOperationsViewProductTypeError.json @@ -0,0 +1,14 @@ +{ + "operations": { + "viewProduct": 123, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/sdk/src/test/resources/ConfigParsing/Settings/SettingsConfig.json b/sdk/src/test/resources/ConfigParsing/Settings/SettingsConfig.json new file mode 100644 index 000000000..ea62a96c9 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Settings/SettingsConfig.json @@ -0,0 +1,16 @@ +{ + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": "1.00:00:00" + } +} diff --git a/sdk/src/test/resources/ConfigParsing/Settings/TtlErrors/SettingsTtlError.json b/sdk/src/test/resources/ConfigParsing/Settings/TtlErrors/SettingsTtlError.json new file mode 100644 index 000000000..c24236dde --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Settings/TtlErrors/SettingsTtlError.json @@ -0,0 +1,16 @@ +{ + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttlTest": { + "inapps": "1.00:00:00" + } +} diff --git a/sdk/src/test/resources/ConfigParsing/Settings/TtlErrors/SettingsTtlInappsError.json b/sdk/src/test/resources/ConfigParsing/Settings/TtlErrors/SettingsTtlInappsError.json new file mode 100644 index 000000000..eb350a040 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Settings/TtlErrors/SettingsTtlInappsError.json @@ -0,0 +1,16 @@ +{ + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inappsTest": "1.00:00:00" + } +} diff --git a/sdk/src/test/resources/ConfigParsing/Settings/TtlErrors/SettingsTtlInappsTypeError.json b/sdk/src/test/resources/ConfigParsing/Settings/TtlErrors/SettingsTtlInappsTypeError.json new file mode 100644 index 000000000..7036c008f --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Settings/TtlErrors/SettingsTtlInappsTypeError.json @@ -0,0 +1,16 @@ +{ + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": { + "inapps": 123 + } +} diff --git a/sdk/src/test/resources/ConfigParsing/Settings/TtlErrors/SettingsTtlTypeError.json b/sdk/src/test/resources/ConfigParsing/Settings/TtlErrors/SettingsTtlTypeError.json new file mode 100644 index 000000000..1201be591 --- /dev/null +++ b/sdk/src/test/resources/ConfigParsing/Settings/TtlErrors/SettingsTtlTypeError.json @@ -0,0 +1,14 @@ +{ + "operations": { + "viewProduct": { + "systemName": "ViewProduct" + }, + "viewCategory": { + "systemName": "ViewCategory" + }, + "setCart": { + "systemName": "SetCart" + } + }, + "ttl": 123 +}