diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 660980d538..931c995d9a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -138,10 +138,6 @@ android:resource="@xml/file_providers" /> - - diff --git a/app/src/main/kotlin/io/element/android/x/MainActivity.kt b/app/src/main/kotlin/io/element/android/x/MainActivity.kt index 7d2f404560..eb3f9450f5 100644 --- a/app/src/main/kotlin/io/element/android/x/MainActivity.kt +++ b/app/src/main/kotlin/io/element/android/x/MainActivity.kt @@ -42,10 +42,10 @@ import io.element.android.compound.theme.ElementTheme import io.element.android.compound.theme.Theme import io.element.android.compound.theme.isDark import io.element.android.compound.theme.mapToTheme +import io.element.android.features.lockscreen.api.LockScreenEntryPoint import io.element.android.features.lockscreen.api.LockScreenLockState import io.element.android.features.lockscreen.api.LockScreenService import io.element.android.features.lockscreen.api.handleSecureFlag -import io.element.android.features.lockscreen.impl.unlock.activity.PinUnlockActivity import io.element.android.libraries.architecture.bindings import io.element.android.libraries.core.log.logger.LoggerTag import io.element.android.libraries.designsystem.utils.snackbar.LocalSnackbarDispatcher @@ -65,7 +65,7 @@ class MainActivity : NodeActivity() { installSplashScreen() super.onCreate(savedInstanceState) appBindings = bindings() - setupLockManagement(appBindings.lockScreenService()) + setupLockManagement(appBindings.lockScreenService(), appBindings.lockScreenEntryPoint()) enableEdgeToEdge() setContent { MainContent(appBindings) @@ -123,13 +123,16 @@ class MainActivity : NodeActivity() { } } - private fun setupLockManagement(lockScreenService: LockScreenService) { + private fun setupLockManagement( + lockScreenService: LockScreenService, + lockScreenEntryPoint: LockScreenEntryPoint + ) { lockScreenService.handleSecureFlag(this) lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.RESUMED) { lockScreenService.lockState.collect { state -> if (state == LockScreenLockState.Locked) { - startActivity(PinUnlockActivity.newIntent(this@MainActivity)) + startActivity(lockScreenEntryPoint.pinUnlockIntent(this@MainActivity)) } } } diff --git a/app/src/main/kotlin/io/element/android/x/di/AppBindings.kt b/app/src/main/kotlin/io/element/android/x/di/AppBindings.kt index d8be841b97..bad34edfa0 100644 --- a/app/src/main/kotlin/io/element/android/x/di/AppBindings.kt +++ b/app/src/main/kotlin/io/element/android/x/di/AppBindings.kt @@ -18,6 +18,7 @@ package io.element.android.x.di import com.squareup.anvil.annotations.ContributesTo import io.element.android.features.api.MigrationEntryPoint +import io.element.android.features.lockscreen.api.LockScreenEntryPoint import io.element.android.features.lockscreen.api.LockScreenService import io.element.android.features.preferences.api.store.AppPreferencesStore import io.element.android.features.rageshake.api.reporter.BugReporter @@ -38,4 +39,6 @@ interface AppBindings { fun preferencesStore(): AppPreferencesStore fun migrationEntryPoint(): MigrationEntryPoint + + fun lockScreenEntryPoint(): LockScreenEntryPoint } diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/FtueFlowNode.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/FtueFlowNode.kt index 772343ea58..6720fa0274 100644 --- a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/FtueFlowNode.kt +++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/FtueFlowNode.kt @@ -132,9 +132,8 @@ class FtueFlowNode @AssistedInject constructor( lifecycleScope.launch { moveToNextStep() } } } - lockScreenEntryPoint.nodeBuilder(this, buildContext) + lockScreenEntryPoint.nodeBuilder(this, buildContext, LockScreenEntryPoint.Target.Setup) .callback(callback) - .target(LockScreenEntryPoint.Target.Setup) .build() } } diff --git a/features/lockscreen/api/src/main/kotlin/io/element/android/features/lockscreen/api/LockScreenEntryPoint.kt b/features/lockscreen/api/src/main/kotlin/io/element/android/features/lockscreen/api/LockScreenEntryPoint.kt index 6a2fb0c72d..f31fc5af4a 100644 --- a/features/lockscreen/api/src/main/kotlin/io/element/android/features/lockscreen/api/LockScreenEntryPoint.kt +++ b/features/lockscreen/api/src/main/kotlin/io/element/android/features/lockscreen/api/LockScreenEntryPoint.kt @@ -16,17 +16,19 @@ package io.element.android.features.lockscreen.api +import android.content.Context +import android.content.Intent import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.plugin.Plugin import io.element.android.libraries.architecture.FeatureEntryPoint interface LockScreenEntryPoint : FeatureEntryPoint { - fun nodeBuilder(parentNode: Node, buildContext: BuildContext): NodeBuilder + fun nodeBuilder(parentNode: Node, buildContext: BuildContext, navTarget: Target): NodeBuilder + fun pinUnlockIntent(context: Context): Intent interface NodeBuilder { fun callback(callback: Callback): NodeBuilder - fun target(target: Target): NodeBuilder fun build(): Node } @@ -37,6 +39,5 @@ interface LockScreenEntryPoint : FeatureEntryPoint { enum class Target { Settings, Setup, - Unlock } } diff --git a/features/lockscreen/impl/src/main/AndroidManifest.xml b/features/lockscreen/impl/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..310d0096cd --- /dev/null +++ b/features/lockscreen/impl/src/main/AndroidManifest.xml @@ -0,0 +1,25 @@ + + + + + + + + + diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenEntryPoint.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenEntryPoint.kt index 5065cdc7f2..a6889a96e7 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenEntryPoint.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenEntryPoint.kt @@ -16,18 +16,20 @@ package io.element.android.features.lockscreen.impl +import android.content.Context +import android.content.Intent import com.bumble.appyx.core.modality.BuildContext import com.bumble.appyx.core.node.Node import com.squareup.anvil.annotations.ContributesBinding import io.element.android.features.lockscreen.api.LockScreenEntryPoint +import io.element.android.features.lockscreen.impl.unlock.activity.PinUnlockActivity import io.element.android.libraries.architecture.createNode import io.element.android.libraries.di.AppScope import javax.inject.Inject @ContributesBinding(AppScope::class) class DefaultLockScreenEntryPoint @Inject constructor() : LockScreenEntryPoint { - override fun nodeBuilder(parentNode: Node, buildContext: BuildContext): LockScreenEntryPoint.NodeBuilder { - var innerTarget: LockScreenEntryPoint.Target = LockScreenEntryPoint.Target.Unlock + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext, navTarget: LockScreenEntryPoint.Target): LockScreenEntryPoint.NodeBuilder { val callbacks = mutableListOf() return object : LockScreenEntryPoint.NodeBuilder { @@ -36,15 +38,9 @@ class DefaultLockScreenEntryPoint @Inject constructor() : LockScreenEntryPoint { return this } - override fun target(target: LockScreenEntryPoint.Target): LockScreenEntryPoint.NodeBuilder { - innerTarget = target - return this - } - override fun build(): Node { val inputs = LockScreenFlowNode.Inputs( - when (innerTarget) { - LockScreenEntryPoint.Target.Unlock -> LockScreenFlowNode.NavTarget.Unlock + when (navTarget) { LockScreenEntryPoint.Target.Setup -> LockScreenFlowNode.NavTarget.Setup LockScreenEntryPoint.Target.Settings -> LockScreenFlowNode.NavTarget.Settings } @@ -54,4 +50,8 @@ class DefaultLockScreenEntryPoint @Inject constructor() : LockScreenEntryPoint { } } } + + override fun pinUnlockIntent(context: Context): Intent { + return PinUnlockActivity.newIntent(context) + } } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/LockScreenFlowNode.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/LockScreenFlowNode.kt index 8dd75fc65d..fcbb0336a4 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/LockScreenFlowNode.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/LockScreenFlowNode.kt @@ -30,7 +30,6 @@ import io.element.android.anvilannotations.ContributesNode import io.element.android.features.lockscreen.api.LockScreenEntryPoint import io.element.android.features.lockscreen.impl.settings.LockScreenSettingsFlowNode import io.element.android.features.lockscreen.impl.setup.LockScreenSetupFlowNode -import io.element.android.features.lockscreen.impl.unlock.PinUnlockNode import io.element.android.libraries.architecture.BackstackView import io.element.android.libraries.architecture.BaseFlowNode import io.element.android.libraries.architecture.NodeInputs @@ -44,20 +43,17 @@ class LockScreenFlowNode @AssistedInject constructor( @Assisted plugins: List, ) : BaseFlowNode( backstack = BackStack( - initialElement = plugins.filterIsInstance(Inputs::class.java).first().initialNavTarget, + initialElement = plugins.filterIsInstance().first().initialNavTarget, savedStateMap = buildContext.savedStateMap, ), buildContext = buildContext, plugins = plugins, ) { data class Inputs( - val initialNavTarget: NavTarget = NavTarget.Unlock, + val initialNavTarget: NavTarget, ) : NodeInputs sealed interface NavTarget : Parcelable { - @Parcelize - data object Unlock : NavTarget - @Parcelize data object Setup : NavTarget @@ -75,10 +71,6 @@ class LockScreenFlowNode @AssistedInject constructor( override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { return when (navTarget) { - NavTarget.Unlock -> { - val inputs = PinUnlockNode.Inputs(isInAppUnlock = false) - createNode(buildContext, plugins = listOf(inputs)) - } NavTarget.Setup -> { val callback = OnSetupDoneCallback(plugins()) createNode(buildContext, plugins = listOf(callback)) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsFlowNode.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsFlowNode.kt index 0890f38d1e..13fe1e62aa 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsFlowNode.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/settings/LockScreenSettingsFlowNode.kt @@ -103,13 +103,12 @@ class LockScreenSettingsFlowNode @AssistedInject constructor( override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { return when (navTarget) { NavTarget.Unlock -> { - val inputs = PinUnlockNode.Inputs(isInAppUnlock = true) val callback = object : PinUnlockNode.Callback { override fun onUnlock() { backstack.newRoot(NavTarget.Settings) } } - createNode(buildContext, plugins = listOf(inputs, callback)) + createNode(buildContext, plugins = listOf(callback)) } NavTarget.SetupPin -> { createNode(buildContext) diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockNode.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockNode.kt index da6853a39c..f357869375 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockNode.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockNode.kt @@ -26,8 +26,6 @@ import com.bumble.appyx.core.plugin.plugins import dagger.assisted.Assisted import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode -import io.element.android.libraries.architecture.NodeInputs -import io.element.android.libraries.architecture.inputs import io.element.android.libraries.di.SessionScope @ContributesNode(SessionScope::class) @@ -40,12 +38,6 @@ class PinUnlockNode @AssistedInject constructor( fun onUnlock() } - data class Inputs( - val isInAppUnlock: Boolean - ) : NodeInputs - - private val inputs: Inputs = inputs() - private fun onUnlock() { plugins().forEach { it.onUnlock() @@ -62,7 +54,9 @@ class PinUnlockNode @AssistedInject constructor( } PinUnlockView( state = state, - isInAppUnlock = inputs.isInAppUnlock, + // UnlockNode is only used for in-app unlock, so we can safely set isInAppUnlock to true. + // It's set to false in PinUnlockActivity. + isInAppUnlock = true, modifier = modifier ) } diff --git a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/activity/PinUnlockActivity.kt b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/activity/PinUnlockActivity.kt index 0c2de97bb2..9c228b0736 100644 --- a/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/activity/PinUnlockActivity.kt +++ b/features/lockscreen/impl/src/main/kotlin/io/element/android/features/lockscreen/impl/unlock/activity/PinUnlockActivity.kt @@ -35,7 +35,7 @@ import kotlinx.coroutines.launch import javax.inject.Inject class PinUnlockActivity : AppCompatActivity() { - companion object { + internal companion object { fun newIntent(context: Context): Intent { return Intent(context, PinUnlockActivity::class.java) } diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/DefaultSignOutTest.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/DefaultSignOutTest.kt new file mode 100644 index 0000000000..6870a336d3 --- /dev/null +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/DefaultSignOutTest.kt @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2024 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 io.element.android.features.lockscreen.impl.unlock + +import com.google.common.truth.Truth.assertThat +import io.element.android.features.lockscreen.impl.unlock.signout.DefaultSignOut +import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.libraries.matrix.test.FakeMatrixClientProvider +import io.element.android.libraries.matrix.test.auth.FakeAuthenticationService +import io.element.android.tests.testutils.lambda.assert +import io.element.android.tests.testutils.lambda.lambdaRecorder +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class DefaultSignOutTest { + private val matrixClient = FakeMatrixClient() + private val authenticationService = FakeAuthenticationService() + private val matrixClientProvider = FakeMatrixClientProvider(getClient = { Result.success(matrixClient) }) + private val sut = DefaultSignOut(authenticationService, matrixClientProvider) + + @Test + fun `when no active session then it throws`() = runTest { + authenticationService.getLatestSessionIdLambda = { null } + val result = runCatching { sut.invoke() } + assertThat(result.isFailure).isTrue() + } + + @Test + fun `with one active session and successful logout on client`() = runTest { + val logoutLambda = lambdaRecorder { _: Boolean -> null } + authenticationService.getLatestSessionIdLambda = { matrixClient.sessionId } + matrixClient.logoutLambda = logoutLambda + val result = runCatching { sut.invoke() } + assertThat(result.isSuccess).isTrue() + assert(logoutLambda).isCalledOnce() + } + + @Test + fun `with one active session and and failed logout on client`() = runTest { + val logoutLambda = lambdaRecorder { _: Boolean -> error("Failed to logout") } + authenticationService.getLatestSessionIdLambda = { matrixClient.sessionId } + matrixClient.logoutLambda = logoutLambda + val result = runCatching { sut.invoke() } + assertThat(result.isFailure).isTrue() + assert(logoutLambda).isCalledOnce() + } +} diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt index 60cc3fff9d..89d0e92ee2 100644 --- a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/unlock/PinUnlockPresenterTest.kt @@ -28,7 +28,10 @@ import io.element.android.features.lockscreen.impl.pin.PinCodeManager import io.element.android.features.lockscreen.impl.pin.model.PinEntry import io.element.android.features.lockscreen.impl.pin.model.assertText import io.element.android.features.lockscreen.impl.unlock.keypad.PinKeypadModel +import io.element.android.features.lockscreen.impl.unlock.signout.SignOut import io.element.android.libraries.architecture.AsyncData +import io.element.android.tests.testutils.lambda.assert +import io.element.android.tests.testutils.lambda.lambdaRecorder import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.test.runTest import org.junit.Test @@ -103,7 +106,9 @@ class PinUnlockPresenterTest { @Test fun `present - forgot pin flow`() = runTest { - val presenter = createPinUnlockPresenter(this) + val signOutLambda = lambdaRecorder { null } + val signOut = FakeSignOut(signOutLambda) + val presenter = createPinUnlockPresenter(this, signOut = signOut) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -130,6 +135,7 @@ class PinUnlockPresenterTest { awaitItem().also { state -> assertThat(state.signOutAction).isInstanceOf(AsyncData.Success::class.java) } + assert(signOutLambda).isCalledOnce().withNoParameter() } } @@ -141,6 +147,7 @@ class PinUnlockPresenterTest { scope: CoroutineScope, biometricUnlockManager: BiometricUnlockManager = FakeBiometricUnlockManager(), callback: PinCodeManager.Callback = DefaultPinCodeManagerCallback(), + signOut: SignOut = FakeSignOut(), ): PinUnlockPresenter { val pinCodeManager = aPinCodeManager().apply { addCallback(callback) @@ -149,7 +156,7 @@ class PinUnlockPresenterTest { return PinUnlockPresenter( pinCodeManager = pinCodeManager, biometricUnlockManager = biometricUnlockManager, - signOut = FakeSignOut(), + signOut = signOut, coroutineScope = scope, pinUnlockHelper = PinUnlockHelper(biometricUnlockManager, pinCodeManager), ) diff --git a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPresenterTest.kt b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPresenterTest.kt index 9531ea8886..70b346ba8d 100644 --- a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPresenterTest.kt +++ b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPresenterTest.kt @@ -144,7 +144,9 @@ class LogoutPresenterTest { @Test fun `present - logout with error then cancel`() = runTest { val matrixClient = FakeMatrixClient().apply { - givenLogoutError(A_THROWABLE) + logoutLambda = { _ -> + throw A_THROWABLE + } } val presenter = createLogoutPresenter( matrixClient, @@ -170,7 +172,13 @@ class LogoutPresenterTest { @Test fun `present - logout with error then force`() = runTest { val matrixClient = FakeMatrixClient().apply { - givenLogoutError(A_THROWABLE) + logoutLambda = { ignoreSdkError -> + if (!ignoreSdkError) { + throw A_THROWABLE + } else { + null + } + } } val presenter = createLogoutPresenter( matrixClient, diff --git a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/direct/DefaultDirectLogoutPresenterTest.kt b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/direct/DefaultDirectLogoutPresenterTest.kt index bf3df93731..14d340570c 100644 --- a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/direct/DefaultDirectLogoutPresenterTest.kt +++ b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/direct/DefaultDirectLogoutPresenterTest.kt @@ -125,7 +125,9 @@ class DefaultDirectLogoutPresenterTest { @Test fun `present - logout with error then cancel`() = runTest { val matrixClient = FakeMatrixClient().apply { - givenLogoutError(A_THROWABLE) + logoutLambda = { _ -> + throw A_THROWABLE + } } val presenter = createDefaultDirectLogoutPresenter( matrixClient, @@ -151,7 +153,13 @@ class DefaultDirectLogoutPresenterTest { @Test fun `present - logout with error then force`() = runTest { val matrixClient = FakeMatrixClient().apply { - givenLogoutError(A_THROWABLE) + logoutLambda = { ignoreSdkError -> + if (!ignoreSdkError) { + throw A_THROWABLE + } else { + null + } + } } val presenter = createDefaultDirectLogoutPresenter( matrixClient, diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt index b93e02dd39..ac8a881348 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/PreferencesFlowNode.kt @@ -212,9 +212,7 @@ class PreferencesFlowNode @AssistedInject constructor( createNode(buildContext, listOf(inputs)) } NavTarget.LockScreenSettings -> { - lockScreenEntryPoint.nodeBuilder(this, buildContext) - .target(LockScreenEntryPoint.Target.Settings) - .build() + lockScreenEntryPoint.nodeBuilder(this, buildContext, LockScreenEntryPoint.Target.Settings).build() } NavTarget.BlockedUsers -> { createNode(buildContext) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt index def7bc01fd..cae1ff06b9 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt @@ -54,7 +54,6 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.flowOf @@ -96,7 +95,6 @@ class FakeMatrixClient( private var createRoomResult: Result = Result.success(A_ROOM_ID) private var createDmResult: Result = Result.success(A_ROOM_ID) private var findDmResult: RoomId? = A_ROOM_ID - private var logoutFailure: Throwable? = null private val getRoomResults = mutableMapOf() private val searchUserResults = mutableMapOf>() private val getProfileResults = mutableMapOf>() @@ -116,6 +114,9 @@ class FakeMatrixClient( var getRoomInfoFlowLambda = { _: RoomId -> flowOf>(Optional.empty()) } + var logoutLambda: (Boolean) -> String? = { + null + } override suspend fun getRoom(roomId: RoomId): MatrixRoom? { return getRoomResults[roomId] @@ -160,12 +161,8 @@ class FakeMatrixClient( override suspend fun clearCache() { } - override suspend fun logout(ignoreSdkError: Boolean): String? { - delay(100) - if (ignoreSdkError.not()) { - logoutFailure?.let { throw it } - } - return null + override suspend fun logout(ignoreSdkError: Boolean): String? = simulateLongTask { + return logoutLambda(ignoreSdkError) } override fun close() = Unit @@ -229,10 +226,6 @@ class FakeMatrixClient( // Mocks - fun givenLogoutError(failure: Throwable?) { - logoutFailure = failure - } - fun givenCreateRoomResult(result: Result) { createRoomResult = result } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeAuthenticationService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeAuthenticationService.kt index 2cf6b77a78..c24df7d717 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeAuthenticationService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/auth/FakeAuthenticationService.kt @@ -39,13 +39,13 @@ class FakeAuthenticationService : MatrixAuthenticationService { private var changeServerError: Throwable? = null private var matrixClient: MatrixClient? = null + var getLatestSessionIdLambda: (() -> SessionId?) = { null } + override fun loggedInStateFlow(): Flow { return flowOf(LoggedInState.NotLoggedIn) } - override suspend fun getLatestSessionId(): SessionId? { - return null - } + override suspend fun getLatestSessionId(): SessionId? = getLatestSessionIdLambda() override suspend fun restoreSession(sessionId: SessionId): Result { return if (matrixClient != null) {