Add test for LoginRootPresenter
This commit is contained in:
parent
5ca2b475cc
commit
8fb1f2655e
2 changed files with 155 additions and 2 deletions
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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.
|
||||
*/
|
||||
|
||||
@file:OptIn(ExperimentalCoroutinesApi::class)
|
||||
|
||||
package io.element.android.features.login.root
|
||||
|
||||
import app.cash.molecule.RecompositionClock
|
||||
import app.cash.molecule.moleculeFlow
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.matrix.core.SessionId
|
||||
import io.element.android.libraries.matrixtest.auth.A_FAILURE
|
||||
import io.element.android.libraries.matrixtest.auth.A_HOMESERVER
|
||||
import io.element.android.libraries.matrixtest.auth.A_HOMESERVER_2
|
||||
import io.element.android.libraries.matrixtest.auth.A_LOGIN
|
||||
import io.element.android.libraries.matrixtest.auth.A_PASSWORD
|
||||
import io.element.android.libraries.matrixtest.auth.A_SESSION_ID
|
||||
import io.element.android.libraries.matrixtest.auth.FakeAuthenticationService
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
class LoginRootPresenterTest {
|
||||
@Test
|
||||
fun `present - initial state`() = runTest {
|
||||
val presenter = LoginRootPresenter(
|
||||
FakeAuthenticationService(),
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState.homeserver).isEqualTo(A_HOMESERVER)
|
||||
assertThat(initialState.loggedInState).isEqualTo(LoggedInState.NotLoggedIn)
|
||||
assertThat(initialState.formState).isEqualTo(LoginFormState.Default)
|
||||
assertThat(initialState.submitEnabled).isFalse()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - enter login and password`() = runTest {
|
||||
val presenter = LoginRootPresenter(
|
||||
FakeAuthenticationService(),
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
initialState.eventSink.invoke(LoginRootEvents.SetLogin(A_LOGIN))
|
||||
val loginState = awaitItem()
|
||||
assertThat(loginState.formState).isEqualTo(LoginFormState(login = A_LOGIN, password = ""))
|
||||
assertThat(loginState.submitEnabled).isFalse()
|
||||
initialState.eventSink.invoke(LoginRootEvents.SetPassword(A_PASSWORD))
|
||||
val loginAndPasswordState = awaitItem()
|
||||
assertThat(loginAndPasswordState.formState).isEqualTo(LoginFormState(login = A_LOGIN, password = A_PASSWORD))
|
||||
assertThat(loginAndPasswordState.submitEnabled).isTrue()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - submit`() = runTest {
|
||||
val presenter = LoginRootPresenter(
|
||||
FakeAuthenticationService(),
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
initialState.eventSink.invoke(LoginRootEvents.SetLogin(A_LOGIN))
|
||||
initialState.eventSink.invoke(LoginRootEvents.SetPassword(A_PASSWORD))
|
||||
skipItems(1)
|
||||
val loginAndPasswordState = awaitItem()
|
||||
loginAndPasswordState.eventSink.invoke(LoginRootEvents.Submit)
|
||||
val submitState = awaitItem()
|
||||
assertThat(submitState.loggedInState).isEqualTo(LoggedInState.LoggingIn)
|
||||
val loggedInState = awaitItem()
|
||||
assertThat(loggedInState.loggedInState).isEqualTo(LoggedInState.LoggedIn(SessionId(A_SESSION_ID)))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - submit with error`() = runTest {
|
||||
val authenticationService = FakeAuthenticationService()
|
||||
val presenter = LoginRootPresenter(
|
||||
authenticationService,
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
initialState.eventSink.invoke(LoginRootEvents.SetLogin(A_LOGIN))
|
||||
initialState.eventSink.invoke(LoginRootEvents.SetPassword(A_PASSWORD))
|
||||
skipItems(1)
|
||||
val loginAndPasswordState = awaitItem()
|
||||
authenticationService.givenLoginError(A_FAILURE)
|
||||
loginAndPasswordState.eventSink.invoke(LoginRootEvents.Submit)
|
||||
val submitState = awaitItem()
|
||||
assertThat(submitState.loggedInState).isEqualTo(LoggedInState.LoggingIn)
|
||||
val loggedInState = awaitItem()
|
||||
assertThat(loggedInState.loggedInState).isEqualTo(LoggedInState.ErrorLoggingIn(A_FAILURE))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - refresh server`() = runTest {
|
||||
val authenticationService = FakeAuthenticationService()
|
||||
val presenter = LoginRootPresenter(
|
||||
authenticationService,
|
||||
)
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState.homeserver).isEqualTo(A_HOMESERVER)
|
||||
authenticationService.givenHomeserver(A_HOMESERVER_2)
|
||||
initialState.eventSink.invoke(LoginRootEvents.RefreshHomeServer)
|
||||
val refreshedState = awaitItem()
|
||||
assertThat(refreshedState.homeserver).isEqualTo(A_HOMESERVER_2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -24,8 +24,16 @@ import kotlinx.coroutines.flow.Flow
|
|||
import kotlinx.coroutines.flow.flowOf
|
||||
|
||||
const val A_HOMESERVER = "matrix.org"
|
||||
const val A_HOMESERVER_2 = "matrix-client.org"
|
||||
const val A_SESSION_ID = "sessionId"
|
||||
const val A_LOGIN = "login"
|
||||
const val A_PASSWORD = "password"
|
||||
val A_FAILURE = Throwable("error")
|
||||
|
||||
class FakeAuthenticationService : MatrixAuthenticationService {
|
||||
private var homeserver: String = A_HOMESERVER
|
||||
private var loginError: Throwable? = null
|
||||
|
||||
override fun isLoggedIn(): Flow<Boolean> {
|
||||
return flowOf(false)
|
||||
}
|
||||
|
|
@ -42,8 +50,12 @@ class FakeAuthenticationService : MatrixAuthenticationService {
|
|||
return null
|
||||
}
|
||||
|
||||
fun givenHomeserver(homeserver: String) {
|
||||
this.homeserver = homeserver
|
||||
}
|
||||
|
||||
override fun getHomeserverOrDefault(): String {
|
||||
return A_HOMESERVER
|
||||
return homeserver
|
||||
}
|
||||
|
||||
override suspend fun setHomeserver(homeserver: String) {
|
||||
|
|
@ -51,6 +63,12 @@ class FakeAuthenticationService : MatrixAuthenticationService {
|
|||
}
|
||||
|
||||
override suspend fun login(username: String, password: String): SessionId {
|
||||
return SessionId("test")
|
||||
delay(100)
|
||||
loginError?.let { throw it }
|
||||
return SessionId(A_SESSION_ID)
|
||||
}
|
||||
|
||||
fun givenLoginError(throwable: Throwable?) {
|
||||
loginError = throwable
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue