LoginPasswordEvents -> LoginPasswordEvent

This commit is contained in:
Benoit Marty
2026-08-25 10:02:25 +02:00
parent 873843b669
commit 835690a1c2
7 changed files with 51 additions and 51 deletions
@@ -8,9 +8,9 @@
package io.element.android.features.login.impl.screens.loginpassword
sealed interface LoginPasswordEvents {
data class SetLogin(val login: String) : LoginPasswordEvents
data class SetPassword(val password: String) : LoginPasswordEvents
data object Submit : LoginPasswordEvents
data object ClearError : LoginPasswordEvents
sealed interface LoginPasswordEvent {
data class SetLogin(val login: String) : LoginPasswordEvent
data class SetPassword(val password: String) : LoginPasswordEvent
data object Submit : LoginPasswordEvent
data object ClearError : LoginPasswordEvent
}
@@ -58,18 +58,18 @@ class LoginPasswordPresenter(
}
val accountProvider by accountProviderDataSource.flow.collectAsState()
fun handleEvent(event: LoginPasswordEvents) {
fun handleEvent(event: LoginPasswordEvent) {
when (event) {
is LoginPasswordEvents.SetLogin -> updateFormState(formState) {
is LoginPasswordEvent.SetLogin -> updateFormState(formState) {
copy(login = event.login)
}
is LoginPasswordEvents.SetPassword -> updateFormState(formState) {
is LoginPasswordEvent.SetPassword -> updateFormState(formState) {
copy(password = event.password)
}
LoginPasswordEvents.Submit -> {
LoginPasswordEvent.Submit -> {
localCoroutineScope.submit(formState.value, loginAction)
}
LoginPasswordEvents.ClearError -> loginAction.value = AsyncData.Uninitialized
LoginPasswordEvent.ClearError -> loginAction.value = AsyncData.Uninitialized
}
}
@@ -18,7 +18,7 @@ data class LoginPasswordState(
val accountProvider: AccountProvider,
val formState: LoginFormState,
val loginAction: AsyncData<SessionId>,
val eventSink: (LoginPasswordEvents) -> Unit
val eventSink: (LoginPasswordEvent) -> Unit
) {
val submitEnabled: Boolean
get() = loginAction !is AsyncData.Failure &&
@@ -29,7 +29,7 @@ fun aLoginPasswordState(
accountProvider: AccountProvider = anAccountProvider(),
formState: LoginFormState = LoginFormState.Default,
loginAction: AsyncData<SessionId> = AsyncData.Uninitialized,
eventSink: (LoginPasswordEvents) -> Unit = {},
eventSink: (LoginPasswordEvent) -> Unit = {},
) = LoginPasswordState(
accountProvider = accountProvider,
formState = formState,
@@ -97,7 +97,7 @@ fun LoginPasswordView(
autofillManager?.commit()
state.eventSink(LoginPasswordEvents.Submit)
state.eventSink(LoginPasswordEvent.Submit)
}
Scaffold(
@@ -166,7 +166,7 @@ fun LoginPasswordView(
if (state.loginAction is AsyncData.Failure) {
LoginErrorDialog(error = state.loginAction.error, onDismiss = {
state.eventSink(LoginPasswordEvents.ClearError)
state.eventSink(LoginPasswordEvent.ClearError)
})
}
}
@@ -202,7 +202,7 @@ private fun LoginForm(
onValueChange = {
val sanitized = it.sanitize()
loginFieldState = sanitized
eventSink(LoginPasswordEvents.SetLogin(sanitized))
eventSink(LoginPasswordEvent.SetLogin(sanitized))
},
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Email,
@@ -220,7 +220,7 @@ private fun LoginForm(
role = Role.Button,
) {
loginFieldState = ""
eventSink(LoginPasswordEvents.SetLogin(""))
eventSink(LoginPasswordEvent.SetLogin(""))
}
) {
Icon(
@@ -254,7 +254,7 @@ private fun LoginForm(
onValueChange = {
val sanitized = it.sanitize()
passwordFieldState = sanitized
eventSink(LoginPasswordEvents.SetPassword(sanitized))
eventSink(LoginPasswordEvent.SetPassword(sanitized))
},
placeholder = stringResource(CommonStrings.common_password),
visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
@@ -54,7 +54,7 @@ class LoginPasswordPresenterTest {
val initialState = awaitItem()
assertThat(initialState.formState.login).isEqualTo(A_USER_NAME)
// Login can be changed
initialState.eventSink.invoke(LoginPasswordEvents.SetLogin(A_USER_NAME_2))
initialState.eventSink.invoke(LoginPasswordEvent.SetLogin(A_USER_NAME_2))
val loginChangedState = awaitItem()
assertThat(loginChangedState.formState.login).isEqualTo(A_USER_NAME_2)
}
@@ -71,11 +71,11 @@ class LoginPasswordPresenterTest {
authenticationService = authenticationService,
).test {
val initialState = awaitItem()
initialState.eventSink.invoke(LoginPasswordEvents.SetLogin(A_USER_NAME))
initialState.eventSink.invoke(LoginPasswordEvent.SetLogin(A_USER_NAME))
val loginState = awaitItem()
assertThat(loginState.formState).isEqualTo(LoginFormState(login = A_USER_NAME, password = ""))
assertThat(loginState.submitEnabled).isFalse()
initialState.eventSink.invoke(LoginPasswordEvents.SetPassword(A_PASSWORD))
initialState.eventSink.invoke(LoginPasswordEvent.SetPassword(A_PASSWORD))
val loginAndPasswordState = awaitItem()
assertThat(loginAndPasswordState.formState).isEqualTo(LoginFormState(login = A_USER_NAME, password = A_PASSWORD))
assertThat(loginAndPasswordState.submitEnabled).isTrue()
@@ -93,11 +93,11 @@ class LoginPasswordPresenterTest {
authenticationService = authenticationService,
).test {
val initialState = awaitItem()
initialState.eventSink.invoke(LoginPasswordEvents.SetLogin(A_USER_NAME))
initialState.eventSink.invoke(LoginPasswordEvents.SetPassword(A_PASSWORD))
initialState.eventSink.invoke(LoginPasswordEvent.SetLogin(A_USER_NAME))
initialState.eventSink.invoke(LoginPasswordEvent.SetPassword(A_PASSWORD))
skipItems(1)
val loginAndPasswordState = awaitItem()
loginAndPasswordState.eventSink.invoke(LoginPasswordEvents.Submit)
loginAndPasswordState.eventSink.invoke(LoginPasswordEvent.Submit)
val submitState = awaitItem()
assertThat(submitState.loginAction).isInstanceOf(AsyncData.Loading::class.java)
val loggedInState = awaitItem()
@@ -118,11 +118,11 @@ class LoginPasswordPresenterTest {
appPreferencesStore = appPreferencesStore,
).test {
val initialState = awaitItem()
initialState.eventSink.invoke(LoginPasswordEvents.SetLogin(A_USER_NAME))
initialState.eventSink.invoke(LoginPasswordEvents.SetPassword(A_PASSWORD))
initialState.eventSink.invoke(LoginPasswordEvent.SetLogin(A_USER_NAME))
initialState.eventSink.invoke(LoginPasswordEvent.SetPassword(A_PASSWORD))
skipItems(1)
val loginAndPasswordState = awaitItem()
loginAndPasswordState.eventSink.invoke(LoginPasswordEvents.Submit)
loginAndPasswordState.eventSink.invoke(LoginPasswordEvent.Submit)
skipItems(1)
val loggedInState = awaitItem()
assertThat(loggedInState.loginAction).isEqualTo(AsyncData.Success(A_SESSION_ID))
@@ -142,12 +142,12 @@ class LoginPasswordPresenterTest {
authenticationService = authenticationService,
).test {
val initialState = awaitItem()
initialState.eventSink.invoke(LoginPasswordEvents.SetLogin(A_USER_NAME))
initialState.eventSink.invoke(LoginPasswordEvents.SetPassword(A_PASSWORD))
initialState.eventSink.invoke(LoginPasswordEvent.SetLogin(A_USER_NAME))
initialState.eventSink.invoke(LoginPasswordEvent.SetPassword(A_PASSWORD))
skipItems(1)
val loginAndPasswordState = awaitItem()
authenticationService.givenLoginError(AN_EXCEPTION)
loginAndPasswordState.eventSink.invoke(LoginPasswordEvents.Submit)
loginAndPasswordState.eventSink.invoke(LoginPasswordEvent.Submit)
val submitState = awaitItem()
assertThat(submitState.loginAction).isInstanceOf(AsyncData.Loading::class.java)
val loggedInState = awaitItem()
@@ -166,19 +166,19 @@ class LoginPasswordPresenterTest {
authenticationService = authenticationService,
).test {
val initialState = awaitItem()
initialState.eventSink.invoke(LoginPasswordEvents.SetLogin(A_USER_NAME))
initialState.eventSink.invoke(LoginPasswordEvents.SetPassword(A_PASSWORD))
initialState.eventSink.invoke(LoginPasswordEvent.SetLogin(A_USER_NAME))
initialState.eventSink.invoke(LoginPasswordEvent.SetPassword(A_PASSWORD))
skipItems(1)
val loginAndPasswordState = awaitItem()
authenticationService.givenLoginError(AN_EXCEPTION)
loginAndPasswordState.eventSink.invoke(LoginPasswordEvents.Submit)
loginAndPasswordState.eventSink.invoke(LoginPasswordEvent.Submit)
val submitState = awaitItem()
assertThat(submitState.loginAction).isInstanceOf(AsyncData.Loading::class.java)
val loggedInState = awaitItem()
// Check an error was returned
assertThat(loggedInState.loginAction).isEqualTo(AsyncData.Failure<SessionId>(AN_EXCEPTION))
// Assert the error is then cleared
loggedInState.eventSink(LoginPasswordEvents.ClearError)
loggedInState.eventSink(LoginPasswordEvent.ClearError)
val clearedState = awaitItem()
assertThat(clearedState.loginAction).isEqualTo(AsyncData.Uninitialized)
}
@@ -39,7 +39,7 @@ import org.robolectric.annotation.Config
class LoginPasswordViewTest : RobolectricTest() {
@Test
fun `clicking on back invoke back callback`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<LoginPasswordEvents>(expectEvents = false)
val eventsRecorder = EventsRecorder<LoginPasswordEvent>(expectEvents = false)
ensureCalledOnce { callback ->
setLoginPasswordView(
aLoginPasswordState(
@@ -53,7 +53,7 @@ class LoginPasswordViewTest : RobolectricTest() {
@Test
fun `changing login invokes the expected event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<LoginPasswordEvents>()
val eventsRecorder = EventsRecorder<LoginPasswordEvent>()
setLoginPasswordView(
aLoginPasswordState(
eventSink = eventsRecorder,
@@ -62,13 +62,13 @@ class LoginPasswordViewTest : RobolectricTest() {
val userNameHint = activity!!.getString(CommonStrings.common_username)
onNodeWithText(userNameHint).performTextInput(A_USER_NAME)
eventsRecorder.assertSingle(
LoginPasswordEvents.SetLogin(A_USER_NAME)
LoginPasswordEvent.SetLogin(A_USER_NAME)
)
}
@Test
fun `changing login removes new lines the expected event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<LoginPasswordEvents>()
val eventsRecorder = EventsRecorder<LoginPasswordEvent>()
setLoginPasswordView(
aLoginPasswordState(
eventSink = eventsRecorder,
@@ -77,13 +77,13 @@ class LoginPasswordViewTest : RobolectricTest() {
val userNameHint = activity!!.getString(CommonStrings.common_username)
onNodeWithText(userNameHint).performTextInput("a\nb")
eventsRecorder.assertSingle(
LoginPasswordEvents.SetLogin("ab")
LoginPasswordEvent.SetLogin("ab")
)
}
@Test
fun `changing login removes carriage returns the expected event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<LoginPasswordEvents>()
val eventsRecorder = EventsRecorder<LoginPasswordEvent>()
setLoginPasswordView(
aLoginPasswordState(
eventSink = eventsRecorder,
@@ -92,13 +92,13 @@ class LoginPasswordViewTest : RobolectricTest() {
val userNameHint = activity!!.getString(CommonStrings.common_username)
onNodeWithText(userNameHint).performTextInput("a\r\nb")
eventsRecorder.assertSingle(
LoginPasswordEvents.SetLogin("ab")
LoginPasswordEvent.SetLogin("ab")
)
}
@Test
fun `clearing login invokes the expected event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<LoginPasswordEvents>()
val eventsRecorder = EventsRecorder<LoginPasswordEvent>()
setLoginPasswordView(
aLoginPasswordState(
formState = aLoginFormState(A_USER_NAME),
@@ -108,13 +108,13 @@ class LoginPasswordViewTest : RobolectricTest() {
val a11yClear = activity!!.getString(CommonStrings.action_clear)
onNodeWithContentDescription(a11yClear).performClick()
eventsRecorder.assertSingle(
LoginPasswordEvents.SetLogin("")
LoginPasswordEvent.SetLogin("")
)
}
@Test
fun `changing password invokes the expected event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<LoginPasswordEvents>()
val eventsRecorder = EventsRecorder<LoginPasswordEvent>()
setLoginPasswordView(
aLoginPasswordState(
eventSink = eventsRecorder,
@@ -123,13 +123,13 @@ class LoginPasswordViewTest : RobolectricTest() {
val userNameHint = activity!!.getString(CommonStrings.common_password)
onNodeWithText(userNameHint).performTextInput(A_PASSWORD)
eventsRecorder.assertSingle(
LoginPasswordEvents.SetPassword(A_PASSWORD)
LoginPasswordEvent.SetPassword(A_PASSWORD)
)
}
@Test
fun `changing password removes carriage returns the expected event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<LoginPasswordEvents>()
val eventsRecorder = EventsRecorder<LoginPasswordEvent>()
setLoginPasswordView(
aLoginPasswordState(
eventSink = eventsRecorder,
@@ -138,13 +138,13 @@ class LoginPasswordViewTest : RobolectricTest() {
val passwordHint = activity!!.getString(CommonStrings.common_password)
onNodeWithText(passwordHint).performTextInput("a\r\nb")
eventsRecorder.assertSingle(
LoginPasswordEvents.SetPassword("ab")
LoginPasswordEvent.SetPassword("ab")
)
}
@Test
fun `reveal password makes the password visible`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<LoginPasswordEvents>(expectEvents = false)
val eventsRecorder = EventsRecorder<LoginPasswordEvent>(expectEvents = false)
setLoginPasswordView(
aLoginPasswordState(
formState = aLoginFormState(password = A_PASSWORD),
@@ -165,7 +165,7 @@ class LoginPasswordViewTest : RobolectricTest() {
@Test
fun `when login is empty, continue button is not enabled`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<LoginPasswordEvents>(expectEvents = false)
val eventsRecorder = EventsRecorder<LoginPasswordEvent>(expectEvents = false)
setLoginPasswordView(
aLoginPasswordState(
formState = aLoginFormState(password = A_PASSWORD),
@@ -178,7 +178,7 @@ class LoginPasswordViewTest : RobolectricTest() {
@Test
fun `when password is empty, continue button is not enabled`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<LoginPasswordEvents>(expectEvents = false)
val eventsRecorder = EventsRecorder<LoginPasswordEvent>(expectEvents = false)
setLoginPasswordView(
aLoginPasswordState(
formState = aLoginFormState(login = A_USER_NAME),
@@ -192,7 +192,7 @@ class LoginPasswordViewTest : RobolectricTest() {
@Config(qualifiers = "h1024dp")
@Test
fun `clicking on Continue sends expected event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<LoginPasswordEvents>()
val eventsRecorder = EventsRecorder<LoginPasswordEvent>()
setLoginPasswordView(
aLoginPasswordState(
formState = aLoginFormState(login = A_USER_NAME, password = A_PASSWORD),
@@ -203,7 +203,7 @@ class LoginPasswordViewTest : RobolectricTest() {
onNodeWithText(continueStr).assertIsEnabled()
clickOn(CommonStrings.action_continue)
eventsRecorder.assertSingle(
LoginPasswordEvents.Submit
LoginPasswordEvent.Submit
)
}
}