From edfabb0f260aaafa9a5333c0c22b68eaf291c2f2 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Mon, 30 May 2022 13:51:33 +0100 Subject: [PATCH] adding missing loading state when confirming password reset - adds reset test cases to the onboarding view model --- .../internal/auth/login/DefaultLoginWizard.kt | 1 - .../app/features/login/LoginViewModel.kt | 5 ++- .../onboarding/OnboardingViewModel.kt | 1 + .../onboarding/OnboardingViewModelTest.kt | 41 +++++++++++++++++++ .../test/fakes/FakeAuthenticationService.kt | 5 +++ .../vector/app/test/fakes/FakeLoginWizard.kt | 32 +++++++++++++++ 6 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 vector/src/test/java/im/vector/app/test/fakes/FakeLoginWizard.kt diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/DefaultLoginWizard.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/DefaultLoginWizard.kt index f947d76b951..20b056f1c79 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/DefaultLoginWizard.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/login/DefaultLoginWizard.kt @@ -30,7 +30,6 @@ import org.matrix.android.sdk.internal.auth.data.ThreePidMedium import org.matrix.android.sdk.internal.auth.data.TokenLoginParams import org.matrix.android.sdk.internal.auth.db.PendingSessionData import org.matrix.android.sdk.internal.auth.registration.AddThreePidRegistrationParams -import org.matrix.android.sdk.internal.auth.registration.AddThreePidRegistrationResponse import org.matrix.android.sdk.internal.auth.registration.RegisterAddThreePidTask import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.session.content.DefaultContentUrlResolver diff --git a/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt b/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt index 5a1e8b107f8..116b035c8e8 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginViewModel.kt @@ -533,13 +533,14 @@ class LoginViewModel @AssistedInject constructor( currentJob = viewModelScope.launch { val state = awaitState() - if (state.resetPasswordNewPassword == null) + if (state.resetPasswordNewPassword == null) { setState { copy( asyncResetPassword = Uninitialized, asyncResetMailConfirmed = Fail(Throwable("Developer error - New password not set")) ) - } else { + } + } else { try { safeLoginWizard.resetPasswordMailConfirmed(state.resetPasswordNewPassword) } catch (failure: Throwable) { diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt index 23bab0c62d3..c24d3dbb485 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt @@ -462,6 +462,7 @@ class OnboardingViewModel @AssistedInject constructor( } private fun handleResetPasswordMailConfirmed() { + setState { copy(isLoading = true) } currentJob = viewModelScope.launch { val resetState = awaitState().resetState when (val newPassword = resetState.newPassword) { diff --git a/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt b/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt index 1abfa7e9a80..77539da2328 100644 --- a/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt +++ b/vector/src/test/java/im/vector/app/features/onboarding/OnboardingViewModelTest.kt @@ -31,6 +31,7 @@ import im.vector.app.test.fakes.FakeContext import im.vector.app.test.fakes.FakeDirectLoginUseCase import im.vector.app.test.fakes.FakeHomeServerConnectionConfigFactory import im.vector.app.test.fakes.FakeHomeServerHistoryService +import im.vector.app.test.fakes.FakeLoginWizard import im.vector.app.test.fakes.FakeRegisterActionHandler import im.vector.app.test.fakes.FakeRegistrationWizard import im.vector.app.test.fakes.FakeSession @@ -67,6 +68,8 @@ private val A_DIRECT_LOGIN = OnboardingAction.AuthenticateAction.LoginDirect("@a private const val A_HOMESERVER_URL = "https://edited-homeserver.org" private val A_HOMESERVER_CONFIG = HomeServerConnectionConfig(FakeUri().instance) private val SELECTED_HOMESERVER_STATE = SelectedHomeserverState(preferredLoginMode = LoginMode.Password) +private const val AN_EMAIL = "hello@example.com" +private const val A_PASSWORD = "a-password" class OnboardingViewModelTest { @@ -85,6 +88,7 @@ class OnboardingViewModelTest { private val fakeHomeServerConnectionConfigFactory = FakeHomeServerConnectionConfigFactory() private val fakeStartAuthenticationFlowUseCase = FakeStartAuthenticationFlowUseCase() private val fakeHomeServerHistoryService = FakeHomeServerHistoryService() + private val fakeLoginWizard = FakeLoginWizard() private var initialState = OnboardingViewState() private lateinit var viewModel: OnboardingViewModel @@ -466,6 +470,43 @@ class OnboardingViewModelTest { .finish() } + @Test + fun `given can successfully reset password, when resetting password, then emits reset done event`() = runTest { + val test = viewModel.test() + fakeLoginWizard.givenResetPasswordSuccess(AN_EMAIL) + fakeAuthenticationService.givenLoginWizard(fakeLoginWizard) + + viewModel.handle(OnboardingAction.ResetPassword(email = AN_EMAIL, newPassword = A_PASSWORD)) + + test + .assertStatesChanges( + initialState, + { copy(isLoading = true) }, + { copy(isLoading = false, resetState = ResetState(AN_EMAIL, A_PASSWORD)) } + ) + .assertEvents(OnboardingViewEvents.OnResetPasswordSendThreePidDone) + .finish() + } + + @Test + fun `given can successfully confirm reset password, when confirm reset password, then emits reset success`() = runTest { + viewModelWith(initialState.copy(resetState = ResetState(AN_EMAIL, A_PASSWORD))) + val test = viewModel.test() + fakeLoginWizard.givenConfirmResetPasswordSuccess(A_PASSWORD) + fakeAuthenticationService.givenLoginWizard(fakeLoginWizard) + + viewModel.handle(OnboardingAction.ResetPasswordMailConfirmed) + + test + .assertStatesChanges( + initialState, + { copy(isLoading = true) }, + { copy(isLoading = false, resetState = ResetState()) } + ) + .assertEvents(OnboardingViewEvents.OnResetPasswordMailConfirmationSuccess) + .finish() + } + private fun viewModelWith(state: OnboardingViewState) { OnboardingViewModel( state, diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeAuthenticationService.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeAuthenticationService.kt index 0456bbd4740..cc606497f5b 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakeAuthenticationService.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeAuthenticationService.kt @@ -23,6 +23,7 @@ import io.mockk.mockk import org.matrix.android.sdk.api.auth.AuthenticationService import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig import org.matrix.android.sdk.api.auth.data.LoginFlowResult +import org.matrix.android.sdk.api.auth.login.LoginWizard import org.matrix.android.sdk.api.auth.registration.RegistrationWizard import org.matrix.android.sdk.api.auth.wellknown.WellknownResult @@ -36,6 +37,10 @@ class FakeAuthenticationService : AuthenticationService by mockk() { every { isRegistrationStarted() } returns started } + fun givenLoginWizard(loginWizard: LoginWizard) { + every { getLoginWizard() } returns loginWizard + } + fun givenLoginFlow(config: HomeServerConnectionConfig, result: LoginFlowResult) { coEvery { getLoginFlow(config) } returns result } diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeLoginWizard.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeLoginWizard.kt new file mode 100644 index 00000000000..38bb75087cc --- /dev/null +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeLoginWizard.kt @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.test.fakes + +import io.mockk.coJustRun +import io.mockk.mockk +import org.matrix.android.sdk.api.auth.login.LoginWizard + +class FakeLoginWizard : LoginWizard by mockk() { + + fun givenResetPasswordSuccess(email: String) { + coJustRun { resetPassword(email) } + } + + fun givenConfirmResetPasswordSuccess(password: String) { + coJustRun { resetPasswordMailConfirmed(password) } + } +}