From 0fe5ee68f2a8e100e88ac63591e29681dfe69ad9 Mon Sep 17 00:00:00 2001 From: Maxime NATUREL Date: Mon, 26 Sep 2022 14:58:03 +0200 Subject: [PATCH] Unit tests for interception of signout process result --- .../InterceptSignoutFlowResponseUseCase.kt | 1 - ...InterceptSignoutFlowResponseUseCaseTest.kt | 174 ++++++++++++++++++ .../vector/app/test/fakes/FakeReAuthHelper.kt | 30 +++ 3 files changed, 204 insertions(+), 1 deletion(-) create mode 100644 vector/src/test/java/im/vector/app/features/settings/devices/v2/signout/InterceptSignoutFlowResponseUseCaseTest.kt create mode 100644 vector/src/test/java/im/vector/app/test/fakes/FakeReAuthHelper.kt diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/signout/InterceptSignoutFlowResponseUseCase.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/signout/InterceptSignoutFlowResponseUseCase.kt index 4e69452ab3..4316995272 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/signout/InterceptSignoutFlowResponseUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/signout/InterceptSignoutFlowResponseUseCase.kt @@ -28,7 +28,6 @@ import javax.inject.Inject import kotlin.coroutines.Continuation import kotlin.coroutines.resume -// TODO add unit tests class InterceptSignoutFlowResponseUseCase @Inject constructor( private val reAuthHelper: ReAuthHelper, private val activeSessionHolder: ActiveSessionHolder, diff --git a/vector/src/test/java/im/vector/app/features/settings/devices/v2/signout/InterceptSignoutFlowResponseUseCaseTest.kt b/vector/src/test/java/im/vector/app/features/settings/devices/v2/signout/InterceptSignoutFlowResponseUseCaseTest.kt new file mode 100644 index 0000000000..35551ba36e --- /dev/null +++ b/vector/src/test/java/im/vector/app/features/settings/devices/v2/signout/InterceptSignoutFlowResponseUseCaseTest.kt @@ -0,0 +1,174 @@ +/* + * 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.features.settings.devices.v2.signout + +import im.vector.app.test.fakes.FakeActiveSessionHolder +import im.vector.app.test.fakes.FakeReAuthHelper +import io.mockk.every +import io.mockk.just +import io.mockk.mockk +import io.mockk.mockkStatic +import io.mockk.runs +import io.mockk.unmockkAll +import org.amshove.kluent.shouldBeEqualTo +import org.amshove.kluent.shouldBeInstanceOf +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.matrix.android.sdk.api.auth.UIABaseAuth +import org.matrix.android.sdk.api.auth.UserPasswordAuth +import org.matrix.android.sdk.api.auth.data.LoginFlowTypes +import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse +import org.matrix.android.sdk.api.auth.registration.nextUncompletedStage +import org.matrix.android.sdk.api.session.uia.DefaultBaseAuth +import kotlin.coroutines.Continuation +import kotlin.coroutines.resume + +private const val A_PASSWORD = "password" +private const val A_SESSION_ID = "session-id" +private const val AN_ERROR_CODE = "error-code" + +class InterceptSignoutFlowResponseUseCaseTest { + + private val fakeReAuthHelper = FakeReAuthHelper() + private val fakeActiveSessionHolder = FakeActiveSessionHolder() + + private val interceptSignoutFlowResponseUseCase = InterceptSignoutFlowResponseUseCase( + reAuthHelper = fakeReAuthHelper.instance, + activeSessionHolder = fakeActiveSessionHolder.instance, + ) + + @Before + fun setUp() { + mockkStatic("org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponseKt") + } + + @After + fun tearDown() { + unmockkAll() + } + + @Test + fun `given no error and a stored password and a next stage as password when intercepting then promise is resumed and success is returned`() { + // Given + val registrationFlowResponse = givenNextUncompletedStage(LoginFlowTypes.PASSWORD, A_SESSION_ID) + fakeReAuthHelper.givenStoredPassword(A_PASSWORD) + val errorCode: String? = null + val promise = mockk>() + every { promise.resume(any()) } just runs + val expectedAuth = UserPasswordAuth( + session = null, + user = fakeActiveSessionHolder.fakeSession.myUserId, + password = A_PASSWORD, + ) + + // When + val result = interceptSignoutFlowResponseUseCase.execute( + flowResponse = registrationFlowResponse, + errCode = errorCode, + promise = promise, + ) + + // Then + result shouldBeInstanceOf (SignoutSessionResult.Completed::class) + every { + promise.resume(expectedAuth) + } + } + + @Test + fun `given an error when intercepting then reAuthNeeded result is returned`() { + // Given + val registrationFlowResponse = givenNextUncompletedStage(LoginFlowTypes.PASSWORD, A_SESSION_ID) + fakeReAuthHelper.givenStoredPassword(A_PASSWORD) + val errorCode = AN_ERROR_CODE + val promise = mockk>() + val expectedResult = SignoutSessionResult.ReAuthNeeded( + pendingAuth = DefaultBaseAuth(session = A_SESSION_ID), + uiaContinuation = promise, + flowResponse = registrationFlowResponse, + errCode = errorCode + ) + + // When + val result = interceptSignoutFlowResponseUseCase.execute( + flowResponse = registrationFlowResponse, + errCode = errorCode, + promise = promise, + ) + + // Then + result shouldBeEqualTo expectedResult + } + + @Test + fun `given next stage is not password when intercepting then reAuthNeeded result is returned`() { + // Given + val registrationFlowResponse = givenNextUncompletedStage(LoginFlowTypes.SSO, A_SESSION_ID) + fakeReAuthHelper.givenStoredPassword(A_PASSWORD) + val errorCode: String? = null + val promise = mockk>() + val expectedResult = SignoutSessionResult.ReAuthNeeded( + pendingAuth = DefaultBaseAuth(session = A_SESSION_ID), + uiaContinuation = promise, + flowResponse = registrationFlowResponse, + errCode = errorCode + ) + + // When + val result = interceptSignoutFlowResponseUseCase.execute( + flowResponse = registrationFlowResponse, + errCode = errorCode, + promise = promise, + ) + + // Then + result shouldBeEqualTo expectedResult + } + + @Test + fun `given no existing stored password when intercepting then reAuthNeeded result is returned`() { + // Given + val registrationFlowResponse = givenNextUncompletedStage(LoginFlowTypes.PASSWORD, A_SESSION_ID) + fakeReAuthHelper.givenStoredPassword(null) + val errorCode: String? = null + val promise = mockk>() + val expectedResult = SignoutSessionResult.ReAuthNeeded( + pendingAuth = DefaultBaseAuth(session = A_SESSION_ID), + uiaContinuation = promise, + flowResponse = registrationFlowResponse, + errCode = errorCode + ) + + // When + val result = interceptSignoutFlowResponseUseCase.execute( + flowResponse = registrationFlowResponse, + errCode = errorCode, + promise = promise, + ) + + // Then + result shouldBeEqualTo expectedResult + } + + private fun givenNextUncompletedStage(nextStage: String, sessionId: String): RegistrationFlowResponse { + val registrationFlowResponse = mockk() + every { registrationFlowResponse.nextUncompletedStage() } returns nextStage + every { registrationFlowResponse.session } returns sessionId + return registrationFlowResponse + } +} diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeReAuthHelper.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeReAuthHelper.kt new file mode 100644 index 0000000000..96004a4990 --- /dev/null +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeReAuthHelper.kt @@ -0,0 +1,30 @@ +/* + * 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 im.vector.app.features.login.ReAuthHelper +import io.mockk.every +import io.mockk.mockk + +class FakeReAuthHelper { + + val instance = mockk() + + fun givenStoredPassword(pwd: String?) { + every { instance.data } returns pwd + } +}