BIT-188 Add switches and links for check password and terms and privacy (#106)

This commit is contained in:
Andrew Haisting
2023-10-12 11:39:09 -05:00
committed by GitHub
parent 7fd1052565
commit 2babd278c2
8 changed files with 435 additions and 47 deletions

View File

@@ -1,5 +1,7 @@
package com.x8bit.bitwarden.ui.auth.feature.createaccount
import android.content.Intent
import android.net.Uri
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.filterToOne
import androidx.compose.ui.test.hasAnyAncestor
@@ -8,7 +10,11 @@ import androidx.compose.ui.test.onAllNodesWithText
import androidx.compose.ui.test.onNodeWithContentDescription
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performScrollTo
import androidx.compose.ui.test.performTextInput
import androidx.core.net.toUri
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
import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.ConfirmPasswordInputChange
import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.EmailInputChange
@@ -16,6 +22,7 @@ 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 io.mockk.every
@@ -56,6 +63,40 @@ class CreateAccountScreenTest : BaseComposeTest() {
verify { viewModel.trySendAction(CloseClick) }
}
@Test
fun `check data breaches click should send CheckDataBreachesToggle action`() {
val viewModel = mockk<CreateAccountViewModel>(relaxed = true) {
every { stateFlow } returns MutableStateFlow(DEFAULT_STATE)
every { eventFlow } returns emptyFlow()
every { trySendAction(CheckDataBreachesToggle(true)) } returns Unit
}
composeTestRule.setContent {
CreateAccountScreen(onNavigateBack = {}, viewModel = viewModel)
}
composeTestRule
.onNodeWithText("Check known data breaches for this password")
.performScrollTo()
.performClick()
verify { viewModel.trySendAction(CheckDataBreachesToggle(true)) }
}
@Test
fun `accept policies click should send AcceptPoliciesToggle action`() {
val viewModel = mockk<CreateAccountViewModel>(relaxed = true) {
every { stateFlow } returns MutableStateFlow(DEFAULT_STATE)
every { eventFlow } returns emptyFlow()
every { trySendAction(AcceptPoliciesToggle(true)) } returns Unit
}
composeTestRule.setContent {
CreateAccountScreen(onNavigateBack = {}, viewModel = viewModel)
}
composeTestRule
.onNodeWithText("By activating this switch you agree", substring = true)
.performScrollTo()
.performClick()
verify { viewModel.trySendAction(AcceptPoliciesToggle(true)) }
}
@Test
fun `NavigateBack event should invoke navigate back lambda`() {
var onNavigateBackCalled = false
@@ -70,6 +111,52 @@ class CreateAccountScreenTest : BaseComposeTest() {
assert(onNavigateBackCalled)
}
@Test
fun `NavigateToPrivacyPolicy event should invoke intent handler`() {
val expectedIntent =
Intent(Intent.ACTION_VIEW, Uri.parse("https://bitwarden.com/privacy/"))
val intentHandler = mockk<IntentHandler>(relaxed = true) {
every { startActivity(expectedIntent) } returns Unit
}
val viewModel = mockk<CreateAccountViewModel>(relaxed = true) {
every { stateFlow } returns MutableStateFlow(DEFAULT_STATE)
every { eventFlow } returns flowOf(CreateAccountEvent.NavigateToPrivacyPolicy)
}
composeTestRule.setContent {
CreateAccountScreen(
onNavigateBack = {},
viewModel = viewModel,
intentHandler = intentHandler,
)
}
verify {
intentHandler.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<IntentHandler>(relaxed = true) {
every { startActivity(expectedIntent) } returns Unit
}
val viewModel = mockk<CreateAccountViewModel>(relaxed = true) {
every { stateFlow } returns MutableStateFlow(DEFAULT_STATE)
every { eventFlow } returns flowOf(CreateAccountEvent.NavigateToTerms)
}
composeTestRule.setContent {
CreateAccountScreen(
onNavigateBack = {},
viewModel = viewModel,
intentHandler = intentHandler,
)
}
verify {
intentHandler.launchUri("https://bitwarden.com/terms/".toUri())
}
}
@Test
fun `email input change should send EmailInputChange action`() {
val viewModel = mockk<CreateAccountViewModel>(relaxed = true) {
@@ -179,6 +266,8 @@ class CreateAccountScreenTest : BaseComposeTest() {
passwordInput = "",
confirmPasswordInput = "",
passwordHintInput = "",
isCheckDataBreachesToggled = false,
isAcceptPoliciesToggled = false,
errorDialogState = BasicDialogState.Hidden,
)
}

View File

@@ -8,6 +8,7 @@ import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.Con
import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.EmailInputChange
import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.PasswordHintChange
import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountAction.PasswordInputChange
import com.x8bit.bitwarden.ui.auth.feature.createaccount.CreateAccountEvent.ShowToast
import com.x8bit.bitwarden.ui.platform.base.BaseViewModelTest
import com.x8bit.bitwarden.ui.platform.base.util.asText
import com.x8bit.bitwarden.ui.platform.components.BasicDialogState
@@ -30,6 +31,8 @@ class CreateAccountViewModelTest : BaseViewModelTest() {
passwordInput = "password",
confirmPasswordInput = "confirmPassword",
passwordHintInput = "hint",
isCheckDataBreachesToggled = false,
isAcceptPoliciesToggled = false,
errorDialogState = BasicDialogState.Hidden,
)
val handle = SavedStateHandle(mapOf("state" to savedState))
@@ -61,7 +64,7 @@ class CreateAccountViewModelTest : BaseViewModelTest() {
viewModel.trySendAction(PasswordInputChange("longenoughpassword"))
viewModel.eventFlow.test {
viewModel.actionChannel.trySend(CreateAccountAction.SubmitClick)
assert(awaitItem() is CreateAccountEvent.ShowToast)
assertEquals(ShowToast("TODO: Handle Submit Click"), awaitItem())
}
}
@@ -70,7 +73,25 @@ class CreateAccountViewModelTest : BaseViewModelTest() {
val viewModel = CreateAccountViewModel(SavedStateHandle())
viewModel.eventFlow.test {
viewModel.actionChannel.trySend(CloseClick)
assert(awaitItem() is CreateAccountEvent.NavigateBack)
assertEquals(CreateAccountEvent.NavigateBack, awaitItem())
}
}
@Test
fun `PrivacyPolicyClick should emit NavigatePrivacyPolicy`() = runTest {
val viewModel = CreateAccountViewModel(SavedStateHandle())
viewModel.eventFlow.test {
viewModel.actionChannel.trySend(CreateAccountAction.PrivacyPolicyClick)
assertEquals(CreateAccountEvent.NavigateToPrivacyPolicy, awaitItem())
}
}
@Test
fun `TermsClick should emit NavigateToTerms`() = runTest {
val viewModel = CreateAccountViewModel(SavedStateHandle())
viewModel.eventFlow.test {
viewModel.actionChannel.trySend(CreateAccountAction.TermsClick)
assertEquals(CreateAccountEvent.NavigateToTerms, awaitItem())
}
}
@@ -110,12 +131,32 @@ class CreateAccountViewModelTest : BaseViewModelTest() {
}
}
@Test
fun `CheckDataBreachesToggle should change isCheckDataBreachesToggled`() = runTest {
val viewModel = CreateAccountViewModel(SavedStateHandle())
viewModel.trySendAction(CreateAccountAction.CheckDataBreachesToggle(true))
viewModel.stateFlow.test {
assertEquals(DEFAULT_STATE.copy(isCheckDataBreachesToggled = true), awaitItem())
}
}
@Test
fun `AcceptPoliciesToggle should change isAcceptPoliciesToggled`() = runTest {
val viewModel = CreateAccountViewModel(SavedStateHandle())
viewModel.trySendAction(CreateAccountAction.AcceptPoliciesToggle(true))
viewModel.stateFlow.test {
assertEquals(DEFAULT_STATE.copy(isAcceptPoliciesToggled = true), awaitItem())
}
}
companion object {
private val DEFAULT_STATE = CreateAccountState(
passwordInput = "",
emailInput = "",
confirmPasswordInput = "",
passwordHintInput = "",
isCheckDataBreachesToggled = false,
isAcceptPoliciesToggled = false,
errorDialogState = BasicDialogState.Hidden,
)
}

View File

@@ -2,9 +2,6 @@ package com.x8bit.bitwarden.ui.auth.feature.landing
import androidx.compose.ui.test.assertIsEnabled
import androidx.compose.ui.test.assertIsNotEnabled
import androidx.compose.ui.test.filterToOne
import androidx.compose.ui.test.hasClickAction
import androidx.compose.ui.test.onChildren
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performScrollTo
@@ -69,7 +66,7 @@ class LandingScreenTest : BaseComposeTest() {
viewModel = viewModel,
)
}
composeTestRule.onNodeWithText("Continue").performClick()
composeTestRule.onNodeWithText("Continue").performScrollTo().performClick()
verify {
viewModel.trySendAction(LandingAction.ContinueButtonClick)
}
@@ -97,8 +94,6 @@ class LandingScreenTest : BaseComposeTest() {
}
composeTestRule
.onNodeWithText("Remember me")
.onChildren()
.filterToOne(hasClickAction())
.performClick()
verify {
viewModel.trySendAction(LandingAction.RememberMeToggle(true))