BITAU-182 BITAU-107 Don't show authetnicator sync toggle below API 31 (#4156)

This commit is contained in:
Andrew Haisting 2024-10-25 16:27:59 -05:00 committed by GitHub
parent 0960f61c37
commit 164cc09f19
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 63 additions and 9 deletions

View file

@ -1,5 +1,6 @@
package com.x8bit.bitwarden.ui.platform.feature.settings.accountsecurity
import android.os.Build
import android.os.Parcelable
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
@ -19,6 +20,7 @@ import com.x8bit.bitwarden.data.platform.repository.model.BiometricsKeyResult
import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeout
import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeoutAction
import com.x8bit.bitwarden.data.platform.repository.util.baseWebVaultUrlOrDefault
import com.x8bit.bitwarden.data.platform.util.isBuildVersionBelow
import com.x8bit.bitwarden.data.vault.datasource.network.model.PolicyTypeJson
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
import com.x8bit.bitwarden.ui.platform.base.BaseViewModel
@ -71,9 +73,9 @@ class AccountSecurityViewModel @Inject constructor(
?.activeAccount
?.hasMasterPassword != false,
isUnlockWithPinEnabled = settingsRepository.isUnlockWithPinEnabled,
shouldShowEnableAuthenticatorSync = featureFlagManager.getFeatureFlag(
key = FlagKey.AuthenticatorSync,
),
shouldShowEnableAuthenticatorSync =
featureFlagManager.getFeatureFlag(FlagKey.AuthenticatorSync) &&
!isBuildVersionBelow(Build.VERSION_CODES.S),
userId = userId,
vaultTimeout = settingsRepository.vaultTimeout,
vaultTimeoutAction = settingsRepository.vaultTimeoutAction,
@ -372,9 +374,11 @@ class AccountSecurityViewModel @Inject constructor(
private fun handleAuthenticatorSyncFeatureFlagUpdate(
action: AccountSecurityAction.Internal.AuthenticatorSyncFeatureFlagUpdate,
) {
val shouldShowAuthenticatorSync =
action.isEnabled && !isBuildVersionBelow(Build.VERSION_CODES.S)
mutableStateFlow.update {
it.copy(
shouldShowEnableAuthenticatorSync = action.isEnabled,
shouldShowEnableAuthenticatorSync = shouldShowAuthenticatorSync,
)
}
}

View file

@ -1001,7 +1001,7 @@ Do you want to switch to this account?</string>
<string name="please_restart_registration_or_try_logging_in">Please restart registration or try logging in. You may already have an account.</string>
<string name="restart_registration">Restart registration</string>
<string name="authenticator_sync">Authenticator Sync</string>
<string name="allow_bitwarden_authenticator_syncing">Allow Bitwarden Authenticator Syncing</string>
<string name="allow_bitwarden_authenticator_syncing">Allow authenticator syncing</string>
<string name="there_was_an_issue_validating_the_registration_token">There was an issue validating the registration token.</string>
<string name="turn_on_autofill">Turn on autofill</string>
<string name="use_autofill_to_log_into_your_accounts">Use autofill to log into your accounts with a single tap.</string>

View file

@ -1465,7 +1465,7 @@ class AccountSecurityScreenTest : BaseComposeTest() {
@Test
fun `sync with Bitwarden authenticator UI should be displayed according to state`() {
val toggleText = "Allow Bitwarden Authenticator Syncing"
val toggleText = "Allow authenticator syncing"
composeTestRule.onNodeWithText(toggleText).assertDoesNotExist()
mutableStateFlow.update { DEFAULT_STATE.copy(shouldShowEnableAuthenticatorSync = true) }
@ -1486,7 +1486,7 @@ class AccountSecurityScreenTest : BaseComposeTest() {
fun `sync with Bitwarden authenticator click should send AuthenticatorSyncToggle action`() {
mutableStateFlow.update { DEFAULT_STATE.copy(shouldShowEnableAuthenticatorSync = true) }
composeTestRule
.onNodeWithText("Allow Bitwarden Authenticator Syncing")
.onNodeWithText("Allow authenticator syncing")
.performScrollTo()
.performClick()
verify { viewModel.trySendAction(AccountSecurityAction.AuthenticatorSyncToggle(true)) }

View file

@ -1,5 +1,6 @@
package com.x8bit.bitwarden.ui.platform.feature.settings.accountsecurity
import android.os.Build
import androidx.lifecycle.SavedStateHandle
import app.cash.turbine.test
import com.x8bit.bitwarden.R
@ -22,6 +23,7 @@ import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeout
import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeoutAction
import com.x8bit.bitwarden.data.platform.repository.util.FakeEnvironmentRepository
import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFlow
import com.x8bit.bitwarden.data.platform.util.isBuildVersionBelow
import com.x8bit.bitwarden.data.vault.datasource.network.model.PolicyTypeJson
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
import com.x8bit.bitwarden.data.vault.datasource.network.model.createMockPolicy
@ -35,7 +37,9 @@ import io.mockk.coVerify
import io.mockk.every
import io.mockk.just
import io.mockk.mockk
import io.mockk.mockkStatic
import io.mockk.runs
import io.mockk.unmockkStatic
import io.mockk.verify
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.emptyFlow
@ -44,7 +48,9 @@ import kotlinx.coroutines.test.runTest
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.encodeToJsonElement
import kotlinx.serialization.json.jsonObject
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import javax.crypto.Cipher
@ -91,6 +97,16 @@ class AccountSecurityViewModelTest : BaseViewModelTest() {
every { getFeatureFlag(FlagKey.AuthenticatorSync) } returns false
}
@BeforeEach
fun setup() {
mockkStatic(::isBuildVersionBelow)
}
@AfterEach
fun teardown() {
unmockkStatic(::isBuildVersionBelow)
}
@Test
fun `initial state should be correct when saved state is set`() {
val viewModel = createViewModel(initialState = DEFAULT_STATE)
@ -679,7 +695,8 @@ class AccountSecurityViewModelTest : BaseViewModelTest() {
@Suppress("MaxLineLength")
@Test
fun `when featureFlagManger returns true for AuthenticatorSync, should show authenticator sync UI`() {
fun `when featureFlagManger returns true for AuthenticatorSync, and version is at least 31 should show authenticator sync UI`() {
every { isBuildVersionBelow(Build.VERSION_CODES.S) } returns false
val vm = createViewModel(
initialState = null,
featureFlagManager = mockk {
@ -693,8 +710,22 @@ class AccountSecurityViewModelTest : BaseViewModelTest() {
)
}
@Suppress("MaxLineLength")
@Test
fun `when featureFlagManger returns true for AuthenticatorSync, and version is under 31 should not show authenticator sync UI`() {
every { isBuildVersionBelow(Build.VERSION_CODES.S) } returns true
every { featureFlagManager.getFeatureFlag(FlagKey.AuthenticatorSync) } returns true
every { featureFlagManager.getFeatureFlagFlow(FlagKey.AuthenticatorSync) } returns emptyFlow()
val vm = createViewModel(initialState = null)
assertEquals(
DEFAULT_STATE,
vm.stateFlow.value,
)
}
@Test
fun `when featureFlagManger updates value AuthenticatorSync, should update UI`() = runTest {
every { isBuildVersionBelow(Build.VERSION_CODES.S) } returns false
val featureFlagFlow = MutableStateFlow(false)
val vm = createViewModel(
initialState = null,
@ -712,6 +743,25 @@ class AccountSecurityViewModelTest : BaseViewModelTest() {
}
}
@Test
@Suppress("MaxLineLength")
fun `when featureFlagManger updates value AuthenticatorSync, authenticator sync row should never show if below API 31`() =
runTest {
every { isBuildVersionBelow(Build.VERSION_CODES.S) } returns true
val featureFlagFlow = MutableStateFlow(false)
every { featureFlagManager.getFeatureFlag(FlagKey.AuthenticatorSync) } returns false
every {
featureFlagManager.getFeatureFlagFlow(FlagKey.AuthenticatorSync)
} returns featureFlagFlow
val vm = createViewModel(initialState = null)
vm.stateFlow.test {
assertEquals(DEFAULT_STATE, awaitItem())
featureFlagFlow.value = true
featureFlagFlow.value = false
expectNoEvents()
}
}
@Test
fun `when showUnlockBadgeFlow updates value, should update state`() = runTest {
val viewModel = createViewModel()

View file

@ -7,4 +7,4 @@ import android.os.Build
*
* @see Build.VERSION_CODES
*/
fun isBuildVersionBelow(version: Int): Boolean = version > Build.VERSION.SDK_INT
internal fun isBuildVersionBelow(version: Int): Boolean = version > Build.VERSION.SDK_INT