mirror of
https://github.com/bitwarden/android.git
synced 2024-11-27 03:49:36 +03:00
PM-12760 Add way to re-show the onboarding carousel via debug menu (#3999)
This commit is contained in:
parent
e2e5042be5
commit
569ffc3583
9 changed files with 170 additions and 13 deletions
|
@ -37,4 +37,11 @@ interface DebugMenuRepository {
|
||||||
* Resets the onboarding status to NOT_STARTED for the current active user, if applicable.
|
* Resets the onboarding status to NOT_STARTED for the current active user, if applicable.
|
||||||
*/
|
*/
|
||||||
fun resetOnboardingStatusForCurrentUser()
|
fun resetOnboardingStatusForCurrentUser()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manipulates the state to force showing the onboarding carousel.
|
||||||
|
*
|
||||||
|
* @param userStateUpdateTrigger A passable lambda to trigger a user state update.
|
||||||
|
*/
|
||||||
|
fun modifyStateToShowOnboardingCarousel(userStateUpdateTrigger: () -> Unit)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import com.x8bit.bitwarden.BuildConfig
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource
|
import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
|
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
|
||||||
import com.x8bit.bitwarden.data.platform.datasource.disk.FeatureFlagOverrideDiskSource
|
import com.x8bit.bitwarden.data.platform.datasource.disk.FeatureFlagOverrideDiskSource
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.disk.SettingsDiskSource
|
||||||
import com.x8bit.bitwarden.data.platform.manager.getFlagValueOrDefault
|
import com.x8bit.bitwarden.data.platform.manager.getFlagValueOrDefault
|
||||||
import com.x8bit.bitwarden.data.platform.manager.model.FlagKey
|
import com.x8bit.bitwarden.data.platform.manager.model.FlagKey
|
||||||
import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFlow
|
import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFlow
|
||||||
|
@ -16,6 +17,7 @@ import kotlinx.coroutines.flow.onSubscription
|
||||||
class DebugMenuRepositoryImpl(
|
class DebugMenuRepositoryImpl(
|
||||||
private val featureFlagOverrideDiskSource: FeatureFlagOverrideDiskSource,
|
private val featureFlagOverrideDiskSource: FeatureFlagOverrideDiskSource,
|
||||||
private val serverConfigRepository: ServerConfigRepository,
|
private val serverConfigRepository: ServerConfigRepository,
|
||||||
|
private val settingsDiskSource: SettingsDiskSource,
|
||||||
private val authDiskSource: AuthDiskSource,
|
private val authDiskSource: AuthDiskSource,
|
||||||
) : DebugMenuRepository {
|
) : DebugMenuRepository {
|
||||||
|
|
||||||
|
@ -53,4 +55,11 @@ class DebugMenuRepositoryImpl(
|
||||||
onboardingStatus = OnboardingStatus.NOT_STARTED,
|
onboardingStatus = OnboardingStatus.NOT_STARTED,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun modifyStateToShowOnboardingCarousel(
|
||||||
|
userStateUpdateTrigger: () -> Unit,
|
||||||
|
) {
|
||||||
|
settingsDiskSource.hasUserLoggedInOrCreatedAccount = false
|
||||||
|
userStateUpdateTrigger.invoke()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,9 +117,11 @@ object PlatformRepositoryModule {
|
||||||
featureFlagOverrideDiskSource: FeatureFlagOverrideDiskSource,
|
featureFlagOverrideDiskSource: FeatureFlagOverrideDiskSource,
|
||||||
serverConfigRepository: ServerConfigRepository,
|
serverConfigRepository: ServerConfigRepository,
|
||||||
authDiskSource: AuthDiskSource,
|
authDiskSource: AuthDiskSource,
|
||||||
|
settingsDiskSource: SettingsDiskSource,
|
||||||
): DebugMenuRepository = DebugMenuRepositoryImpl(
|
): DebugMenuRepository = DebugMenuRepositoryImpl(
|
||||||
featureFlagOverrideDiskSource = featureFlagOverrideDiskSource,
|
featureFlagOverrideDiskSource = featureFlagOverrideDiskSource,
|
||||||
serverConfigRepository = serverConfigRepository,
|
serverConfigRepository = serverConfigRepository,
|
||||||
authDiskSource = authDiskSource,
|
authDiskSource = authDiskSource,
|
||||||
|
settingsDiskSource = settingsDiskSource,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
|
||||||
* Top level screen for the debug menu.
|
* Top level screen for the debug menu.
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Suppress("LongMethod")
|
||||||
@Composable
|
@Composable
|
||||||
fun DebugMenuScreen(
|
fun DebugMenuScreen(
|
||||||
onNavigateBack: () -> Unit,
|
onNavigateBack: () -> Unit,
|
||||||
|
@ -95,11 +96,21 @@ fun DebugMenuScreen(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
Spacer(Modifier.height(12.dp))
|
Spacer(Modifier.height(12.dp))
|
||||||
|
// Pulled these into variable to avoid over-nested formatting in the composable call.
|
||||||
|
val isRestartOnboardingEnabled = state.featureFlags[FlagKey.OnboardingFlow] as? Boolean
|
||||||
|
val isRestartOnboardingCarouselEnabled = state
|
||||||
|
.featureFlags[FlagKey.OnboardingCarousel] as? Boolean
|
||||||
OnboardingOverrideContent(
|
OnboardingOverrideContent(
|
||||||
enabled = (state.featureFlags[FlagKey.OnboardingFlow] as? Boolean) == true,
|
isRestartOnboardingEnabled = isRestartOnboardingEnabled == true,
|
||||||
onStartOnboarding = remember(viewModel) {
|
onStartOnboarding = remember(viewModel) {
|
||||||
{
|
{
|
||||||
viewModel.trySendAction(DebugMenuAction.ReStartOnboarding)
|
viewModel.trySendAction(DebugMenuAction.RestartOnboarding)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isCarouselOverrideEnabled = isRestartOnboardingCarouselEnabled == true,
|
||||||
|
onStartOnboardingCarousel = remember(viewModel) {
|
||||||
|
{
|
||||||
|
viewModel.trySendAction(DebugMenuAction.RestartOnboardingCarousel)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -144,10 +155,15 @@ private fun FeatureFlagContent(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The content for the onboarding override feature flag.
|
||||||
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
private fun OnboardingOverrideContent(
|
private fun OnboardingOverrideContent(
|
||||||
enabled: Boolean,
|
isRestartOnboardingEnabled: Boolean,
|
||||||
onStartOnboarding: () -> Unit,
|
onStartOnboarding: () -> Unit,
|
||||||
|
isCarouselOverrideEnabled: Boolean,
|
||||||
|
onStartOnboardingCarousel: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
Column(modifier) {
|
Column(modifier) {
|
||||||
|
@ -161,7 +177,7 @@ private fun OnboardingOverrideContent(
|
||||||
BitwardenFilledButton(
|
BitwardenFilledButton(
|
||||||
label = stringResource(R.string.restart_onboarding_cta),
|
label = stringResource(R.string.restart_onboarding_cta),
|
||||||
onClick = onStartOnboarding,
|
onClick = onStartOnboarding,
|
||||||
isEnabled = enabled,
|
isEnabled = isRestartOnboardingEnabled,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.standardHorizontalMargin(),
|
.standardHorizontalMargin(),
|
||||||
|
@ -176,6 +192,25 @@ private fun OnboardingOverrideContent(
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
)
|
)
|
||||||
|
Spacer(Modifier.height(16.dp))
|
||||||
|
BitwardenFilledButton(
|
||||||
|
label = stringResource(R.string.restart_onboarding_carousel),
|
||||||
|
onClick = onStartOnboardingCarousel,
|
||||||
|
isEnabled = isCarouselOverrideEnabled,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.standardHorizontalMargin(),
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.restart_onboarding_carousel_details),
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.CenterHorizontally)
|
||||||
|
.standardHorizontalMargin(),
|
||||||
|
style = BitwardenTheme.typography.bodySmall,
|
||||||
|
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,6 +234,11 @@ private fun FeatureFlagContent_preview() {
|
||||||
@Composable
|
@Composable
|
||||||
private fun OnboardingOverrideContent_preview() {
|
private fun OnboardingOverrideContent_preview() {
|
||||||
BitwardenTheme {
|
BitwardenTheme {
|
||||||
OnboardingOverrideContent(onStartOnboarding = {}, enabled = true)
|
OnboardingOverrideContent(
|
||||||
|
onStartOnboarding = {},
|
||||||
|
isRestartOnboardingEnabled = true,
|
||||||
|
onStartOnboardingCarousel = {},
|
||||||
|
isCarouselOverrideEnabled = true,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.x8bit.bitwarden.ui.platform.feature.debugmenu
|
package com.x8bit.bitwarden.ui.platform.feature.debugmenu
|
||||||
|
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
|
||||||
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
|
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.model.FlagKey
|
import com.x8bit.bitwarden.data.platform.manager.model.FlagKey
|
||||||
import com.x8bit.bitwarden.data.platform.repository.DebugMenuRepository
|
import com.x8bit.bitwarden.data.platform.repository.DebugMenuRepository
|
||||||
|
@ -22,6 +23,7 @@ import javax.inject.Inject
|
||||||
class DebugMenuViewModel @Inject constructor(
|
class DebugMenuViewModel @Inject constructor(
|
||||||
featureFlagManager: FeatureFlagManager,
|
featureFlagManager: FeatureFlagManager,
|
||||||
private val debugMenuRepository: DebugMenuRepository,
|
private val debugMenuRepository: DebugMenuRepository,
|
||||||
|
private val authRepository: AuthRepository,
|
||||||
) : BaseViewModel<DebugMenuState, DebugMenuEvent, DebugMenuAction>(
|
) : BaseViewModel<DebugMenuState, DebugMenuEvent, DebugMenuAction>(
|
||||||
initialState = DebugMenuState(featureFlags = emptyMap()),
|
initialState = DebugMenuState(featureFlags = emptyMap()),
|
||||||
) {
|
) {
|
||||||
|
@ -44,10 +46,19 @@ class DebugMenuViewModel @Inject constructor(
|
||||||
is DebugMenuAction.Internal.UpdateFeatureFlagMap -> handleUpdateFeatureFlagMap(action)
|
is DebugMenuAction.Internal.UpdateFeatureFlagMap -> handleUpdateFeatureFlagMap(action)
|
||||||
DebugMenuAction.NavigateBack -> handleNavigateBack()
|
DebugMenuAction.NavigateBack -> handleNavigateBack()
|
||||||
DebugMenuAction.ResetFeatureFlagValues -> handleResetFeatureFlagValues()
|
DebugMenuAction.ResetFeatureFlagValues -> handleResetFeatureFlagValues()
|
||||||
DebugMenuAction.ReStartOnboarding -> handleResetOnboardingStatus()
|
DebugMenuAction.RestartOnboarding -> handleResetOnboardingStatus()
|
||||||
|
DebugMenuAction.RestartOnboardingCarousel -> handleResetOnboardingCarousel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun handleResetOnboardingCarousel() {
|
||||||
|
debugMenuRepository.modifyStateToShowOnboardingCarousel(
|
||||||
|
userStateUpdateTrigger = {
|
||||||
|
authRepository.hasPendingAccountAddition = true
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun handleResetOnboardingStatus() {
|
private fun handleResetOnboardingStatus() {
|
||||||
debugMenuRepository.resetOnboardingStatusForCurrentUser()
|
debugMenuRepository.resetOnboardingStatusForCurrentUser()
|
||||||
}
|
}
|
||||||
|
@ -115,7 +126,12 @@ sealed class DebugMenuAction {
|
||||||
/**
|
/**
|
||||||
* The user has clicked the restart onboarding button for the onboarding section.
|
* The user has clicked the restart onboarding button for the onboarding section.
|
||||||
*/
|
*/
|
||||||
data object ReStartOnboarding : DebugMenuAction()
|
data object RestartOnboarding : DebugMenuAction()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user has clicked the restart onboarding button for the onboarding section.
|
||||||
|
*/
|
||||||
|
data object RestartOnboardingCarousel : DebugMenuAction()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal actions not triggered from the UI.
|
* Internal actions not triggered from the UI.
|
||||||
|
|
|
@ -17,5 +17,7 @@
|
||||||
<string name="onboarding_override">Onboarding Status Override</string>
|
<string name="onboarding_override">Onboarding Status Override</string>
|
||||||
<string name="restart_onboarding_cta">Restart Onboarding</string>
|
<string name="restart_onboarding_cta">Restart Onboarding</string>
|
||||||
<string name="restart_onboarding_details">This will reset the onboarding status for the current user, if available. After clicking the button you will immediately be redirected to the onboarding flow. Onboarding flag must be enabled.</string>
|
<string name="restart_onboarding_details">This will reset the onboarding status for the current user, if available. After clicking the button you will immediately be redirected to the onboarding flow. Onboarding flag must be enabled.</string>
|
||||||
|
<string name="restart_onboarding_carousel">Show Onboarding Carousel</string>
|
||||||
|
<string name="restart_onboarding_carousel_details">This will force the change to app state which will cause the first time carousel to show. The carousel will continue to show for any \"new\" account until a login is completed. May need to exit debug menu manually.</string>
|
||||||
<!-- /Debug Menu -->
|
<!-- /Debug Menu -->
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -5,6 +5,7 @@ import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
|
import com.x8bit.bitwarden.data.auth.datasource.disk.model.OnboardingStatus
|
||||||
import com.x8bit.bitwarden.data.auth.datasource.disk.model.UserStateJson
|
import com.x8bit.bitwarden.data.auth.datasource.disk.model.UserStateJson
|
||||||
import com.x8bit.bitwarden.data.platform.datasource.disk.FeatureFlagOverrideDiskSource
|
import com.x8bit.bitwarden.data.platform.datasource.disk.FeatureFlagOverrideDiskSource
|
||||||
|
import com.x8bit.bitwarden.data.platform.datasource.disk.SettingsDiskSource
|
||||||
import com.x8bit.bitwarden.data.platform.datasource.disk.model.ServerConfig
|
import com.x8bit.bitwarden.data.platform.datasource.disk.model.ServerConfig
|
||||||
import com.x8bit.bitwarden.data.platform.datasource.network.model.ConfigResponseJson
|
import com.x8bit.bitwarden.data.platform.datasource.network.model.ConfigResponseJson
|
||||||
import com.x8bit.bitwarden.data.platform.manager.model.FlagKey
|
import com.x8bit.bitwarden.data.platform.manager.model.FlagKey
|
||||||
|
@ -39,9 +40,15 @@ class DebugMenuRepositoryTest {
|
||||||
every { storeOnboardingStatus(any(), any()) } just runs
|
every { storeOnboardingStatus(any(), any()) } just runs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val mockSettingsDiskSource = mockk<SettingsDiskSource>(relaxed = true) {
|
||||||
|
every { hasUserLoggedInOrCreatedAccount } returns true
|
||||||
|
every { hasUserLoggedInOrCreatedAccount = any() } just runs
|
||||||
|
}
|
||||||
|
|
||||||
private val debugMenuRepository = DebugMenuRepositoryImpl(
|
private val debugMenuRepository = DebugMenuRepositoryImpl(
|
||||||
featureFlagOverrideDiskSource = mockFeatureFlagOverrideDiskSource,
|
featureFlagOverrideDiskSource = mockFeatureFlagOverrideDiskSource,
|
||||||
serverConfigRepository = mockServerConfigRepository,
|
serverConfigRepository = mockServerConfigRepository,
|
||||||
|
settingsDiskSource = mockSettingsDiskSource,
|
||||||
authDiskSource = mockAuthDiskSource,
|
authDiskSource = mockAuthDiskSource,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -182,6 +189,20 @@ class DebugMenuRepositoryTest {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("MaxLineLength")
|
||||||
|
@Test
|
||||||
|
fun `modifyStateToShowOnboardingCarousel should set hasUserLoggedInOrCreatedAccount to false and trigger user state update`() {
|
||||||
|
var lambdaHasBeenCalled = false
|
||||||
|
val triggerUserStateUpdate = {
|
||||||
|
lambdaHasBeenCalled = true
|
||||||
|
}
|
||||||
|
debugMenuRepository.modifyStateToShowOnboardingCarousel(triggerUserStateUpdate)
|
||||||
|
verify {
|
||||||
|
mockSettingsDiskSource.hasUserLoggedInOrCreatedAccount = false
|
||||||
|
}
|
||||||
|
assertTrue(lambdaHasBeenCalled)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private const val TEST_STRING_VALUE = "test"
|
private const val TEST_STRING_VALUE = "test"
|
||||||
|
|
|
@ -110,7 +110,7 @@ class DebugMenuScreenTest : BaseComposeTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `restart onboarding should send action when clicked`() {
|
fun `restart onboarding should send action when enabled and clicked`() {
|
||||||
mutableStateFlow.tryEmit(
|
mutableStateFlow.tryEmit(
|
||||||
DebugMenuState(
|
DebugMenuState(
|
||||||
featureFlags = mapOf(
|
featureFlags = mapOf(
|
||||||
|
@ -124,11 +124,11 @@ class DebugMenuScreenTest : BaseComposeTest() {
|
||||||
.assertIsEnabled()
|
.assertIsEnabled()
|
||||||
.performClick()
|
.performClick()
|
||||||
|
|
||||||
verify { viewModel.trySendAction(DebugMenuAction.ReStartOnboarding) }
|
verify { viewModel.trySendAction(DebugMenuAction.RestartOnboarding) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `no restart onboarding should not send action when not enabled`() {
|
fun `restart onboarding should not send action when not enabled`() {
|
||||||
mutableStateFlow.tryEmit(
|
mutableStateFlow.tryEmit(
|
||||||
DebugMenuState(
|
DebugMenuState(
|
||||||
featureFlags = mapOf(
|
featureFlags = mapOf(
|
||||||
|
@ -143,6 +143,43 @@ class DebugMenuScreenTest : BaseComposeTest() {
|
||||||
.assertIsNotEnabled()
|
.assertIsNotEnabled()
|
||||||
.performClick()
|
.performClick()
|
||||||
|
|
||||||
verify(exactly = 0) { viewModel.trySendAction(DebugMenuAction.ReStartOnboarding) }
|
verify(exactly = 0) { viewModel.trySendAction(DebugMenuAction.RestartOnboarding) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Show onboarding carousel should send action when enabled and clicked`() {
|
||||||
|
mutableStateFlow.tryEmit(
|
||||||
|
DebugMenuState(
|
||||||
|
featureFlags = mapOf(
|
||||||
|
FlagKey.OnboardingCarousel to true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
composeTestRule
|
||||||
|
.onNodeWithText("Show Onboarding Carousel", ignoreCase = true)
|
||||||
|
.performScrollTo()
|
||||||
|
.assertIsEnabled()
|
||||||
|
.performClick()
|
||||||
|
|
||||||
|
verify { viewModel.trySendAction(DebugMenuAction.RestartOnboardingCarousel) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `show onboarding carousel should not send action when not enabled`() {
|
||||||
|
mutableStateFlow.tryEmit(
|
||||||
|
DebugMenuState(
|
||||||
|
featureFlags = mapOf(
|
||||||
|
FlagKey.OnboardingCarousel to false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
composeTestRule
|
||||||
|
.onNodeWithText("Show Onboarding Carousel", ignoreCase = true)
|
||||||
|
.performScrollTo()
|
||||||
|
.assertIsNotEnabled()
|
||||||
|
.performClick()
|
||||||
|
|
||||||
|
verify(exactly = 0) { viewModel.trySendAction(DebugMenuAction.RestartOnboardingCarousel) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.x8bit.bitwarden.ui.platform.feature.debugmenu
|
package com.x8bit.bitwarden.ui.platform.feature.debugmenu
|
||||||
|
|
||||||
import app.cash.turbine.test
|
import app.cash.turbine.test
|
||||||
|
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
|
||||||
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
|
import com.x8bit.bitwarden.data.platform.manager.FeatureFlagManager
|
||||||
import com.x8bit.bitwarden.data.platform.manager.model.FlagKey
|
import com.x8bit.bitwarden.data.platform.manager.model.FlagKey
|
||||||
import com.x8bit.bitwarden.data.platform.repository.DebugMenuRepository
|
import com.x8bit.bitwarden.data.platform.repository.DebugMenuRepository
|
||||||
|
@ -23,10 +24,20 @@ class DebugMenuViewModelTest : BaseViewModelTest() {
|
||||||
every { getFeatureFlagFlow<Boolean>(any()) } returns flowOf(true)
|
every { getFeatureFlagFlow<Boolean>(any()) } returns flowOf(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val mockDebugMenuRepository = mockk<DebugMenuRepository> {
|
private val mockAuthRepository = mockk<AuthRepository>(relaxed = true) {
|
||||||
|
every { hasPendingAccountAddition = true } just runs
|
||||||
|
}
|
||||||
|
|
||||||
|
private val mockDebugMenuRepository = mockk<DebugMenuRepository>(relaxed = true) {
|
||||||
coEvery { resetFeatureFlagOverrides() } just runs
|
coEvery { resetFeatureFlagOverrides() } just runs
|
||||||
every { updateFeatureFlag<Boolean>(any(), any()) } just runs
|
every { updateFeatureFlag<Boolean>(any(), any()) } just runs
|
||||||
every { resetOnboardingStatusForCurrentUser() } just runs
|
every { resetOnboardingStatusForCurrentUser() } just runs
|
||||||
|
every {
|
||||||
|
modifyStateToShowOnboardingCarousel(userStateUpdateTrigger = any())
|
||||||
|
} answers {
|
||||||
|
// invokes the passed in lambda, allowing verification in tests.
|
||||||
|
firstArg<() -> Unit>().invoke()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -73,13 +84,25 @@ class DebugMenuViewModelTest : BaseViewModelTest() {
|
||||||
@Test
|
@Test
|
||||||
fun `handleResetOnboardingStatus should reset the onboarding status`() {
|
fun `handleResetOnboardingStatus should reset the onboarding status`() {
|
||||||
val viewModel = createViewModel()
|
val viewModel = createViewModel()
|
||||||
viewModel.trySendAction(DebugMenuAction.ReStartOnboarding)
|
viewModel.trySendAction(DebugMenuAction.RestartOnboarding)
|
||||||
verify { mockDebugMenuRepository.resetOnboardingStatusForCurrentUser() }
|
verify { mockDebugMenuRepository.resetOnboardingStatusForCurrentUser() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("MaxLineLength")
|
||||||
|
@Test
|
||||||
|
fun `handleResetOnboardingCarousel should reset the onboarding carousel and update user state pending account action`() {
|
||||||
|
val viewModel = createViewModel()
|
||||||
|
viewModel.trySendAction(DebugMenuAction.RestartOnboardingCarousel)
|
||||||
|
verify {
|
||||||
|
mockDebugMenuRepository.modifyStateToShowOnboardingCarousel(any())
|
||||||
|
mockAuthRepository.hasPendingAccountAddition = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun createViewModel(): DebugMenuViewModel = DebugMenuViewModel(
|
private fun createViewModel(): DebugMenuViewModel = DebugMenuViewModel(
|
||||||
featureFlagManager = mockFeatureFlagManager,
|
featureFlagManager = mockFeatureFlagManager,
|
||||||
debugMenuRepository = mockDebugMenuRepository,
|
debugMenuRepository = mockDebugMenuRepository,
|
||||||
|
authRepository = mockAuthRepository,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue