From 57857621f36226600d7b62373a42ed32ca1cc96d Mon Sep 17 00:00:00 2001 From: Oleg Semenenko <146032743+oleg-livefront@users.noreply.github.com> Date: Tue, 30 Jan 2024 23:44:21 -0600 Subject: [PATCH] Save the clear clipboard frequency in settings. (#886) --- .../datasource/disk/SettingsDiskSource.kt | 10 +++ .../datasource/disk/SettingsDiskSourceImpl.kt | 12 ++++ .../platform/repository/SettingsRepository.kt | 6 ++ .../repository/SettingsRepositoryImpl.kt | 20 ++++++ .../model/ClearClipboardFrequency.kt | 17 ++++++ .../util/ClearClipboardFrequencyUtils.kt | 21 +++++++ .../feature/settings/other/OtherScreen.kt | 14 +++-- .../feature/settings/other/OtherViewModel.kt | 24 ++------ .../datasource/disk/SettingsDiskSourceTest.kt | 61 +++++++++++++++++++ .../disk/util/FakeSettingsDiskSource.kt | 9 +++ .../repository/SettingsRepositoryTest.kt | 26 ++++++++ .../feature/settings/other/OtherScreenTest.kt | 5 +- .../settings/other/OtherViewModelTest.kt | 44 +++++++------ 13 files changed, 224 insertions(+), 45 deletions(-) create mode 100644 app/src/main/java/com/x8bit/bitwarden/data/platform/repository/model/ClearClipboardFrequency.kt create mode 100644 app/src/main/java/com/x8bit/bitwarden/data/platform/repository/util/ClearClipboardFrequencyUtils.kt diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/disk/SettingsDiskSource.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/disk/SettingsDiskSource.kt index e9580ab8bd..5fdcb89537 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/disk/SettingsDiskSource.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/disk/SettingsDiskSource.kt @@ -129,6 +129,16 @@ interface SettingsDiskSource { vaultTimeoutAction: VaultTimeoutAction?, ) + /** + * Gets the clipboard clearing frequency in seconds for the given [userId]. + */ + fun getClearClipboardFrequencySeconds(userId: String): Int? + + /** + * Stores the clipboard clearing frequency in seconds for the given [userId]. + */ + fun storeClearClipboardFrequencySeconds(userId: String, frequency: Int?) + /** * Gets the default [UriMatchType] for the given [userId]. */ diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/disk/SettingsDiskSourceImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/disk/SettingsDiskSourceImpl.kt index 2b6b6e1725..921abc6832 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/disk/SettingsDiskSourceImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/disk/SettingsDiskSourceImpl.kt @@ -31,6 +31,7 @@ private const val SCREEN_CAPTURE_ALLOW_KEY = "$BASE_KEY:screenCaptureAllowed" private const val SYSTEM_BIOMETRIC_INTEGRITY_SOURCE_KEY = "$BASE_KEY:biometricIntegritySource" private const val ACCOUNT_BIOMETRIC_INTEGRITY_VALID_KEY = "$BASE_KEY:accountBiometricIntegrityValid" private const val CRASH_LOGGING_ENABLED_KEY = "$BASE_KEY:crashLoggingEnabled" +private const val CLEAR_CLIPBOARD_INTERVAL_KEY = "$BASE_KEY:clearClipboard" /** * Primary implementation of [SettingsDiskSource]. @@ -136,6 +137,7 @@ class SettingsDiskSourceImpl( ) storeLastSyncTime(userId = userId, lastSyncTime = null) storeScreenCaptureAllowed(userId = userId, isScreenCaptureAllowed = null) + storeClearClipboardFrequencySeconds(userId = userId, frequency = null) removeWithPrefix(prefix = "${ACCOUNT_BIOMETRIC_INTEGRITY_VALID_KEY}_$userId") } @@ -191,6 +193,16 @@ class SettingsDiskSourceImpl( getMutableVaultTimeoutInMinutesFlow(userId = userId).tryEmit(vaultTimeoutInMinutes) } + override fun getClearClipboardFrequencySeconds(userId: String): Int? = + getInt(key = "${CLEAR_CLIPBOARD_INTERVAL_KEY}_$userId") + + override fun storeClearClipboardFrequencySeconds(userId: String, frequency: Int?) { + putInt( + key = "${CLEAR_CLIPBOARD_INTERVAL_KEY}_$userId", + value = frequency, + ) + } + override fun getVaultTimeoutAction(userId: String): VaultTimeoutAction? = getString(key = "${VAULT_TIMEOUT_ACTION_KEY}_$userId")?.let { storedValue -> VaultTimeoutAction.entries.firstOrNull { storedValue == it.value } diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepository.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepository.kt index 5606826c51..e9b1539e9a 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepository.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepository.kt @@ -2,6 +2,7 @@ package com.x8bit.bitwarden.data.platform.repository import com.x8bit.bitwarden.data.auth.repository.model.UserFingerprintResult import com.x8bit.bitwarden.data.platform.repository.model.BiometricsKeyResult +import com.x8bit.bitwarden.data.platform.repository.model.ClearClipboardFrequency import com.x8bit.bitwarden.data.platform.repository.model.UriMatchType import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeout import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeoutAction @@ -51,6 +52,11 @@ interface SettingsRepository { */ val isIconLoadingDisabledFlow: Flow + /** + * The frequency in seconds at which we clear the clipboard. + */ + var clearClipboardFrequency: ClearClipboardFrequency + /** * The current setting for crash logging. */ diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryImpl.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryImpl.kt index a69f2cfce0..baefe67a30 100644 --- a/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryImpl.kt +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryImpl.kt @@ -9,6 +9,7 @@ import com.x8bit.bitwarden.data.platform.datasource.disk.SettingsDiskSource import com.x8bit.bitwarden.data.platform.manager.BiometricsEncryptionManager import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager import com.x8bit.bitwarden.data.platform.repository.model.BiometricsKeyResult +import com.x8bit.bitwarden.data.platform.repository.model.ClearClipboardFrequency import com.x8bit.bitwarden.data.platform.repository.model.UriMatchType import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeout import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeoutAction @@ -101,6 +102,18 @@ class SettingsRepositoryImpl( .isIconLoadingDisabled ?: false, ) + override var clearClipboardFrequency: ClearClipboardFrequency + get() = activeUserId + ?.let { userId -> + settingsDiskSource + .getClearClipboardFrequencySeconds(userId) + .toClearClipboardFrequency() + } + ?: ClearClipboardFrequency.NEVER + set(value) { + val userId = activeUserId ?: return + settingsDiskSource.storeClearClipboardFrequencySeconds(userId, value.frequencySeconds) + } override var isCrashLoggingEnabled: Boolean get() = settingsDiskSource.isCrashLoggingEnabled ?: true @@ -439,6 +452,13 @@ private fun Int?.toVaultTimeout(): VaultTimeout = else -> VaultTimeout.Custom(vaultTimeoutInMinutes = this) } +/** + * Converts the given Int into a [ClearClipboardFrequency] item. + */ +private fun Int?.toClearClipboardFrequency(): ClearClipboardFrequency = + ClearClipboardFrequency.entries.firstOrNull { it.frequencySeconds == this } + ?: ClearClipboardFrequency.NEVER + /** * Returns the given [VaultTimeoutAction] or a default value if `null`. */ diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/model/ClearClipboardFrequency.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/model/ClearClipboardFrequency.kt new file mode 100644 index 0000000000..42bc3269c9 --- /dev/null +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/model/ClearClipboardFrequency.kt @@ -0,0 +1,17 @@ +package com.x8bit.bitwarden.data.platform.repository.model + +/** + * Represents the frequency for clearing the clipboard for the current user. + */ +@Suppress("MagicNumber") +enum class ClearClipboardFrequency( + val frequencySeconds: Int?, +) { + NEVER(null), + TEN_SECONDS(10), + TWENTY_SECONDS(20), + THIRTY_SECONDS(30), + ONE_MINUTE(60), + TWO_MINUTES(120), + FIVE_MINUTES(300), +} diff --git a/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/util/ClearClipboardFrequencyUtils.kt b/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/util/ClearClipboardFrequencyUtils.kt new file mode 100644 index 0000000000..d8d950e7dc --- /dev/null +++ b/app/src/main/java/com/x8bit/bitwarden/data/platform/repository/util/ClearClipboardFrequencyUtils.kt @@ -0,0 +1,21 @@ +package com.x8bit.bitwarden.data.platform.repository.util + +import com.x8bit.bitwarden.R +import com.x8bit.bitwarden.data.platform.repository.model.ClearClipboardFrequency +import com.x8bit.bitwarden.ui.platform.base.util.Text +import com.x8bit.bitwarden.ui.platform.base.util.asText + +/** + * Provides a human-readable display label for the given [ClearClipboardFrequency]. + */ +val ClearClipboardFrequency.displayLabel: Text + get() = when (this) { + ClearClipboardFrequency.NEVER -> R.string.never + ClearClipboardFrequency.TEN_SECONDS -> R.string.ten_seconds + ClearClipboardFrequency.TWENTY_SECONDS -> R.string.twenty_seconds + ClearClipboardFrequency.THIRTY_SECONDS -> R.string.thirty_seconds + ClearClipboardFrequency.ONE_MINUTE -> R.string.one_minute + ClearClipboardFrequency.TWO_MINUTES -> R.string.two_minutes + ClearClipboardFrequency.FIVE_MINUTES -> R.string.five_minutes + } + .asText() diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherScreen.kt index ff2cbbf1de..dcda9e30ab 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherScreen.kt @@ -29,6 +29,8 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import com.x8bit.bitwarden.R +import com.x8bit.bitwarden.data.platform.repository.model.ClearClipboardFrequency +import com.x8bit.bitwarden.data.platform.repository.util.displayLabel import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect import com.x8bit.bitwarden.ui.platform.components.BitwardenFilledTonalButton import com.x8bit.bitwarden.ui.platform.components.BitwardenLoadingDialog @@ -191,8 +193,8 @@ private fun ScreenCaptureRow( @Composable private fun ClearClipboardFrequencyRow( - currentSelection: OtherState.ClearClipboardFrequency, - onFrequencySelection: (OtherState.ClearClipboardFrequency) -> Unit, + currentSelection: ClearClipboardFrequency, + onFrequencySelection: (ClearClipboardFrequency) -> Unit, modifier: Modifier = Modifier, ) { var shouldShowClearClipboardDialog by remember { mutableStateOf(false) } @@ -204,7 +206,7 @@ private fun ClearClipboardFrequencyRow( modifier = modifier, ) { Text( - text = currentSelection.text(), + text = currentSelection.displayLabel.invoke(), style = MaterialTheme.typography.labelSmall, color = MaterialTheme.colorScheme.onSurfaceVariant, ) @@ -215,14 +217,14 @@ private fun ClearClipboardFrequencyRow( title = stringResource(id = R.string.clear_clipboard), onDismissRequest = { shouldShowClearClipboardDialog = false }, ) { - OtherState.ClearClipboardFrequency.entries.forEach { option -> + ClearClipboardFrequency.entries.forEach { option -> BitwardenSelectionRow( - text = option.text, + text = option.displayLabel, isSelected = option == currentSelection, onClick = { shouldShowClearClipboardDialog = false onFrequencySelection( - OtherState.ClearClipboardFrequency.entries.first { it == option }, + ClearClipboardFrequency.entries.first { it == option }, ) }, ) diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherViewModel.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherViewModel.kt index af11dad027..13f1e43549 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherViewModel.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import com.x8bit.bitwarden.R import com.x8bit.bitwarden.data.platform.repository.SettingsRepository +import com.x8bit.bitwarden.data.platform.repository.model.ClearClipboardFrequency import com.x8bit.bitwarden.data.vault.repository.VaultRepository import com.x8bit.bitwarden.ui.platform.base.BaseViewModel import com.x8bit.bitwarden.ui.platform.base.util.Text @@ -38,7 +39,7 @@ class OtherViewModel @Inject constructor( ?: OtherState( allowScreenCapture = settingsRepo.isScreenCaptureAllowed, allowSyncOnRefresh = settingsRepo.getPullToRefreshEnabledFlow().value, - clearClipboardFrequency = OtherState.ClearClipboardFrequency.DEFAULT, + clearClipboardFrequency = settingsRepo.clearClipboardFrequency, lastSyncTime = settingsRepo .vaultLastSync ?.toFormattedPattern(VAULT_LAST_SYNC_TIME_PATTERN, clock.zone) @@ -80,12 +81,10 @@ class OtherViewModel @Inject constructor( private fun handleClearClipboardFrequencyChanged( action: OtherAction.ClearClipboardFrequencyChange, ) { - // TODO BIT-1283 implement clear clipboard setting mutableStateFlow.update { - it.copy( - clearClipboardFrequency = action.clearClipboardFrequency, - ) + it.copy(clearClipboardFrequency = action.clearClipboardFrequency) } + settingsRepo.clearClipboardFrequency = action.clearClipboardFrequency } private fun handleSyncNowButtonClicked() { @@ -125,19 +124,6 @@ data class OtherState( val lastSyncTime: String, val dialogState: DialogState?, ) : Parcelable { - /** - * Represents the different frequencies with which the user clipboard can be cleared. - */ - enum class ClearClipboardFrequency(val text: Text) { - DEFAULT(text = R.string.never.asText()), - TEN_SECONDS(text = R.string.ten_seconds.asText()), - TWENTY_SECONDS(text = R.string.twenty_seconds.asText()), - THIRTY_SECONDS(text = R.string.thirty_seconds.asText()), - ONE_MINUTE(text = R.string.one_minute.asText()), - TWO_MINUTES(text = R.string.two_minutes.asText()), - FIVE_MINUTES(text = R.string.five_minutes.asText()), - } - /** * Represents the current state of any dialogs on the screen. */ @@ -189,7 +175,7 @@ sealed class OtherAction { * Indicates that the user changed the clear clipboard frequency. */ data class ClearClipboardFrequencyChange( - val clearClipboardFrequency: OtherState.ClearClipboardFrequency, + val clearClipboardFrequency: ClearClipboardFrequency, ) : OtherAction() /** diff --git a/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/disk/SettingsDiskSourceTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/disk/SettingsDiskSourceTest.kt index 695de7cbf5..06d821cc9b 100644 --- a/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/disk/SettingsDiskSourceTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/disk/SettingsDiskSourceTest.kt @@ -4,6 +4,7 @@ import androidx.core.content.edit import app.cash.turbine.test import com.x8bit.bitwarden.data.platform.base.FakeSharedPreferences import com.x8bit.bitwarden.data.platform.datasource.network.di.PlatformNetworkModule +import com.x8bit.bitwarden.data.platform.repository.model.ClearClipboardFrequency import com.x8bit.bitwarden.data.platform.repository.model.UriMatchType import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeoutAction import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppLanguage @@ -875,4 +876,64 @@ class SettingsDiskSourceTest { ) assertFalse(fakeSharedPreferences.contains(screenCaptureAllowKey)) } + + @Test + fun `storeClearClipboardFrequency should update SharedPreferences`() { + val clearClipboardBaseKey = "bwPreferencesStorage:clearClipboard" + val mockUserId = "mockUserId" + val clearClipboardKey = "${clearClipboardBaseKey}_$mockUserId" + + assertNull(settingsDiskSource.getClearClipboardFrequencySeconds(mockUserId)) + assertEquals(fakeSharedPreferences.getInt(mockUserId, 0), 0) + + // Updating the disk source updates shared preferences + settingsDiskSource.storeClearClipboardFrequencySeconds( + mockUserId, + ClearClipboardFrequency.ONE_MINUTE.frequencySeconds, + ) + + assertEquals( + ClearClipboardFrequency.ONE_MINUTE.frequencySeconds, + fakeSharedPreferences.getInt(clearClipboardKey, 0), + ) + } + + @Suppress("MaxLineLength") + @Test + fun `storeClearClipboardFrequency should clear the SharedPreferences value if the value is null`() { + val clearClipboardBaseKey = "bwPreferencesStorage:clearClipboard" + val mockUserId = "mockUserId" + val clearClipboardKey = "${clearClipboardBaseKey}_$mockUserId" + + assertNull(settingsDiskSource.getClearClipboardFrequencySeconds(mockUserId)) + assertEquals(fakeSharedPreferences.getInt(mockUserId, 0), 0) + + // Updating the disk source updates shared preferences + settingsDiskSource.storeClearClipboardFrequencySeconds( + mockUserId, + null, + ) + + assertFalse(fakeSharedPreferences.contains(clearClipboardKey)) + } + + @Test + fun `getClearClipboardFrequency should pull from SharedPreferences`() { + val clearClipboardBaseKey = "bwPreferencesStorage:clearClipboard" + val mockUserId = "mockUserId" + val expectedValue = 20 + val clearClipboardKey = "${clearClipboardBaseKey}_$mockUserId" + + assertNull(settingsDiskSource.getClearClipboardFrequencySeconds(mockUserId)) + assertEquals(fakeSharedPreferences.getInt(mockUserId, 0), 0) + + // Update SharedPreferences updates the disk source + fakeSharedPreferences.edit { + putInt(clearClipboardKey, expectedValue) + } + assertEquals( + expectedValue, + settingsDiskSource.getClearClipboardFrequencySeconds(mockUserId), + ) + } } diff --git a/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/disk/util/FakeSettingsDiskSource.kt b/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/disk/util/FakeSettingsDiskSource.kt index f5f2153170..d340b6f5e2 100644 --- a/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/disk/util/FakeSettingsDiskSource.kt +++ b/app/src/test/java/com/x8bit/bitwarden/data/platform/datasource/disk/util/FakeSettingsDiskSource.kt @@ -44,6 +44,7 @@ class FakeSettingsDiskSource : SettingsDiskSource { private val storedVaultTimeoutActions = mutableMapOf() private val storedVaultTimeoutInMinutes = mutableMapOf() private val storedUriMatchTypes = mutableMapOf() + private val storedClearClipboardFrequency = mutableMapOf() private val storedDisableAutofillSavePrompt = mutableMapOf() private val storedPullToRefreshEnabled = mutableMapOf() private val storedInlineAutofillEnabled = mutableMapOf() @@ -121,6 +122,7 @@ class FakeSettingsDiskSource : SettingsDiskSource { storedInlineAutofillEnabled.remove(userId) storedBlockedAutofillUris.remove(userId) storedScreenCaptureAllowed.remove(userId) + storedClearClipboardFrequency.remove(userId) mutableVaultTimeoutActionsFlowMap.remove(userId) mutableVaultTimeoutInMinutesFlowMap.remove(userId) @@ -168,6 +170,13 @@ class FakeSettingsDiskSource : SettingsDiskSource { getMutableVaultTimeoutActionsFlow(userId = userId).tryEmit(vaultTimeoutAction) } + override fun getClearClipboardFrequencySeconds(userId: String): Int? = + storedClearClipboardFrequency[userId] + + override fun storeClearClipboardFrequencySeconds(userId: String, frequency: Int?) { + storedClearClipboardFrequency[userId] = frequency + } + override fun getDefaultUriMatchType(userId: String): UriMatchType? = storedUriMatchTypes[userId] diff --git a/app/src/test/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryTest.kt index d908a9359f..adc21f2b31 100644 --- a/app/src/test/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/data/platform/repository/SettingsRepositoryTest.kt @@ -12,6 +12,7 @@ import com.x8bit.bitwarden.data.platform.base.FakeDispatcherManager import com.x8bit.bitwarden.data.platform.datasource.disk.util.FakeSettingsDiskSource import com.x8bit.bitwarden.data.platform.manager.BiometricsEncryptionManager import com.x8bit.bitwarden.data.platform.repository.model.BiometricsKeyResult +import com.x8bit.bitwarden.data.platform.repository.model.ClearClipboardFrequency import com.x8bit.bitwarden.data.platform.repository.model.UriMatchType import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeout import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeoutAction @@ -872,6 +873,31 @@ class SettingsRepositoryTest { assertEquals(false, fakeSettingsDiskSource.getScreenCaptureAllowed(userId)) } } + + @Suppress("MaxLineLength") + @Test + fun `clearClipboardFrequency should pull from and update SettingsDiskSource`() = + runTest { + val userId = "userId" + fakeAuthDiskSource.userState = MOCK_USER_STATE + + fakeSettingsDiskSource.storeClearClipboardFrequencySeconds( + userId, + ClearClipboardFrequency.ONE_MINUTE.frequencySeconds, + ) + + assertEquals( + ClearClipboardFrequency.ONE_MINUTE, + settingsRepository.clearClipboardFrequency, + ) + + settingsRepository.clearClipboardFrequency = ClearClipboardFrequency.TEN_SECONDS + + assertEquals( + ClearClipboardFrequency.TEN_SECONDS, + settingsRepository.clearClipboardFrequency, + ) + } } private val MOCK_USER_STATE = diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherScreenTest.kt index 8e13ce7c7e..c708281ebd 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherScreenTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherScreenTest.kt @@ -9,6 +9,7 @@ import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick +import com.x8bit.bitwarden.data.platform.repository.model.ClearClipboardFrequency import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFlow import com.x8bit.bitwarden.ui.platform.base.BaseComposeTest import com.x8bit.bitwarden.ui.platform.base.util.asText @@ -103,7 +104,7 @@ class OtherScreenTest : BaseComposeTest() { verify { viewModel.trySendAction( OtherAction.ClearClipboardFrequencyChange( - clearClipboardFrequency = OtherState.ClearClipboardFrequency.TEN_SECONDS, + clearClipboardFrequency = ClearClipboardFrequency.TEN_SECONDS, ), ) } @@ -148,7 +149,7 @@ class OtherScreenTest : BaseComposeTest() { private val DEFAULT_STATE = OtherState( allowScreenCapture = false, allowSyncOnRefresh = false, - clearClipboardFrequency = OtherState.ClearClipboardFrequency.DEFAULT, + clearClipboardFrequency = ClearClipboardFrequency.NEVER, lastSyncTime = "5/14/2023 4:52 PM", dialogState = null, ) diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherViewModelTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherViewModelTest.kt index c6c949ebcb..d85f2d9740 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherViewModelTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/other/OtherViewModelTest.kt @@ -4,6 +4,7 @@ import androidx.lifecycle.SavedStateHandle import app.cash.turbine.test import com.x8bit.bitwarden.R import com.x8bit.bitwarden.data.platform.repository.SettingsRepository +import com.x8bit.bitwarden.data.platform.repository.model.ClearClipboardFrequency import com.x8bit.bitwarden.data.vault.repository.VaultRepository import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest import com.x8bit.bitwarden.ui.platform.base.util.asText @@ -31,6 +32,8 @@ class OtherViewModelTest : BaseViewModelTest() { private val mutableVaultLastSyncStateFlow = MutableStateFlow(instant) private val mutableScreenCaptureAllowedStateFlow = MutableStateFlow(isAllowed) private val settingsRepository = mockk { + every { clearClipboardFrequency } returns ClearClipboardFrequency.NEVER + every { clearClipboardFrequency = any() } just runs every { getPullToRefreshEnabledFlow() } returns mutablePullToRefreshStateFlow every { vaultLastSyncStateFlow } returns mutableVaultLastSyncStateFlow every { vaultLastSync } returns instant @@ -49,7 +52,7 @@ class OtherViewModelTest : BaseViewModelTest() { @Test fun `initial state should be correct when set`() { val state = DEFAULT_STATE.copy( - clearClipboardFrequency = OtherState.ClearClipboardFrequency.FIVE_MINUTES, + clearClipboardFrequency = ClearClipboardFrequency.FIVE_MINUTES, ) val viewModel = createViewModel(state = state) assertEquals(state, viewModel.stateFlow.value) @@ -57,23 +60,28 @@ class OtherViewModelTest : BaseViewModelTest() { @Suppress("MaxLineLength") @Test - fun `on AllowScreenCaptureToggled should update value in state and SettingsRepository`() = runTest { - val viewModel = createViewModel() - val newScreenCaptureAllowedValue = true + fun `on AllowScreenCaptureToggled should update value in state and SettingsRepository`() = + runTest { + val viewModel = createViewModel() + val newScreenCaptureAllowedValue = true - viewModel.trySendAction(OtherAction.AllowScreenCaptureToggle(newScreenCaptureAllowedValue)) - - verify(exactly = 1) { - settingsRepository.isScreenCaptureAllowed = newScreenCaptureAllowedValue - } - - viewModel.stateFlow.test { - assertEquals( - DEFAULT_STATE.copy(allowScreenCapture = true), - awaitItem(), + viewModel.trySendAction( + OtherAction.AllowScreenCaptureToggle( + newScreenCaptureAllowedValue, + ), ) + + verify(exactly = 1) { + settingsRepository.isScreenCaptureAllowed = newScreenCaptureAllowedValue + } + + viewModel.stateFlow.test { + assertEquals( + DEFAULT_STATE.copy(allowScreenCapture = true), + awaitItem(), + ) + } } - } @Test fun `on AllowSyncToggled should update value in state`() { @@ -110,12 +118,12 @@ class OtherViewModelTest : BaseViewModelTest() { ) viewModel.trySendAction( OtherAction.ClearClipboardFrequencyChange( - clearClipboardFrequency = OtherState.ClearClipboardFrequency.ONE_MINUTE, + clearClipboardFrequency = ClearClipboardFrequency.ONE_MINUTE, ), ) assertEquals( DEFAULT_STATE.copy( - clearClipboardFrequency = OtherState.ClearClipboardFrequency.ONE_MINUTE, + clearClipboardFrequency = ClearClipboardFrequency.ONE_MINUTE, ), awaitItem(), ) @@ -173,7 +181,7 @@ class OtherViewModelTest : BaseViewModelTest() { private val DEFAULT_STATE = OtherState( allowScreenCapture = false, allowSyncOnRefresh = false, - clearClipboardFrequency = OtherState.ClearClipboardFrequency.DEFAULT, + clearClipboardFrequency = ClearClipboardFrequency.NEVER, lastSyncTime = "10/26/2023 12:00 PM", dialogState = null, )