Skip to content

Commit 4f81336

Browse files
authored
Fix login flow (#4813)
* Also clear the data, to let the next screen be able to go back * Disable the change account provider button when the form is loading the data to prevent double navigation * Improve OnboardingViewTest, ensure that no Event are emitted. * OnboardingViewTest: add tests to cover the change.
1 parent efdc10e commit 4f81336

File tree

3 files changed

+69
-3
lines changed

3 files changed

+69
-3
lines changed

features/login/impl/src/main/kotlin/io/element/android/features/login/impl/login/LoginModeView.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ fun LoginModeView(
8181
LoginMode.PasswordLogin -> onNeedLoginPassword()
8282
is LoginMode.AccountCreation -> onCreateAccountContinue(loginModeData.url)
8383
}
84+
// Also clear the data, to let the next screen be able to go back
85+
onClearError()
8486
}
8587
AsyncData.Uninitialized -> Unit
8688
}

features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderView.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ fun ConfirmAccountProviderView(
8888
TextButton(
8989
text = stringResource(id = R.string.screen_account_provider_change),
9090
onClick = onChange,
91-
enabled = true,
91+
enabled = !isLoading,
9292
modifier = Modifier
9393
.fillMaxWidth()
9494
.testTag(TestTags.loginChangeServer)

features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/onboarding/OnboardingViewTest.kt

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import androidx.compose.ui.test.onNodeWithText
1414
import androidx.compose.ui.test.performClick
1515
import androidx.test.ext.junit.runners.AndroidJUnit4
1616
import io.element.android.features.login.impl.R
17+
import io.element.android.features.login.impl.login.LoginMode
1718
import io.element.android.libraries.architecture.AsyncData
1819
import io.element.android.libraries.matrix.api.auth.OidcDetails
1920
import io.element.android.libraries.matrix.test.AN_EXCEPTION
@@ -36,9 +37,13 @@ class OnboardingViewTest {
3637

3738
@Test
3839
fun `when can create account - clicking on create account calls the expected callback`() {
40+
val eventSink = EventsRecorder<OnBoardingEvents>(expectEvents = false)
3941
ensureCalledOnce { callback ->
4042
rule.setOnboardingView(
41-
state = anOnBoardingState(canCreateAccount = true),
43+
state = anOnBoardingState(
44+
canCreateAccount = true,
45+
eventSink = eventSink,
46+
),
4247
onCreateAccount = callback,
4348
)
4449
rule.clickOn(R.string.screen_onboarding_sign_up)
@@ -47,9 +52,13 @@ class OnboardingViewTest {
4752

4853
@Test
4954
fun `when can login with QR code - clicking on sign in with QR code calls the expected callback`() {
55+
val eventSink = EventsRecorder<OnBoardingEvents>(expectEvents = false)
5056
ensureCalledOnce { callback ->
5157
rule.setOnboardingView(
52-
state = anOnBoardingState(canLoginWithQrCode = true),
58+
state = anOnBoardingState(
59+
canLoginWithQrCode = true,
60+
eventSink = eventSink,
61+
),
5362
onSignInWithQrCode = callback,
5463
)
5564
rule.clickOn(R.string.screen_onboarding_sign_in_with_qr_code)
@@ -73,11 +82,13 @@ class OnboardingViewTest {
7382
private fun `when can login with QR code - clicking on sign in manually calls the expected callback`(
7483
mustChooseAccountProvider: Boolean,
7584
) {
85+
val eventSink = EventsRecorder<OnBoardingEvents>(expectEvents = false)
7686
ensureCalledOnceWithParam(mustChooseAccountProvider) { callback ->
7787
rule.setOnboardingView(
7888
state = anOnBoardingState(
7989
canLoginWithQrCode = true,
8090
mustChooseAccountProvider = mustChooseAccountProvider,
91+
eventSink = eventSink,
8192
),
8293
onSignIn = callback,
8394
)
@@ -102,12 +113,14 @@ class OnboardingViewTest {
102113
private fun `when cannot login with QR code or create account - clicking on continue calls the sign in callback`(
103114
mustChooseAccountProvider: Boolean,
104115
) {
116+
val eventSink = EventsRecorder<OnBoardingEvents>(expectEvents = false)
105117
ensureCalledOnceWithParam(mustChooseAccountProvider) { callback ->
106118
rule.setOnboardingView(
107119
state = anOnBoardingState(
108120
canLoginWithQrCode = false,
109121
canCreateAccount = false,
110122
mustChooseAccountProvider = mustChooseAccountProvider,
123+
eventSink = eventSink,
111124
),
112125
onSignIn = callback,
113126
)
@@ -145,10 +158,12 @@ class OnboardingViewTest {
145158

146159
@Test
147160
fun `clicking on report a problem calls the sign in callback`() {
161+
val eventSink = EventsRecorder<OnBoardingEvents>(expectEvents = false)
148162
ensureCalledOnce { callback ->
149163
rule.setOnboardingView(
150164
state = anOnBoardingState(
151165
canReportBug = true,
166+
eventSink = eventSink,
152167
),
153168
onReportProblem = callback,
154169
)
@@ -160,15 +175,64 @@ class OnboardingViewTest {
160175

161176
@Test
162177
fun `cannot report a problem when the feature is disabled`() {
178+
val eventSink = EventsRecorder<OnBoardingEvents>(expectEvents = false)
163179
rule.setOnboardingView(
164180
state = anOnBoardingState(
165181
canReportBug = false,
182+
eventSink = eventSink,
166183
),
167184
)
168185
val text = rule.activity.getString(CommonStrings.common_report_a_problem)
169186
rule.onNodeWithText(text).assertDoesNotExist()
170187
}
171188

189+
@Test
190+
fun `when success PasswordLogin - the expected callback is invoked and the event is received`() {
191+
val eventSink = EventsRecorder<OnBoardingEvents>()
192+
ensureCalledOnce { callback ->
193+
rule.setOnboardingView(
194+
state = anOnBoardingState(
195+
loginMode = AsyncData.Success(LoginMode.PasswordLogin),
196+
eventSink = eventSink,
197+
),
198+
onNeedLoginPassword = callback,
199+
)
200+
}
201+
eventSink.assertSingle(OnBoardingEvents.ClearError)
202+
}
203+
204+
@Test
205+
fun `when success Oidc - the expected callback is invoked and the event is received`() {
206+
val eventSink = EventsRecorder<OnBoardingEvents>()
207+
val oidcDetails = OidcDetails("aUrl")
208+
ensureCalledOnceWithParam(oidcDetails) { callback ->
209+
rule.setOnboardingView(
210+
state = anOnBoardingState(
211+
loginMode = AsyncData.Success(LoginMode.Oidc(oidcDetails)),
212+
eventSink = eventSink,
213+
),
214+
onOidcDetails = callback,
215+
)
216+
}
217+
eventSink.assertSingle(OnBoardingEvents.ClearError)
218+
}
219+
220+
@Test
221+
fun `when success AccountCreation - the expected callback is invoked and the event is received`() {
222+
val eventSink = EventsRecorder<OnBoardingEvents>()
223+
val oidcDetails = OidcDetails("aUrl")
224+
ensureCalledOnceWithParam(oidcDetails.url) { callback ->
225+
rule.setOnboardingView(
226+
state = anOnBoardingState(
227+
loginMode = AsyncData.Success(LoginMode.AccountCreation("aUrl")),
228+
eventSink = eventSink,
229+
),
230+
onCreateAccountContinue = callback,
231+
)
232+
}
233+
eventSink.assertSingle(OnBoardingEvents.ClearError)
234+
}
235+
172236
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setOnboardingView(
173237
state: OnBoardingState,
174238
onSignInWithQrCode: () -> Unit = EnsureNeverCalled(),

0 commit comments

Comments
 (0)