BIT-810: Implement resend notification (#803)

This commit is contained in:
Caleb Derosier 2024-01-26 14:42:56 -07:00 committed by Álison Fernandes
parent a7e393e325
commit e5bfdd0fa7
4 changed files with 61 additions and 18 deletions

View file

@ -4,12 +4,14 @@ import android.widget.Toast
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.CircularProgressIndicator
@ -198,14 +200,28 @@ private fun LoginWithDeviceScreenContent(
Spacer(modifier = Modifier.height(24.dp))
BitwardenClickableText(
Column(
modifier = Modifier
.padding(horizontal = 16.dp)
.semantics { testTag = "ResendNotificationButton" }
.fillMaxWidth(),
label = stringResource(id = R.string.resend_notification),
onClick = onResendNotificationClick,
)
.defaultMinSize(minHeight = 32.dp)
.align(Alignment.Start),
) {
if (state.isResendNotificationLoading) {
CircularProgressIndicator(
modifier = Modifier
.padding(horizontal = 64.dp)
.size(size = 16.dp),
)
} else {
BitwardenClickableText(
modifier = Modifier
.padding(horizontal = 16.dp)
.semantics { testTag = "ResendNotificationButton" }
.fillMaxWidth(),
label = stringResource(id = R.string.resend_notification),
onClick = onResendNotificationClick,
)
}
}
Spacer(modifier = Modifier.height(24.dp))

View file

@ -52,8 +52,7 @@ class LoginWithDeviceViewModel @Inject constructor(
}
private fun handleResendNotificationClicked() {
// TODO BIT-810: implement Resend Notification button
sendEvent(LoginWithDeviceEvent.ShowToast("Not yet implemented."))
sendNewAuthRequest()
}
private fun handleViewAllLogInOptionsClicked() {
@ -69,6 +68,7 @@ class LoginWithDeviceViewModel @Inject constructor(
it.copy(
viewState = LoginWithDeviceState.ViewState.Content(
fingerprintPhrase = action.result.authRequest.fingerprint,
isResendNotificationLoading = false,
),
)
}
@ -88,6 +88,7 @@ class LoginWithDeviceViewModel @Inject constructor(
}
private fun sendNewAuthRequest() {
setIsResendNotificationLoading(true)
viewModelScope.launch {
trySendAction(
LoginWithDeviceAction.Internal.NewAuthRequestResultReceive(
@ -98,6 +99,21 @@ class LoginWithDeviceViewModel @Inject constructor(
)
}
}
private fun setIsResendNotificationLoading(isLoading: Boolean) {
when (val viewState = mutableStateFlow.value.viewState) {
is LoginWithDeviceState.ViewState.Content -> {
mutableStateFlow.update {
it.copy(
viewState = viewState.copy(
isResendNotificationLoading = isLoading,
),
)
}
}
else -> Unit
}
}
}
/**
@ -139,6 +155,7 @@ data class LoginWithDeviceState(
@Parcelize
data class Content(
val fingerprintPhrase: String,
val isResendNotificationLoading: Boolean,
) : ViewState()
}
}

View file

@ -110,6 +110,7 @@ class LoginWithDeviceScreenTest : BaseComposeTest() {
emailAddress = EMAIL,
viewState = LoginWithDeviceState.ViewState.Content(
fingerprintPhrase = "alabster-drinkable-mystified-rapping-irrigate",
isResendNotificationLoading = false,
),
)
}

View file

@ -45,6 +45,7 @@ class LoginWithDeviceViewModelTest : BaseViewModelTest() {
emailAddress = newEmail,
viewState = LoginWithDeviceState.ViewState.Content(
fingerprintPhrase = FINGERPRINT,
isResendNotificationLoading = false,
),
)
val viewModel = createViewModel(state)
@ -69,16 +70,22 @@ class LoginWithDeviceViewModelTest : BaseViewModelTest() {
}
@Test
fun `ResendNotificationClick should emit ShowToast`() = runTest {
fun `ResendNotificationClick should create new auth request and update state`() = runTest {
val newFingerprint = "newFingerprint"
coEvery {
authRepository.createAuthRequest(EMAIL)
} returns AuthRequestResult.Success(AUTH_REQUEST.copy(fingerprint = newFingerprint))
val viewModel = createViewModel()
viewModel.eventFlow.test {
viewModel.actionChannel.trySend(LoginWithDeviceAction.ResendNotificationClick)
assertEquals(DEFAULT_STATE, viewModel.stateFlow.value)
assertEquals(
LoginWithDeviceEvent.ShowToast("Not yet implemented."),
awaitItem(),
)
}
viewModel.actionChannel.trySend(LoginWithDeviceAction.ResendNotificationClick)
assertEquals(
DEFAULT_STATE.copy(
viewState = LoginWithDeviceState.ViewState.Content(
fingerprintPhrase = newFingerprint,
isResendNotificationLoading = false,
),
),
viewModel.stateFlow.value,
)
}
@Test
@ -112,6 +119,7 @@ class LoginWithDeviceViewModelTest : BaseViewModelTest() {
DEFAULT_STATE.copy(
viewState = LoginWithDeviceState.ViewState.Content(
fingerprintPhrase = newFingerprint,
isResendNotificationLoading = false,
),
),
viewModel.stateFlow.value,
@ -152,6 +160,7 @@ class LoginWithDeviceViewModelTest : BaseViewModelTest() {
emailAddress = EMAIL,
viewState = LoginWithDeviceState.ViewState.Content(
fingerprintPhrase = FINGERPRINT,
isResendNotificationLoading = false,
),
)
private val AUTH_REQUEST = AuthRequest(