diff --git a/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/SubscriptionsManager.kt b/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/SubscriptionsManager.kt index 01ad464d56cf..bf76a1d40a2f 100644 --- a/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/SubscriptionsManager.kt +++ b/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/SubscriptionsManager.kt @@ -56,9 +56,6 @@ import com.duckduckgo.subscriptions.impl.billing.PlayBillingManager import com.duckduckgo.subscriptions.impl.billing.PurchaseState import com.duckduckgo.subscriptions.impl.billing.RetryPolicy import com.duckduckgo.subscriptions.impl.billing.retry -import com.duckduckgo.subscriptions.impl.freetrial.FreeTrialPrivacyProPixelsPlugin -import com.duckduckgo.subscriptions.impl.freetrial.onSubscriptionStartedMonthly -import com.duckduckgo.subscriptions.impl.freetrial.onSubscriptionStartedYearly import com.duckduckgo.subscriptions.impl.pixels.SubscriptionPixelSender import com.duckduckgo.subscriptions.impl.repository.AccessToken import com.duckduckgo.subscriptions.impl.repository.Account @@ -245,7 +242,6 @@ class RealSubscriptionsManager @Inject constructor( private val pkceGenerator: PkceGenerator, private val timeProvider: CurrentTimeProvider, private val backgroundTokenRefresh: BackgroundTokenRefresh, - private val freeTrialPrivacyProPixelsPlugin: Lazy, ) : SubscriptionsManager { private val adapter = Moshi.Builder().build().adapter(ResponseError::class.java) @@ -467,9 +463,9 @@ class RealSubscriptionsManager @Inject constructor( if (subscription.isActive()) { // Free Trial experiment metrics if (confirmationResponse.subscription.productId.contains("monthly-renews-us")) { - freeTrialPrivacyProPixelsPlugin.get().onSubscriptionStartedMonthly() + pixelSender.reportFreeTrialOnSubscriptionStartedMonthly() } else if (confirmationResponse.subscription.productId.contains("yearly-renews-us")) { - freeTrialPrivacyProPixelsPlugin.get().onSubscriptionStartedYearly() + pixelSender.reportFreeTrialOnSubscriptionStartedYearly() } pixelSender.reportPurchaseSuccess() pixelSender.reportSubscriptionActivated() diff --git a/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/freetrial/FreeTrialExperimentDataStore.kt b/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/freetrial/FreeTrialExperimentDataStore.kt index 31051e30dfaa..c4dff958b23c 100644 --- a/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/freetrial/FreeTrialExperimentDataStore.kt +++ b/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/freetrial/FreeTrialExperimentDataStore.kt @@ -40,12 +40,15 @@ interface FreeTrialExperimentDataStore { /** * Returns the number [Int] of paywall impressions for the given [definition] */ - suspend fun getMetricForPixelDefinition(definition: PixelDefinition): Int + suspend fun getMetricForPixelDefinition(definition: PixelDefinition): String? /** * Increases the count of paywall impressions for the given [definition] */ - suspend fun increaseMetricForPixelDefinition(definition: PixelDefinition): Int + suspend fun increaseMetricForPixelDefinition( + definition: PixelDefinition, + value: String, + ): String? } @ContributesBinding(AppScope::class) @@ -54,7 +57,11 @@ class FreeTrialExperimentDataStoreImpl @Inject constructor( private val dispatcherProvider: DispatcherProvider, ) : FreeTrialExperimentDataStore { - private val preferences: SharedPreferences by lazy { sharedPreferencesProvider.getSharedPreferences(FILENAME) } + private val preferences: SharedPreferences by lazy { + sharedPreferencesProvider.getSharedPreferences( + FILENAME, + ) + } override var paywallImpressions: Int get() = preferences.getInt(KEY_PAYWALL_IMPRESSIONS, 0) @@ -66,22 +73,24 @@ class FreeTrialExperimentDataStoreImpl @Inject constructor( } } - override suspend fun getMetricForPixelDefinition(definition: PixelDefinition): Int { + override suspend fun getMetricForPixelDefinition(definition: PixelDefinition): String? { val tag = "$definition" return withContext(dispatcherProvider.io()) { - preferences.getInt(tag, 0) + preferences.getString(tag, null) } } - override suspend fun increaseMetricForPixelDefinition(definition: PixelDefinition): Int = + override suspend fun increaseMetricForPixelDefinition( + definition: PixelDefinition, + value: String, + ): String? = withContext(dispatcherProvider.io()) { val tag = "$definition" - val count = preferences.getInt(tag, 0) preferences.edit { - putInt(tag, count + 1) + putString(tag, value) apply() } - preferences.getInt(tag, 0) + preferences.getString(tag, null) } companion object { diff --git a/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/freetrial/FreeTrialPrivacyProMetricsPixelPlugin.kt b/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/freetrial/FreeTrialPrivacyProMetricsPixelPlugin.kt index 5c588c64999b..43e752ec1888 100644 --- a/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/freetrial/FreeTrialPrivacyProMetricsPixelPlugin.kt +++ b/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/freetrial/FreeTrialPrivacyProMetricsPixelPlugin.kt @@ -111,10 +111,8 @@ class FreeTrialPrivacyProPixelsPlugin @Inject constructor( metricsPixel?.let { metric -> metric.getPixelDefinitions().forEach { definition -> if (definition.isInConversionWindow()) { - freeTrialExperimentDataStore.getMetricForPixelDefinition(definition).takeIf { - it < freeTrialExperimentDataStore.paywallImpressions - }?.let { - freeTrialExperimentDataStore.increaseMetricForPixelDefinition(definition) + freeTrialExperimentDataStore.getMetricForPixelDefinition(definition).takeIf { it != metric.value }?.let { + freeTrialExperimentDataStore.increaseMetricForPixelDefinition(definition, metric.value) pixel.fire(definition.pixelName, definition.params) } } diff --git a/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/messaging/SubscriptionMessagingInterface.kt b/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/messaging/SubscriptionMessagingInterface.kt index 0d8a8b6b4291..4c67a60844af 100644 --- a/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/messaging/SubscriptionMessagingInterface.kt +++ b/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/messaging/SubscriptionMessagingInterface.kt @@ -230,8 +230,14 @@ class SubscriptionMessagingInterface @Inject constructor( ) { appCoroutineScope.launch { when (jsMessage.method) { - "subscriptionsMonthlyPriceClicked" -> pixelSender.reportMonthlyPriceClick() - "subscriptionsYearlyPriceClicked" -> pixelSender.reportYearlyPriceClick() + "subscriptionsMonthlyPriceClicked" -> { + pixelSender.reportMonthlyPriceClick() + pixelSender.reportFreeTrialOnStartClickedMonthly() + } + "subscriptionsYearlyPriceClicked" -> { + pixelSender.reportYearlyPriceClick() + pixelSender.reportFreeTrialOnStartClickedYearly() + } "subscriptionsAddEmailSuccess" -> { pixelSender.reportAddEmailSuccess() subscriptionsManager.tryRefreshAccessToken() diff --git a/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/pixels/SubscriptionPixelSender.kt b/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/pixels/SubscriptionPixelSender.kt index 28f4fc0efd0a..ba2b9d6f4a6c 100644 --- a/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/pixels/SubscriptionPixelSender.kt +++ b/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/pixels/SubscriptionPixelSender.kt @@ -20,6 +20,12 @@ import com.duckduckgo.app.statistics.pixels.Pixel import com.duckduckgo.appbuildconfig.api.AppBuildConfig import com.duckduckgo.common.utils.extensions.toSanitizedLanguageTag import com.duckduckgo.di.scopes.AppScope +import com.duckduckgo.subscriptions.impl.freetrial.FreeTrialPrivacyProPixelsPlugin +import com.duckduckgo.subscriptions.impl.freetrial.onPaywallImpression +import com.duckduckgo.subscriptions.impl.freetrial.onStartClickedMonthly +import com.duckduckgo.subscriptions.impl.freetrial.onStartClickedYearly +import com.duckduckgo.subscriptions.impl.freetrial.onSubscriptionStartedMonthly +import com.duckduckgo.subscriptions.impl.freetrial.onSubscriptionStartedYearly import com.duckduckgo.subscriptions.impl.pixels.SubscriptionPixel.ACTIVATE_SUBSCRIPTION_ENTER_EMAIL_CLICK import com.duckduckgo.subscriptions.impl.pixels.SubscriptionPixel.ACTIVATE_SUBSCRIPTION_RESTORE_PURCHASE_CLICK import com.duckduckgo.subscriptions.impl.pixels.SubscriptionPixel.APP_SETTINGS_IDTR_CLICK @@ -106,12 +112,18 @@ interface SubscriptionPixelSender { fun reportAuthV2MigrationFailureOther() fun reportAuthV2TokenValidationError() fun reportAuthV2TokenStoreError() + suspend fun reportFreeTrialExperimentOnPaywallImpression() + suspend fun reportFreeTrialOnStartClickedMonthly() + suspend fun reportFreeTrialOnStartClickedYearly() + suspend fun reportFreeTrialOnSubscriptionStartedMonthly() + suspend fun reportFreeTrialOnSubscriptionStartedYearly() } @ContributesBinding(AppScope::class) class SubscriptionPixelSenderImpl @Inject constructor( private val pixelSender: Pixel, private val appBuildConfig: AppBuildConfig, + private val freeTrialPrivacyProPixelsPlugin: FreeTrialPrivacyProPixelsPlugin, ) : SubscriptionPixelSender { override fun reportSubscriptionActive() = @@ -252,6 +264,26 @@ class SubscriptionPixelSenderImpl @Inject constructor( fire(AUTH_V2_TOKEN_STORE_ERROR) } + override suspend fun reportFreeTrialExperimentOnPaywallImpression() { + freeTrialPrivacyProPixelsPlugin.onPaywallImpression() + } + + override suspend fun reportFreeTrialOnStartClickedMonthly() { + freeTrialPrivacyProPixelsPlugin.onStartClickedMonthly() + } + + override suspend fun reportFreeTrialOnStartClickedYearly() { + freeTrialPrivacyProPixelsPlugin.onStartClickedYearly() + } + + override suspend fun reportFreeTrialOnSubscriptionStartedMonthly() { + freeTrialPrivacyProPixelsPlugin.onSubscriptionStartedMonthly() + } + + override suspend fun reportFreeTrialOnSubscriptionStartedYearly() { + freeTrialPrivacyProPixelsPlugin.onSubscriptionStartedYearly() + } + private fun fire(pixel: SubscriptionPixel, params: Map = emptyMap()) { pixel.getPixelNames().forEach { (pixelType, pixelName) -> pixelSender.fire(pixelName = pixelName, type = pixelType, parameters = params) diff --git a/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/ui/SubscriptionWebViewViewModel.kt b/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/ui/SubscriptionWebViewViewModel.kt index 33be6f9f0c5d..a4a249f597f0 100644 --- a/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/ui/SubscriptionWebViewViewModel.kt +++ b/subscriptions/subscriptions-impl/src/main/java/com/duckduckgo/subscriptions/impl/ui/SubscriptionWebViewViewModel.kt @@ -51,10 +51,6 @@ import com.duckduckgo.subscriptions.impl.SubscriptionsConstants.YEARLY_PLAN_ROW import com.duckduckgo.subscriptions.impl.SubscriptionsConstants.YEARLY_PLAN_US import com.duckduckgo.subscriptions.impl.SubscriptionsManager import com.duckduckgo.subscriptions.impl.freetrial.FreeTrialExperimentDataStore -import com.duckduckgo.subscriptions.impl.freetrial.FreeTrialPrivacyProPixelsPlugin -import com.duckduckgo.subscriptions.impl.freetrial.onPaywallImpression -import com.duckduckgo.subscriptions.impl.freetrial.onStartClickedMonthly -import com.duckduckgo.subscriptions.impl.freetrial.onStartClickedYearly import com.duckduckgo.subscriptions.impl.pixels.SubscriptionPixelSender import com.duckduckgo.subscriptions.impl.repository.isActive import com.duckduckgo.subscriptions.impl.repository.isExpired @@ -88,7 +84,6 @@ class SubscriptionWebViewViewModel @Inject constructor( private val networkProtectionAccessState: NetworkProtectionAccessState, private val pixelSender: SubscriptionPixelSender, private val privacyProFeature: PrivacyProFeature, - private val freeTrialPrivacyProPixelsPlugin: FreeTrialPrivacyProPixelsPlugin, private val freeTrialExperimentDataStore: FreeTrialExperimentDataStore, ) : ViewModel() { @@ -235,13 +230,6 @@ class SubscriptionWebViewViewModel @Inject constructor( } else { command.send(SubscriptionSelected(id, offerId)) } - - // Free Trial experiment metrics - if (id?.contains("monthly-renews-us") == true) { - freeTrialPrivacyProPixelsPlugin.onStartClickedMonthly() - } else if (id?.contains("yearly-renews-us") == true) { - freeTrialPrivacyProPixelsPlugin.onStartClickedYearly() - } } } @@ -371,7 +359,7 @@ class SubscriptionWebViewViewModel @Inject constructor( pixelSender.reportOfferScreenShown() viewModelScope.launch { freeTrialExperimentDataStore.increaseMetricForPaywallImpressions() - freeTrialPrivacyProPixelsPlugin.onPaywallImpression() + pixelSender.reportFreeTrialExperimentOnPaywallImpression() } } diff --git a/subscriptions/subscriptions-impl/src/test/java/com/duckduckgo/subscriptions/impl/RealSubscriptionsManagerTest.kt b/subscriptions/subscriptions-impl/src/test/java/com/duckduckgo/subscriptions/impl/RealSubscriptionsManagerTest.kt index 27ebb48d2d6c..80d720ebdf35 100644 --- a/subscriptions/subscriptions-impl/src/test/java/com/duckduckgo/subscriptions/impl/RealSubscriptionsManagerTest.kt +++ b/subscriptions/subscriptions-impl/src/test/java/com/duckduckgo/subscriptions/impl/RealSubscriptionsManagerTest.kt @@ -38,7 +38,6 @@ import com.duckduckgo.subscriptions.impl.auth2.RefreshTokenClaims import com.duckduckgo.subscriptions.impl.auth2.TokenPair import com.duckduckgo.subscriptions.impl.billing.PlayBillingManager import com.duckduckgo.subscriptions.impl.billing.PurchaseState -import com.duckduckgo.subscriptions.impl.freetrial.FreeTrialPrivacyProPixelsPlugin import com.duckduckgo.subscriptions.impl.model.Entitlement import com.duckduckgo.subscriptions.impl.pixels.SubscriptionPixelSender import com.duckduckgo.subscriptions.impl.repository.AuthRepository @@ -117,7 +116,6 @@ class RealSubscriptionsManagerTest(private val authApiV2Enabled: Boolean) { private val authJwtValidator: AuthJwtValidator = mock() private val timeProvider = FakeTimeProvider() private val backgroundTokenRefresh: BackgroundTokenRefresh = mock() - private val freeTrialPrivacyProPixelsPlugin: FreeTrialPrivacyProPixelsPlugin = mock() private lateinit var subscriptionsManager: RealSubscriptionsManager @Before @@ -140,7 +138,6 @@ class RealSubscriptionsManagerTest(private val authApiV2Enabled: Boolean) { pkceGenerator, timeProvider, backgroundTokenRefresh, - { freeTrialPrivacyProPixelsPlugin }, ) } @@ -561,7 +558,6 @@ class RealSubscriptionsManagerTest(private val authApiV2Enabled: Boolean) { pkceGenerator, timeProvider, backgroundTokenRefresh, - { freeTrialPrivacyProPixelsPlugin }, ) manager.subscriptionStatus.test { @@ -590,7 +586,6 @@ class RealSubscriptionsManagerTest(private val authApiV2Enabled: Boolean) { pkceGenerator, timeProvider, backgroundTokenRefresh, - { freeTrialPrivacyProPixelsPlugin }, ) manager.subscriptionStatus.test { @@ -624,7 +619,6 @@ class RealSubscriptionsManagerTest(private val authApiV2Enabled: Boolean) { pkceGenerator, timeProvider, backgroundTokenRefresh, - { freeTrialPrivacyProPixelsPlugin }, ) manager.currentPurchaseState.test { @@ -672,7 +666,6 @@ class RealSubscriptionsManagerTest(private val authApiV2Enabled: Boolean) { pkceGenerator, timeProvider, backgroundTokenRefresh, - { freeTrialPrivacyProPixelsPlugin }, ) manager.currentPurchaseState.test { @@ -710,7 +703,6 @@ class RealSubscriptionsManagerTest(private val authApiV2Enabled: Boolean) { pkceGenerator, timeProvider, backgroundTokenRefresh, - { freeTrialPrivacyProPixelsPlugin }, ) manager.currentPurchaseState.test { @@ -1010,7 +1002,6 @@ class RealSubscriptionsManagerTest(private val authApiV2Enabled: Boolean) { pkceGenerator, timeProvider, backgroundTokenRefresh, - { freeTrialPrivacyProPixelsPlugin }, ) manager.signOut() verify(mockRepo).setSubscription(null) @@ -1056,7 +1047,6 @@ class RealSubscriptionsManagerTest(private val authApiV2Enabled: Boolean) { pkceGenerator, timeProvider, backgroundTokenRefresh, - { freeTrialPrivacyProPixelsPlugin }, ) manager.subscriptionStatus.test { @@ -1238,7 +1228,6 @@ class RealSubscriptionsManagerTest(private val authApiV2Enabled: Boolean) { pkceGenerator, timeProvider, backgroundTokenRefresh, - { freeTrialPrivacyProPixelsPlugin }, ) assertFalse(subscriptionsManager.canSupportEncryption()) diff --git a/subscriptions/subscriptions-impl/src/test/java/com/duckduckgo/subscriptions/impl/messaging/SubscriptionMessagingInterfaceTest.kt b/subscriptions/subscriptions-impl/src/test/java/com/duckduckgo/subscriptions/impl/messaging/SubscriptionMessagingInterfaceTest.kt index fe8b14cd156d..098c80656436 100644 --- a/subscriptions/subscriptions-impl/src/test/java/com/duckduckgo/subscriptions/impl/messaging/SubscriptionMessagingInterfaceTest.kt +++ b/subscriptions/subscriptions-impl/src/test/java/com/duckduckgo/subscriptions/impl/messaging/SubscriptionMessagingInterfaceTest.kt @@ -15,7 +15,9 @@ import com.duckduckgo.subscriptions.impl.pixels.SubscriptionPixelSender import com.duckduckgo.subscriptions.impl.repository.Subscription import kotlinx.coroutines.test.runTest import org.json.JSONObject -import org.junit.Assert.* +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Assert.assertTrue import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @@ -567,7 +569,7 @@ class SubscriptionMessagingInterfaceTest { messagingInterface.process(message, "duckduckgo-android-messaging-secret") verify(pixelSender).reportMonthlyPriceClick() - verifyNoMoreInteractions(pixelSender) + // verifyNoMoreInteractions(pixelSender) Add it back when Free Trials experiment is removed } @Test @@ -581,7 +583,33 @@ class SubscriptionMessagingInterfaceTest { messagingInterface.process(message, "duckduckgo-android-messaging-secret") verify(pixelSender).reportYearlyPriceClick() - verifyNoMoreInteractions(pixelSender) + // verifyNoMoreInteractions(pixelSender) Add it back when Free Trials experiment is removed + } + + @Test + fun `when process and monthly price clicked then experiment pixel sent`() = runTest { + givenInterfaceIsRegistered() + + val message = """ + {"context":"subscriptionPages","featureName":"useSubscription","method":"subscriptionsMonthlyPriceClicked","id":"myId","params":{}} + """.trimIndent() + + messagingInterface.process(message, "duckduckgo-android-messaging-secret") + + verify(pixelSender).reportFreeTrialOnStartClickedMonthly() + } + + @Test + fun `when process and yearly price clicked then experiment pixel sent`() = runTest { + givenInterfaceIsRegistered() + + val message = """ + {"context":"subscriptionPages","featureName":"useSubscription","method":"subscriptionsYearlyPriceClicked","id":"myId","params":{}} + """.trimIndent() + + messagingInterface.process(message, "duckduckgo-android-messaging-secret") + + verify(pixelSender).reportFreeTrialOnStartClickedYearly() } @Test diff --git a/subscriptions/subscriptions-impl/src/test/java/com/duckduckgo/subscriptions/impl/ui/SubscriptionWebViewViewModelTest.kt b/subscriptions/subscriptions-impl/src/test/java/com/duckduckgo/subscriptions/impl/ui/SubscriptionWebViewViewModelTest.kt index 7b849d7a92c6..6e88a3de5e37 100644 --- a/subscriptions/subscriptions-impl/src/test/java/com/duckduckgo/subscriptions/impl/ui/SubscriptionWebViewViewModelTest.kt +++ b/subscriptions/subscriptions-impl/src/test/java/com/duckduckgo/subscriptions/impl/ui/SubscriptionWebViewViewModelTest.kt @@ -24,7 +24,6 @@ import com.duckduckgo.subscriptions.impl.SubscriptionsConstants.MONTHLY_PLAN_US import com.duckduckgo.subscriptions.impl.SubscriptionsConstants.YEARLY_PLAN_US import com.duckduckgo.subscriptions.impl.SubscriptionsManager import com.duckduckgo.subscriptions.impl.freetrial.FreeTrialExperimentDataStore -import com.duckduckgo.subscriptions.impl.freetrial.FreeTrialPrivacyProPixelsPlugin import com.duckduckgo.subscriptions.impl.pixels.SubscriptionPixelSender import com.duckduckgo.subscriptions.impl.ui.SubscriptionWebViewViewModel.Command import com.duckduckgo.subscriptions.impl.ui.SubscriptionWebViewViewModel.Command.BackToSettings @@ -40,7 +39,9 @@ import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.runTest import org.json.JSONObject -import org.junit.Assert.* +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotNull +import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Rule import org.junit.Test @@ -62,7 +63,6 @@ class SubscriptionWebViewViewModelTest { private val subscriptionsChecker: SubscriptionsChecker = mock() private val pixelSender: SubscriptionPixelSender = mock() private val privacyProFeature = FakeFeatureToggleFactory.create(PrivacyProFeature::class.java, FakeToggleStore()) - private val freeTrialPrivacyProPixelsPlugin: FreeTrialPrivacyProPixelsPlugin = mock() private val freeTrialExperimentDataStore: FreeTrialExperimentDataStore = mock() private lateinit var viewModel: SubscriptionWebViewViewModel @@ -77,7 +77,6 @@ class SubscriptionWebViewViewModelTest { networkProtectionAccessState, pixelSender, privacyProFeature, - freeTrialPrivacyProPixelsPlugin, freeTrialExperimentDataStore, ) givenSubscriptionStatus(UNKNOWN)