From 172a118a51788bdaa25ef56574ec274104739bbc Mon Sep 17 00:00:00 2001 From: Gabriel Luong Date: Mon, 31 May 2021 17:35:47 -0400 Subject: [PATCH] For #18711 - Refactor credit card telemetry under the Metrics ping (#19733) --- app/metrics.yaml | 101 +++++++++--------- .../org/mozilla/fenix/FenixApplication.kt | 12 +++ .../mozilla/fenix/components/metrics/Event.kt | 5 - .../components/metrics/GleanMetricsService.kt | 12 --- .../components/metrics/MetricController.kt | 6 +- .../creditcards/CreditCardEditorFragment.kt | 5 +- .../controller/CreditCardEditorController.kt | 15 ++- .../java/org/mozilla/fenix/utils/Settings.kt | 32 +++++- app/src/main/res/values/preference_keys.xml | 6 ++ .../org/mozilla/fenix/FenixApplicationTest.kt | 6 ++ .../metrics/MetricControllerTest.kt | 30 ++++++ .../DefaultCreditCardEditorControllerTest.kt | 29 +++-- .../org/mozilla/fenix/utils/SettingsTest.kt | 19 ++++ 13 files changed, 180 insertions(+), 98 deletions(-) diff --git a/app/metrics.yaml b/app/metrics.yaml index b58088a2f..7776dfdde 100644 --- a/app/metrics.yaml +++ b/app/metrics.yaml @@ -1007,6 +1007,57 @@ metrics: notification_emails: - fenix-core@mozilla.com expires: "2021-08-01" + credit_cards_saved_count: + type: counter + lifetime: application + description: | + A counter that indicates the number of credit cards that have been + saved manually by the user. + send_in_pings: + - metrics + bugs: + - https://github.com/mozilla-mobile/fenix/issues/18711 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/19548#issuecomment-848811030 + data_sensitivity: + - interaction + notification_emails: + - fenix-core@mozilla.com + expires: "2021-10-01" + credit_cards_deleted_count: + type: counter + lifetime: application + description: | + A counter that indicates the number of credit cards that have been + deleted by the user. + send_in_pings: + - metrics + bugs: + - https://github.com/mozilla-mobile/fenix/issues/18711 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/19548#issuecomment-848811030 + data_sensitivity: + - interaction + notification_emails: + - fenix-core@mozilla.com + expires: "2021-10-01" + credit_cards_autofill_count: + type: counter + lifetime: application + description: | + A counter that indicates the number of times the user has autofilled + a credit card. + send_in_pings: + - metrics + bugs: + - https://github.com/mozilla-mobile/fenix/issues/18711 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/19548#issuecomment-848811030 + data_sensitivity: + - interaction + notification_emails: + - fenix-core@mozilla.com + expires: "2021-10-01" mozilla_products: type: string_list lifetime: application @@ -5394,53 +5445,3 @@ set_default_setting_experiment: notification_emails: - fenix-core@mozilla.com expires: "2021-10-01" - -credit_cards: - manual_save: - type: counter - description: | - A counter of the number of credit cards that have been saved - manually by the user. - send_in_pings: - - metrics - bugs: - - https://github.com/mozilla-mobile/fenix/issues/18711 - data_reviews: - - https://github.com/mozilla-mobile/fenix/pull/19548#issuecomment-848811030 - data_sensitivity: - - interaction - notification_emails: - - fenix-core@mozilla.com - expires: "2021-10-01" - delete_card: - type: counter - description: | - A counter of the number of credit cards that have been deleted by - the user. - send_in_pings: - - metrics - bugs: - - https://github.com/mozilla-mobile/fenix/issues/18711 - data_reviews: - - https://github.com/mozilla-mobile/fenix/pull/19548#issuecomment-848811030 - data_sensitivity: - - interaction - notification_emails: - - fenix-core@mozilla.com - expires: "2021-10-01" - autofill_card: - type: counter - description: | - A counter of the number of times the user has autofilled - a credit card. - send_in_pings: - - metrics - bugs: - - https://github.com/mozilla-mobile/fenix/issues/18711 - data_reviews: - - https://github.com/mozilla-mobile/fenix/pull/19548#issuecomment-848811030 - data_sensitivity: - - interaction - notification_emails: - - fenix-core@mozilla.com - expires: "2021-10-01" diff --git a/app/src/main/java/org/mozilla/fenix/FenixApplication.kt b/app/src/main/java/org/mozilla/fenix/FenixApplication.kt index a9d6d775a..4cb11de43 100644 --- a/app/src/main/java/org/mozilla/fenix/FenixApplication.kt +++ b/app/src/main/java/org/mozilla/fenix/FenixApplication.kt @@ -565,6 +565,18 @@ open class FenixApplication : LocaleAwareApplication(), Provider { topSitesCount.add(topSitesSize) } + if (settings.creditCardsSavedCount > 0) { + creditCardsSavedCount.add(settings.creditCardsSavedCount) + } + + if (settings.creditCardsDeletedCount > 0) { + creditCardsDeletedCount.add(settings.creditCardsDeletedCount) + } + + if (settings.creditCardsAutofilledCount > 0) { + creditCardsAutofillCount.add(settings.creditCardsAutofilledCount) + } + val installedAddonSize = settings.installedAddonsCount Addons.hasInstalledAddons.set(installedAddonSize > 0) if (installedAddonSize > 0) { diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/Event.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/Event.kt index 69be9083c..aff2f88d8 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/Event.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/Event.kt @@ -236,11 +236,6 @@ sealed class Event { object HomeMenuSettingsItemClicked : Event() object HomeScreenDisplayed : Event() - // Credit cards - object CreditCardManualSave : Event() - object CreditCardDelete : Event() - object CreditCardAutofill : Event() - // Interaction events with extras data class TopSiteSwipeCarousel(val page: Int) : Event() { diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt index 0da296449..74f49ccfa 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt @@ -22,7 +22,6 @@ import org.mozilla.fenix.GleanMetrics.ContextMenu import org.mozilla.fenix.GleanMetrics.ContextualHintTrackingProtection import org.mozilla.fenix.GleanMetrics.ContextualMenu import org.mozilla.fenix.GleanMetrics.CrashReporter -import org.mozilla.fenix.GleanMetrics.CreditCards import org.mozilla.fenix.GleanMetrics.CustomTab import org.mozilla.fenix.GleanMetrics.DownloadNotification import org.mozilla.fenix.GleanMetrics.DownloadsMisc @@ -834,17 +833,6 @@ private val Event.wrapper: EventWrapper<*>? { HomeScreen.homeScreenDisplayed.record(it) } ) - // Credit cards - is Event.CreditCardManualSave -> EventWrapper( - { CreditCards.manualSave.add(1) } - ) - is Event.CreditCardDelete -> EventWrapper( - { CreditCards.deleteCard.add(1) } - ) - is Event.CreditCardAutofill -> EventWrapper( - { CreditCards.autofillCard.add(1) } - ) - // Don't record other events in Glean: is Event.AddBookmark -> null is Event.OpenedAppFirstRun -> null diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt index 924040b52..c38ebb62d 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt @@ -162,8 +162,10 @@ internal class ReleaseMetricController( Component.FEATURE_PROMPTS to LoginDialogFacts.Items.CANCEL -> Event.LoginDialogPromptCancelled Component.FEATURE_PROMPTS to LoginDialogFacts.Items.NEVER_SAVE -> Event.LoginDialogPromptNeverSave Component.FEATURE_PROMPTS to LoginDialogFacts.Items.SAVE -> Event.LoginDialogPromptSave - Component.FEATURE_PROMPTS to CreditCardAutofillDialogFacts.Items.AUTOFILL_CREDIT_CARD_SUCCESS -> - Event.CreditCardAutofill + Component.FEATURE_PROMPTS to CreditCardAutofillDialogFacts.Items.AUTOFILL_CREDIT_CARD_SUCCESS -> { + settings.creditCardsAutofilledCount += 1 + null + } Component.FEATURE_FINDINPAGE to FindInPageFacts.Items.CLOSE -> Event.FindInPageClosed Component.FEATURE_FINDINPAGE to FindInPageFacts.Items.INPUT -> Event.FindInPageSearchCommitted diff --git a/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorFragment.kt index c1f972638..c47f874a2 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorFragment.kt @@ -16,6 +16,7 @@ import org.mozilla.fenix.R import org.mozilla.fenix.SecureFragment import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.redirectToReAuth +import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.showToolbar import org.mozilla.fenix.settings.creditcards.controller.DefaultCreditCardEditorController import org.mozilla.fenix.settings.creditcards.interactor.CreditCardEditorInteractor @@ -55,10 +56,10 @@ class CreditCardEditorFragment : SecureFragment(R.layout.fragment_credit_card_ed val storage = requireContext().components.core.autofillStorage interactor = DefaultCreditCardEditorInteractor( controller = DefaultCreditCardEditorController( - context = requireContext(), storage = storage, lifecycleScope = lifecycleScope, - navController = findNavController() + navController = findNavController(), + settings = requireContext().settings() ) ) diff --git a/app/src/main/java/org/mozilla/fenix/settings/creditcards/controller/CreditCardEditorController.kt b/app/src/main/java/org/mozilla/fenix/settings/creditcards/controller/CreditCardEditorController.kt index 7296f952c..71e8175ec 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/creditcards/controller/CreditCardEditorController.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/creditcards/controller/CreditCardEditorController.kt @@ -4,7 +4,6 @@ package org.mozilla.fenix.settings.creditcards.controller -import android.content.Context import androidx.navigation.NavController import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope @@ -13,10 +12,9 @@ import kotlinx.coroutines.launch import mozilla.components.concept.storage.NewCreditCardFields import mozilla.components.concept.storage.UpdatableCreditCardFields import mozilla.components.service.sync.autofill.AutofillCreditCardsAddressesStorage -import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.settings.creditcards.CreditCardEditorFragment import org.mozilla.fenix.settings.creditcards.interactor.CreditCardEditorInteractor -import org.mozilla.fenix.ext.components +import org.mozilla.fenix.utils.Settings /** * [CreditCardEditorFragment] controller. An interface that handles the view manipulation of the @@ -52,26 +50,26 @@ interface CreditCardEditorController { * credit cards. * @param lifecycleScope [CoroutineScope] scope to launch coroutines. * @param navController [NavController] used for navigation. + * @param settings [Settings] application settings. * @param ioDispatcher [CoroutineDispatcher] used for executing async tasks. Defaults to [Dispatchers.IO]. */ class DefaultCreditCardEditorController( - context: Context, private val storage: AutofillCreditCardsAddressesStorage, private val lifecycleScope: CoroutineScope, private val navController: NavController, + private val settings: Settings, private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO ) : CreditCardEditorController { - private val metrics = context.components.analytics.metrics - override fun handleCancelButtonClicked() { navController.popBackStack() } override fun handleDeleteCreditCard(guid: String) { + settings.creditCardsDeletedCount += 1 + lifecycleScope.launch(ioDispatcher) { storage.deleteCreditCard(guid) - metrics.track(Event.CreditCardDelete) lifecycleScope.launch(Dispatchers.Main) { navController.popBackStack() @@ -80,9 +78,10 @@ class DefaultCreditCardEditorController( } override fun handleSaveCreditCard(creditCardFields: NewCreditCardFields) { + settings.creditCardsSavedCount += 1 + lifecycleScope.launch(ioDispatcher) { storage.addCreditCard(creditCardFields) - metrics.track(Event.CreditCardManualSave) lifecycleScope.launch(Dispatchers.Main) { navController.popBackStack() diff --git a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt index d838c9ebd..25dbe9310 100644 --- a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt +++ b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt @@ -971,7 +971,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { ) /** - * Storing number of installed add-ons for telemetry purposes + * Stores the number of installed add-ons for telemetry purposes */ var installedAddonsCount by intPreference( appContext.getPreferenceKey(R.string.pref_key_installed_addons_count), @@ -979,7 +979,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { ) /** - * Storing the list of installed add-ons for telemetry purposes + * Stores the list of installed add-ons for telemetry purposes */ var installedAddonsList by stringPreference( appContext.getPreferenceKey(R.string.pref_key_installed_addons_list), @@ -987,7 +987,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { ) /** - * Storing number of enabled add-ons for telemetry purposes + * Stores the number of enabled add-ons for telemetry purposes */ var enabledAddonsCount by intPreference( appContext.getPreferenceKey(R.string.pref_key_enabled_addons_count), @@ -995,13 +995,37 @@ class Settings(private val appContext: Context) : PreferencesHolder { ) /** - * Storing the list of enabled add-ons for telemetry purposes + * Stores the list of enabled add-ons for telemetry purposes */ var enabledAddonsList by stringPreference( appContext.getPreferenceKey(R.string.pref_key_enabled_addons_list), default = "" ) + /** + * Stores the number of credit cards that have been saved manually by the user. + */ + var creditCardsSavedCount by intPreference( + appContext.getPreferenceKey(R.string.pref_key_credit_cards_saved_count), + 0 + ) + + /** + * Stores the number of credit cards that have been deleted by the user. + */ + var creditCardsDeletedCount by intPreference( + appContext.getPreferenceKey(R.string.pref_key_credit_cards_deleted_count), + 0 + ) + + /** + * Stores the number of times that user has autofilled a credit card. + */ + var creditCardsAutofilledCount by intPreference( + appContext.getPreferenceKey(R.string.pref_key_credit_cards_autofilled_count), + 0 + ) + private var savedLoginsSortingStrategyString by stringPreference( appContext.getPreferenceKey(R.string.pref_key_saved_logins_sorting_strategy), default = SavedLoginsSortingStrategyMenu.Item.AlphabeticallySort.strategyString diff --git a/app/src/main/res/values/preference_keys.xml b/app/src/main/res/values/preference_keys.xml index 0ec70291b..ada9737dd 100644 --- a/app/src/main/res/values/preference_keys.xml +++ b/app/src/main/res/values/preference_keys.xml @@ -182,6 +182,12 @@ pref_key_credit_cards_sync_cards_across_devices pref_key_credit_cards_manage_cards + + pref_key_credit_cards_saved_count + + pref_key_credit_cards_deleted_count + + pref_key_credit_cards_autofilled_count pref_key_open_links_in_a_private_tab diff --git a/app/src/test/java/org/mozilla/fenix/FenixApplicationTest.kt b/app/src/test/java/org/mozilla/fenix/FenixApplicationTest.kt index 55f16ae2e..08a2395f0 100644 --- a/app/src/test/java/org/mozilla/fenix/FenixApplicationTest.kt +++ b/app/src/test/java/org/mozilla/fenix/FenixApplicationTest.kt @@ -128,6 +128,9 @@ class FenixApplicationTest { every { settings.touchExplorationIsEnabled } returns true every { settings.shouldUseLightTheme } returns true every { settings.signedInFxaAccount } returns true + every { settings.creditCardsSavedCount } returns 1 + every { settings.creditCardsDeletedCount } returns 2 + every { settings.creditCardsAutofilledCount } returns 3 application.setStartupMetrics(browserStore, settings, browsersCache, mozillaProductDetector) @@ -146,6 +149,9 @@ class FenixApplicationTest { assertEquals(true, Metrics.hasTopSites.testGetValue()) assertEquals(2, Metrics.topSitesCount.testGetValue()) assertEquals(true, Addons.hasInstalledAddons.testGetValue()) + assertEquals(1, Metrics.creditCardsSavedCount.testGetValue()) + assertEquals(2, Metrics.creditCardsDeletedCount.testGetValue()) + assertEquals(3, Metrics.creditCardsAutofillCount.testGetValue()) assertEquals(listOf("test1", "test2", "test3"), Addons.installedAddons.testGetValue()) assertEquals(true, Addons.hasEnabledAddons.testGetValue()) assertEquals(listOf("test1", "test2"), Addons.enabledAddons.testGetValue()) diff --git a/app/src/test/java/org/mozilla/fenix/components/metrics/MetricControllerTest.kt b/app/src/test/java/org/mozilla/fenix/components/metrics/MetricControllerTest.kt index 25bf2274e..026efeed8 100644 --- a/app/src/test/java/org/mozilla/fenix/components/metrics/MetricControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/components/metrics/MetricControllerTest.kt @@ -10,6 +10,7 @@ import io.mockk.impl.annotations.MockK import io.mockk.mockk import io.mockk.verify import io.mockk.verifyAll +import mozilla.components.feature.prompts.facts.CreditCardAutofillDialogFacts import mozilla.components.feature.top.sites.facts.TopSitesFacts import mozilla.components.support.base.Component import mozilla.components.support.base.facts.Action @@ -364,10 +365,39 @@ class MetricControllerTest { assertEquals(settings.installedAddonsList, "") assertEquals(settings.enabledAddonsCount, 0) assertEquals(settings.enabledAddonsList, "") + controller.factToEvent(fact) + assertEquals(settings.installedAddonsCount, 4) assertEquals(settings.installedAddonsList, "test1,test2,test3,test4") assertEquals(settings.enabledAddonsCount, 2) assertEquals(settings.enabledAddonsList, "test2,test4") } + + @Test + fun `credit card autofill fact shold set value in SharedPreference`() { + val enabled = true + val settings = Settings(testContext) + val controller = ReleaseMetricController( + services = listOf(dataService1), + isDataTelemetryEnabled = { enabled }, + isMarketingDataTelemetryEnabled = { enabled }, + settings + ) + val fact = Fact( + component = Component.FEATURE_PROMPTS, + action = Action.INTERACTION, + item = CreditCardAutofillDialogFacts.Items.AUTOFILL_CREDIT_CARD_SUCCESS + ) + + assertEquals(0, settings.creditCardsAutofilledCount) + + controller.factToEvent(fact) + + assertEquals(1, settings.creditCardsAutofilledCount) + + controller.factToEvent(fact) + + assertEquals(2, settings.creditCardsAutofilledCount) + } } diff --git a/app/src/test/java/org/mozilla/fenix/settings/creditcards/DefaultCreditCardEditorControllerTest.kt b/app/src/test/java/org/mozilla/fenix/settings/creditcards/DefaultCreditCardEditorControllerTest.kt index 2b76ab8b7..664e6a818 100644 --- a/app/src/test/java/org/mozilla/fenix/settings/creditcards/DefaultCreditCardEditorControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/settings/creditcards/DefaultCreditCardEditorControllerTest.kt @@ -4,10 +4,8 @@ package org.mozilla.fenix.settings.creditcards -import android.content.Context import androidx.navigation.NavController import io.mockk.coVerify -import io.mockk.every import io.mockk.mockk import io.mockk.spyk import io.mockk.verify @@ -19,18 +17,18 @@ import mozilla.components.concept.storage.CreditCardNumber import mozilla.components.concept.storage.NewCreditCardFields import mozilla.components.concept.storage.UpdatableCreditCardFields import mozilla.components.service.sync.autofill.AutofillCreditCardsAddressesStorage +import mozilla.components.support.test.robolectric.testContext import mozilla.components.support.test.rule.MainCoroutineRule import mozilla.components.support.utils.CreditCardNetworkType import org.junit.After +import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -import org.mozilla.fenix.components.metrics.Event -import org.mozilla.fenix.components.metrics.MetricController -import org.mozilla.fenix.ext.components import org.mozilla.fenix.helpers.FenixRobolectricTestRunner import org.mozilla.fenix.settings.creditcards.controller.DefaultCreditCardEditorController +import org.mozilla.fenix.utils.Settings @ExperimentalCoroutinesApi @RunWith(FenixRobolectricTestRunner::class) @@ -43,25 +41,20 @@ class DefaultCreditCardEditorControllerTest { private val testDispatcher = TestCoroutineDispatcher() private lateinit var controller: DefaultCreditCardEditorController - private lateinit var context: Context - private lateinit var metrics: MetricController + private lateinit var settings: Settings @get:Rule val coroutinesTestRule = MainCoroutineRule(testDispatcher) @Before fun setup() { - metrics = mockk() - context = mockk() - every { metrics.track(any()) } returns Unit - every { context.components.analytics.metrics } returns metrics - + settings = Settings(testContext) controller = spyk( DefaultCreditCardEditorController( - context = context, storage = storage, lifecycleScope = testCoroutineScope, navController = navController, + settings = settings, ioDispatcher = testDispatcher ) ) @@ -84,19 +77,24 @@ class DefaultCreditCardEditorControllerTest { @Test fun handleDeleteCreditCard() = testCoroutineScope.runBlockingTest { + assertEquals(0, settings.creditCardsDeletedCount) + val creditCardId = "id" controller.handleDeleteCreditCard(creditCardId) + assertEquals(1, settings.creditCardsDeletedCount) + coVerify { storage.deleteCreditCard(creditCardId) navController.popBackStack() - metrics.track(Event.CreditCardDelete) } } @Test fun handleSaveCreditCard() = testCoroutineScope.runBlockingTest { + assertEquals(0, settings.creditCardsSavedCount) + val creditCardFields = NewCreditCardFields( billingName = "Banana Apple", plaintextCardNumber = CreditCardNumber.Plaintext("4111111111111112"), @@ -108,10 +106,11 @@ class DefaultCreditCardEditorControllerTest { controller.handleSaveCreditCard(creditCardFields) + assertEquals(1, settings.creditCardsSavedCount) + coVerify { storage.addCreditCard(creditCardFields) navController.popBackStack() - metrics.track(Event.CreditCardManualSave) } } diff --git a/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt b/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt index 09800fe1c..1fb6803f9 100644 --- a/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt +++ b/app/src/test/java/org/mozilla/fenix/utils/SettingsTest.kt @@ -671,4 +671,23 @@ class SettingsTest { assertEquals("testAmoUser", settings.overrideAmoUser) assertTrue(settings.amoCollectionOverrideConfigured()) } + + @Test + fun creditCardsSavedCount() { + // When just created + // Then + assertEquals(0, settings.creditCardsSavedCount) + + // When + settings.creditCardsSavedCount += 1 + + // Then + assertEquals(1, settings.creditCardsSavedCount) + + // When + settings.creditCardsSavedCount += 1 + + // Then + assertEquals(2, settings.creditCardsSavedCount) + } }