From bd84a8649d5c624a66f337ff55857e1073338e45 Mon Sep 17 00:00:00 2001 From: Patrick Honkonen <1883101+SaintPatrck@users.noreply.github.com> Date: Mon, 4 Mar 2024 16:36:06 -0500 Subject: [PATCH] BIT-1962: Add Direct Link to Privacy Policy in About Screen (#1084) --- .../feature/settings/about/AboutScreen.kt | 16 ++++++++++ .../feature/settings/about/AboutViewModel.kt | 15 +++++++++ .../feature/settings/about/AboutScreenTest.kt | 32 +++++++++++++++++-- .../settings/about/AboutViewModelTest.kt | 9 ++++++ 4 files changed, 70 insertions(+), 2 deletions(-) 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 8f9d24524c..b9bf3556b8 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 @@ -75,6 +75,10 @@ fun AboutScreen( intentManager.launchUri("https://bitwarden.com/help".toUri()) } + AboutEvent.NavigateToPrivacyPolicy -> { + intentManager.launchUri("https://bitwarden.com/privacy".toUri()) + } + AboutEvent.NavigateToLearnAboutOrganizations -> { intentManager.launchUri("https://bitwarden.com/help/about-organizations".toUri()) } @@ -113,6 +117,9 @@ fun AboutScreen( onHelpCenterClick = remember(viewModel) { { viewModel.trySendAction(AboutAction.HelpCenterClick) } }, + onPrivacyPolicyClick = remember(viewModel) { + { viewModel.trySendAction(AboutAction.PrivacyPolicyClick) } + }, onLearnAboutOrgsClick = remember(viewModel) { { viewModel.trySendAction(AboutAction.LearnAboutOrganizationsClick) } }, @@ -137,6 +144,7 @@ fun AboutScreen( private fun ContentColumn( state: AboutState, onHelpCenterClick: () -> Unit, + onPrivacyPolicyClick: () -> Unit, onLearnAboutOrgsClick: () -> Unit, onRateTheAppClick: () -> Unit, onSubmitCrashLogsCheckedChange: (Boolean) -> Unit, @@ -170,6 +178,14 @@ private fun ContentColumn( id = R.string.learn_more_about_how_to_use_bitwarden_on_the_help_center, ), ) + BitwardenExternalLinkRow( + text = stringResource(id = R.string.privacy_policy), + onConfirmClick = onPrivacyPolicyClick, + dialogTitle = stringResource(id = R.string.continue_to_privacy_policy), + dialogMessage = stringResource( + id = R.string.privacy_policy_description_long, + ), + ) BitwardenExternalLinkRow( text = stringResource(id = R.string.web_vault), onConfirmClick = onWebVaultClick, diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutViewModel.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutViewModel.kt index 161a199248..34ba869ecb 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutViewModel.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutViewModel.kt @@ -50,6 +50,7 @@ class AboutViewModel @Inject constructor( override fun handleAction(action: AboutAction): Unit = when (action) { AboutAction.BackClick -> handleBackClick() AboutAction.HelpCenterClick -> handleHelpCenterClick() + AboutAction.PrivacyPolicyClick -> handlePrivacyPolicyClick() AboutAction.LearnAboutOrganizationsClick -> handleLearnAboutOrganizationsClick() AboutAction.RateAppClick -> handleRateAppClick() is AboutAction.SubmitCrashLogsClick -> handleSubmitCrashLogsClick(action) @@ -65,6 +66,10 @@ class AboutViewModel @Inject constructor( sendEvent(AboutEvent.NavigateToHelpCenter) } + private fun handlePrivacyPolicyClick() { + sendEvent(AboutEvent.NavigateToPrivacyPolicy) + } + private fun handleLearnAboutOrganizationsClick() { sendEvent(AboutEvent.NavigateToLearnAboutOrganizations) } @@ -139,6 +144,11 @@ sealed class AboutEvent { */ data object NavigateToHelpCenter : AboutEvent() + /** + * Navigates to the private policy. + */ + data object NavigateToPrivacyPolicy : AboutEvent() + /** * Navigates to learn about organizations. */ @@ -169,6 +179,11 @@ sealed class AboutAction { */ data object HelpCenterClick : AboutAction() + /** + * User clicked the privacy policy row. + */ + data object PrivacyPolicyClick : AboutAction() + /** * User clicked the learn about organizations row. */ 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 01d914d79b..0d858d3d3d 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 @@ -88,6 +88,22 @@ class AboutScreenTest : BaseComposeTest() { } } + @Suppress("MaxLineLength") + @Test + fun `on privacy policy click should display confirmation dialog and confirm click should emit PrivacyPolicyClick`() { + composeTestRule.onNode(isDialog()).assertDoesNotExist() + composeTestRule.onNodeWithText("Privacy Policy").performClick() + composeTestRule.onNode(isDialog()).assertExists() + composeTestRule + .onAllNodesWithText("Continue") + .filterToOne(hasAnyAncestor(isDialog())) + .performClick() + composeTestRule.onNode(isDialog()).assertDoesNotExist() + verify { + viewModel.trySendAction(AboutAction.PrivacyPolicyClick) + } + } + @Suppress("MaxLineLength") @Test fun `on bitwarden web vault click should display confirmation dialog and confirm click should emit WebVaultClick`() { @@ -134,6 +150,14 @@ class AboutScreenTest : BaseComposeTest() { } } + @Test + fun `on NavigateToPrivacyPolicy should call launchUri on IntentManager`() { + mutableEventFlow.tryEmit(AboutEvent.NavigateToPrivacyPolicy) + verify { + intentManager.launchUri("https://bitwarden.com/privacy".toUri()) + } + } + @Test fun `on NavigateToLearnAboutOrganizations should call launchUri on IntentManager`() { mutableEventFlow.tryEmit(AboutEvent.NavigateToLearnAboutOrganizations) @@ -209,7 +233,9 @@ class AboutScreenTest : BaseComposeTest() { @Test fun `on version info click should send VersionClick`() { - composeTestRule.onNodeWithText("Version: 1.0.0 (1)").performClick() + composeTestRule.onNodeWithText("Version: 1.0.0 (1)") + .performScrollTo() + .performClick() verify { viewModel.trySendAction(AboutAction.VersionClick) } @@ -217,7 +243,9 @@ class AboutScreenTest : BaseComposeTest() { @Test fun `version should update according to the state`() = runTest { - composeTestRule.onNodeWithText("Version: 1.0.0 (1)").assertIsDisplayed() + composeTestRule.onNodeWithText("Version: 1.0.0 (1)") + .performScrollTo() + .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/about/AboutViewModelTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutViewModelTest.kt index 21193c47dc..a2970e503d 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutViewModelTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/platform/feature/settings/about/AboutViewModelTest.kt @@ -53,6 +53,15 @@ class AboutViewModelTest : BaseViewModelTest() { } } + @Test + fun `on PrivacyPolicyClick should emit NavigateToPrivacyPolicy`() = runTest { + val viewModel = createViewModel(DEFAULT_ABOUT_STATE) + viewModel.eventFlow.test { + viewModel.trySendAction(AboutAction.PrivacyPolicyClick) + assertEquals(AboutEvent.NavigateToPrivacyPolicy, awaitItem()) + } + } + @Test fun `on LearnAboutOrganizationsClick should emit NavigateToLearnAboutOrganizations`() = runTest {