From 2a15548556c1f0357307e085a80938355a17a7b6 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 22 Jul 2026 02:32:34 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../kotlin/com/tangem/common/BaseTestCase.kt | 1 + .../configs/feature_toggles_config.json | 4 ++++ .../PushNotificationsFeatureToggles.kt | 7 ++++++ .../DefaultPushNotificationsFeatureToggles.kt | 16 +++++++++++++ .../impl/di/PushNotificationsModule.kt | 7 ++++++ ...ushNotificationsDoubleAskVariantUseCase.kt | 5 ++++ ...otificationsDoubleAskVariantUseCaseTest.kt | 23 ++++++++++++++++--- 7 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 features/push-notifications/api/src/main/java/com/tangem/features/pushnotifications/PushNotificationsFeatureToggles.kt create mode 100644 features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/DefaultPushNotificationsFeatureToggles.kt diff --git a/app/src/androidTest/kotlin/com/tangem/common/BaseTestCase.kt b/app/src/androidTest/kotlin/com/tangem/common/BaseTestCase.kt index fab9e10cfb..b76f96e8ee 100644 --- a/app/src/androidTest/kotlin/com/tangem/common/BaseTestCase.kt +++ b/app/src/androidTest/kotlin/com/tangem/common/BaseTestCase.kt @@ -202,6 +202,7 @@ abstract class BaseTestCase : TestCase( "TWI_1326_YIELD_MODE_SWAP_ENABLED" to true, // 6.1 "TWI_1638_VA_MVP0_ENABLED" to true, + "TWI_1403_ONBOARDING_PUSH_NOTIFICATION_DOUBLE_ASK_AB_ENABLED" to true, ) ) } diff --git a/core/config-toggles/src/main/assets/configs/feature_toggles_config.json b/core/config-toggles/src/main/assets/configs/feature_toggles_config.json index ad0ad68734..9cf8fd39b6 100644 --- a/core/config-toggles/src/main/assets/configs/feature_toggles_config.json +++ b/core/config-toggles/src/main/assets/configs/feature_toggles_config.json @@ -39,6 +39,10 @@ "name": "TWI_1403_PUSH_NOTIFICATION_SETTINGS_ENABLED", "version": "6.1" }, + { + "name": "TWI_1403_ONBOARDING_PUSH_NOTIFICATION_DOUBLE_ASK_AB_ENABLED", + "version": "6.1" + }, { "name": "AND_15438_BACKEND_AUTHENTICATION_ENABLED", "version": "undefined" diff --git a/features/push-notifications/api/src/main/java/com/tangem/features/pushnotifications/PushNotificationsFeatureToggles.kt b/features/push-notifications/api/src/main/java/com/tangem/features/pushnotifications/PushNotificationsFeatureToggles.kt new file mode 100644 index 0000000000..ab66489854 --- /dev/null +++ b/features/push-notifications/api/src/main/java/com/tangem/features/pushnotifications/PushNotificationsFeatureToggles.kt @@ -0,0 +1,7 @@ +package com.tangem.features.pushnotifications + +interface PushNotificationsFeatureToggles { + + /** Kill switch for the onboarding "Double Ask" A/B experiment (`twi_1403_onboarding_push_notification_double_ask`). */ + val isOnboardingPushDoubleAskAbEnabled: Boolean +} \ No newline at end of file diff --git a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/DefaultPushNotificationsFeatureToggles.kt b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/DefaultPushNotificationsFeatureToggles.kt new file mode 100644 index 0000000000..bd27847e01 --- /dev/null +++ b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/DefaultPushNotificationsFeatureToggles.kt @@ -0,0 +1,16 @@ +package com.tangem.features.pushnotifications.impl + +import com.tangem.core.configtoggle.FeatureToggles +import com.tangem.core.configtoggle.feature.FeatureTogglesManager +import com.tangem.features.pushnotifications.PushNotificationsFeatureToggles +import javax.inject.Inject + +internal class DefaultPushNotificationsFeatureToggles @Inject constructor( + private val featureTogglesManager: FeatureTogglesManager, +) : PushNotificationsFeatureToggles { + + override val isOnboardingPushDoubleAskAbEnabled: Boolean + get() = featureTogglesManager.isFeatureEnabled( + FeatureToggles.TWI_1403_ONBOARDING_PUSH_NOTIFICATION_DOUBLE_ASK_AB_ENABLED, + ) +} \ No newline at end of file diff --git a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/di/PushNotificationsModule.kt b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/di/PushNotificationsModule.kt index 06d4376447..278d4274a8 100644 --- a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/di/PushNotificationsModule.kt +++ b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/di/PushNotificationsModule.kt @@ -1,10 +1,12 @@ package com.tangem.features.pushnotifications.impl.di import com.tangem.core.decompose.model.Model +import com.tangem.features.pushnotifications.PushNotificationsFeatureToggles import com.tangem.features.pushnotifications.api.PushNotificationsBottomSheetComponent import com.tangem.features.pushnotifications.api.PushNotificationsComponent import com.tangem.features.pushnotifications.impl.DefaultPushNotificationsBottomSheetComponent import com.tangem.features.pushnotifications.impl.DefaultPushNotificationsComponent +import com.tangem.features.pushnotifications.impl.DefaultPushNotificationsFeatureToggles import com.tangem.features.pushnotifications.impl.model.PushNotificationsModel import dagger.Binds import dagger.Module @@ -12,6 +14,7 @@ import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap +import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) @@ -29,4 +32,8 @@ internal interface PushNotificationsModule { @IntoMap @ClassKey(PushNotificationsModel::class) fun bindModel(model: PushNotificationsModel): Model + + @Binds + @Singleton + fun bindFeatureToggles(impl: DefaultPushNotificationsFeatureToggles): PushNotificationsFeatureToggles } \ No newline at end of file diff --git a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/domain/GetPushNotificationsDoubleAskVariantUseCase.kt b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/domain/GetPushNotificationsDoubleAskVariantUseCase.kt index 6b1e8c5f72..9d8bdc2024 100644 --- a/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/domain/GetPushNotificationsDoubleAskVariantUseCase.kt +++ b/features/push-notifications/impl/src/main/java/com/tangem/features/pushnotifications/impl/domain/GetPushNotificationsDoubleAskVariantUseCase.kt @@ -1,13 +1,18 @@ package com.tangem.features.pushnotifications.impl.domain import com.tangem.core.abtests.manager.ABTestsManager +import com.tangem.features.pushnotifications.PushNotificationsFeatureToggles import javax.inject.Inject class GetPushNotificationsDoubleAskVariantUseCase @Inject constructor( + private val pushNotificationsFeatureToggles: PushNotificationsFeatureToggles, private val abTestsManager: ABTestsManager, ) { suspend operator fun invoke(): DoubleAskVariant { + if (!pushNotificationsFeatureToggles.isOnboardingPushDoubleAskAbEnabled) { + return DoubleAskVariant.Off + } val variant = abTestsManager.getValue(AMPLITUDE_ID, DoubleAskVariant.Off.key) return DoubleAskVariant.fromKey(variant) } diff --git a/features/push-notifications/impl/src/test/kotlin/com/tangem/features/pushnotifications/impl/domain/GetPushNotificationsDoubleAskVariantUseCaseTest.kt b/features/push-notifications/impl/src/test/kotlin/com/tangem/features/pushnotifications/impl/domain/GetPushNotificationsDoubleAskVariantUseCaseTest.kt index 151b04f878..a42e32f434 100644 --- a/features/push-notifications/impl/src/test/kotlin/com/tangem/features/pushnotifications/impl/domain/GetPushNotificationsDoubleAskVariantUseCaseTest.kt +++ b/features/push-notifications/impl/src/test/kotlin/com/tangem/features/pushnotifications/impl/domain/GetPushNotificationsDoubleAskVariantUseCaseTest.kt @@ -2,22 +2,37 @@ package com.tangem.features.pushnotifications.impl.domain import com.google.common.truth.Truth.assertThat import com.tangem.core.abtests.manager.ABTestsManager +import com.tangem.features.pushnotifications.PushNotificationsFeatureToggles import io.mockk.coEvery import io.mockk.coVerify +import io.mockk.every import io.mockk.mockk import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.Test internal class GetPushNotificationsDoubleAskVariantUseCaseTest { + private val featureToggles: PushNotificationsFeatureToggles = mockk() private val abTestsManager: ABTestsManager = mockk() private val useCase = GetPushNotificationsDoubleAskVariantUseCase( + pushNotificationsFeatureToggles = featureToggles, abTestsManager = abTestsManager, ) @Test - fun `GIVEN AB returns treatment WHEN invoke THEN returns On`() = runTest { + fun `GIVEN toggle disabled WHEN invoke THEN returns Off and AB not queried`() = runTest { + every { featureToggles.isOnboardingPushDoubleAskAbEnabled } returns false + + val result = useCase() + + assertThat(result).isEqualTo(DoubleAskVariant.Off) + coVerify(exactly = 0) { abTestsManager.getValue(any(), any()) } + } + + @Test + fun `GIVEN toggle enabled AND AB returns treatment WHEN invoke THEN returns On`() = runTest { + every { featureToggles.isOnboardingPushDoubleAskAbEnabled } returns true coEvery { abTestsManager.getValue(KEY, "control") } returns "treatment" val result = useCase() @@ -27,14 +42,16 @@ internal class GetPushNotificationsDoubleAskVariantUseCaseTest { } @Test - fun `GIVEN AB returns control WHEN invoke THEN returns Off`() = runTest { + fun `GIVEN toggle enabled AND AB returns control WHEN invoke THEN returns Off`() = runTest { + every { featureToggles.isOnboardingPushDoubleAskAbEnabled } returns true coEvery { abTestsManager.getValue(KEY, "control") } returns "control" assertThat(useCase()).isEqualTo(DoubleAskVariant.Off) } @Test - fun `GIVEN AB returns unknown WHEN invoke THEN returns Off`() = runTest { + fun `GIVEN toggle enabled AND AB returns unknown WHEN invoke THEN returns Off`() = runTest { + every { featureToggles.isOnboardingPushDoubleAskAbEnabled } returns true coEvery { abTestsManager.getValue(KEY, "control") } returns "unexpected_value" assertThat(useCase()).isEqualTo(DoubleAskVariant.Off)