[PM-10664] Display server error message during 2FA login (#3719)

This commit is contained in:
Patrick Honkonen 2024-08-14 11:30:05 -04:00 committed by GitHub
parent 499bc20850
commit aaa0ce4ecd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 89 additions and 1 deletions

View file

@ -31,6 +31,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.Lifecycle
@ -59,6 +60,7 @@ import com.x8bit.bitwarden.ui.platform.composition.LocalIntentManager
import com.x8bit.bitwarden.ui.platform.composition.LocalNfcManager
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
import com.x8bit.bitwarden.ui.platform.manager.nfc.NfcManager
import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme
import kotlinx.collections.immutable.toPersistentList
/**
@ -295,3 +297,31 @@ private fun TwoFactorLoginScreenContent(
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@Preview(showBackground = true)
private fun TwoFactorLoginScreenContentPreview() {
BitwardenTheme {
BitwardenScaffold {
TwoFactorLoginScreenContent(
state = TwoFactorLoginState(
TwoFactorAuthMethod.EMAIL,
availableAuthMethods = listOf(TwoFactorAuthMethod.EMAIL),
codeInput = "",
dialogState = null,
displayEmail = "email@dot.com",
isContinueButtonEnabled = true,
isRememberMeEnabled = true,
captchaToken = null,
email = "",
password = "",
),
onCodeInputChange = {},
onContinueButtonClick = {},
onRememberMeToggle = {},
onResendEmailButtonClick = {},
)
}
}
}

View file

@ -290,7 +290,8 @@ class TwoFactorLoginViewModel @Inject constructor(
it.copy(
dialogState = TwoFactorLoginState.DialogState.Error(
title = R.string.an_error_has_occurred.asText(),
message = R.string.invalid_verification_code.asText(),
message = loginResult.errorMessage?.asText()
?: R.string.invalid_verification_code.asText(),
),
)
}

View file

@ -553,6 +553,63 @@ class TwoFactorLoginViewModelTest : BaseViewModelTest() {
}
}
@Test
fun `ContinueButtonClick login returns Error with message should update dialogState`() =
runTest {
coEvery {
authRepository.login(
email = "example@email.com",
password = "password123",
twoFactorData = TwoFactorDataModel(
code = "",
method = TwoFactorAuthMethod.AUTHENTICATOR_APP.value.toString(),
remember = false,
),
captchaToken = null,
)
} returns LoginResult.Error(errorMessage = "Mock error message")
val viewModel = createViewModel()
viewModel.stateFlow.test {
assertEquals(DEFAULT_STATE, awaitItem())
viewModel.trySendAction(TwoFactorLoginAction.ContinueButtonClick)
assertEquals(
DEFAULT_STATE.copy(
dialogState = TwoFactorLoginState.DialogState.Loading(
message = R.string.logging_in.asText(),
),
),
awaitItem(),
)
assertEquals(
DEFAULT_STATE.copy(
dialogState = TwoFactorLoginState.DialogState.Error(
title = R.string.an_error_has_occurred.asText(),
message = "Mock error message".asText(),
),
),
awaitItem(),
)
viewModel.trySendAction(TwoFactorLoginAction.DialogDismiss)
assertEquals(DEFAULT_STATE, awaitItem())
}
coVerify {
authRepository.login(
email = "example@email.com",
password = "password123",
twoFactorData = TwoFactorDataModel(
code = "",
method = TwoFactorAuthMethod.AUTHENTICATOR_APP.value.toString(),
remember = false,
),
captchaToken = null,
)
}
}
@Test
fun `RememberMeToggle should update the state`() {
val viewModel = createViewModel()