diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModel.kt index afdd28096f..717c51978a 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModel.kt @@ -94,7 +94,6 @@ class SessionOverviewViewModel @AssistedInject constructor( } } - // TODO add unit tests override fun handle(action: SessionOverviewAction) { when (action) { is SessionOverviewAction.VerifySession -> handleVerifySessionAction() @@ -128,7 +127,6 @@ class SessionOverviewViewModel @AssistedInject constructor( _viewEvents.post(SessionOverviewViewEvent.ShowVerifyOtherSession(deviceId)) } - // TODO add unit tests private fun handleSignoutSession() = withState { state -> if (state.deviceInfo.invoke()?.isCurrentDevice.orFalse()) { handleSignoutCurrentSession() diff --git a/vector/src/test/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModelTest.kt b/vector/src/test/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModelTest.kt index 205e173353..c05c6daa3f 100644 --- a/vector/src/test/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModelTest.kt +++ b/vector/src/test/java/im/vector/app/features/settings/devices/v2/overview/SessionOverviewViewModelTest.kt @@ -44,6 +44,7 @@ import io.mockk.unmockkAll import io.mockk.verify import io.mockk.verifyAll import kotlinx.coroutines.flow.flowOf +import org.amshove.kluent.shouldBeEqualTo import org.junit.After import org.junit.Before import org.junit.Rule @@ -53,6 +54,7 @@ import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel +import org.matrix.android.sdk.api.session.uia.DefaultBaseAuth import javax.net.ssl.HttpsURLConnection import kotlin.coroutines.Continuation @@ -321,6 +323,31 @@ class SessionOverviewViewModelTest { .finish() } + @Test + fun `given another session and reAuth is needed during signout when handling signout action then requestReAuth is sent and pending auth is stored`() { + // Given + val deviceFullInfo = mockk() + every { deviceFullInfo.isCurrentDevice } returns false + every { getDeviceFullInfoUseCase.execute(A_SESSION_ID_1) } returns flowOf(deviceFullInfo) + val reAuthNeeded = givenSignoutReAuthNeeded(A_SESSION_ID_1) + val signoutAction = SessionOverviewAction.SignoutSession + givenCurrentSessionIsTrusted() + val expectedPendingAuth = DefaultBaseAuth(session = reAuthNeeded.flowResponse.session) + val expectedReAuthEvent = SessionOverviewViewEvent.RequestReAuth(reAuthNeeded.flowResponse, reAuthNeeded.errCode) + + // When + val viewModel = createViewModel() + val viewModelTest = viewModel.test() + viewModel.handle(signoutAction) + + // Then + viewModelTest + .assertEvent { it == expectedReAuthEvent } + .finish() + fakePendingAuthHandler.instance.pendingAuth shouldBeEqualTo expectedPendingAuth + fakePendingAuthHandler.instance.uiaContinuation shouldBeEqualTo reAuthNeeded.uiaContinuation + } + @Test fun `given SSO auth has been done when handling ssoAuthDone action then corresponding method of pending auth handler is called`() { // Given @@ -399,6 +426,27 @@ class SessionOverviewViewModelTest { } } + private fun givenSignoutReAuthNeeded(deviceId: String): SignoutSessionResult.ReAuthNeeded { + val interceptor = slot() + val flowResponse = mockk() + every { flowResponse.session } returns A_SESSION_ID_1 + val errorCode = "errorCode" + val promise = mockk>() + val reAuthNeeded = SignoutSessionResult.ReAuthNeeded( + pendingAuth = mockk(), + uiaContinuation = promise, + flowResponse = flowResponse, + errCode = errorCode, + ) + every { interceptSignoutFlowResponseUseCase.execute(flowResponse, errorCode, promise) } returns reAuthNeeded + coEvery { signoutSessionUseCase.execute(deviceId, capture(interceptor)) } coAnswers { + secondArg().performStage(flowResponse, errorCode, promise) + Result.success(Unit) + } + + return reAuthNeeded + } + private fun givenSignoutError(deviceId: String, error: Throwable) { coEvery { signoutSessionUseCase.execute(deviceId, any()) } returns Result.failure(error) } diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakePendingAuthHandler.kt b/vector/src/test/java/im/vector/app/test/fakes/FakePendingAuthHandler.kt index 5d49dc3a77..9feea016e3 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakePendingAuthHandler.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakePendingAuthHandler.kt @@ -18,8 +18,9 @@ package im.vector.app.test.fakes import im.vector.app.features.auth.PendingAuthHandler import io.mockk.mockk +import io.mockk.spyk class FakePendingAuthHandler { - val instance = mockk() + val instance = spyk(mockk()) }