StartDM : add tests
This commit is contained in:
parent
e55fab29e4
commit
3efbf4747d
19 changed files with 320 additions and 196 deletions
|
|
@ -21,7 +21,6 @@ import com.squareup.anvil.annotations.ContributesBinding
|
|||
import im.vector.app.features.analytics.plan.CreatedRoom
|
||||
import io.element.android.features.createroom.api.StartDMAction
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.di.SessionScope
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package io.element.android.features.createroom.impl
|
||||
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import im.vector.app.features.analytics.plan.CreatedRoom
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.room.StartDMResult
|
||||
import io.element.android.libraries.matrix.test.A_FAILURE_REASON
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.matrix.test.A_THROWABLE
|
||||
import io.element.android.libraries.matrix.test.A_USER_ID
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
import io.element.android.services.analytics.test.FakeAnalyticsService
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
class DefaultStartDMActionTests {
|
||||
|
||||
@Test
|
||||
fun `when dm is found, assert state is updated with given room id`() = runTest {
|
||||
val matrixClient = FakeMatrixClient().apply {
|
||||
givenFindDmResult(A_ROOM_ID)
|
||||
}
|
||||
val action = createStartDMAction(matrixClient)
|
||||
val state = mutableStateOf<Async<RoomId>>(Async.Uninitialized)
|
||||
action.execute(A_USER_ID, state)
|
||||
assertThat(state.value).isEqualTo(Async.Success(A_ROOM_ID))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when dm is not found, assert dm is created, state is updated with given room id and analytics get called`() = runTest {
|
||||
val matrixClient = FakeMatrixClient().apply {
|
||||
givenFindDmResult(null)
|
||||
givenCreateDmResult(Result.success(A_ROOM_ID))
|
||||
}
|
||||
val analyticsService = FakeAnalyticsService()
|
||||
val action = createStartDMAction(matrixClient, analyticsService)
|
||||
val state = mutableStateOf<Async<RoomId>>(Async.Uninitialized)
|
||||
action.execute(A_USER_ID, state)
|
||||
assertThat(state.value).isEqualTo(Async.Success(A_ROOM_ID))
|
||||
assertThat(analyticsService.capturedEvents).containsExactly(CreatedRoom(isDM = true))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when dm creation fails, assert state is updated with given error`() = runTest {
|
||||
val matrixClient = FakeMatrixClient().apply {
|
||||
givenFindDmResult(null)
|
||||
givenCreateDmResult(Result.failure(A_THROWABLE))
|
||||
}
|
||||
val action = createStartDMAction(matrixClient)
|
||||
val state = mutableStateOf<Async<RoomId>>(Async.Uninitialized)
|
||||
action.execute(A_USER_ID, state)
|
||||
assertThat(state.value).isEqualTo(Async.Failure<RoomId>(StartDMResult.Failure(A_FAILURE_REASON)))
|
||||
}
|
||||
|
||||
private fun createStartDMAction(
|
||||
matrixClient: MatrixClient = FakeMatrixClient(),
|
||||
analyticsService: AnalyticsService = FakeAnalyticsService(),
|
||||
): DefaultStartDMAction {
|
||||
return DefaultStartDMAction(
|
||||
matrixClient = matrixClient,
|
||||
analyticsService = analyticsService,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -20,25 +20,22 @@ import app.cash.molecule.RecompositionMode
|
|||
import app.cash.molecule.moleculeFlow
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import im.vector.app.features.analytics.plan.CreatedRoom
|
||||
import io.element.android.features.createroom.api.StartDMAction
|
||||
import io.element.android.features.createroom.impl.userlist.FakeUserListPresenter
|
||||
import io.element.android.features.createroom.impl.userlist.FakeUserListPresenterFactory
|
||||
import io.element.android.features.createroom.impl.userlist.UserListDataStore
|
||||
import io.element.android.features.createroom.impl.userlist.aUserListState
|
||||
import io.element.android.features.createroom.test.FakeStartDMAction
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.room.StartDMResult
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.matrix.test.A_THROWABLE
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.libraries.matrix.test.A_FAILURE_REASON
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.matrix.test.core.aBuildMeta
|
||||
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
|
||||
import io.element.android.libraries.usersearch.test.FakeUserRepository
|
||||
import io.element.android.services.analytics.test.FakeAnalyticsService
|
||||
import io.element.android.tests.testutils.WarmUpRule
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
||||
|
|
@ -47,142 +44,57 @@ class CreateRoomRootPresenterTests {
|
|||
@get:Rule
|
||||
val warmUpRule = WarmUpRule()
|
||||
|
||||
private lateinit var userRepository: FakeUserRepository
|
||||
private lateinit var presenter: CreateRoomRootPresenter
|
||||
private lateinit var fakeUserListPresenter: FakeUserListPresenter
|
||||
private lateinit var fakeMatrixClient: FakeMatrixClient
|
||||
private lateinit var fakeAnalyticsService: FakeAnalyticsService
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
fakeUserListPresenter = FakeUserListPresenter()
|
||||
fakeMatrixClient = FakeMatrixClient()
|
||||
fakeAnalyticsService = FakeAnalyticsService()
|
||||
userRepository = FakeUserRepository()
|
||||
presenter = CreateRoomRootPresenter(
|
||||
presenterFactory = FakeUserListPresenterFactory(fakeUserListPresenter),
|
||||
userRepository = userRepository,
|
||||
userListDataStore = UserListDataStore(),
|
||||
matrixClient = fakeMatrixClient,
|
||||
analyticsService = fakeAnalyticsService,
|
||||
buildMeta = aBuildMeta(),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - initial state`() = runTest {
|
||||
fun `present - start DM action complete scenario`() = runTest {
|
||||
val startDMAction = FakeStartDMAction()
|
||||
val presenter = createCreateRoomRootPresenter(startDMAction)
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
|
||||
assertThat(initialState.startDmAction).isInstanceOf(Async.Uninitialized::class.java)
|
||||
assertThat(initialState.applicationName).isEqualTo(aBuildMeta().applicationName)
|
||||
assertThat(initialState.userListState.selectedUsers).isEmpty()
|
||||
assertThat(initialState.userListState.isSearchActive).isFalse()
|
||||
assertThat(initialState.userListState.isMultiSelectionEnabled).isFalse()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - trigger create DM action`() = runTest {
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
val matrixUser = MatrixUser(UserId("@name:domain"))
|
||||
val createDmResult = Result.success(RoomId("!createDmResult:domain"))
|
||||
|
||||
fakeMatrixClient.givenFindDmResult(null)
|
||||
fakeMatrixClient.givenCreateDmResult(createDmResult)
|
||||
|
||||
initialState.eventSink(CreateRoomRootEvents.StartDM(matrixUser))
|
||||
assertThat(awaitItem().startDmAction).isInstanceOf(Async.Loading::class.java)
|
||||
val stateAfterStartDM = awaitItem()
|
||||
assertThat(stateAfterStartDM.startDmAction).isInstanceOf(Async.Success::class.java)
|
||||
assertThat(stateAfterStartDM.startDmAction.dataOrNull()).isEqualTo(createDmResult.getOrNull())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - creating a DM records analytics event`() = runTest {
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
val matrixUser = MatrixUser(UserId("@name:domain"))
|
||||
val createDmResult = Result.success(RoomId("!createDmResult:domain"))
|
||||
|
||||
fakeMatrixClient.givenFindDmResult(null)
|
||||
fakeMatrixClient.givenCreateDmResult(createDmResult)
|
||||
|
||||
initialState.eventSink(CreateRoomRootEvents.StartDM(matrixUser))
|
||||
skipItems(2)
|
||||
|
||||
val analyticsEvent = fakeAnalyticsService.capturedEvents.filterIsInstance<CreatedRoom>().firstOrNull()
|
||||
assertThat(analyticsEvent).isNotNull()
|
||||
assertThat(analyticsEvent?.isDM).isTrue()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - trigger retrieve DM action`() = runTest {
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
val matrixUser = MatrixUser(UserId("@name:domain"))
|
||||
val fakeDmResult = FakeMatrixRoom(roomId = RoomId("!fakeDmResult:domain"))
|
||||
|
||||
fakeMatrixClient.givenFindDmResult(fakeDmResult)
|
||||
|
||||
initialState.eventSink(CreateRoomRootEvents.StartDM(matrixUser))
|
||||
val stateAfterStartDM = awaitItem()
|
||||
assertThat(stateAfterStartDM.startDmAction).isInstanceOf(Async.Success::class.java)
|
||||
assertThat(stateAfterStartDM.startDmAction.dataOrNull()).isEqualTo(fakeDmResult.roomId)
|
||||
assertThat(fakeAnalyticsService.capturedEvents.filterIsInstance<CreatedRoom>()).isEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - trigger retry create DM action`() = runTest {
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
val matrixUser = MatrixUser(UserId("@name:domain"))
|
||||
val createDmResult = Result.success(RoomId("!createDmResult:domain"))
|
||||
fakeUserListPresenter.givenState(aUserListState().copy(selectedUsers = persistentListOf(matrixUser)))
|
||||
|
||||
fakeMatrixClient.givenFindDmResult(null)
|
||||
fakeMatrixClient.givenCreateDmError(A_THROWABLE)
|
||||
fakeMatrixClient.givenCreateDmResult(createDmResult)
|
||||
val startDMSuccessResult = Async.Success(A_ROOM_ID)
|
||||
val startDMFailureResult = Async.Failure<RoomId>(StartDMResult.Failure(A_FAILURE_REASON))
|
||||
|
||||
// Failure
|
||||
startDMAction.givenExecuteResult(startDMFailureResult)
|
||||
initialState.eventSink(CreateRoomRootEvents.StartDM(matrixUser))
|
||||
assertThat(awaitItem().startDmAction).isInstanceOf(Async.Loading::class.java)
|
||||
val stateAfterStartDM = awaitItem()
|
||||
assertThat(stateAfterStartDM.startDmAction).isInstanceOf(Async.Failure::class.java)
|
||||
assertThat(fakeAnalyticsService.capturedEvents.filterIsInstance<CreatedRoom>()).isEmpty()
|
||||
awaitItem().also { state ->
|
||||
assertThat(state.startDmAction).isEqualTo(startDMFailureResult)
|
||||
state.eventSink(CreateRoomRootEvents.CancelStartDM)
|
||||
}
|
||||
|
||||
// Cancel
|
||||
stateAfterStartDM.eventSink(CreateRoomRootEvents.CancelStartDM)
|
||||
val stateAfterCancel = awaitItem()
|
||||
assertThat(stateAfterCancel.startDmAction).isInstanceOf(Async.Uninitialized::class.java)
|
||||
|
||||
// Failure
|
||||
stateAfterCancel.eventSink(CreateRoomRootEvents.StartDM(matrixUser))
|
||||
// Success
|
||||
startDMAction.givenExecuteResult(startDMSuccessResult)
|
||||
awaitItem().also { state ->
|
||||
assertThat(state.startDmAction).isEqualTo(Async.Uninitialized)
|
||||
state.eventSink(CreateRoomRootEvents.StartDM(matrixUser))
|
||||
}
|
||||
assertThat(awaitItem().startDmAction).isInstanceOf(Async.Loading::class.java)
|
||||
val stateAfterSecondAttempt = awaitItem()
|
||||
assertThat(stateAfterSecondAttempt.startDmAction).isInstanceOf(Async.Failure::class.java)
|
||||
assertThat(fakeAnalyticsService.capturedEvents.filterIsInstance<CreatedRoom>()).isEmpty()
|
||||
awaitItem().also { state ->
|
||||
assertThat(state.startDmAction).isEqualTo(startDMSuccessResult)
|
||||
}
|
||||
|
||||
// Retry with success
|
||||
fakeMatrixClient.givenCreateDmError(null)
|
||||
stateAfterSecondAttempt.eventSink(CreateRoomRootEvents.StartDM(matrixUser))
|
||||
assertThat(awaitItem().startDmAction).isInstanceOf(Async.Loading::class.java)
|
||||
val stateAfterRetryStartDM = awaitItem()
|
||||
assertThat(stateAfterRetryStartDM.startDmAction).isInstanceOf(Async.Success::class.java)
|
||||
assertThat(stateAfterRetryStartDM.startDmAction.dataOrNull()).isEqualTo(createDmResult.getOrNull())
|
||||
}
|
||||
}
|
||||
|
||||
private fun createCreateRoomRootPresenter(
|
||||
startDMAction: StartDMAction = FakeStartDMAction(),
|
||||
): CreateRoomRootPresenter {
|
||||
return CreateRoomRootPresenter(
|
||||
presenterFactory = FakeUserListPresenterFactory(FakeUserListPresenter()),
|
||||
userRepository = FakeUserRepository(),
|
||||
userListDataStore = UserListDataStore(),
|
||||
startDMAction = startDMAction,
|
||||
buildMeta = aBuildMeta(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue