From d9d1e9a12c28ffa89befefc71a473ed79903ef63 Mon Sep 17 00:00:00 2001 From: David Perez Date: Thu, 27 Jun 2024 09:11:58 -0500 Subject: [PATCH] Update CipherViewExtensions to use previous state to avoid clearing user set values (#3368) --- .../vault/feature/item/VaultItemViewModel.kt | 1 + .../feature/item/util/CipherViewExtensions.kt | 19 ++++- .../feature/item/VaultItemViewModelTest.kt | 81 +++++++++++++++++++ .../item/util/CipherViewExtensionsTest.kt | 59 ++++++++++++++ 4 files changed, 156 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModel.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModel.kt index 5952438f2..767ee6d70 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModel.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModel.kt @@ -918,6 +918,7 @@ class VaultItemViewModel @Inject constructor( .data ?.cipher ?.toViewState( + previousState = state.viewState as? VaultItemState.ViewState.Content, isPremiumUser = account.isPremium, hasMasterPassword = account.hasMasterPassword, totpCodeItemData = this.data?.totpCodeItemData, diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/util/CipherViewExtensions.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/util/CipherViewExtensions.kt index e40e7dc0a..dc03e559c 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/util/CipherViewExtensions.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/util/CipherViewExtensions.kt @@ -35,6 +35,7 @@ private const val FIDO2_CREDENTIAL_CREATION_TIME_PATTERN: String = "h:mm a" */ @Suppress("CyclomaticComplexMethod", "LongMethod") fun CipherView.toViewState( + previousState: VaultItemState.ViewState.Content?, isPremiumUser: Boolean, hasMasterPassword: Boolean, totpCodeItemData: TotpCodeItemData?, @@ -44,7 +45,8 @@ fun CipherView.toViewState( common = VaultItemState.ViewState.Content.Common( currentCipher = this, name = name, - requiresReprompt = reprompt == CipherRepromptType.PASSWORD && hasMasterPassword, + requiresReprompt = (reprompt == CipherRepromptType.PASSWORD && hasMasterPassword) && + previousState?.common?.requiresReprompt != false, customFields = fields.orEmpty().map { it.toCustomField() }, lastUpdated = revisionDate.toFormattedPattern( pattern = LAST_UPDATED_DATE_TIME_PATTERN, @@ -87,7 +89,10 @@ fun CipherView.toViewState( passwordData = loginValues.password?.let { VaultItemState.ViewState.Content.ItemType.Login.PasswordData( password = it, - isVisible = false, + isVisible = (previousState?.type as? + VaultItemState.ViewState.Content.ItemType.Login) + ?.passwordData + ?.isVisible == true, canViewPassword = viewPassword, ) }, @@ -118,7 +123,10 @@ fun CipherView.toViewState( number = card?.number?.let { VaultItemState.ViewState.Content.ItemType.Card.NumberData( number = it, - isVisible = false, + isVisible = (previousState?.type + as? VaultItemState.ViewState.Content.ItemType.Card) + ?.number + ?.isVisible == true, ) }, brand = card?.cardBrand, @@ -126,7 +134,10 @@ fun CipherView.toViewState( securityCode = card?.code?.let { VaultItemState.ViewState.Content.ItemType.Card.CodeData( code = it, - isVisible = false, + isVisible = (previousState?.type + as? VaultItemState.ViewState.Content.ItemType.Card) + ?.securityCode + ?.isVisible == true, ) }, ) diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModelTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModelTest.kt index 9f5ed891d..ab0bc433c 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModelTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemViewModelTest.kt @@ -157,6 +157,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -179,6 +180,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { verify(exactly = 1) { mockCipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -197,6 +199,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -239,6 +242,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -270,6 +274,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = createTotpCodeData(), @@ -312,6 +317,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -357,6 +363,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = createTotpCodeData(), @@ -396,6 +403,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = createTotpCodeData(), @@ -435,6 +443,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = createTotpCodeData(), @@ -483,6 +492,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = any(), isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = createTotpCodeData(), @@ -514,6 +524,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = any(), isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -527,6 +538,14 @@ class VaultItemViewModelTest : BaseViewModelTest() { viewModel.eventFlow.test { viewModel.trySendAction(VaultItemAction.Common.EditClick) + verify { + mockCipherView.toViewState( + previousState = loginViewState, + isPremiumUser = true, + hasMasterPassword = true, + totpCodeItemData = null, + ) + } assertEquals( VaultItemEvent.NavigateToAddEdit( itemId = VAULT_ITEM_ID, @@ -547,6 +566,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = any(), isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -609,6 +629,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = any(), isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -661,6 +682,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = any(), isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -724,6 +746,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -746,6 +769,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { verify(exactly = 1) { mockCipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -760,6 +784,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -776,6 +801,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { verify(exactly = 1) { clipboardManager.setText(text = field) mockCipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -814,6 +840,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -844,6 +871,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { verify(exactly = 1) { mockCipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -875,6 +903,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -905,6 +934,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { verify(exactly = 1) { mockCipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -924,6 +954,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -946,6 +977,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { verify(exactly = 1) { mockCipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -964,6 +996,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -997,6 +1030,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -1021,6 +1055,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { verify(exactly = 1) { mockCipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -1043,6 +1078,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -1090,6 +1126,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -1112,6 +1149,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { verify(exactly = 1) { mockCipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -1130,6 +1168,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -1160,6 +1199,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -1182,6 +1222,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { verify(exactly = 1) { mockCipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -1200,6 +1241,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -1241,6 +1283,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = any(), isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -1296,6 +1339,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = any(), isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -1360,6 +1404,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = any(), isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -1537,6 +1582,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = createTotpCodeData(), @@ -1576,6 +1622,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { verify(exactly = 1) { mockCipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = createTotpCodeData(), @@ -1593,6 +1640,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = createTotpCodeData(), @@ -1618,6 +1666,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { verify(exactly = 1) { mockCipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = createTotpCodeData(), @@ -1631,6 +1680,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = createTotpCodeData(), @@ -1648,6 +1698,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { verify(exactly = 1) { clipboardManager.setText(text = DEFAULT_LOGIN_PASSWORD) mockCipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = createTotpCodeData(), @@ -1687,6 +1738,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = createTotpCodeData(), @@ -1702,6 +1754,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { verify(exactly = 1) { clipboardManager.setText(text = DEFAULT_LOGIN_USERNAME) mockCipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = createTotpCodeData(), @@ -1725,6 +1778,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = createTotpCodeData(), @@ -1748,6 +1802,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { verify(exactly = 1) { mockCipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = createTotpCodeData(), @@ -1762,6 +1817,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = createTotpCodeData(), @@ -1787,6 +1843,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { verify(exactly = 1) { mockCipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = createTotpCodeData(), @@ -1802,6 +1859,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = createTotpCodeData(), @@ -1829,6 +1887,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { verify(exactly = 1) { mockCipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = createTotpCodeData(), @@ -1847,6 +1906,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = createTotpCodeData(), @@ -1877,6 +1937,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { verify(exactly = 1) { mockCipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = createTotpCodeData(), @@ -1910,6 +1971,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -1934,6 +1996,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { verify(exactly = 1) { mockCipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -1947,6 +2010,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -1965,6 +2029,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { verify(exactly = 1) { clipboardManager.setText(text = "12345436") mockCipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -1979,6 +2044,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -2003,6 +2069,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { verify(exactly = 1) { mockCipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -2016,6 +2083,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -2040,6 +2108,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { ), ) mockCipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -2054,6 +2123,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -2078,6 +2148,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { verify(exactly = 1) { mockCipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -2091,6 +2162,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -2109,6 +2181,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { verify(exactly = 1) { clipboardManager.setText(text = "987") mockCipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -2123,6 +2196,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -2147,6 +2221,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { verify(exactly = 1) { mockCipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -2160,6 +2235,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val mockCipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -2184,6 +2260,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { ), ) mockCipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -2218,6 +2295,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val cipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -2253,6 +2331,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val cipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -2289,6 +2368,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val cipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -2324,6 +2404,7 @@ class VaultItemViewModelTest : BaseViewModelTest() { val cipherView = mockk { every { toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/util/CipherViewExtensionsTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/util/CipherViewExtensionsTest.kt index 4f775530f..b52f226fe 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/util/CipherViewExtensionsTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/util/CipherViewExtensionsTest.kt @@ -16,11 +16,61 @@ class CipherViewExtensionsTest { ZoneOffset.UTC, ) + @Suppress("MaxLineLength") + @Test + fun `toViewState should transform full CipherView into ViewState Login Content maintaining re-prompt and visibility state`() { + val cipherView = createCipherView(type = CipherType.LOGIN, isEmpty = false) + val viewState = cipherView.toViewState( + previousState = VaultItemState.ViewState.Content( + common = createCommonContent(isEmpty = false, isPremiumUser = true).copy( + currentCipher = cipherView, + // This re-prompt state should be preserved + requiresReprompt = false, + ), + type = createLoginContent(isEmpty = false).copy( + passwordData = VaultItemState.ViewState.Content.ItemType.Login.PasswordData( + password = "password", + // This visibility state should be preserved + isVisible = true, + canViewPassword = false, + ) + ), + ), + isPremiumUser = true, + hasMasterPassword = true, + totpCodeItemData = TotpCodeItemData( + periodSeconds = 30, + timeLeftSeconds = 15, + verificationCode = "123456", + totpCode = "testCode", + ), + clock = fixedClock, + ) + + assertEquals( + VaultItemState.ViewState.Content( + common = createCommonContent(isEmpty = false, isPremiumUser = true).copy( + currentCipher = cipherView, + requiresReprompt = false, + ), + type = createLoginContent(isEmpty = false).copy( + passwordData = VaultItemState.ViewState.Content.ItemType.Login.PasswordData( + password = "password", + isVisible = true, + canViewPassword = false, + ) + ), + ), + viewState, + ) + } + @Suppress("MaxLineLength") @Test fun `toViewState should transform full CipherView into ViewState Login Content without master password reprompt`() { val cipherView = createCipherView(type = CipherType.LOGIN, isEmpty = false) val viewState = cipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = false, totpCodeItemData = TotpCodeItemData( @@ -48,6 +98,7 @@ class CipherViewExtensionsTest { fun `toViewState should transform full CipherView into ViewState Login Content with premium`() { val cipherView = createCipherView(type = CipherType.LOGIN, isEmpty = false) val viewState = cipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = TotpCodeItemData( @@ -75,6 +126,7 @@ class CipherViewExtensionsTest { val isPremiumUser = false val cipherView = createCipherView(type = CipherType.LOGIN, isEmpty = false) val viewState = cipherView.toViewState( + previousState = null, isPremiumUser = isPremiumUser, hasMasterPassword = true, totpCodeItemData = TotpCodeItemData( @@ -100,6 +152,7 @@ class CipherViewExtensionsTest { fun `toViewState should transform empty CipherView into ViewState Login Content`() { val cipherView = createCipherView(type = CipherType.LOGIN, isEmpty = true) val viewState = cipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -121,6 +174,7 @@ class CipherViewExtensionsTest { fun `toViewState should transform full CipherView into ViewState Identity Content`() { val cipherView = createCipherView(type = CipherType.IDENTITY, isEmpty = false) val viewState = cipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -141,6 +195,7 @@ class CipherViewExtensionsTest { fun `toViewState should transform empty CipherView into ViewState Identity Content`() { val cipherView = createCipherView(type = CipherType.IDENTITY, isEmpty = true) val viewState = cipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -171,6 +226,7 @@ class CipherViewExtensionsTest { ), ) val viewState = cipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -206,6 +262,7 @@ class CipherViewExtensionsTest { ), ) val result = cipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -243,6 +300,7 @@ class CipherViewExtensionsTest { fun `toViewState should transform full CipherView into ViewState Secure Note Content`() { val cipherView = createCipherView(type = CipherType.SECURE_NOTE, isEmpty = false) val viewState = cipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null, @@ -264,6 +322,7 @@ class CipherViewExtensionsTest { fun `toViewState should transform empty Secure Note CipherView into ViewState Secure Note Content`() { val cipherView = createCipherView(type = CipherType.SECURE_NOTE, isEmpty = true) val viewState = cipherView.toViewState( + previousState = null, isPremiumUser = true, hasMasterPassword = true, totpCodeItemData = null,