From 05f61b87799e2e1804cd5a28945ea791b27a61dd Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 20 Feb 2025 17:10:43 +0100 Subject: [PATCH] Add a way to override default homeserver. --- .../android/appconfig/AuthenticationConfig.kt | 5 -- enterprise | 2 +- .../enterprise/api/EnterpriseService.kt | 1 + .../impl/DefaultEnterpriseService.kt | 2 + .../impl/DefaultEnterpriseServiceTest.kt | 6 ++ features/enterprise/test/build.gradle.kts | 20 +++++ .../enterprise/test/FakeEnterpriseService.kt | 42 ++++++++++ features/login/impl/build.gradle.kts | 2 + .../AccountProviderDataSource.kt | 16 +++- .../login/impl/util/LoginConstants.kt | 18 ---- .../changeserver/ChangeServerPresenterTest.kt | 40 ++++----- .../ConfirmAccountProviderPresenterTest.kt | 6 +- .../createaccount/DefaultMessageParserTest.kt | 22 ++--- .../LoginPasswordPresenterTest.kt | 84 +++++++------------ 14 files changed, 145 insertions(+), 121 deletions(-) create mode 100644 features/enterprise/test/build.gradle.kts create mode 100644 features/enterprise/test/src/main/kotlin/io/element/android/features/enterprise/test/FakeEnterpriseService.kt delete mode 100644 features/login/impl/src/main/kotlin/io/element/android/features/login/impl/util/LoginConstants.kt diff --git a/appconfig/src/main/kotlin/io/element/android/appconfig/AuthenticationConfig.kt b/appconfig/src/main/kotlin/io/element/android/appconfig/AuthenticationConfig.kt index 2e0e46fa0b..5061290948 100644 --- a/appconfig/src/main/kotlin/io/element/android/appconfig/AuthenticationConfig.kt +++ b/appconfig/src/main/kotlin/io/element/android/appconfig/AuthenticationConfig.kt @@ -10,11 +10,6 @@ package io.element.android.appconfig object AuthenticationConfig { const val MATRIX_ORG_URL = "https://matrix.org" - /** - * Default homeserver url to sign in with, unless the user selects a different one. - */ - const val DEFAULT_HOMESERVER_URL = MATRIX_ORG_URL - /** * URL with some docs that explain what's sliding sync and how to add it to your home server. */ diff --git a/enterprise b/enterprise index 0c028db8a4..6df20902d6 160000 --- a/enterprise +++ b/enterprise @@ -1 +1 @@ -Subproject commit 0c028db8a48118433c7e11737080a6a01fb90f69 +Subproject commit 6df20902d64c28abb660bf83bea05e7bfb6fe691 diff --git a/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/EnterpriseService.kt b/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/EnterpriseService.kt index 305aae2243..4fddfe283c 100644 --- a/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/EnterpriseService.kt +++ b/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/EnterpriseService.kt @@ -13,6 +13,7 @@ import io.element.android.libraries.matrix.api.core.SessionId interface EnterpriseService { val isEnterpriseBuild: Boolean suspend fun isEnterpriseUser(sessionId: SessionId): Boolean + fun defaultHomeserver(): String? fun semanticColorsLight(): SemanticColors fun semanticColorsDark(): SemanticColors diff --git a/features/enterprise/impl/src/main/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseService.kt b/features/enterprise/impl/src/main/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseService.kt index 1a18ddbee3..898f59969c 100644 --- a/features/enterprise/impl/src/main/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseService.kt +++ b/features/enterprise/impl/src/main/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseService.kt @@ -22,6 +22,8 @@ class DefaultEnterpriseService @Inject constructor() : EnterpriseService { override suspend fun isEnterpriseUser(sessionId: SessionId) = false + override fun defaultHomeserver() = null + override fun semanticColorsLight(): SemanticColors = compoundColorsLight override fun semanticColorsDark(): SemanticColors = compoundColorsDark diff --git a/features/enterprise/impl/src/test/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseServiceTest.kt b/features/enterprise/impl/src/test/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseServiceTest.kt index e2a6a11a9a..0d5593dab9 100644 --- a/features/enterprise/impl/src/test/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseServiceTest.kt +++ b/features/enterprise/impl/src/test/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseServiceTest.kt @@ -19,6 +19,12 @@ class DefaultEnterpriseServiceTest { assertThat(defaultEnterpriseService.isEnterpriseBuild).isFalse() } + @Test + fun `defaultHomeserver should return null`() { + val defaultEnterpriseService = DefaultEnterpriseService() + assertThat(defaultEnterpriseService.defaultHomeserver()).isNull() + } + @Test fun `isEnterpriseUser always return false`() = runTest { val defaultEnterpriseService = DefaultEnterpriseService() diff --git a/features/enterprise/test/build.gradle.kts b/features/enterprise/test/build.gradle.kts new file mode 100644 index 0000000000..91b76f4fa7 --- /dev/null +++ b/features/enterprise/test/build.gradle.kts @@ -0,0 +1,20 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ +plugins { + id("io.element.android-library") +} + +android { + namespace = "io.element.android.features.enterprise.test" +} + +dependencies { + api(projects.features.enterprise.api) + implementation(libs.compound) + implementation(projects.libraries.matrix.api) + implementation(projects.tests.testutils) +} diff --git a/features/enterprise/test/src/main/kotlin/io/element/android/features/enterprise/test/FakeEnterpriseService.kt b/features/enterprise/test/src/main/kotlin/io/element/android/features/enterprise/test/FakeEnterpriseService.kt new file mode 100644 index 0000000000..fbb826ec73 --- /dev/null +++ b/features/enterprise/test/src/main/kotlin/io/element/android/features/enterprise/test/FakeEnterpriseService.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.enterprise.test + +import io.element.android.compound.tokens.generated.SemanticColors +import io.element.android.features.enterprise.api.EnterpriseService +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.simulateLongTask + +class FakeEnterpriseService( + override val isEnterpriseBuild: Boolean = false, + private val isEnterpriseUserResult: (SessionId) -> Boolean = { lambdaError() }, + private val defaultHomeserverResult: () -> String? = { A_FAKE_HOMESERVER }, + private val semanticColorsLightResult: () -> SemanticColors = { lambdaError() }, + private val semanticColorsDarkResult: () -> SemanticColors = { lambdaError() }, +) : EnterpriseService { + override suspend fun isEnterpriseUser(sessionId: SessionId): Boolean = simulateLongTask { + isEnterpriseUserResult(sessionId) + } + + override fun defaultHomeserver(): String? { + return defaultHomeserverResult() + } + + override fun semanticColorsLight(): SemanticColors { + return semanticColorsLightResult() + } + + override fun semanticColorsDark(): SemanticColors { + return semanticColorsDarkResult() + } + + companion object { + const val A_FAKE_HOMESERVER = "a_fake_homeserver" + } +} diff --git a/features/login/impl/build.gradle.kts b/features/login/impl/build.gradle.kts index 327eaa5416..02c38e2a57 100644 --- a/features/login/impl/build.gradle.kts +++ b/features/login/impl/build.gradle.kts @@ -28,6 +28,7 @@ setupAnvil(componentMergingStrategy = ComponentMergingStrategy.KSP) dependencies { implementation(projects.appconfig) + implementation(projects.features.enterprise.api) implementation(projects.libraries.core) implementation(projects.libraries.androidutils) implementation(projects.libraries.architecture) @@ -55,6 +56,7 @@ dependencies { testImplementation(libs.test.robolectric) testImplementation(libs.test.truth) testImplementation(libs.test.turbine) + testImplementation(projects.features.enterprise.test) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.oidc.impl) testImplementation(projects.libraries.permissions.test) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/accountprovider/AccountProviderDataSource.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/accountprovider/AccountProviderDataSource.kt index 913cfb6f0c..3f9c368a1d 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/accountprovider/AccountProviderDataSource.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/accountprovider/AccountProviderDataSource.kt @@ -7,7 +7,8 @@ package io.element.android.features.login.impl.accountprovider -import io.element.android.features.login.impl.util.defaultAccountProvider +import io.element.android.appconfig.AuthenticationConfig +import io.element.android.features.enterprise.api.EnterpriseService import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.SingleIn import kotlinx.coroutines.flow.MutableStateFlow @@ -16,7 +17,18 @@ import kotlinx.coroutines.flow.asStateFlow import javax.inject.Inject @SingleIn(AppScope::class) -class AccountProviderDataSource @Inject constructor() { +class AccountProviderDataSource @Inject constructor( + enterpriseService: EnterpriseService, +) { + private val defaultAccountProvider = (enterpriseService.defaultHomeserver() ?: AuthenticationConfig.MATRIX_ORG_URL).let { url -> + AccountProvider( + url = url, + subtitle = null, + isPublic = url == AuthenticationConfig.MATRIX_ORG_URL, + isMatrixOrg = url == AuthenticationConfig.MATRIX_ORG_URL, + ) + } + private val accountProvider: MutableStateFlow = MutableStateFlow( defaultAccountProvider ) diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/util/LoginConstants.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/util/LoginConstants.kt deleted file mode 100644 index 6d06ad8c3e..0000000000 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/util/LoginConstants.kt +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright 2023, 2024 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial - * Please see LICENSE files in the repository root for full details. - */ - -package io.element.android.features.login.impl.util - -import io.element.android.appconfig.AuthenticationConfig -import io.element.android.features.login.impl.accountprovider.AccountProvider - -val defaultAccountProvider = AccountProvider( - url = AuthenticationConfig.DEFAULT_HOMESERVER_URL, - subtitle = null, - isPublic = AuthenticationConfig.DEFAULT_HOMESERVER_URL == AuthenticationConfig.MATRIX_ORG_URL, - isMatrixOrg = AuthenticationConfig.DEFAULT_HOMESERVER_URL == AuthenticationConfig.MATRIX_ORG_URL, -) diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenterTest.kt index 2dbde8633e..15b8856969 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/changeserver/ChangeServerPresenterTest.kt @@ -7,10 +7,8 @@ package io.element.android.features.login.impl.changeserver -import app.cash.molecule.RecompositionMode -import app.cash.molecule.moleculeFlow -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat +import io.element.android.features.enterprise.test.FakeEnterpriseService import io.element.android.features.login.impl.accountprovider.AccountProvider import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource import io.element.android.libraries.architecture.AsyncData @@ -18,6 +16,7 @@ import io.element.android.libraries.matrix.test.A_HOMESERVER import io.element.android.libraries.matrix.test.A_HOMESERVER_URL import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.test import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test @@ -28,13 +27,7 @@ class ChangeServerPresenterTest { @Test fun `present - initial state`() = runTest { - val presenter = ChangeServerPresenter( - FakeMatrixAuthenticationService(), - AccountProviderDataSource() - ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + createPresenter().test { val initialState = awaitItem() assertThat(initialState.changeServerAction).isEqualTo(AsyncData.Uninitialized) } @@ -43,13 +36,9 @@ class ChangeServerPresenterTest { @Test fun `present - change server ok`() = runTest { val authenticationService = FakeMatrixAuthenticationService() - val presenter = ChangeServerPresenter( - authenticationService, - AccountProviderDataSource() - ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + createPresenter( + authenticationService = authenticationService, + ).test { val initialState = awaitItem() assertThat(initialState.changeServerAction).isEqualTo(AsyncData.Uninitialized) authenticationService.givenHomeserver(A_HOMESERVER) @@ -63,14 +52,7 @@ class ChangeServerPresenterTest { @Test fun `present - change server error`() = runTest { - val authenticationService = FakeMatrixAuthenticationService() - val presenter = ChangeServerPresenter( - authenticationService, - AccountProviderDataSource() - ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + createPresenter().test { val initialState = awaitItem() assertThat(initialState.changeServerAction).isEqualTo(AsyncData.Uninitialized) initialState.eventSink.invoke(ChangeServerEvents.ChangeServer(AccountProvider(url = A_HOMESERVER_URL))) @@ -84,4 +66,12 @@ class ChangeServerPresenterTest { assertThat(finalState.changeServerAction).isEqualTo(AsyncData.Uninitialized) } } + + private fun createPresenter( + authenticationService: FakeMatrixAuthenticationService = FakeMatrixAuthenticationService(), + accountProviderDataSource: AccountProviderDataSource = AccountProviderDataSource(FakeEnterpriseService()), + ) = ChangeServerPresenter( + authenticationService = authenticationService, + accountProviderDataSource = accountProviderDataSource + ) } diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt index 3ff604a1c5..89065f95ea 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/confirmaccountprovider/ConfirmAccountProviderPresenterTest.kt @@ -11,10 +11,10 @@ import app.cash.molecule.RecompositionMode import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth.assertThat +import io.element.android.features.enterprise.test.FakeEnterpriseService import io.element.android.features.login.impl.DefaultLoginUserStory import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource import io.element.android.features.login.impl.screens.createaccount.AccountCreationNotSupported -import io.element.android.features.login.impl.util.defaultAccountProvider import io.element.android.features.login.impl.web.FakeWebClientUrlForAuthenticationRetriever import io.element.android.features.login.impl.web.WebClientUrlForAuthenticationRetriever import io.element.android.libraries.architecture.AsyncData @@ -44,7 +44,7 @@ class ConfirmAccountProviderPresenterTest { val initialState = awaitItem() assertThat(initialState.isAccountCreation).isFalse() assertThat(initialState.submitEnabled).isTrue() - assertThat(initialState.accountProvider).isEqualTo(defaultAccountProvider) + assertThat(initialState.accountProvider.url).isEqualTo(FakeEnterpriseService.A_FAKE_HOMESERVER) assertThat(initialState.loginFlow).isEqualTo(AsyncData.Uninitialized) } } @@ -350,7 +350,7 @@ class ConfirmAccountProviderPresenterTest { private fun createConfirmAccountProviderPresenter( params: ConfirmAccountProviderPresenter.Params = ConfirmAccountProviderPresenter.Params(isAccountCreation = false), - accountProviderDataSource: AccountProviderDataSource = AccountProviderDataSource(), + accountProviderDataSource: AccountProviderDataSource = AccountProviderDataSource(FakeEnterpriseService()), matrixAuthenticationService: MatrixAuthenticationService = FakeMatrixAuthenticationService(), defaultOidcActionFlow: DefaultOidcActionFlow = DefaultOidcActionFlow(), defaultLoginUserStory: DefaultLoginUserStory = DefaultLoginUserStory(), diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/createaccount/DefaultMessageParserTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/createaccount/DefaultMessageParserTest.kt index e118570f4e..8c39685316 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/createaccount/DefaultMessageParserTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/createaccount/DefaultMessageParserTest.kt @@ -8,8 +8,8 @@ package io.element.android.features.login.impl.screens.createaccount import com.google.common.truth.Truth.assertThat +import io.element.android.features.enterprise.test.FakeEnterpriseService import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource -import io.element.android.features.login.impl.util.defaultAccountProvider import io.element.android.libraries.matrix.api.auth.external.ExternalSession import kotlinx.serialization.SerializationException import org.junit.Assert.assertThrows @@ -27,9 +27,7 @@ class DefaultMessageParserTest { @Test fun `DefaultMessageParser is able to parse correct message`() { - val sut = DefaultMessageParser( - AccountProviderDataSource() - ) + val sut = createDefaultMessageParser() assertThat(sut.parse(validMessage)).isEqualTo( anExternalSession( homeserverUrl = "home_server", @@ -39,9 +37,7 @@ class DefaultMessageParserTest { @Test fun `DefaultMessageParser should throw Exception in case of error`() { - val sut = DefaultMessageParser( - AccountProviderDataSource() - ) + val sut = createDefaultMessageParser() // kotlinx.serialization.json.internal.JsonDecodingException assertThrows(SerializationException::class.java) { sut.parse("invalid json") } // missing userId @@ -60,16 +56,20 @@ class DefaultMessageParserTest { @Test fun `DefaultMessageParser should be successful even is homeserver url is missing`() { - val sut = DefaultMessageParser( - AccountProviderDataSource() - ) + val sut = createDefaultMessageParser() // missing homeServer assertThat(sut.parse(validMessage.replace(""""home_server": "home_server",""", ""))).isEqualTo( anExternalSession( - homeserverUrl = defaultAccountProvider.url, + homeserverUrl = FakeEnterpriseService.A_FAKE_HOMESERVER, ) ) } + + private fun createDefaultMessageParser(): DefaultMessageParser { + return DefaultMessageParser( + AccountProviderDataSource(FakeEnterpriseService()) + ) + } } internal fun anExternalSession( diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordPresenterTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordPresenterTest.kt index cced3fece5..bb5b226536 100644 --- a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordPresenterTest.kt +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordPresenterTest.kt @@ -7,13 +7,10 @@ package io.element.android.features.login.impl.screens.loginpassword -import app.cash.molecule.RecompositionMode -import app.cash.molecule.moleculeFlow -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat +import io.element.android.features.enterprise.test.FakeEnterpriseService import io.element.android.features.login.impl.DefaultLoginUserStory import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource -import io.element.android.features.login.impl.util.defaultAccountProvider import io.element.android.libraries.architecture.AsyncData import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.test.A_HOMESERVER @@ -23,6 +20,7 @@ import io.element.android.libraries.matrix.test.A_THROWABLE import io.element.android.libraries.matrix.test.A_USER_NAME import io.element.android.libraries.matrix.test.auth.FakeMatrixAuthenticationService import io.element.android.tests.testutils.WarmUpRule +import io.element.android.tests.testutils.test import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test @@ -33,19 +31,9 @@ class LoginPasswordPresenterTest { @Test fun `present - initial state`() = runTest { - val authenticationService = FakeMatrixAuthenticationService() - val accountProviderDataSource = AccountProviderDataSource() - val loginUserStory = DefaultLoginUserStory() - val presenter = LoginPasswordPresenter( - authenticationService, - accountProviderDataSource, - loginUserStory, - ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + createLoginPasswordPresenter().test { val initialState = awaitItem() - assertThat(initialState.accountProvider).isEqualTo(defaultAccountProvider) + assertThat(initialState.accountProvider.url).isEqualTo(FakeEnterpriseService.A_FAKE_HOMESERVER) assertThat(initialState.formState).isEqualTo(LoginFormState.Default) assertThat(initialState.loginAction).isEqualTo(AsyncData.Uninitialized) assertThat(initialState.submitEnabled).isFalse() @@ -55,17 +43,10 @@ class LoginPasswordPresenterTest { @Test fun `present - enter login and password`() = runTest { val authenticationService = FakeMatrixAuthenticationService() - val accountProviderDataSource = AccountProviderDataSource() - val loginUserStory = DefaultLoginUserStory() - val presenter = LoginPasswordPresenter( - authenticationService, - accountProviderDataSource, - loginUserStory, - ) authenticationService.givenHomeserver(A_HOMESERVER) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + createLoginPasswordPresenter( + authenticationService = authenticationService, + ).test { val initialState = awaitItem() initialState.eventSink.invoke(LoginPasswordEvents.SetLogin(A_USER_NAME)) val loginState = awaitItem() @@ -81,17 +62,12 @@ class LoginPasswordPresenterTest { @Test fun `present - submit`() = runTest { val authenticationService = FakeMatrixAuthenticationService() - val accountProviderDataSource = AccountProviderDataSource() - val loginUserStory = DefaultLoginUserStory().apply { setLoginFlowIsDone(false) } - val presenter = LoginPasswordPresenter( - authenticationService, - accountProviderDataSource, - loginUserStory, - ) authenticationService.givenHomeserver(A_HOMESERVER) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + val loginUserStory = DefaultLoginUserStory().apply { setLoginFlowIsDone(false) } + createLoginPasswordPresenter( + authenticationService = authenticationService, + defaultLoginUserStory = loginUserStory, + ).test { assertThat(loginUserStory.loginFlowIsDone.value).isFalse() val initialState = awaitItem() initialState.eventSink.invoke(LoginPasswordEvents.SetLogin(A_USER_NAME)) @@ -110,17 +86,10 @@ class LoginPasswordPresenterTest { @Test fun `present - submit with error`() = runTest { val authenticationService = FakeMatrixAuthenticationService() - val accountProviderDataSource = AccountProviderDataSource() - val loginUserStory = DefaultLoginUserStory() - val presenter = LoginPasswordPresenter( - authenticationService, - accountProviderDataSource, - loginUserStory, - ) authenticationService.givenHomeserver(A_HOMESERVER) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + createLoginPasswordPresenter( + authenticationService = authenticationService, + ).test { val initialState = awaitItem() initialState.eventSink.invoke(LoginPasswordEvents.SetLogin(A_USER_NAME)) initialState.eventSink.invoke(LoginPasswordEvents.SetPassword(A_PASSWORD)) @@ -138,17 +107,10 @@ class LoginPasswordPresenterTest { @Test fun `present - clear error`() = runTest { val authenticationService = FakeMatrixAuthenticationService() - val accountProviderDataSource = AccountProviderDataSource() - val loginUserStory = DefaultLoginUserStory() - val presenter = LoginPasswordPresenter( - authenticationService, - accountProviderDataSource, - loginUserStory, - ) authenticationService.givenHomeserver(A_HOMESERVER) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + createLoginPasswordPresenter( + authenticationService = authenticationService, + ).test { val initialState = awaitItem() initialState.eventSink.invoke(LoginPasswordEvents.SetLogin(A_USER_NAME)) initialState.eventSink.invoke(LoginPasswordEvents.SetPassword(A_PASSWORD)) @@ -167,4 +129,14 @@ class LoginPasswordPresenterTest { assertThat(clearedState.loginAction).isEqualTo(AsyncData.Uninitialized) } } + + private fun createLoginPasswordPresenter( + authenticationService: FakeMatrixAuthenticationService = FakeMatrixAuthenticationService(), + accountProviderDataSource: AccountProviderDataSource = AccountProviderDataSource(FakeEnterpriseService()), + defaultLoginUserStory: DefaultLoginUserStory = DefaultLoginUserStory() + ): LoginPasswordPresenter = LoginPasswordPresenter( + authenticationService = authenticationService, + accountProviderDataSource = accountProviderDataSource, + defaultLoginUserStory = defaultLoginUserStory, + ) }