From c52ae0ed2a97178b655a85e6cbd8733c95c30f3a Mon Sep 17 00:00:00 2001 From: David Perez Date: Mon, 15 Jan 2024 21:27:07 -0600 Subject: [PATCH] Provide IntentManager from compositionLocal (#630) --- .../createaccount/CreateAccountScreen.kt | 11 +- .../ui/auth/feature/login/LoginScreen.kt | 7 +- .../feature/settings/about/AboutScreen.kt | 11 +- .../accountsecurity/AccountSecurityScreen.kt | 7 +- .../platform/manager/intent/IntentManager.kt | 35 ++ .../intent/IntentManagerImpl.kt} | 34 +- .../ui/platform/theme/BitwardenTheme.kt | 12 +- .../ui/tools/feature/send/SendScreen.kt | 9 +- .../feature/send/addsend/AddSendScreen.kt | 7 +- .../ui/vault/feature/item/VaultItemScreen.kt | 7 +- .../manualcodeentry/ManualCodeEntryScreen.kt | 7 +- .../ui/vault/feature/vault/VaultScreen.kt | 7 +- .../createaccount/CreateAccountScreenTest.kt | 347 +++--------------- .../ui/auth/feature/login/LoginScreenTest.kt | 10 +- .../feature/settings/about/AboutScreenTest.kt | 191 ++-------- .../AccountSecurityScreenTest.kt | 10 +- .../ui/tools/feature/send/SendScreenTest.kt | 14 +- .../feature/send/addsend/AddSendScreenTest.kt | 10 +- .../vault/feature/item/VaultItemScreenTest.kt | 10 +- .../ManualCodeEntryScreenTests.kt | 8 +- .../ui/vault/feature/vault/VaultScreenTest.kt | 10 +- 21 files changed, 227 insertions(+), 537 deletions(-) create mode 100644 app/src/main/java/com/x8bit/bitwarden/ui/platform/manager/intent/IntentManager.kt rename app/src/main/java/com/x8bit/bitwarden/ui/platform/{base/util/IntentHandler.kt => manager/intent/IntentManagerImpl.kt} (61%) diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/createaccount/CreateAccountScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/createaccount/CreateAccountScreen.kt index 63d49213d..9b35e6874 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/createaccount/CreateAccountScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/createaccount/CreateAccountScreen.kt @@ -67,7 +67,6 @@ import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.Ter import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountEvent.NavigateToPrivacyPolicy import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountEvent.NavigateToTerms import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect -import com.x8bit.bitwarden.ui.platform.base.util.IntentHandler import com.x8bit.bitwarden.ui.platform.base.util.asText import com.x8bit.bitwarden.ui.platform.components.BitwardenBasicDialog import com.x8bit.bitwarden.ui.platform.components.BitwardenLoadingDialog @@ -79,6 +78,8 @@ import com.x8bit.bitwarden.ui.platform.components.BitwardenTextField import com.x8bit.bitwarden.ui.platform.components.BitwardenTopAppBar import com.x8bit.bitwarden.ui.platform.components.BitwardenTwoButtonDialog import com.x8bit.bitwarden.ui.platform.components.LoadingDialogState +import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager +import com.x8bit.bitwarden.ui.platform.theme.LocalIntentManager import com.x8bit.bitwarden.ui.platform.theme.clickableSpanStyle /** @@ -90,7 +91,7 @@ import com.x8bit.bitwarden.ui.platform.theme.clickableSpanStyle fun CreateAccountScreen( onNavigateBack: () -> Unit, onNavigateToLogin: (emailAddress: String, captchaToken: String) -> Unit, - intentHandler: IntentHandler = IntentHandler(context = LocalContext.current), + intentManager: IntentManager = LocalIntentManager.current, viewModel: CreateAccountViewModel = hiltViewModel(), ) { val state by viewModel.stateFlow.collectAsState() @@ -98,11 +99,11 @@ fun CreateAccountScreen( EventsEffect(viewModel) { event -> when (event) { is NavigateToPrivacyPolicy -> { - intentHandler.launchUri("https://bitwarden.com/privacy/".toUri()) + intentManager.launchUri("https://bitwarden.com/privacy/".toUri()) } is NavigateToTerms -> { - intentHandler.launchUri("https://bitwarden.com/terms/".toUri()) + intentManager.launchUri("https://bitwarden.com/terms/".toUri()) } is CreateAccountEvent.NavigateBack -> onNavigateBack.invoke() @@ -111,7 +112,7 @@ fun CreateAccountScreen( } is CreateAccountEvent.NavigateToCaptcha -> { - intentHandler.startCustomTabsActivity(uri = event.uri) + intentManager.startCustomTabsActivity(uri = event.uri) } is CreateAccountEvent.NavigateToLogin -> { diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginScreen.kt index e489911b0..1e88035d8 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginScreen.kt @@ -39,7 +39,6 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.x8bit.bitwarden.R import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect -import com.x8bit.bitwarden.ui.platform.base.util.IntentHandler import com.x8bit.bitwarden.ui.platform.components.BitwardenAccountSwitcher import com.x8bit.bitwarden.ui.platform.components.BitwardenBasicDialog import com.x8bit.bitwarden.ui.platform.components.BitwardenClickableText @@ -52,6 +51,8 @@ import com.x8bit.bitwarden.ui.platform.components.BitwardenPlaceholderAccountAct import com.x8bit.bitwarden.ui.platform.components.BitwardenScaffold import com.x8bit.bitwarden.ui.platform.components.BitwardenTopAppBar import com.x8bit.bitwarden.ui.platform.components.OverflowMenuItemData +import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager +import com.x8bit.bitwarden.ui.platform.theme.LocalIntentManager import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList @@ -66,7 +67,7 @@ fun LoginScreen( onNavigateToEnterpriseSignOn: () -> Unit, onNavigateToLoginWithDevice: () -> Unit, viewModel: LoginViewModel = hiltViewModel(), - intentHandler: IntentHandler = IntentHandler(context = LocalContext.current), + intentManager: IntentManager = LocalIntentManager.current, ) { val state by viewModel.stateFlow.collectAsStateWithLifecycle() val context = LocalContext.current @@ -74,7 +75,7 @@ fun LoginScreen( when (event) { LoginEvent.NavigateBack -> onNavigateBack() is LoginEvent.NavigateToCaptcha -> { - intentHandler.startCustomTabsActivity(uri = event.uri) + intentManager.startCustomTabsActivity(uri = event.uri) } LoginEvent.NavigateToEnterpriseSignOn -> onNavigateToEnterpriseSignOn() diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutScreen.kt index 602e3eaa2..99c5bd05f 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutScreen.kt @@ -41,14 +41,15 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.x8bit.bitwarden.R import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect -import com.x8bit.bitwarden.ui.platform.base.util.IntentHandler import com.x8bit.bitwarden.ui.platform.base.util.Text import com.x8bit.bitwarden.ui.platform.base.util.asText import com.x8bit.bitwarden.ui.platform.components.BitwardenExternalLinkRow import com.x8bit.bitwarden.ui.platform.components.BitwardenScaffold import com.x8bit.bitwarden.ui.platform.components.BitwardenTopAppBar import com.x8bit.bitwarden.ui.platform.components.BitwardenWideSwitch +import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme +import com.x8bit.bitwarden.ui.platform.theme.LocalIntentManager /** * Displays the about screen. @@ -59,7 +60,7 @@ import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme fun AboutScreen( onNavigateBack: () -> Unit, viewModel: AboutViewModel = hiltViewModel(), - intentHandler: IntentHandler = IntentHandler(context = LocalContext.current), + intentManager: IntentManager = LocalIntentManager.current, ) { val state by viewModel.stateFlow.collectAsStateWithLifecycle() val context = LocalContext.current @@ -69,15 +70,15 @@ fun AboutScreen( AboutEvent.NavigateBack -> onNavigateBack.invoke() AboutEvent.NavigateToHelpCenter -> { - intentHandler.launchUri("https://bitwarden.com/help".toUri()) + intentManager.launchUri("https://bitwarden.com/help".toUri()) } AboutEvent.NavigateToLearnAboutOrganizations -> { - intentHandler.launchUri("https://bitwarden.com/help/about-organizations".toUri()) + intentManager.launchUri("https://bitwarden.com/help/about-organizations".toUri()) } AboutEvent.NavigateToWebVault -> { - intentHandler.launchUri("https://vault.bitwarden.com".toUri()) + intentManager.launchUri("https://vault.bitwarden.com".toUri()) } is AboutEvent.ShowToast -> { diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/AccountSecurityScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/AccountSecurityScreen.kt index db2052f53..991b8638b 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/AccountSecurityScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/AccountSecurityScreen.kt @@ -34,7 +34,6 @@ import com.x8bit.bitwarden.R import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeout import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeoutAction import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect -import com.x8bit.bitwarden.ui.platform.base.util.IntentHandler import com.x8bit.bitwarden.ui.platform.base.util.Text import com.x8bit.bitwarden.ui.platform.components.BitwardenExternalLinkRow import com.x8bit.bitwarden.ui.platform.components.BitwardenListHeaderText @@ -48,6 +47,8 @@ import com.x8bit.bitwarden.ui.platform.components.BitwardenTopAppBar import com.x8bit.bitwarden.ui.platform.components.BitwardenTwoButtonDialog import com.x8bit.bitwarden.ui.platform.components.BitwardenWideSwitch import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenTimePickerDialog +import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager +import com.x8bit.bitwarden.ui.platform.theme.LocalIntentManager import com.x8bit.bitwarden.ui.platform.theme.LocalNonMaterialColors import com.x8bit.bitwarden.ui.platform.theme.LocalNonMaterialTypography import com.x8bit.bitwarden.ui.platform.util.displayLabel @@ -66,7 +67,7 @@ fun AccountSecurityScreen( onNavigateBack: () -> Unit, onNavigateToDeleteAccount: () -> Unit, viewModel: AccountSecurityViewModel = hiltViewModel(), - intentHandler: IntentHandler = IntentHandler(context = LocalContext.current), + intentManager: IntentManager = LocalIntentManager.current, ) { val state by viewModel.stateFlow.collectAsState() val context = LocalContext.current @@ -78,7 +79,7 @@ fun AccountSecurityScreen( AccountSecurityEvent.NavigateToDeleteAccount -> onNavigateToDeleteAccount() AccountSecurityEvent.NavigateToFingerprintPhrase -> { - intentHandler.launchUri("http://bitwarden.com/help/fingerprint-phrase".toUri()) + intentManager.launchUri("http://bitwarden.com/help/fingerprint-phrase".toUri()) } is AccountSecurityEvent.ShowToast -> { diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/manager/intent/IntentManager.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/manager/intent/IntentManager.kt new file mode 100644 index 000000000..a5c70c6a7 --- /dev/null +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/manager/intent/IntentManager.kt @@ -0,0 +1,35 @@ +package com.x8bit.bitwarden.ui.platform.manager.intent + +import android.content.Intent +import android.net.Uri + +/** + * A manager class for simplifying the handling of Android Intents within a given context. + */ +interface IntentManager { + + /** + * Starts an intent to exit the application. + */ + fun exitApplication() + + /** + * Start an activity using the provided [Intent]. + */ + fun startActivity(intent: Intent) + + /** + * Start a Custom Tabs Activity using the provided [Uri]. + */ + fun startCustomTabsActivity(uri: Uri) + + /** + * Start an activity to view the given [uri] in an external browser. + */ + fun launchUri(uri: Uri) + + /** + * Launches the share sheet with the given [text]. + */ + fun shareText(text: String) +} diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/base/util/IntentHandler.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/manager/intent/IntentManagerImpl.kt similarity index 61% rename from app/src/main/java/com/x8bit/bitwarden/ui/platform/base/util/IntentHandler.kt rename to app/src/main/java/com/x8bit/bitwarden/ui/platform/manager/intent/IntentManagerImpl.kt index 14319123c..cc2990761 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/base/util/IntentHandler.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/manager/intent/IntentManagerImpl.kt @@ -1,4 +1,4 @@ -package com.x8bit.bitwarden.ui.platform.base.util +package com.x8bit.bitwarden.ui.platform.manager.intent import android.content.Context import android.content.Intent @@ -7,15 +7,15 @@ import androidx.browser.customtabs.CustomTabsIntent import com.x8bit.bitwarden.data.platform.annotation.OmitFromCoverage /** - * A utility class for simplifying the handling of Android Intents within a given context. + * The default implementation of the [IntentManager] for simplifying the handling of Android + * Intents within a given context. */ @OmitFromCoverage -class IntentHandler(private val context: Context) { +class IntentManagerImpl( + private val context: Context, +) : IntentManager { - /** - * Starts an intent to exit the application. - */ - fun exitApplication() { + override fun exitApplication() { // Note that we fire an explicit Intent rather than try to cast to an Activity and call // finish to avoid assumptions about what kind of context we have. val intent = Intent(Intent.ACTION_MAIN).apply { @@ -24,27 +24,18 @@ class IntentHandler(private val context: Context) { startActivity(intent) } - /** - * Start an activity using the provided [Intent]. - */ - fun startActivity(intent: Intent) { + override fun startActivity(intent: Intent) { context.startActivity(intent) } - /** - * Start a Custom Tabs Activity using the provided [Uri]. - */ - fun startCustomTabsActivity(uri: Uri) { + override fun startCustomTabsActivity(uri: Uri) { CustomTabsIntent .Builder() .build() .launchUrl(context, uri) } - /** - * Start an activity to view the given [uri] in an external browser. - */ - fun launchUri(uri: Uri) { + override fun launchUri(uri: Uri) { val newUri = if (uri.scheme == null) { uri.buildUpon().scheme("https").build() } else { @@ -53,10 +44,7 @@ class IntentHandler(private val context: Context) { startActivity(Intent(Intent.ACTION_VIEW, newUri)) } - /** - * Launches the share sheet with the given [text]. - */ - fun shareText(text: String) { + override fun shareText(text: String) { val sendIntent: Intent = Intent(Intent.ACTION_SEND).apply { putExtra(Intent.EXTRA_TEXT, text) type = "text/plain" diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/theme/BitwardenTheme.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/theme/BitwardenTheme.kt index 5da94b0e4..bb65c0142 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/theme/BitwardenTheme.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/theme/BitwardenTheme.kt @@ -22,6 +22,8 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalView import androidx.core.view.WindowCompat import com.x8bit.bitwarden.R +import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager +import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManagerImpl import com.x8bit.bitwarden.ui.platform.manager.permissions.PermissionsManager import com.x8bit.bitwarden.ui.platform.manager.permissions.PermissionsManagerImpl @@ -69,6 +71,7 @@ fun BitwardenTheme( LocalNonMaterialColors provides nonMaterialColors, LocalNonMaterialTypography provides nonMaterialTypography, LocalPermissionsManager provides PermissionsManagerImpl(context as Activity), + LocalIntentManager provides IntentManagerImpl(context), ) { // Set overall theme based on color scheme and typography settings MaterialTheme( @@ -156,7 +159,14 @@ private fun Int.toColor(context: Context): Color = Color(context.getColor(this)) /** - * Provides access to non material theme typography throughout the app. + * Provides access to the intent manager throughout the app. + */ +val LocalIntentManager: ProvidableCompositionLocal = compositionLocalOf { + error("CompositionLocal LocalIntentManager not present") +} + +/** + * Provides access to the permission manager throughout the app. */ val LocalPermissionsManager: ProvidableCompositionLocal = compositionLocalOf { error("CompositionLocal LocalPermissionsManager not present") diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/send/SendScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/send/SendScreen.kt index 2771584f7..8353c6759 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/send/SendScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/send/SendScreen.kt @@ -28,7 +28,6 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.x8bit.bitwarden.R import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect -import com.x8bit.bitwarden.ui.platform.base.util.IntentHandler import com.x8bit.bitwarden.ui.platform.components.BasicDialogState import com.x8bit.bitwarden.ui.platform.components.BitwardenBasicDialog import com.x8bit.bitwarden.ui.platform.components.BitwardenErrorContent @@ -40,6 +39,8 @@ import com.x8bit.bitwarden.ui.platform.components.BitwardenScaffold import com.x8bit.bitwarden.ui.platform.components.BitwardenSearchActionItem import com.x8bit.bitwarden.ui.platform.components.LoadingDialogState import com.x8bit.bitwarden.ui.platform.components.OverflowMenuItemData +import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager +import com.x8bit.bitwarden.ui.platform.theme.LocalIntentManager import com.x8bit.bitwarden.ui.tools.feature.send.handlers.SendHandlers import kotlinx.collections.immutable.persistentListOf @@ -53,7 +54,7 @@ fun SendScreen( onNavigateToAddSend: () -> Unit, onNavigateToEditSend: (sendItemId: String) -> Unit, viewModel: SendViewModel = hiltViewModel(), - intentHandler: IntentHandler = IntentHandler(context = LocalContext.current), + intentManager: IntentManager = LocalIntentManager.current, ) { val state by viewModel.stateFlow.collectAsStateWithLifecycle() val context = LocalContext.current @@ -74,11 +75,11 @@ fun SendScreen( is SendEvent.NavigateToEditSend -> onNavigateToEditSend(event.sendId) is SendEvent.NavigateToAboutSend -> { - intentHandler.launchUri("https://bitwarden.com/products/send".toUri()) + intentManager.launchUri("https://bitwarden.com/products/send".toUri()) } is SendEvent.ShowShareSheet -> { - intentHandler.shareText(event.url) + intentManager.shareText(event.url) } is SendEvent.ShowToast -> { diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/send/addsend/AddSendScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/send/addsend/AddSendScreen.kt index a508338fd..63204a1bd 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/send/addsend/AddSendScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/tools/feature/send/addsend/AddSendScreen.kt @@ -22,7 +22,6 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.x8bit.bitwarden.R import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect -import com.x8bit.bitwarden.ui.platform.base.util.IntentHandler import com.x8bit.bitwarden.ui.platform.components.BasicDialogState import com.x8bit.bitwarden.ui.platform.components.BitwardenBasicDialog import com.x8bit.bitwarden.ui.platform.components.BitwardenErrorContent @@ -35,6 +34,8 @@ import com.x8bit.bitwarden.ui.platform.components.BitwardenTopAppBar import com.x8bit.bitwarden.ui.platform.components.BitwardenTwoButtonDialog import com.x8bit.bitwarden.ui.platform.components.LoadingDialogState import com.x8bit.bitwarden.ui.platform.components.OverflowMenuItemData +import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager +import com.x8bit.bitwarden.ui.platform.theme.LocalIntentManager import com.x8bit.bitwarden.ui.platform.util.persistentListOfNotNull import com.x8bit.bitwarden.ui.tools.feature.send.addsend.handlers.AddSendHandlers @@ -46,7 +47,7 @@ import com.x8bit.bitwarden.ui.tools.feature.send.addsend.handlers.AddSendHandler @Composable fun AddSendScreen( viewModel: AddSendViewModel = hiltViewModel(), - intentHandler: IntentHandler = IntentHandler(LocalContext.current), + intentManager: IntentManager = LocalIntentManager.current, onNavigateBack: () -> Unit, ) { val state by viewModel.stateFlow.collectAsStateWithLifecycle() @@ -58,7 +59,7 @@ fun AddSendScreen( when (event) { is AddSendEvent.NavigateBack -> onNavigateBack() is AddSendEvent.ShowShareSheet -> { - intentHandler.shareText(event.message) + intentManager.shareText(event.message) } is AddSendEvent.ShowToast -> { diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreen.kt index 20713a8ba..a2ace6a03 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreen.kt @@ -27,7 +27,6 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.x8bit.bitwarden.R import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect -import com.x8bit.bitwarden.ui.platform.base.util.IntentHandler import com.x8bit.bitwarden.ui.platform.base.util.asText import com.x8bit.bitwarden.ui.platform.components.BasicDialogState import com.x8bit.bitwarden.ui.platform.components.BitwardenBasicDialog @@ -40,6 +39,8 @@ import com.x8bit.bitwarden.ui.platform.components.BitwardenScaffold import com.x8bit.bitwarden.ui.platform.components.BitwardenTopAppBar import com.x8bit.bitwarden.ui.platform.components.LoadingDialogState import com.x8bit.bitwarden.ui.platform.components.OverflowMenuItemData +import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager +import com.x8bit.bitwarden.ui.platform.theme.LocalIntentManager import com.x8bit.bitwarden.ui.vault.feature.item.handlers.VaultCardItemTypeHandlers import com.x8bit.bitwarden.ui.vault.feature.item.handlers.VaultCommonItemTypeHandlers import com.x8bit.bitwarden.ui.vault.feature.item.handlers.VaultLoginItemTypeHandlers @@ -53,7 +54,7 @@ import kotlinx.collections.immutable.persistentListOf @Composable fun VaultItemScreen( viewModel: VaultItemViewModel = hiltViewModel(), - intentHandler: IntentHandler = IntentHandler(context = LocalContext.current), + intentManager: IntentManager = LocalIntentManager.current, onNavigateBack: () -> Unit, onNavigateToVaultAddEditItem: (vaultItemId: String) -> Unit, onNavigateToMoveToOrganization: (vaultItemId: String) -> Unit, @@ -75,7 +76,7 @@ fun VaultItemScreen( Toast.makeText(context, "Not yet implemented.", Toast.LENGTH_SHORT).show() } - is VaultItemEvent.NavigateToUri -> intentHandler.launchUri(event.uri.toUri()) + is VaultItemEvent.NavigateToUri -> intentManager.launchUri(event.uri.toUri()) is VaultItemEvent.NavigateToAttachments -> { // TODO implement attachments in BIT-522 diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/manualcodeentry/ManualCodeEntryScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/manualcodeentry/ManualCodeEntryScreen.kt index 0cc831775..804780390 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/manualcodeentry/ManualCodeEntryScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/manualcodeentry/ManualCodeEntryScreen.kt @@ -32,14 +32,15 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.x8bit.bitwarden.R import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect -import com.x8bit.bitwarden.ui.platform.base.util.IntentHandler import com.x8bit.bitwarden.ui.platform.base.util.toAnnotatedString import com.x8bit.bitwarden.ui.platform.components.BitwardenFilledTonalButton import com.x8bit.bitwarden.ui.platform.components.BitwardenScaffold import com.x8bit.bitwarden.ui.platform.components.BitwardenTextField import com.x8bit.bitwarden.ui.platform.components.BitwardenTopAppBar import com.x8bit.bitwarden.ui.platform.components.BitwardenTwoButtonDialog +import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager import com.x8bit.bitwarden.ui.platform.manager.permissions.PermissionsManager +import com.x8bit.bitwarden.ui.platform.theme.LocalIntentManager import com.x8bit.bitwarden.ui.platform.theme.LocalPermissionsManager /** @@ -52,7 +53,7 @@ fun ManualCodeEntryScreen( onNavigateBack: () -> Unit, onNavigateToQrCodeScreen: () -> Unit, viewModel: ManualCodeEntryViewModel = hiltViewModel(), - intentHandler: IntentHandler = IntentHandler(LocalContext.current), + intentManager: IntentManager = LocalIntentManager.current, permissionsManager: PermissionsManager = LocalPermissionsManager.current, ) { var shouldShowPermissionDialog by rememberSaveable { mutableStateOf(false) } @@ -74,7 +75,7 @@ fun ManualCodeEntryScreen( val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) intent.data = Uri.parse("package:" + context.packageName) - intentHandler.startActivity(intent = intent) + intentManager.startActivity(intent = intent) } is ManualCodeEntryEvent.ShowToast -> { diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreen.kt index 13cb56eb6..1a1bd16c8 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreen.kt @@ -35,7 +35,6 @@ import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import com.x8bit.bitwarden.R import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect -import com.x8bit.bitwarden.ui.platform.base.util.IntentHandler import com.x8bit.bitwarden.ui.platform.base.util.asText import com.x8bit.bitwarden.ui.platform.base.util.showNotYetImplementedToast import com.x8bit.bitwarden.ui.platform.components.BasicDialogState @@ -53,6 +52,8 @@ import com.x8bit.bitwarden.ui.platform.components.BitwardenTwoButtonDialog import com.x8bit.bitwarden.ui.platform.components.LoadingDialogState import com.x8bit.bitwarden.ui.platform.components.OverflowMenuItemData import com.x8bit.bitwarden.ui.platform.components.model.AccountSummary +import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager +import com.x8bit.bitwarden.ui.platform.theme.LocalIntentManager import com.x8bit.bitwarden.ui.vault.feature.vault.model.VaultFilterType import com.x8bit.bitwarden.ui.vault.model.VaultItemListingType import kotlinx.collections.immutable.persistentListOf @@ -71,7 +72,7 @@ fun VaultScreen( onNavigateToVaultEditItemScreen: (vaultItemId: String) -> Unit, onNavigateToVaultItemListingScreen: (vaultItemType: VaultItemListingType) -> Unit, onDimBottomNavBarRequest: (shouldDim: Boolean) -> Unit, - intentHandler: IntentHandler = IntentHandler(LocalContext.current), + intentManager: IntentManager = LocalIntentManager.current, ) { val state by viewModel.stateFlow.collectAsState() val context = LocalContext.current @@ -107,7 +108,7 @@ fun VaultScreen( onNavigateToVaultItemListingScreen(event.itemListingType) } - VaultEvent.NavigateOutOfApp -> intentHandler.exitApplication() + VaultEvent.NavigateOutOfApp -> intentManager.exitApplication() is VaultEvent.ShowToast -> { Toast .makeText(context, event.message(context.resources), Toast.LENGTH_SHORT) diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/createaccount/CreateAccountScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/createaccount/CreateAccountScreenTest.kt index 33962f0cb..381d3456e 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/createaccount/CreateAccountScreenTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/createaccount/CreateAccountScreenTest.kt @@ -1,6 +1,5 @@ package com.x8bit.bitwarden.ui.auth.feature.createaccount -import android.content.Intent import android.net.Uri import androidx.compose.ui.test.assertCountEquals import androidx.compose.ui.test.assertIsDisplayed @@ -17,6 +16,7 @@ import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performScrollTo import androidx.compose.ui.test.performTextInput import androidx.core.net.toUri +import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFlow import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.AcceptPoliciesToggle import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.CheckDataBreachesToggle import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.CloseClick @@ -26,71 +26,64 @@ import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.Pas import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.PasswordInputChange import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.SubmitClick import com.x8bit.bitwarden.ui.platform.base.BaseComposeTest -import com.x8bit.bitwarden.ui.platform.base.util.IntentHandler import com.x8bit.bitwarden.ui.platform.base.util.asText import com.x8bit.bitwarden.ui.platform.components.BasicDialogState +import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager import io.mockk.every +import io.mockk.just import io.mockk.mockk +import io.mockk.runs import io.mockk.verify import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.emptyFlow -import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.update import org.junit.Assert.assertTrue +import org.junit.Before import org.junit.Test class CreateAccountScreenTest : BaseComposeTest() { - @Test - fun `app bar submit click should send SubmitClick action`() { - val viewModel = mockk(relaxed = true) { - every { stateFlow } returns MutableStateFlow(DEFAULT_STATE) - every { eventFlow } returns emptyFlow() - every { trySendAction(SubmitClick) } returns Unit - } + private var onNavigateBackCalled = false + private var onNavigateToLoginCalled = false + + private val intentManager = mockk(relaxed = true) { + every { startCustomTabsActivity(any()) } just runs + every { startActivity(any()) } just runs + } + + private val mutableStateFlow = MutableStateFlow(DEFAULT_STATE) + private val mutableEventFlow = bufferedMutableSharedFlow() + private val viewModel = mockk(relaxed = true) { + every { stateFlow } returns mutableStateFlow + every { eventFlow } returns mutableEventFlow + every { trySendAction(any()) } just runs + } + + @Before + fun setup() { composeTestRule.setContent { CreateAccountScreen( - onNavigateBack = {}, - onNavigateToLogin = { _, _ -> }, + onNavigateBack = { onNavigateBackCalled = true }, + onNavigateToLogin = { _, _ -> onNavigateToLoginCalled = true }, + intentManager = intentManager, viewModel = viewModel, ) } + } + + @Test + fun `app bar submit click should send SubmitClick action`() { composeTestRule.onNodeWithText("Submit").performClick() verify { viewModel.trySendAction(SubmitClick) } } @Test fun `close click should send CloseClick action`() { - val viewModel = mockk(relaxed = true) { - every { stateFlow } returns MutableStateFlow(DEFAULT_STATE) - every { eventFlow } returns emptyFlow() - every { trySendAction(CloseClick) } returns Unit - } - composeTestRule.setContent { - CreateAccountScreen( - onNavigateBack = {}, - onNavigateToLogin = { _, _ -> }, - viewModel = viewModel, - ) - } composeTestRule.onNodeWithContentDescription("Close").performClick() verify { viewModel.trySendAction(CloseClick) } } @Test fun `check data breaches click should send CheckDataBreachesToggle action`() { - val viewModel = mockk(relaxed = true) { - every { stateFlow } returns MutableStateFlow(DEFAULT_STATE) - every { eventFlow } returns emptyFlow() - every { trySendAction(CheckDataBreachesToggle(true)) } returns Unit - } - composeTestRule.setContent { - CreateAccountScreen( - onNavigateBack = {}, - onNavigateToLogin = { _, _ -> }, - viewModel = viewModel, - ) - } composeTestRule .onNodeWithText("Check known data breaches for this password") .performScrollTo() @@ -100,19 +93,6 @@ class CreateAccountScreenTest : BaseComposeTest() { @Test fun `accept policies should be toggled on or off according to the state`() { - val mutableStateFlow = MutableStateFlow(DEFAULT_STATE) - val viewModel = mockk(relaxed = true) { - every { stateFlow } returns mutableStateFlow - every { eventFlow } returns emptyFlow() - every { trySendAction(AcceptPoliciesToggle(true)) } returns Unit - } - composeTestRule.setContent { - CreateAccountScreen( - onNavigateBack = {}, - onNavigateToLogin = { _, _ -> }, - viewModel = viewModel, - ) - } composeTestRule .onNodeWithText("By activating this switch you agree", substring = true) .assertIsOff() @@ -126,18 +106,6 @@ class CreateAccountScreenTest : BaseComposeTest() { @Test fun `accept policies click should send AcceptPoliciesToggle action`() { - val viewModel = mockk(relaxed = true) { - every { stateFlow } returns MutableStateFlow(DEFAULT_STATE) - every { eventFlow } returns emptyFlow() - every { trySendAction(AcceptPoliciesToggle(true)) } returns Unit - } - composeTestRule.setContent { - CreateAccountScreen( - onNavigateBack = {}, - onNavigateToLogin = { _, _ -> }, - viewModel = viewModel, - ) - } composeTestRule .onNodeWithText("By activating this switch you agree", substring = true) .performScrollTo() @@ -147,188 +115,61 @@ class CreateAccountScreenTest : BaseComposeTest() { @Test fun `NavigateBack event should invoke navigate back lambda`() { - var onNavigateBackCalled = false - val onNavigateBack = { onNavigateBackCalled = true } - val viewModel = mockk(relaxed = true) { - every { stateFlow } returns MutableStateFlow(DEFAULT_STATE) - every { eventFlow } returns flowOf(CreateAccountEvent.NavigateBack) - } - composeTestRule.setContent { - CreateAccountScreen( - onNavigateBack = onNavigateBack, - onNavigateToLogin = { _, _ -> }, - viewModel = viewModel, - ) - } + mutableEventFlow.tryEmit(CreateAccountEvent.NavigateBack) assertTrue(onNavigateBackCalled) } @Test fun `NavigateToLogin event should invoke navigate login lambda`() { - var onNavigateToLoginCalled = false - val onNavigateToLogin = { _: String, _: String -> onNavigateToLoginCalled = true } - val viewModel = mockk(relaxed = true) { - every { stateFlow } returns MutableStateFlow(DEFAULT_STATE) - every { eventFlow } returns flowOf( - CreateAccountEvent.NavigateToLogin( - email = "", - captchaToken = "", - ), - ) - } - composeTestRule.setContent { - CreateAccountScreen( - onNavigateBack = {}, - onNavigateToLogin = onNavigateToLogin, - viewModel = viewModel, - ) - } + mutableEventFlow.tryEmit(CreateAccountEvent.NavigateToLogin(email = "", captchaToken = "")) assertTrue(onNavigateToLoginCalled) } @Test - fun `NavigateToCaptcha event should invoke intent handler`() { + fun `NavigateToCaptcha event should invoke intent manager`() { val mockUri = mockk() - val intentHandler = mockk(relaxed = true) { - every { startCustomTabsActivity(mockUri) } returns Unit - } - val viewModel = mockk(relaxed = true) { - every { stateFlow } returns MutableStateFlow(DEFAULT_STATE) - every { eventFlow } returns flowOf( - CreateAccountEvent.NavigateToCaptcha( - uri = mockUri, - ), - ) - } - composeTestRule.setContent { - CreateAccountScreen( - onNavigateBack = {}, - onNavigateToLogin = { _, _ -> }, - viewModel = viewModel, - intentHandler = intentHandler, - ) - } + mutableEventFlow.tryEmit(CreateAccountEvent.NavigateToCaptcha(uri = mockUri)) verify { - intentHandler.startCustomTabsActivity(mockUri) + intentManager.startCustomTabsActivity(mockUri) } } @Test - fun `NavigateToPrivacyPolicy event should invoke intent handler`() { - val expectedIntent = - Intent(Intent.ACTION_VIEW, Uri.parse("https://bitwarden.com/privacy/")) - val intentHandler = mockk(relaxed = true) { - every { startActivity(expectedIntent) } returns Unit - } - val viewModel = mockk(relaxed = true) { - every { stateFlow } returns MutableStateFlow(DEFAULT_STATE) - every { eventFlow } returns flowOf(CreateAccountEvent.NavigateToPrivacyPolicy) - } - composeTestRule.setContent { - CreateAccountScreen( - onNavigateBack = {}, - onNavigateToLogin = { _, _ -> }, - viewModel = viewModel, - intentHandler = intentHandler, - ) - } + fun `NavigateToPrivacyPolicy event should invoke intent manager`() { + mutableEventFlow.tryEmit(CreateAccountEvent.NavigateToPrivacyPolicy) verify { - intentHandler.launchUri("https://bitwarden.com/privacy/".toUri()) + intentManager.launchUri("https://bitwarden.com/privacy/".toUri()) } } @Test - fun `NavigateToTerms event should invoke intent handler`() { - val expectedIntent = - Intent(Intent.ACTION_VIEW, Uri.parse("https://bitwarden.com/terms/")) - val intentHandler = mockk(relaxed = true) { - every { startActivity(expectedIntent) } returns Unit - } - val viewModel = mockk(relaxed = true) { - every { stateFlow } returns MutableStateFlow(DEFAULT_STATE) - every { eventFlow } returns flowOf(CreateAccountEvent.NavigateToTerms) - } - composeTestRule.setContent { - CreateAccountScreen( - onNavigateBack = {}, - onNavigateToLogin = { _, _ -> }, - viewModel = viewModel, - intentHandler = intentHandler, - ) - } + fun `NavigateToTerms event should invoke intent manager`() { + mutableEventFlow.tryEmit(CreateAccountEvent.NavigateToTerms) verify { - intentHandler.launchUri("https://bitwarden.com/terms/".toUri()) + intentManager.launchUri("https://bitwarden.com/terms/".toUri()) } } @Test fun `email input change should send EmailInputChange action`() { - val viewModel = mockk(relaxed = true) { - every { stateFlow } returns MutableStateFlow(DEFAULT_STATE) - every { eventFlow } returns emptyFlow() - every { trySendAction(EmailInputChange("input")) } returns Unit - } - composeTestRule.setContent { - CreateAccountScreen( - onNavigateBack = {}, - onNavigateToLogin = { _, _ -> }, - viewModel = viewModel, - ) - } composeTestRule.onNodeWithText("Email address").performTextInput(TEST_INPUT) verify { viewModel.trySendAction(EmailInputChange(TEST_INPUT)) } } @Test fun `password input change should send PasswordInputChange action`() { - val viewModel = mockk(relaxed = true) { - every { stateFlow } returns MutableStateFlow(DEFAULT_STATE) - every { eventFlow } returns emptyFlow() - every { trySendAction(PasswordInputChange("input")) } returns Unit - } - composeTestRule.setContent { - CreateAccountScreen( - onNavigateBack = {}, - onNavigateToLogin = { _, _ -> }, - viewModel = viewModel, - ) - } composeTestRule.onNodeWithText("Master password").performTextInput(TEST_INPUT) verify { viewModel.trySendAction(PasswordInputChange(TEST_INPUT)) } } @Test fun `confirm password input change should send ConfirmPasswordInputChange action`() { - val viewModel = mockk(relaxed = true) { - every { stateFlow } returns MutableStateFlow(DEFAULT_STATE) - every { eventFlow } returns emptyFlow() - every { trySendAction(ConfirmPasswordInputChange("input")) } returns Unit - } - composeTestRule.setContent { - CreateAccountScreen( - onNavigateBack = {}, - onNavigateToLogin = { _, _ -> }, - viewModel = viewModel, - ) - } composeTestRule.onNodeWithText("Re-type master password").performTextInput(TEST_INPUT) verify { viewModel.trySendAction(ConfirmPasswordInputChange(TEST_INPUT)) } } @Test fun `password hint input change should send PasswordHintChange action`() { - val viewModel = mockk(relaxed = true) { - every { stateFlow } returns MutableStateFlow(DEFAULT_STATE) - every { eventFlow } returns emptyFlow() - every { trySendAction(PasswordHintChange("input")) } returns Unit - } - composeTestRule.setContent { - CreateAccountScreen( - onNavigateBack = {}, - onNavigateToLogin = { _, _ -> }, - viewModel = viewModel, - ) - } composeTestRule .onNodeWithText("Master password hint (optional)") .performTextInput(TEST_INPUT) @@ -337,26 +178,15 @@ class CreateAccountScreenTest : BaseComposeTest() { @Test fun `clicking OK on the error dialog should send ErrorDialogDismiss action`() { - val viewModel = mockk(relaxed = true) { - every { stateFlow } returns MutableStateFlow( - DEFAULT_STATE.copy( - dialog = CreateAccountDialog.Error( - BasicDialogState.Shown( - title = "title".asText(), - message = "message".asText(), - ), + mutableStateFlow.update { + it.copy( + dialog = CreateAccountDialog.Error( + BasicDialogState.Shown( + title = "title".asText(), + message = "message".asText(), ), ), ) - every { eventFlow } returns emptyFlow() - every { trySendAction(CreateAccountAction.ErrorDialogDismiss) } returns Unit - } - composeTestRule.setContent { - CreateAccountScreen( - onNavigateBack = {}, - onNavigateToLogin = { _, _ -> }, - viewModel = viewModel, - ) } composeTestRule .onAllNodesWithText("Ok") @@ -367,19 +197,8 @@ class CreateAccountScreenTest : BaseComposeTest() { @Test fun `clicking No on the HIBP dialog should send ErrorDialogDismiss action`() { - val viewModel = mockk(relaxed = true) { - every { stateFlow } returns MutableStateFlow( - DEFAULT_STATE.copy(dialog = CreateAccountDialog.HaveIBeenPwned), - ) - every { eventFlow } returns emptyFlow() - every { trySendAction(CreateAccountAction.ErrorDialogDismiss) } returns Unit - } - composeTestRule.setContent { - CreateAccountScreen( - onNavigateBack = {}, - onNavigateToLogin = { _, _ -> }, - viewModel = viewModel, - ) + mutableStateFlow.update { + it.copy(dialog = CreateAccountDialog.HaveIBeenPwned) } composeTestRule .onAllNodesWithText("No") @@ -390,19 +209,8 @@ class CreateAccountScreenTest : BaseComposeTest() { @Test fun `clicking Yes on the HIBP dialog should send ContinueWithBreachedPasswordClick action`() { - val viewModel = mockk(relaxed = true) { - every { stateFlow } returns MutableStateFlow( - DEFAULT_STATE.copy(dialog = CreateAccountDialog.HaveIBeenPwned), - ) - every { eventFlow } returns emptyFlow() - every { trySendAction(CreateAccountAction.ErrorDialogDismiss) } returns Unit - } - composeTestRule.setContent { - CreateAccountScreen( - onNavigateBack = {}, - onNavigateToLogin = { _, _ -> }, - viewModel = viewModel, - ) + mutableStateFlow.update { + it.copy(dialog = CreateAccountDialog.HaveIBeenPwned) } composeTestRule .onAllNodesWithText("Yes") @@ -413,44 +221,21 @@ class CreateAccountScreenTest : BaseComposeTest() { @Test fun `when BasicDialogState is Shown should show dialog`() { - val viewModel = mockk(relaxed = true) { - every { stateFlow } returns MutableStateFlow( - DEFAULT_STATE.copy( - dialog = CreateAccountDialog.Error( - BasicDialogState.Shown( - title = "title".asText(), - message = "message".asText(), - ), + mutableStateFlow.update { + it.copy( + dialog = CreateAccountDialog.Error( + BasicDialogState.Shown( + title = "title".asText(), + message = "message".asText(), ), ), ) - every { eventFlow } returns emptyFlow() - every { trySendAction(CreateAccountAction.ErrorDialogDismiss) } returns Unit - } - composeTestRule.setContent { - CreateAccountScreen( - onNavigateBack = {}, - onNavigateToLogin = { _, _ -> }, - viewModel = viewModel, - ) } composeTestRule.onNode(isDialog()).assertIsDisplayed() } @Test fun `password strength should change as state changes`() { - val mutableStateFlow = MutableStateFlow(DEFAULT_STATE) - val viewModel = mockk(relaxed = true) { - every { stateFlow } returns mutableStateFlow - every { eventFlow } returns emptyFlow() - } - composeTestRule.setContent { - CreateAccountScreen( - onNavigateBack = {}, - onNavigateToLogin = { _, _ -> }, - viewModel = viewModel, - ) - } mutableStateFlow.update { DEFAULT_STATE.copy(passwordStrengthState = PasswordStrengthState.WEAK_1) } @@ -479,23 +264,10 @@ class CreateAccountScreenTest : BaseComposeTest() { @Test fun `toggling one password field visibility should toggle the other`() { - val viewModel = mockk(relaxed = true) { - every { stateFlow } returns MutableStateFlow(DEFAULT_STATE) - every { eventFlow } returns emptyFlow() - } - composeTestRule.setContent { - CreateAccountScreen( - onNavigateBack = {}, - onNavigateToLogin = { _, _ -> }, - viewModel = viewModel, - ) - } - // should start with 2 Show buttons: composeTestRule .onAllNodesWithContentDescription("Show") - .assertCountEquals(2) - .get(0) + .assertCountEquals(2)[0] .performClick() // after clicking there should be no Show buttons: @@ -506,8 +278,7 @@ class CreateAccountScreenTest : BaseComposeTest() { // and there should be 2 hide buttons now, and we'll click the second one: composeTestRule .onAllNodesWithContentDescription("Hide") - .assertCountEquals(2) - .get(1) + .assertCountEquals(2)[1] .performClick() // then there should be two show buttons again diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginScreenTest.kt index e3a6a5a67..af0029724 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginScreenTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/login/LoginScreenTest.kt @@ -15,10 +15,10 @@ import androidx.compose.ui.test.performScrollTo import androidx.compose.ui.test.performTextInput 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.IntentHandler import com.x8bit.bitwarden.ui.platform.components.BasicDialogState import com.x8bit.bitwarden.ui.platform.components.LoadingDialogState import com.x8bit.bitwarden.ui.platform.components.model.AccountSummary +import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager import com.x8bit.bitwarden.ui.util.assertLockOrLogoutDialogIsDisplayed import com.x8bit.bitwarden.ui.util.assertLogoutConfirmationDialogIsDisplayed import com.x8bit.bitwarden.ui.util.assertNoDialogExists @@ -41,7 +41,7 @@ import org.junit.Before import org.junit.Test class LoginScreenTest : BaseComposeTest() { - private val intentHandler = mockk(relaxed = true) { + private val intentManager = mockk(relaxed = true) { every { startCustomTabsActivity(any()) } returns Unit } private var onNavigateBackCalled = false @@ -62,7 +62,7 @@ class LoginScreenTest : BaseComposeTest() { onNavigateToEnterpriseSignOn = { onNavigateToEnterpriseSignOnCalled = true }, onNavigateToLoginWithDevice = { onNavigateToLoginWithDeviceCalled = true }, viewModel = viewModel, - intentHandler = intentHandler, + intentManager = intentManager, ) } } @@ -262,10 +262,10 @@ class LoginScreenTest : BaseComposeTest() { } @Test - fun `NavigateToCaptcha should call intentHandler startCustomTabsActivity`() { + fun `NavigateToCaptcha should call intentManager startCustomTabsActivity`() { val mockUri = mockk() mutableEventFlow.tryEmit(LoginEvent.NavigateToCaptcha(mockUri)) - verify { intentHandler.startCustomTabsActivity(mockUri) } + verify { intentManager.startCustomTabsActivity(mockUri) } } @Test diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutScreenTest.kt index 23ae245f4..02fccda59 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutScreenTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutScreenTest.kt @@ -11,43 +11,55 @@ import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.core.net.toUri +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.IntentHandler import com.x8bit.bitwarden.ui.platform.base.util.asText -import io.mockk.Runs +import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager import io.mockk.every import io.mockk.just import io.mockk.mockk +import io.mockk.runs import io.mockk.verify import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.emptyFlow -import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.update import kotlinx.coroutines.test.runTest import org.junit.Assert.assertTrue +import org.junit.Before import org.junit.Test class AboutScreenTest : BaseComposeTest() { + private var haveCalledNavigateBack = false + private val mutableStateFlow = MutableStateFlow( AboutState( version = "Version: 1.0.0 (1)".asText(), isSubmitCrashLogsEnabled = false, ), ) + private val mutableEventFlow = bufferedMutableSharedFlow() + val viewModel: AboutViewModel = mockk { + every { stateFlow } returns mutableStateFlow + every { eventFlow } returns mutableEventFlow + every { trySendAction(any()) } just runs + } - @Test - fun `on back click should send BackClick`() { - val viewModel: AboutViewModel = mockk { - every { stateFlow } returns mutableStateFlow - every { eventFlow } returns emptyFlow() - every { trySendAction(AboutAction.BackClick) } returns Unit - } + private val intentManager: IntentManager = mockk { + every { launchUri(any()) } just runs + } + + @Before + fun setup() { composeTestRule.setContent { AboutScreen( viewModel = viewModel, - onNavigateBack = { }, + intentManager = intentManager, + onNavigateBack = { haveCalledNavigateBack = true }, ) } + } + + @Test + fun `on back click should send BackClick`() { composeTestRule.onNodeWithContentDescription("Back").performClick() verify { viewModel.trySendAction(AboutAction.BackClick) } } @@ -55,17 +67,6 @@ class AboutScreenTest : BaseComposeTest() { @Suppress("MaxLineLength") @Test fun `on bitwarden help center click should display confirmation dialog and confirm click should emit HelpCenterClick`() { - val viewModel: AboutViewModel = mockk { - every { stateFlow } returns mutableStateFlow - every { eventFlow } returns emptyFlow() - every { trySendAction(AboutAction.HelpCenterClick) } returns Unit - } - composeTestRule.setContent { - AboutScreen( - viewModel = viewModel, - onNavigateBack = { }, - ) - } composeTestRule.onNode(isDialog()).assertDoesNotExist() composeTestRule.onNodeWithText("Bitwarden Help Center").performClick() composeTestRule.onNode(isDialog()).assertExists() @@ -82,17 +83,6 @@ class AboutScreenTest : BaseComposeTest() { @Suppress("MaxLineLength") @Test fun `on bitwarden web vault click should display confirmation dialog and confirm click should emit WebVaultClick`() { - val viewModel: AboutViewModel = mockk { - every { stateFlow } returns mutableStateFlow - every { eventFlow } returns emptyFlow() - every { trySendAction(AboutAction.WebVaultClick) } returns Unit - } - composeTestRule.setContent { - AboutScreen( - viewModel = viewModel, - onNavigateBack = { }, - ) - } composeTestRule.onNode(isDialog()).assertDoesNotExist() composeTestRule.onNodeWithText("Bitwarden web vault").performClick() composeTestRule.onNode(isDialog()).assertExists() @@ -109,17 +99,6 @@ class AboutScreenTest : BaseComposeTest() { @Suppress("MaxLineLength") @Test fun `on learn about organizations click should display confirmation dialog and confirm click should emit LearnAboutOrganizationsClick`() { - val viewModel: AboutViewModel = mockk { - every { stateFlow } returns mutableStateFlow - every { eventFlow } returns emptyFlow() - every { trySendAction(AboutAction.LearnAboutOrganizationsClick) } returns Unit - } - composeTestRule.setContent { - AboutScreen( - viewModel = viewModel, - onNavigateBack = { }, - ) - } composeTestRule.onNode(isDialog()).assertDoesNotExist() composeTestRule.onNodeWithText("Learn about organizations").performClick() composeTestRule.onNode(isDialog()).assertExists() @@ -135,97 +114,37 @@ class AboutScreenTest : BaseComposeTest() { @Test fun `on NavigateBack should call onNavigateBack`() { - var haveCalledNavigateBack = false - val viewModel = mockk { - every { stateFlow } returns mutableStateFlow - every { eventFlow } returns flowOf(AboutEvent.NavigateBack) - } - composeTestRule.setContent { - AboutScreen( - viewModel = viewModel, - onNavigateBack = { haveCalledNavigateBack = true }, - ) - } + mutableEventFlow.tryEmit(AboutEvent.NavigateBack) assertTrue(haveCalledNavigateBack) } @Test - fun `on NavigateToHelpCenter should call launchUri on IntentHandler`() { - val intentHandler = mockk { - every { launchUri(any()) } just Runs - } - val viewModel = mockk { - every { stateFlow } returns mutableStateFlow - every { eventFlow } returns flowOf(AboutEvent.NavigateToHelpCenter) - } - composeTestRule.setContent { - AboutScreen( - viewModel = viewModel, - onNavigateBack = { }, - intentHandler = intentHandler, - ) - } + fun `on NavigateToHelpCenter should call launchUri on IntentManager`() { + mutableEventFlow.tryEmit(AboutEvent.NavigateToHelpCenter) verify { - intentHandler.launchUri("https://bitwarden.com/help".toUri()) + intentManager.launchUri("https://bitwarden.com/help".toUri()) } } @Test - fun `on NavigateToLearnAboutOrganizations should call launchUri on IntentHandler`() { - val intentHandler = mockk { - every { launchUri(any()) } just Runs - } - val viewModel = mockk { - every { stateFlow } returns mutableStateFlow - every { eventFlow } returns flowOf(AboutEvent.NavigateToLearnAboutOrganizations) - } - composeTestRule.setContent { - AboutScreen( - viewModel = viewModel, - onNavigateBack = { }, - intentHandler = intentHandler, - ) - } + fun `on NavigateToLearnAboutOrganizations should call launchUri on IntentManager`() { + mutableEventFlow.tryEmit(AboutEvent.NavigateToLearnAboutOrganizations) verify { - intentHandler.launchUri("https://bitwarden.com/help/about-organizations".toUri()) + intentManager.launchUri("https://bitwarden.com/help/about-organizations".toUri()) } } @Test - fun `on NavigateToWebVault should call launchUri on IntentHandler`() { - val intentHandler = mockk { - every { launchUri(any()) } just Runs - } - val viewModel = mockk { - every { stateFlow } returns mutableStateFlow - every { eventFlow } returns flowOf(AboutEvent.NavigateToWebVault) - } - composeTestRule.setContent { - AboutScreen( - viewModel = viewModel, - onNavigateBack = { }, - intentHandler = intentHandler, - ) - } + fun `on NavigateToWebVault should call launchUri on IntentManager`() { + mutableEventFlow.tryEmit(AboutEvent.NavigateToWebVault) verify { - intentHandler.launchUri("https://vault.bitwarden.com".toUri()) + intentManager.launchUri("https://vault.bitwarden.com".toUri()) } } @Suppress("MaxLineLength") @Test fun `on rate the app click should display confirmation dialog and confirm click should emit RateAppClick`() { - val viewModel: AboutViewModel = mockk { - every { stateFlow } returns mutableStateFlow - every { eventFlow } returns emptyFlow() - every { trySendAction(AboutAction.RateAppClick) } returns Unit - } - composeTestRule.setContent { - AboutScreen( - viewModel = viewModel, - onNavigateBack = { }, - ) - } composeTestRule.onNode(isDialog()).assertDoesNotExist() composeTestRule.onNodeWithText("Rate the app").performClick() composeTestRule.onNode(isDialog()).assertExists() @@ -242,17 +161,6 @@ class AboutScreenTest : BaseComposeTest() { @Test fun `on submit crash logs toggle should send SubmitCrashLogsClick`() { val enabled = true - val viewModel: AboutViewModel = mockk { - every { stateFlow } returns mutableStateFlow - every { eventFlow } returns emptyFlow() - every { trySendAction(AboutAction.SubmitCrashLogsClick(enabled)) } returns Unit - } - composeTestRule.setContent { - AboutScreen( - viewModel = viewModel, - onNavigateBack = { }, - ) - } composeTestRule.onNodeWithText("Submit crash logs").performClick() verify { viewModel.trySendAction(AboutAction.SubmitCrashLogsClick(enabled)) @@ -260,16 +168,6 @@ class AboutScreenTest : BaseComposeTest() { } fun `on submit crash logs should be toggled on or off according to the state`() { - val viewModel = mockk(relaxed = true) { - every { eventFlow } returns emptyFlow() - every { stateFlow } returns mutableStateFlow - } - composeTestRule.setContent { - AboutScreen( - viewModel = viewModel, - onNavigateBack = { }, - ) - } composeTestRule.onNodeWithText("Submit crash logs").assertIsOff() mutableStateFlow.update { it.copy(isSubmitCrashLogsEnabled = true) } composeTestRule.onNodeWithText("Submit crash logs").assertIsOn() @@ -277,17 +175,6 @@ class AboutScreenTest : BaseComposeTest() { @Test fun `on version info click should send VersionClick`() { - val viewModel: AboutViewModel = mockk { - every { stateFlow } returns mutableStateFlow - every { eventFlow } returns emptyFlow() - every { trySendAction(AboutAction.VersionClick) } returns Unit - } - composeTestRule.setContent { - AboutScreen( - viewModel = viewModel, - onNavigateBack = { }, - ) - } composeTestRule.onNodeWithText("Version: 1.0.0 (1)").performClick() verify { viewModel.trySendAction(AboutAction.VersionClick) @@ -296,16 +183,6 @@ class AboutScreenTest : BaseComposeTest() { @Test fun `version should update according to the state`() = runTest { - val viewModel = mockk { - every { eventFlow } returns emptyFlow() - every { stateFlow } returns mutableStateFlow - } - composeTestRule.setContent { - AboutScreen( - viewModel = viewModel, - onNavigateBack = { }, - ) - } composeTestRule.onNodeWithText("Version: 1.0.0 (1)").assertIsDisplayed() mutableStateFlow.update { it.copy(version = "Version: 1.1.0 (2)".asText()) } diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/AccountSecurityScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/AccountSecurityScreenTest.kt index f7230cd65..116296669 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/AccountSecurityScreenTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/accountsecurity/AccountSecurityScreenTest.kt @@ -21,8 +21,8 @@ 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.bufferedMutableSharedFlow import com.x8bit.bitwarden.ui.platform.base.BaseComposeTest -import com.x8bit.bitwarden.ui.platform.base.util.IntentHandler import com.x8bit.bitwarden.ui.platform.base.util.asText +import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager import com.x8bit.bitwarden.ui.util.assertNoDialogExists import io.mockk.every import io.mockk.just @@ -41,7 +41,7 @@ class AccountSecurityScreenTest : BaseComposeTest() { private var onNavigateBackCalled = false private var onNavigateToDeleteAccountCalled = false - private val intentHandler = mockk { + private val intentManager = mockk { every { launchUri(any()) } just runs } private val mutableEventFlow = bufferedMutableSharedFlow() @@ -58,7 +58,7 @@ class AccountSecurityScreenTest : BaseComposeTest() { onNavigateBack = { onNavigateBackCalled = true }, onNavigateToDeleteAccount = { onNavigateToDeleteAccountCalled = true }, viewModel = viewModel, - intentHandler = intentHandler, + intentManager = intentManager, ) } } @@ -997,10 +997,10 @@ class AccountSecurityScreenTest : BaseComposeTest() { } @Test - fun `on NavigateToFingerprintPhrase should call launchUri on intentHandler`() { + fun `on NavigateToFingerprintPhrase should call launchUri on intentManager`() { mutableEventFlow.tryEmit(AccountSecurityEvent.NavigateToFingerprintPhrase) verify { - intentHandler.launchUri("http://bitwarden.com/help/fingerprint-phrase".toUri()) + intentManager.launchUri("http://bitwarden.com/help/fingerprint-phrase".toUri()) } } diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/send/SendScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/send/SendScreenTest.kt index 5c23476bd..13d116ca1 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/send/SendScreenTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/send/SendScreenTest.kt @@ -20,8 +20,8 @@ import androidx.compose.ui.test.performScrollToNode import androidx.core.net.toUri 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.IntentHandler import com.x8bit.bitwarden.ui.platform.base.util.asText +import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager import com.x8bit.bitwarden.ui.util.assertNoDialogExists import com.x8bit.bitwarden.ui.util.isProgressBar import io.mockk.every @@ -41,7 +41,7 @@ class SendScreenTest : BaseComposeTest() { private var onNavigateToNewSendCalled = false private var onNavigateToEditSendId: String? = null - private val intentHandler = mockk { + private val intentManager = mockk { every { launchUri(any()) } just runs every { shareText(any()) } just runs } @@ -59,7 +59,7 @@ class SendScreenTest : BaseComposeTest() { viewModel = viewModel, onNavigateToAddSend = { onNavigateToNewSendCalled = true }, onNavigateToEditSend = { onNavigateToEditSendId = it }, - intentHandler = intentHandler, + intentManager = intentManager, ) } } @@ -78,19 +78,19 @@ class SendScreenTest : BaseComposeTest() { } @Test - fun `on NavigateToAboutSend should call launchUri on intentHandler`() { + fun `on NavigateToAboutSend should call launchUri on intentManager`() { mutableEventFlow.tryEmit(SendEvent.NavigateToAboutSend) verify { - intentHandler.launchUri("https://bitwarden.com/products/send".toUri()) + intentManager.launchUri("https://bitwarden.com/products/send".toUri()) } } @Test - fun `on ShowShareSheet should call shareText on IntentHandler`() { + fun `on ShowShareSheet should call shareText on IntentManager`() { val text = "sharable stuff" mutableEventFlow.tryEmit(SendEvent.ShowShareSheet(text)) verify { - intentHandler.shareText(text) + intentManager.shareText(text) } } diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/send/addsend/AddSendScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/send/addsend/AddSendScreenTest.kt index 286e2b786..ab93e8cd6 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/send/addsend/AddSendScreenTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/tools/feature/send/addsend/AddSendScreenTest.kt @@ -22,8 +22,8 @@ import androidx.compose.ui.test.performScrollTo import androidx.compose.ui.test.performTextInput 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.IntentHandler import com.x8bit.bitwarden.ui.platform.base.util.asText +import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager import com.x8bit.bitwarden.ui.tools.feature.send.addsend.model.AddSendType import com.x8bit.bitwarden.ui.util.isEditableText import com.x8bit.bitwarden.ui.util.isProgressBar @@ -44,7 +44,7 @@ class AddSendScreenTest : BaseComposeTest() { private var onNavigateBackCalled = false - private val intentHandler: IntentHandler = mockk { + private val intentManager: IntentManager = mockk { every { shareText(any()) } just runs } private val mutableEventFlow = bufferedMutableSharedFlow() @@ -59,7 +59,7 @@ class AddSendScreenTest : BaseComposeTest() { composeTestRule.setContent { AddSendScreen( viewModel = viewModel, - intentHandler = intentHandler, + intentManager = intentManager, onNavigateBack = { onNavigateBackCalled = true }, ) } @@ -72,11 +72,11 @@ class AddSendScreenTest : BaseComposeTest() { } @Test - fun `on ShowShareSheet should call shareText on IntentHandler`() { + fun `on ShowShareSheet should call shareText on IntentManager`() { val text = "sharable stuff" mutableEventFlow.tryEmit(AddSendEvent.ShowShareSheet(text)) verify { - intentHandler.shareText(text) + intentManager.shareText(text) } } diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreenTest.kt index c55174db0..ae01d67c7 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreenTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/item/VaultItemScreenTest.kt @@ -25,8 +25,8 @@ import androidx.compose.ui.test.performTextInput import androidx.core.net.toUri 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.IntentHandler import com.x8bit.bitwarden.ui.platform.base.util.asText +import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager import com.x8bit.bitwarden.ui.util.assertScrollableNodeDoesNotExist import com.x8bit.bitwarden.ui.util.isProgressBar import com.x8bit.bitwarden.ui.util.onFirstNodeWithTextAfterScroll @@ -53,7 +53,7 @@ class VaultItemScreenTest : BaseComposeTest() { private var onNavigateToVaultEditItemId: String? = null private var onNavigateToMoveToOrganizationItemId: String? = null - private val intentHandler = mockk() + private val intentManager = mockk() private val mutableEventFlow = bufferedMutableSharedFlow() private val mutableStateFlow = MutableStateFlow(DEFAULT_STATE) @@ -70,7 +70,7 @@ class VaultItemScreenTest : BaseComposeTest() { onNavigateBack = { onNavigateBackCalled = true }, onNavigateToVaultAddEditItem = { onNavigateToVaultEditItemId = it }, onNavigateToMoveToOrganization = { onNavigateToMoveToOrganizationItemId = it }, - intentHandler = intentHandler, + intentManager = intentManager, ) } } @@ -109,12 +109,12 @@ class VaultItemScreenTest : BaseComposeTest() { fun `NavigateToUri event should invoke launchUri`() { val uriString = "http://www.example.com" val uri = uriString.toUri() - every { intentHandler.launchUri(uri) } just runs + every { intentManager.launchUri(uri) } just runs mutableEventFlow.tryEmit(VaultItemEvent.NavigateToUri(uriString)) verify(exactly = 1) { - intentHandler.launchUri(uri) + intentManager.launchUri(uri) } } diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/manualcodeentry/ManualCodeEntryScreenTests.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/manualcodeentry/ManualCodeEntryScreenTests.kt index 4ee120066..fed86456b 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/manualcodeentry/ManualCodeEntryScreenTests.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/manualcodeentry/ManualCodeEntryScreenTests.kt @@ -17,7 +17,7 @@ import androidx.compose.ui.test.performTextInput import androidx.test.core.app.ApplicationProvider 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.IntentHandler +import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager import com.x8bit.bitwarden.ui.platform.manager.permissions.FakePermissionManager import io.mockk.every import io.mockk.mockk @@ -40,7 +40,7 @@ class ManualCodeEntryScreenTests : BaseComposeTest() { MutableStateFlow(ManualCodeEntryState("")) private val fakePermissionManager: FakePermissionManager = FakePermissionManager() - private val intentHandler = mockk(relaxed = true) + private val intentManager = mockk(relaxed = true) private val viewModel = mockk(relaxed = true) { every { eventFlow } returns mutableEventFlow @@ -57,7 +57,7 @@ class ManualCodeEntryScreenTests : BaseComposeTest() { onNavigateToScanQrCodeCalled = true }, permissionsManager = fakePermissionManager, - intentHandler = intentHandler, + intentManager = intentManager, ) } } @@ -86,7 +86,7 @@ class ManualCodeEntryScreenTests : BaseComposeTest() { ) val intentSlot = slot() - verify { intentHandler.startActivity(capture(intentSlot)) } + verify { intentManager.startActivity(capture(intentSlot)) } assertEquals( uri, diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreenTest.kt index ef81d713a..5ea51ba53 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreenTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/vault/feature/vault/VaultScreenTest.kt @@ -18,9 +18,9 @@ import androidx.compose.ui.test.performScrollToNode import com.x8bit.bitwarden.R 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.IntentHandler import com.x8bit.bitwarden.ui.platform.base.util.asText import com.x8bit.bitwarden.ui.platform.components.model.AccountSummary +import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager import com.x8bit.bitwarden.ui.util.assertLockOrLogoutDialogIsDisplayed import com.x8bit.bitwarden.ui.util.assertLogoutConfirmationDialogIsDisplayed import com.x8bit.bitwarden.ui.util.assertNoDialogExists @@ -58,7 +58,7 @@ class VaultScreenTest : BaseComposeTest() { private var onNavigateToVaultEditItemId: String? = null private var onNavigateToVaultItemListingType: VaultItemListingType? = null private var onDimBottomNavBarRequestCalled = false - private val intentHandler = mockk(relaxed = true) + private val intentManager = mockk(relaxed = true) private val mutableEventFlow = bufferedMutableSharedFlow() private val mutableStateFlow = MutableStateFlow(DEFAULT_STATE) @@ -77,7 +77,7 @@ class VaultScreenTest : BaseComposeTest() { onNavigateToVaultEditItemScreen = { onNavigateToVaultEditItemId = it }, onNavigateToVaultItemListingScreen = { onNavigateToVaultItemListingType = it }, onDimBottomNavBarRequest = { onDimBottomNavBarRequestCalled = true }, - intentHandler = intentHandler, + intentManager = intentManager, ) } } @@ -618,9 +618,9 @@ class VaultScreenTest : BaseComposeTest() { } @Test - fun `NavigateOutOfApp event should call exitApplication on the IntentHandler`() { + fun `NavigateOutOfApp event should call exitApplication on the IntentManager`() { mutableEventFlow.tryEmit(VaultEvent.NavigateOutOfApp) - verify { intentHandler.exitApplication() } + verify { intentManager.exitApplication() } } @Test