diff --git a/messaginginapp/src/androidTest/java/io/customer/messaginginapp/ModuleMessagingInAppTest.kt b/messaginginapp/src/androidTest/java/io/customer/messaginginapp/ModuleMessagingInAppTest.kt index 8fc6100c2..0a64bff8e 100644 --- a/messaginginapp/src/androidTest/java/io/customer/messaginginapp/ModuleMessagingInAppTest.kt +++ b/messaginginapp/src/androidTest/java/io/customer/messaginginapp/ModuleMessagingInAppTest.kt @@ -2,12 +2,19 @@ package io.customer.messaginginapp import androidx.test.ext.junit.runners.AndroidJUnit4 import io.customer.commontest.BaseIntegrationTest +import io.customer.messaginginapp.di.inAppMessaging import io.customer.messaginginapp.provider.InAppMessagesProvider import io.customer.messaginginapp.type.InAppEventListener +import io.customer.sdk.CustomerIO import io.customer.sdk.CustomerIOConfig +import io.customer.sdk.data.model.Region +import io.customer.sdk.extensions.random +import io.customer.sdk.hooks.HookModule import io.customer.sdk.hooks.HooksManager import io.customer.sdk.module.CustomerIOModule import io.customer.sdk.repository.preference.SitePreferenceRepository +import java.lang.reflect.Field +import org.amshove.kluent.shouldBe import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -44,6 +51,27 @@ internal class ModuleMessagingInAppTest : BaseIntegrationTest() { modules[ModuleMessagingInApp.moduleName] = module } + @Test + fun initialize_givenComponentInitialize_expectGistToInitializeWithCorrectValuesAndHooks() { + module.initialize() + + // verify gist is initialized + verify(gistInAppMessagesProvider).initProvider( + any(), + eq(cioConfig.siteId), + eq(cioConfig.region.code) + ) + + // verify hook was added + verify(hooksManager).add(eq(HookModule.MessagingInApp), any()) + + // verify events + verify(gistInAppMessagesProvider).subscribeToEvents(any(), any(), any()) + + // verify given event listener gets registered + verify(gistInAppMessagesProvider).setListener(eventListenerMock) + } + @Test fun initialize_givenProfilePreviouslyIdentified_expectGistToSetUserToken() { prefRepository.saveIdentifier("identifier") @@ -60,4 +88,59 @@ internal class ModuleMessagingInAppTest : BaseIntegrationTest() { // verify gist sets userToken verify(gistInAppMessagesProvider).setUserToken(eq("identifier")) } + + @Test + fun initialize_givenNoProfileIdentified_expectGistNoUserSet() { + module.initialize() + + // verify gist is initialized + verify(gistInAppMessagesProvider).initProvider( + any(), + eq(cioConfig.siteId), + eq(cioConfig.region.code) + ) + + // verify gist doesn't userToken + verify(gistInAppMessagesProvider, never()).setUserToken(any()) + } + + @Test + fun initialize_givenComponentInitializedWithOrganizationId_expectOrganizationIdToBeIgnored() { + // since `organizationId` is a private member, to check if its being used we have to use reflection + // this test will be deleted when the deprecated variable is removed + + val orgId = String.random + val module = ModuleMessagingInApp( + organizationId = orgId + ) + val fields = ModuleMessagingInApp::class.java.declaredFields + var organizationId: Field? = null + for (field in fields) { + if (field.name == "organizationId") { + organizationId = field + break + } + } + organizationId?.isAccessible = true + (organizationId?.get(module)) shouldBe null + } + + @Test + fun whenDismissMessageCalledOnCustomerIO_thenDismissMessageIsCalledOnGist() { + // initialize the SDK + val customerIO = CustomerIO.Builder( + siteId = siteId, + apiKey = String.random, + region = Region.US, + appContext = application + ).apply { + overrideDiGraph = di + }.build() + + // call dismissMessage on the CustomerIO instance + customerIO.inAppMessaging().dismissMessage() + + // verify that the module's dismissMessage method was called + verify(gistInAppMessagesProvider).dismissMessage() + } } diff --git a/messaginginapp/src/test/java/io/customer/messaginginapp/ModuleMessagingInAppTest.kt b/messaginginapp/src/test/java/io/customer/messaginginapp/ModuleMessagingInAppTest.kt deleted file mode 100644 index 1ead54deb..000000000 --- a/messaginginapp/src/test/java/io/customer/messaginginapp/ModuleMessagingInAppTest.kt +++ /dev/null @@ -1,130 +0,0 @@ -package io.customer.messaginginapp - -import io.customer.commontest.BaseUnitTest -import io.customer.messaginginapp.di.inAppMessaging -import io.customer.messaginginapp.provider.InAppMessagesProvider -import io.customer.messaginginapp.type.InAppEventListener -import io.customer.sdk.CustomerIO -import io.customer.sdk.CustomerIOConfig -import io.customer.sdk.data.model.Region -import io.customer.sdk.extensions.random -import io.customer.sdk.hooks.HookModule -import io.customer.sdk.hooks.HooksManager -import io.customer.sdk.module.CustomerIOModule -import io.customer.sdk.repository.preference.SitePreferenceRepository -import java.lang.reflect.Field -import org.amshove.kluent.shouldBe -import org.junit.Before -import org.junit.Test -import org.mockito.kotlin.any -import org.mockito.kotlin.eq -import org.mockito.kotlin.mock -import org.mockito.kotlin.never -import org.mockito.kotlin.verify - -internal class ModuleMessagingInAppTest : BaseUnitTest() { - - private lateinit var module: ModuleMessagingInApp - private val gistInAppMessagesProvider: InAppMessagesProvider = mock() - private val hooksManager: HooksManager = mock() - private val eventListenerMock: InAppEventListener = mock() - private val prefRepository: SitePreferenceRepository - get() = di.sitePreferenceRepository - - private val modules = hashMapOf>() - - override fun setupConfig(): CustomerIOConfig = createConfig( - modules = modules - ) - - @Before - override fun setup() { - super.setup() - - di.overrideDependency(InAppMessagesProvider::class.java, gistInAppMessagesProvider) - di.overrideDependency(HooksManager::class.java, hooksManager) - - module = ModuleMessagingInApp( - moduleConfig = MessagingInAppModuleConfig.Builder().setEventListener(eventListenerMock) - .build(), - overrideDiGraph = di - ) - modules[ModuleMessagingInApp.moduleName] = module - } - - @Test - fun initialize_givenComponentInitialize_expectGistToInitializeWithCorrectValuesAndHooks() { - module.initialize() - - // verify gist is initialized - verify(gistInAppMessagesProvider).initProvider( - any(), - eq(cioConfig.siteId), - eq(cioConfig.region.code) - ) - - // verify hook was added - verify(hooksManager).add(eq(HookModule.MessagingInApp), any()) - - // verify events - verify(gistInAppMessagesProvider).subscribeToEvents(any(), any(), any()) - - // verify given event listener gets registered - verify(gistInAppMessagesProvider).setListener(eventListenerMock) - } - - @Test - fun initialize_givenNoProfileIdentified_expectGistNoUserSet() { - module.initialize() - - // verify gist is initialized - verify(gistInAppMessagesProvider).initProvider( - any(), - eq(cioConfig.siteId), - eq(cioConfig.region.code) - ) - - // verify gist doesn't userToken - verify(gistInAppMessagesProvider, never()).setUserToken(any()) - } - - @Test - fun initialize_givenComponentInitializedWithOrganizationId_expectOrganizationIdToBeIgnored() { - // since `organizationId` is a private member, to check if its being used we have to use reflection - // this test will be deleted when the deprecated variable is removed - - val orgId = String.random - val module = ModuleMessagingInApp( - organizationId = orgId - ) - val fields = ModuleMessagingInApp::class.java.declaredFields - var organizationId: Field? = null - for (field in fields) { - if (field.name == "organizationId") { - organizationId = field - break - } - } - organizationId?.isAccessible = true - (organizationId?.get(module)) shouldBe null - } - - @Test - fun whenDismissMessageCalledOnCustomerIO_thenDismissMessageIsCalledOnGist() { - // initialize the SDK - val customerIO = CustomerIO.Builder( - siteId = siteId, - apiKey = String.random, - region = Region.US, - appContext = application - ).apply { - overrideDiGraph = di - }.build() - - // call dismissMessage on the CustomerIO instance - customerIO.inAppMessaging().dismissMessage() - - // verify that the module's dismissMessage method was called - verify(gistInAppMessagesProvider).dismissMessage() - } -} diff --git a/sdk/src/androidTest/java/io/customer/sdk/CustomerIOSharedTest.kt b/sdk/src/androidTest/java/io/customer/sdk/CustomerIOSharedTest.kt index 28541cd64..edbe7e24f 100644 --- a/sdk/src/androidTest/java/io/customer/sdk/CustomerIOSharedTest.kt +++ b/sdk/src/androidTest/java/io/customer/sdk/CustomerIOSharedTest.kt @@ -2,17 +2,48 @@ package io.customer.sdk import androidx.test.ext.junit.runners.AndroidJUnit4 import io.customer.commontest.BaseIntegrationTest +import io.customer.sdk.di.CustomerIOSharedComponent import io.customer.sdk.di.CustomerIOStaticComponent +import io.customer.sdk.repository.preference.CustomerIOStoredValues +import io.customer.sdk.repository.preference.SharedPreferenceRepository import io.customer.sdk.util.LogcatLogger import io.customer.sdk.util.StaticSettingsProvider import org.amshove.kluent.shouldBeEqualTo +import org.amshove.kluent.shouldNotBe import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.mock +import org.mockito.kotlin.verify import org.mockito.kotlin.whenever @RunWith(AndroidJUnit4::class) class CustomerIOSharedTest : BaseIntegrationTest() { + @Test + fun verifyInstanceAccessedMultipleTimes_givenNoSpecialCondition_expectSameInstance() { + val instance1 = CustomerIOShared.instance() + val instance2 = CustomerIOShared.instance() + + instance1 shouldBeEqualTo instance2 + } + + @Test + fun verifySharedComponentInstanceAccessedMultipleTimes_givenNoSpecialCondition_expectSameInstance() { + val instance1 = CustomerIOShared.instance().initializeAndGetSharedComponent(context) + val instance2 = CustomerIOShared.instance().initializeAndGetSharedComponent(context) + + instance1 shouldBeEqualTo instance2 + } + + @Test + fun verifyDIGraphProvided_givenInstanceNotInitializedBefore_expectProvidedDIGraph() { + val instance = with(CustomerIOShared) { + clearInstance() + createInstance(diStaticGraph = staticDIComponent) + } + + instance.diStaticGraph shouldBeEqualTo staticDIComponent + } + @Test fun verifyAttachedWithSDK_givenNoSpecificEnvironment_expectProvidedLogLevel() { val diGraph = CustomerIOStaticComponent() @@ -26,4 +57,30 @@ class CustomerIOSharedTest : BaseIntegrationTest() { (instance.diStaticGraph.logger as LogcatLogger).logLevel shouldBeEqualTo cioConfig.logLevel } + + @Test + fun verifyAttachedWithSDK_givenNoSpecificEnvironment_expectSharedComponentToBeInitialized() { + val diGraph = CustomerIOStaticComponent() + + val instance = CustomerIOShared.createInstance(diStaticGraph = diGraph) + instance.attachSDKConfig(sdkConfig = cioConfig, context = context) + + val sharedGraph = instance.diSharedGraph + sharedGraph shouldNotBe null + } + + @Test + fun verifyAttachedWithSDK_givenSharedComponentIsInitialized_expectConfigValuesToBeStored() { + val diGraph = CustomerIOStaticComponent() + val diIOSharedComponent = CustomerIOSharedComponent(context) + + val sharedPreferenceRepository: SharedPreferenceRepository = mock() + diIOSharedComponent.overrideDependency(SharedPreferenceRepository::class.java, sharedPreferenceRepository) + + val instance = CustomerIOShared.createInstance(diStaticGraph = diGraph) + instance.diSharedGraph = diIOSharedComponent + instance.attachSDKConfig(sdkConfig = cioConfig, context = context) + + verify(sharedPreferenceRepository).saveSettings(CustomerIOStoredValues(cioConfig)) + } } diff --git a/sdk/src/androidTest/java/io/customer/sdk/CustomerIOTest.kt b/sdk/src/androidTest/java/io/customer/sdk/CustomerIOTest.kt index 8dff4ff38..9df7bc28c 100644 --- a/sdk/src/androidTest/java/io/customer/sdk/CustomerIOTest.kt +++ b/sdk/src/androidTest/java/io/customer/sdk/CustomerIOTest.kt @@ -2,16 +2,31 @@ package io.customer.sdk import androidx.test.ext.junit.runners.AndroidJUnit4 import io.customer.commontest.BaseIntegrationTest +import io.customer.sdk.data.model.Region +import io.customer.sdk.data.store.Client +import io.customer.sdk.di.CustomerIOSharedComponent +import io.customer.sdk.di.CustomerIOStaticComponent import io.customer.sdk.extensions.random +import io.customer.sdk.module.CustomerIOGenericModule import io.customer.sdk.repository.CleanupRepository import io.customer.sdk.repository.DeviceRepository import io.customer.sdk.repository.ProfileRepository +import io.customer.sdk.repository.preference.CustomerIOStoredValues +import io.customer.sdk.repository.preference.SharedPreferenceRepository +import io.customer.sdk.util.CioLogLevel +import io.customer.sdk.util.Seconds +import kotlinx.coroutines.runBlocking import org.amshove.kluent.shouldBe import org.amshove.kluent.shouldBeEqualTo +import org.amshove.kluent.shouldNotBe +import org.amshove.kluent.shouldNotBeNull import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.mock +import org.mockito.kotlin.never +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever @RunWith(AndroidJUnit4::class) class CustomerIOTest : BaseIntegrationTest() { @@ -29,6 +44,76 @@ class CustomerIOTest : BaseIntegrationTest() { di.overrideDependency(ProfileRepository::class.java, profileRepositoryMock) } + @Test + fun verifySDKConfigurationSetAfterBuild() { + val givenSiteId = String.random + val givenApiKey = String.random + val builder = CustomerIO.Builder( + siteId = givenSiteId, + apiKey = givenApiKey, + region = Region.EU, + appContext = application + ) + + val client = builder.build() + + val actual = client.diGraph.sdkConfig + + actual.siteId shouldBeEqualTo givenSiteId + actual.apiKey shouldBeEqualTo givenApiKey + actual.timeout.shouldNotBeNull() + actual.region shouldBeEqualTo Region.EU + actual.autoTrackScreenViews shouldBeEqualTo false + actual.trackingApiUrl shouldBeEqualTo null + actual.trackingApiHostname shouldBeEqualTo "https://track-sdk-eu.customer.io/" + actual.backgroundQueueTaskExpiredSeconds shouldBeEqualTo Seconds.fromDays(3).value + actual.backgroundQueueMinNumberOfTasks shouldBeEqualTo 10 + actual.backgroundQueueSecondsDelay shouldBeEqualTo 30.0 + actual.logLevel shouldBeEqualTo CioLogLevel.ERROR + } + + @Test + fun verifyTrackingApiHostnameUpdateAfterUpdatingTrackingApiUrl() { + val givenSiteId = String.random + val givenApiKey = String.random + val givenTrackingApiUrl = "https://local/track/" + val builder = CustomerIO.Builder( + siteId = givenSiteId, + apiKey = givenApiKey, + region = Region.EU, + appContext = application + ).autoTrackScreenViews(true) + + val client = builder.build() + + val actual = client.diGraph.sdkConfig + actual.region shouldBeEqualTo Region.EU + actual.trackingApiUrl shouldBeEqualTo null + actual.trackingApiHostname shouldBeEqualTo "https://track-sdk-eu.customer.io/" + + builder.setTrackingApiURL(givenTrackingApiUrl) + + val updatedClient = builder.build() + + val updatedConfig = updatedClient.diGraph.sdkConfig + + // region stays the same but doesn't effect trackingApiHostname + updatedConfig.region shouldBeEqualTo Region.EU + updatedConfig.trackingApiUrl shouldBeEqualTo givenTrackingApiUrl + updatedConfig.trackingApiHostname shouldBeEqualTo givenTrackingApiUrl + } + + @Test + fun deviceToken_givenGetValue_expectDeviceRepositoryGetDeviceToken() { + val givenDeviceToken = String.random + whenever(deviceRepositoryMock.getDeviceToken()).thenReturn(givenDeviceToken) + val customerIO = CustomerIO(di) + + val actual = customerIO.registeredDeviceToken + + actual shouldBeEqualTo givenDeviceToken + } + @Test fun deviceToken_testRegisterDeviceTokenWhenPreviouslyNull() { val givenDeviceToken = String.random @@ -39,4 +124,177 @@ class CustomerIOTest : BaseIntegrationTest() { CustomerIO.instance().registeredDeviceToken shouldBeEqualTo givenDeviceToken } + + @Test + fun deviceAttributes_givenSetValue_expectMakeRequestToAddAttributes() { + val givenAttributes = mapOf(String.random to String.random) + val customerIO = CustomerIO(di) + + customerIO.deviceAttributes = givenAttributes + + verify(deviceRepositoryMock).addCustomDeviceAttributes(givenAttributes) + } + + @Test + fun profileAttributes_givenSetValue_expectMakeRequestToAddAttributes() { + val givenAttributes = mapOf(String.random to String.random) + val customerIO = CustomerIO(di) + customerIO.profileAttributes = givenAttributes + + verify(profileRepositoryMock).addCustomProfileAttributes(givenAttributes) + } + + @Test + fun build_givenModule_expectInitializeModule() { + val givenModule: CustomerIOGenericModule = mock().apply { + whenever(this.moduleName).thenReturn(String.random) + } + + CustomerIO.Builder( + siteId = String.random, + apiKey = String.random, + appContext = application + ).addCustomerIOModule(givenModule).build() + + verify(givenModule).initialize() + } + + @Test + fun build_givenMultipleModules_expectInitializeAllModules() { + val givenModule1: CustomerIOGenericModule = mock().apply { + whenever(this.moduleName).thenReturn(String.random) + } + val givenModule2: CustomerIOGenericModule = mock().apply { + whenever(this.moduleName).thenReturn(String.random) + } + + CustomerIO.Builder( + siteId = String.random, + apiKey = String.random, + appContext = application + ).addCustomerIOModule(givenModule1).addCustomerIOModule(givenModule2).build() + + verify(givenModule1).initialize() + verify(givenModule2).initialize() + } + + @Test + fun build_givenMultipleModulesOfSameType_expectOnlyInitializeOneModuleInstance() { + val givenModule1: CustomerIOGenericModule = mock().apply { + whenever(this.moduleName).thenReturn("shared-module-name") + } + val givenModule2: CustomerIOGenericModule = mock().apply { + whenever(this.moduleName).thenReturn("shared-module-name") + } + + CustomerIO.Builder( + siteId = String.random, + apiKey = String.random, + appContext = application + ).addCustomerIOModule(givenModule1).addCustomerIOModule(givenModule2).build() + + verify(givenModule1, never()).initialize() + verify(givenModule2).initialize() + } + + @Test + fun initializeSdk_expectRunCleanup(): Unit = runBlocking { + getRandomCustomerIOBuilder().build() + + verify(cleanupRepositoryMock).cleanup() + } + + @Test + fun givenCustomerIONotInitialized_andConfigValuesNotStored_expectNullAsInstance() { + // clear current instance + CustomerIO.clearInstance() + + val diGraph = CustomerIOStaticComponent() + val diIOSharedComponent = CustomerIOSharedComponent(context) + + val sharedPreferenceRepository = mock().apply { + whenever(this.loadSettings()).thenReturn(CustomerIOStoredValues.empty) + } + diIOSharedComponent.overrideDependency( + SharedPreferenceRepository::class.java, + sharedPreferenceRepository + ) + + val instance = CustomerIOShared.createInstance(diStaticGraph = diGraph) + instance.diSharedGraph = diIOSharedComponent + + val customerIO = CustomerIO.instanceOrNull(context) + customerIO shouldBe null + } + + @Test + fun givenCustomerIONotInitialized_andConfigValuesStored_expectCorrectValuesFromInstance() { + // clear current instance + CustomerIO.clearInstance() + + val diGraph = CustomerIOStaticComponent() + val diIOSharedComponent = CustomerIOSharedComponent(context) + + val sharedPreferenceRepository = mock().apply { + whenever(this.loadSettings()).thenReturn(CustomerIOStoredValues(cioConfig)) + } + diIOSharedComponent.overrideDependency( + SharedPreferenceRepository::class.java, + sharedPreferenceRepository + ) + + val instance = CustomerIOShared.createInstance(diStaticGraph = diGraph) + instance.diSharedGraph = diIOSharedComponent + + val customerIO = CustomerIO.instanceOrNull(context) + customerIO shouldNotBe null + + val sdkConfig = customerIO!!.diGraph.sdkConfig + sdkConfig.siteId shouldBeEqualTo cioConfig.siteId + sdkConfig.apiKey shouldBeEqualTo cioConfig.apiKey + sdkConfig.region shouldBeEqualTo cioConfig.region + sdkConfig.client.toString() shouldBeEqualTo cioConfig.client.toString() + sdkConfig.trackingApiUrl shouldBeEqualTo cioConfig.trackingApiUrl + sdkConfig.autoTrackDeviceAttributes shouldBeEqualTo cioConfig.autoTrackDeviceAttributes + sdkConfig.logLevel shouldBeEqualTo cioConfig.logLevel + sdkConfig.backgroundQueueMinNumberOfTasks shouldBeEqualTo cioConfig.backgroundQueueMinNumberOfTasks + sdkConfig.backgroundQueueSecondsDelay shouldBeEqualTo cioConfig.backgroundQueueSecondsDelay + } + + @Test + fun test_sdkConfigMapping_givenConfigParamsMap_expectCorrectlyMappedConfigValues() { + val givenConfigMap = mapOf( + Pair(CustomerIOConfig.Companion.Keys.BACKGROUND_QUEUE_MIN_NUMBER_OF_TASKS, 3), + Pair(CustomerIOConfig.Companion.Keys.BACKGROUND_QUEUE_SECONDS_DELAY, 40.0), + Pair(CustomerIOConfig.Companion.Keys.AUTO_TRACK_DEVICE_ATTRIBUTES, false), + Pair(CustomerIOConfig.Companion.Keys.LOG_LEVEL, "none"), + Pair(CustomerIOConfig.Companion.Keys.SOURCE_SDK_SOURCE, "Flutter"), + Pair(CustomerIOConfig.Companion.Keys.SOURCE_SDK_VERSION, "1.0.0") + ) + val builder = CustomerIO.Builder( + siteId = String.random, + apiKey = String.random, + region = Region.EU, + appContext = application, + config = givenConfigMap + ).build() + + val actualConfig = builder.diGraph.sdkConfig + actualConfig.backgroundQueueMinNumberOfTasks shouldBeEqualTo 3 + actualConfig.backgroundQueueSecondsDelay shouldBeEqualTo 40.0 + actualConfig.autoTrackDeviceAttributes shouldBeEqualTo false + actualConfig.logLevel shouldBeEqualTo CioLogLevel.NONE + val actualClient = Client.Flutter("1.0.0") + actualConfig.client.source shouldBeEqualTo actualClient.source + actualConfig.client.sdkVersion shouldBeEqualTo actualClient.sdkVersion + } + + private fun getRandomCustomerIOBuilder(): CustomerIO.Builder = CustomerIO.Builder( + siteId = String.random, + apiKey = String.random, + region = Region.EU, + appContext = application + ).apply { + this.overrideDiGraph = di + } } diff --git a/sdk/src/test/java/io/customer/sdk/CustomerIOSharedTest.kt b/sdk/src/test/java/io/customer/sdk/CustomerIOSharedTest.kt deleted file mode 100644 index 7ca62af34..000000000 --- a/sdk/src/test/java/io/customer/sdk/CustomerIOSharedTest.kt +++ /dev/null @@ -1,66 +0,0 @@ -package io.customer.sdk - -import io.customer.commontest.BaseUnitTest -import io.customer.sdk.di.CustomerIOSharedComponent -import io.customer.sdk.di.CustomerIOStaticComponent -import io.customer.sdk.repository.preference.CustomerIOStoredValues -import io.customer.sdk.repository.preference.SharedPreferenceRepository -import org.amshove.kluent.shouldBeEqualTo -import org.amshove.kluent.shouldNotBe -import org.junit.Test -import org.mockito.kotlin.mock -import org.mockito.kotlin.verify - -class CustomerIOSharedTest : BaseUnitTest() { - @Test - fun verifyInstanceAccessedMultipleTimes_givenNoSpecialCondition_expectSameInstance() { - val instance1 = CustomerIOShared.instance() - val instance2 = CustomerIOShared.instance() - - instance1 shouldBeEqualTo instance2 - } - - @Test - fun verifySharedComponentInstanceAccessedMultipleTimes_givenNoSpecialCondition_expectSameInstance() { - val instance1 = CustomerIOShared.instance().initializeAndGetSharedComponent(context) - val instance2 = CustomerIOShared.instance().initializeAndGetSharedComponent(context) - - instance1 shouldBeEqualTo instance2 - } - - @Test - fun verifyDIGraphProvided_givenInstanceNotInitializedBefore_expectProvidedDIGraph() { - val instance = with(CustomerIOShared) { - clearInstance() - createInstance(diStaticGraph = staticDIComponent) - } - - instance.diStaticGraph shouldBeEqualTo staticDIComponent - } - - @Test - fun verifyAttachedWithSDK_givenNoSpecificEnvironment_expectSharedComponentToBeInitialized() { - val diGraph = CustomerIOStaticComponent() - - val instance = CustomerIOShared.createInstance(diStaticGraph = diGraph) - instance.attachSDKConfig(sdkConfig = cioConfig, context = context) - - val sharedGraph = instance.diSharedGraph - sharedGraph shouldNotBe null - } - - @Test - fun verifyAttachedWithSDK_givenSharedComponentIsInitialized_expectConfigValuesToBeStored() { - val diGraph = CustomerIOStaticComponent() - val diIOSharedComponent = CustomerIOSharedComponent(context) - - val sharedPreferenceRepository: SharedPreferenceRepository = mock() - diIOSharedComponent.overrideDependency(SharedPreferenceRepository::class.java, sharedPreferenceRepository) - - val instance = CustomerIOShared.createInstance(diStaticGraph = diGraph) - instance.diSharedGraph = diIOSharedComponent - instance.attachSDKConfig(sdkConfig = cioConfig, context = context) - - verify(sharedPreferenceRepository).saveSettings(CustomerIOStoredValues(cioConfig)) - } -} diff --git a/sdk/src/test/java/io/customer/sdk/CustomerIOTest.kt b/sdk/src/test/java/io/customer/sdk/CustomerIOTest.kt deleted file mode 100644 index 7322c5a6b..000000000 --- a/sdk/src/test/java/io/customer/sdk/CustomerIOTest.kt +++ /dev/null @@ -1,286 +0,0 @@ -package io.customer.sdk - -import io.customer.commontest.BaseUnitTest -import io.customer.sdk.data.model.Region -import io.customer.sdk.data.store.Client -import io.customer.sdk.di.CustomerIOSharedComponent -import io.customer.sdk.di.CustomerIOStaticComponent -import io.customer.sdk.extensions.random -import io.customer.sdk.module.CustomerIOGenericModule -import io.customer.sdk.repository.CleanupRepository -import io.customer.sdk.repository.DeviceRepository -import io.customer.sdk.repository.ProfileRepository -import io.customer.sdk.repository.preference.CustomerIOStoredValues -import io.customer.sdk.repository.preference.SharedPreferenceRepository -import io.customer.sdk.util.CioLogLevel -import io.customer.sdk.util.Seconds -import kotlinx.coroutines.runBlocking -import org.amshove.kluent.shouldBe -import org.amshove.kluent.shouldBeEqualTo -import org.amshove.kluent.shouldNotBe -import org.amshove.kluent.shouldNotBeNull -import org.junit.Before -import org.junit.Test -import org.mockito.kotlin.mock -import org.mockito.kotlin.never -import org.mockito.kotlin.verify -import org.mockito.kotlin.whenever - -class CustomerIOTest : BaseUnitTest() { - - private val cleanupRepositoryMock: CleanupRepository = mock() - private val deviceRepositoryMock: DeviceRepository = mock() - private val profileRepositoryMock: ProfileRepository = mock() - - @Before - fun setUp() { - super.setup() - - di.overrideDependency(CleanupRepository::class.java, cleanupRepositoryMock) - di.overrideDependency(DeviceRepository::class.java, deviceRepositoryMock) - di.overrideDependency(ProfileRepository::class.java, profileRepositoryMock) - } - - @Test - fun verifySDKConfigurationSetAfterBuild() { - val givenSiteId = String.random - val givenApiKey = String.random - val builder = CustomerIO.Builder( - siteId = givenSiteId, - apiKey = givenApiKey, - region = Region.EU, - appContext = application - ) - - val client = builder.build() - - val actual = client.diGraph.sdkConfig - - actual.siteId shouldBeEqualTo givenSiteId - actual.apiKey shouldBeEqualTo givenApiKey - actual.timeout.shouldNotBeNull() - actual.region shouldBeEqualTo Region.EU - actual.autoTrackScreenViews shouldBeEqualTo false - actual.trackingApiUrl shouldBeEqualTo null - actual.trackingApiHostname shouldBeEqualTo "https://track-sdk-eu.customer.io/" - actual.backgroundQueueTaskExpiredSeconds shouldBeEqualTo Seconds.fromDays(3).value - actual.backgroundQueueMinNumberOfTasks shouldBeEqualTo 10 - actual.backgroundQueueSecondsDelay shouldBeEqualTo 30.0 - actual.logLevel shouldBeEqualTo CioLogLevel.ERROR - } - - @Test - fun verifyTrackingApiHostnameUpdateAfterUpdatingTrackingApiUrl() { - val givenSiteId = String.random - val givenApiKey = String.random - val givenTrackingApiUrl = "https://local/track/" - val builder = CustomerIO.Builder( - siteId = givenSiteId, - apiKey = givenApiKey, - region = Region.EU, - appContext = application - ).autoTrackScreenViews(true) - - val client = builder.build() - - val actual = client.diGraph.sdkConfig - actual.region shouldBeEqualTo Region.EU - actual.trackingApiUrl shouldBeEqualTo null - actual.trackingApiHostname shouldBeEqualTo "https://track-sdk-eu.customer.io/" - - builder.setTrackingApiURL(givenTrackingApiUrl) - - val updatedClient = builder.build() - - val updatedConfig = updatedClient.diGraph.sdkConfig - - // region stays the same but doesn't effect trackingApiHostname - updatedConfig.region shouldBeEqualTo Region.EU - updatedConfig.trackingApiUrl shouldBeEqualTo givenTrackingApiUrl - updatedConfig.trackingApiHostname shouldBeEqualTo givenTrackingApiUrl - } - - @Test - fun deviceToken_givenGetValue_expectDeviceRepositoryGetDeviceToken() { - val givenDeviceToken = String.random - whenever(deviceRepositoryMock.getDeviceToken()).thenReturn(givenDeviceToken) - val customerIO = CustomerIO(di) - - val actual = customerIO.registeredDeviceToken - - actual shouldBeEqualTo givenDeviceToken - } - - @Test - fun deviceAttributes_givenSetValue_expectMakeRequestToAddAttributes() { - val givenAttributes = mapOf(String.random to String.random) - val customerIO = CustomerIO(di) - - customerIO.deviceAttributes = givenAttributes - - verify(deviceRepositoryMock).addCustomDeviceAttributes(givenAttributes) - } - - @Test - fun profileAttributes_givenSetValue_expectMakeRequestToAddAttributes() { - val givenAttributes = mapOf(String.random to String.random) - val customerIO = CustomerIO(di) - customerIO.profileAttributes = givenAttributes - - verify(profileRepositoryMock).addCustomProfileAttributes(givenAttributes) - } - - @Test - fun build_givenModule_expectInitializeModule() { - val givenModule: CustomerIOGenericModule = mock().apply { - whenever(this.moduleName).thenReturn(String.random) - } - - CustomerIO.Builder( - siteId = String.random, - apiKey = String.random, - appContext = application - ).addCustomerIOModule(givenModule).build() - - verify(givenModule).initialize() - } - - @Test - fun build_givenMultipleModules_expectInitializeAllModules() { - val givenModule1: CustomerIOGenericModule = mock().apply { - whenever(this.moduleName).thenReturn(String.random) - } - val givenModule2: CustomerIOGenericModule = mock().apply { - whenever(this.moduleName).thenReturn(String.random) - } - - CustomerIO.Builder( - siteId = String.random, - apiKey = String.random, - appContext = application - ).addCustomerIOModule(givenModule1).addCustomerIOModule(givenModule2).build() - - verify(givenModule1).initialize() - verify(givenModule2).initialize() - } - - @Test - fun build_givenMultipleModulesOfSameType_expectOnlyInitializeOneModuleInstance() { - val givenModule1: CustomerIOGenericModule = mock().apply { - whenever(this.moduleName).thenReturn("shared-module-name") - } - val givenModule2: CustomerIOGenericModule = mock().apply { - whenever(this.moduleName).thenReturn("shared-module-name") - } - - CustomerIO.Builder( - siteId = String.random, - apiKey = String.random, - appContext = application - ).addCustomerIOModule(givenModule1).addCustomerIOModule(givenModule2).build() - - verify(givenModule1, never()).initialize() - verify(givenModule2).initialize() - } - - @Test - fun initializeSdk_expectRunCleanup(): Unit = runBlocking { - getRandomCustomerIOBuilder().build() - - verify(cleanupRepositoryMock).cleanup() - } - - @Test - fun givenCustomerIONotInitialized_andConfigValuesNotStored_expectNullAsInstance() { - // clear current instance - CustomerIO.clearInstance() - - val diGraph = CustomerIOStaticComponent() - val diIOSharedComponent = CustomerIOSharedComponent(context) - - val sharedPreferenceRepository = mock().apply { - whenever(this.loadSettings()).thenReturn(CustomerIOStoredValues.empty) - } - diIOSharedComponent.overrideDependency( - SharedPreferenceRepository::class.java, - sharedPreferenceRepository - ) - - val instance = CustomerIOShared.createInstance(diStaticGraph = diGraph) - instance.diSharedGraph = diIOSharedComponent - - val customerIO = CustomerIO.instanceOrNull(context) - customerIO shouldBe null - } - - @Test - fun givenCustomerIONotInitialized_andConfigValuesStored_expectCorrectValuesFromInstance() { - // clear current instance - CustomerIO.clearInstance() - - val diGraph = CustomerIOStaticComponent() - val diIOSharedComponent = CustomerIOSharedComponent(context) - - val sharedPreferenceRepository = mock().apply { - whenever(this.loadSettings()).thenReturn(CustomerIOStoredValues(cioConfig)) - } - diIOSharedComponent.overrideDependency( - SharedPreferenceRepository::class.java, - sharedPreferenceRepository - ) - - val instance = CustomerIOShared.createInstance(diStaticGraph = diGraph) - instance.diSharedGraph = diIOSharedComponent - - val customerIO = CustomerIO.instanceOrNull(context) - customerIO shouldNotBe null - - val sdkConfig = customerIO!!.diGraph.sdkConfig - sdkConfig.siteId shouldBeEqualTo cioConfig.siteId - sdkConfig.apiKey shouldBeEqualTo cioConfig.apiKey - sdkConfig.region shouldBeEqualTo cioConfig.region - sdkConfig.client.toString() shouldBeEqualTo cioConfig.client.toString() - sdkConfig.trackingApiUrl shouldBeEqualTo cioConfig.trackingApiUrl - sdkConfig.autoTrackDeviceAttributes shouldBeEqualTo cioConfig.autoTrackDeviceAttributes - sdkConfig.logLevel shouldBeEqualTo cioConfig.logLevel - sdkConfig.backgroundQueueMinNumberOfTasks shouldBeEqualTo cioConfig.backgroundQueueMinNumberOfTasks - sdkConfig.backgroundQueueSecondsDelay shouldBeEqualTo cioConfig.backgroundQueueSecondsDelay - } - - @Test - fun test_sdkConfigMapping_givenConfigParamsMap_expectCorrectlyMappedConfigValues() { - val givenConfigMap = mapOf( - Pair(CustomerIOConfig.Companion.Keys.BACKGROUND_QUEUE_MIN_NUMBER_OF_TASKS, 3), - Pair(CustomerIOConfig.Companion.Keys.BACKGROUND_QUEUE_SECONDS_DELAY, 40.0), - Pair(CustomerIOConfig.Companion.Keys.AUTO_TRACK_DEVICE_ATTRIBUTES, false), - Pair(CustomerIOConfig.Companion.Keys.LOG_LEVEL, "none"), - Pair(CustomerIOConfig.Companion.Keys.SOURCE_SDK_SOURCE, "Flutter"), - Pair(CustomerIOConfig.Companion.Keys.SOURCE_SDK_VERSION, "1.0.0") - ) - val builder = CustomerIO.Builder( - siteId = String.random, - apiKey = String.random, - region = Region.EU, - appContext = application, - config = givenConfigMap - ).build() - - val actualConfig = builder.diGraph.sdkConfig - actualConfig.backgroundQueueMinNumberOfTasks shouldBeEqualTo 3 - actualConfig.backgroundQueueSecondsDelay shouldBeEqualTo 40.0 - actualConfig.autoTrackDeviceAttributes shouldBeEqualTo false - actualConfig.logLevel shouldBeEqualTo CioLogLevel.NONE - val actualClient = Client.Flutter("1.0.0") - actualConfig.client.source shouldBeEqualTo actualClient.source - actualConfig.client.sdkVersion shouldBeEqualTo actualClient.sdkVersion - } - - private fun getRandomCustomerIOBuilder(): CustomerIO.Builder = CustomerIO.Builder( - siteId = String.random, - apiKey = String.random, - region = Region.EU, - appContext = application - ).apply { - this.overrideDiGraph = di - } -}