change(invites) : add some tests and update some fakes

This commit is contained in:
ganfra 2025-02-27 21:33:28 +01:00
parent 148fe9db43
commit abb0460bbb
4 changed files with 128 additions and 50 deletions

View file

@ -63,7 +63,7 @@ class AcceptDeclineInvitePresenterTest {
) )
} }
awaitItem().also { state -> awaitItem().also { state ->
assertThat(state.declineAction).isEqualTo(ConfirmingDeclineInvite(inviteData)) assertThat(state.declineAction).isEqualTo(ConfirmingDeclineInvite(inviteData, false))
state.eventSink( state.eventSink(
InternalAcceptDeclineInviteEvents.CancelDeclineInvite InternalAcceptDeclineInviteEvents.CancelDeclineInvite
) )
@ -93,9 +93,9 @@ class AcceptDeclineInvitePresenterTest {
) )
} }
awaitItem().also { state -> awaitItem().also { state ->
assertThat(state.declineAction).isEqualTo(ConfirmingDeclineInvite(inviteData)) assertThat(state.declineAction).isEqualTo(ConfirmingDeclineInvite(inviteData, false))
state.eventSink( state.eventSink(
InternalAcceptDeclineInviteEvents.ConfirmDeclineInvite() InternalAcceptDeclineInviteEvents.ConfirmDeclineInvite
) )
} }
assertThat(awaitItem().declineAction.isLoading()).isTrue() assertThat(awaitItem().declineAction.isLoading()).isTrue()
@ -141,9 +141,9 @@ class AcceptDeclineInvitePresenterTest {
) )
} }
awaitItem().also { state -> awaitItem().also { state ->
assertThat(state.declineAction).isEqualTo(ConfirmingDeclineInvite(inviteData)) assertThat(state.declineAction).isEqualTo(ConfirmingDeclineInvite(inviteData, false))
state.eventSink( state.eventSink(
InternalAcceptDeclineInviteEvents.ConfirmDeclineInvite() InternalAcceptDeclineInviteEvents.ConfirmDeclineInvite
) )
} }
assertThat(awaitItem().declineAction.isLoading()).isTrue() assertThat(awaitItem().declineAction.isLoading()).isTrue()
@ -158,6 +158,80 @@ class AcceptDeclineInvitePresenterTest {
.with(value(A_SESSION_ID), value(A_ROOM_ID)) .with(value(A_SESSION_ID), value(A_ROOM_ID))
} }
@Test
fun `present - declining invite with block success flow`() = runTest {
val clearMembershipNotificationForRoomLambda = lambdaRecorder<SessionId, RoomId, Unit> { _, _ ->
Result.success(Unit)
}
val fakeNotificationCleaner = FakeNotificationCleaner(
clearMembershipNotificationForRoomLambda = clearMembershipNotificationForRoomLambda
)
val declineInviteSuccess = lambdaRecorder { -> Result.success(Unit) }
val ignoreUserSuccess = lambdaRecorder { _: UserId -> Result.success(Unit) }
val client = FakeMatrixClient(
getRoomPreviewResult = { _, _ ->
Result.success(FakeRoomPreview(declineInviteResult = declineInviteSuccess))
},
ignoreUserResult = ignoreUserSuccess
)
val presenter = createAcceptDeclineInvitePresenter(
client = client,
notificationCleaner = fakeNotificationCleaner,
)
presenter.test {
val inviteData = anInviteData()
awaitItem().also { state ->
state.eventSink(
AcceptDeclineInviteEvents.DeclineInvite(inviteData, blockUser = true)
)
}
awaitItem().also { state ->
assertThat(state.declineAction).isEqualTo(ConfirmingDeclineInvite(inviteData, true))
state.eventSink(
InternalAcceptDeclineInviteEvents.ConfirmDeclineInvite
)
}
assertThat(awaitItem().declineAction.isLoading()).isTrue()
awaitItem().also { state ->
assertThat(state.declineAction).isInstanceOf(AsyncAction.Success::class.java)
}
cancelAndConsumeRemainingEvents()
}
declineInviteSuccess.assertions().isCalledOnce()
ignoreUserSuccess.assertions().isCalledOnce().with(value(A_USER_ID))
clearMembershipNotificationForRoomLambda.assertions()
.isCalledOnce()
.with(value(A_SESSION_ID), value(A_ROOM_ID))
}
@Test
fun `present - declining invite with block error flow`() = runTest {
val declineInviteFailure = lambdaRecorder { ->
Result.failure<Unit>(RuntimeException("Failed to leave room"))
}
val client = FakeMatrixClient(
getRoomPreviewResult = { _, _ ->
Result.success(FakeRoomPreview(declineInviteResult = declineInviteFailure))
}
)
val presenter = createAcceptDeclineInvitePresenter(client = client)
presenter.test {
val inviteData = anInviteData()
awaitItem().also { state ->
state.eventSink(
AcceptDeclineInviteEvents.DeclineInvite(inviteData, blockUser = true)
)
}
awaitItem().also { state ->
assertThat(state.declineAction).isEqualTo(ConfirmingDeclineInvite(inviteData, true))
state.eventSink(
InternalAcceptDeclineInviteEvents.ConfirmDeclineInvite
)
}
assertThat(awaitItem().declineAction.isLoading()).isTrue()
}
}
@Test @Test
fun `present - accepting invite error flow`() = runTest { fun `present - accepting invite error flow`() = runTest {
val joinRoomFailure = lambdaRecorder { roomIdOrAlias: RoomIdOrAlias, _: List<String>, _: JoinedRoom.Trigger -> val joinRoomFailure = lambdaRecorder { roomIdOrAlias: RoomIdOrAlias, _: List<String>, _: JoinedRoom.Trigger ->

View file

@ -21,6 +21,7 @@ import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.A_USER_ID_2 import io.element.android.libraries.matrix.test.A_USER_ID_2
import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.FakeMatrixClient
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.Test import org.junit.Test
@ -40,9 +41,9 @@ class BlockedUsersPresenterTest {
@Test @Test
fun `present - initial state with blocked users`() = runTest { fun `present - initial state with blocked users`() = runTest {
val matrixClient = FakeMatrixClient().apply { val matrixClient = FakeMatrixClient(
ignoredUsersFlow.value = persistentListOf(A_USER_ID) ignoredUsersFlow = MutableStateFlow(persistentListOf(A_USER_ID))
} )
val presenter = aBlockedUsersPresenter(matrixClient = matrixClient) val presenter = aBlockedUsersPresenter(matrixClient = matrixClient)
moleculeFlow(RecompositionMode.Immediate) { moleculeFlow(RecompositionMode.Immediate) {
presenter.present() presenter.present()
@ -56,9 +57,10 @@ class BlockedUsersPresenterTest {
@Test @Test
fun `present - blocked users list updates with new emissions`() = runTest { fun `present - blocked users list updates with new emissions`() = runTest {
val matrixClient = FakeMatrixClient().apply { val ignoredUsersFlow = MutableStateFlow(persistentListOf(A_USER_ID))
ignoredUsersFlow.value = persistentListOf(A_USER_ID) val matrixClient = FakeMatrixClient(
} ignoredUsersFlow = ignoredUsersFlow
)
val presenter = aBlockedUsersPresenter(matrixClient = matrixClient) val presenter = aBlockedUsersPresenter(matrixClient = matrixClient)
moleculeFlow(RecompositionMode.Immediate) { moleculeFlow(RecompositionMode.Immediate) {
presenter.present() presenter.present()
@ -66,7 +68,7 @@ class BlockedUsersPresenterTest {
with(awaitItem()) { with(awaitItem()) {
assertThat(blockedUsers).isEqualTo(listOf(MatrixUser(A_USER_ID))) assertThat(blockedUsers).isEqualTo(listOf(MatrixUser(A_USER_ID)))
} }
matrixClient.ignoredUsersFlow.value = persistentListOf(A_USER_ID, A_USER_ID_2) ignoredUsersFlow.value = persistentListOf(A_USER_ID, A_USER_ID_2)
skipItems(1) skipItems(1)
with(awaitItem()) { with(awaitItem()) {
assertThat(blockedUsers).isEqualTo(listOf(MatrixUser(A_USER_ID), MatrixUser(A_USER_ID_2))) assertThat(blockedUsers).isEqualTo(listOf(MatrixUser(A_USER_ID), MatrixUser(A_USER_ID_2)))
@ -77,8 +79,9 @@ class BlockedUsersPresenterTest {
@Test @Test
fun `present - blocked users list with data`() = runTest { fun `present - blocked users list with data`() = runTest {
val alice = MatrixUser(A_USER_ID, displayName = "Alice", avatarUrl = "aliceAvatar") val alice = MatrixUser(A_USER_ID, displayName = "Alice", avatarUrl = "aliceAvatar")
val matrixClient = FakeMatrixClient().apply { val matrixClient = FakeMatrixClient(
ignoredUsersFlow.value = persistentListOf(A_USER_ID, A_USER_ID_2) ignoredUsersFlow = MutableStateFlow(persistentListOf(A_USER_ID, A_USER_ID_2))
).apply {
givenGetProfileResult(A_USER_ID, Result.success(alice)) givenGetProfileResult(A_USER_ID, Result.success(alice))
givenGetProfileResult(A_USER_ID_2, Result.failure(AN_EXCEPTION)) givenGetProfileResult(A_USER_ID_2, Result.failure(AN_EXCEPTION))
} }
@ -103,9 +106,9 @@ class BlockedUsersPresenterTest {
@Test @Test
fun `present - unblock user`() = runTest { fun `present - unblock user`() = runTest {
val matrixClient = FakeMatrixClient().apply { val matrixClient = FakeMatrixClient(
ignoredUsersFlow.value = persistentListOf(A_USER_ID) ignoredUsersFlow = MutableStateFlow(persistentListOf(A_USER_ID))
} )
val presenter = aBlockedUsersPresenter(matrixClient = matrixClient) val presenter = aBlockedUsersPresenter(matrixClient = matrixClient)
moleculeFlow(RecompositionMode.Immediate) { moleculeFlow(RecompositionMode.Immediate) {
presenter.present() presenter.present()
@ -125,10 +128,10 @@ class BlockedUsersPresenterTest {
@Test @Test
fun `present - unblock user handles failure`() = runTest { fun `present - unblock user handles failure`() = runTest {
val matrixClient = FakeMatrixClient().apply { val matrixClient = FakeMatrixClient(
ignoredUsersFlow.value = persistentListOf(A_USER_ID) unIgnoreUserResult = { Result.failure(IllegalStateException("User not banned")) },
givenUnignoreUserResult(Result.failure(IllegalStateException("User not banned"))) ignoredUsersFlow = MutableStateFlow(persistentListOf(A_USER_ID))
} )
val presenter = aBlockedUsersPresenter(matrixClient = matrixClient) val presenter = aBlockedUsersPresenter(matrixClient = matrixClient)
moleculeFlow(RecompositionMode.Immediate) { moleculeFlow(RecompositionMode.Immediate) {
presenter.present() presenter.present()
@ -147,10 +150,10 @@ class BlockedUsersPresenterTest {
@Test @Test
fun `present - unblock user then cancel`() = runTest { fun `present - unblock user then cancel`() = runTest {
val matrixClient = FakeMatrixClient().apply { val matrixClient = FakeMatrixClient(
ignoredUsersFlow.value = persistentListOf(A_USER_ID) unIgnoreUserResult = { Result.failure(IllegalStateException("User not banned")) },
givenUnignoreUserResult(Result.failure(IllegalStateException("User not banned"))) ignoredUsersFlow = MutableStateFlow(persistentListOf(A_USER_ID))
} )
val presenter = aBlockedUsersPresenter(matrixClient = matrixClient) val presenter = aBlockedUsersPresenter(matrixClient = matrixClient)
moleculeFlow(RecompositionMode.Immediate) { moleculeFlow(RecompositionMode.Immediate) {
presenter.present() presenter.present()

View file

@ -40,7 +40,11 @@ import io.element.android.tests.testutils.lambda.any
import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.lambdaRecorder
import io.element.android.tests.testutils.lambda.value import io.element.android.tests.testutils.lambda.value
import io.element.android.tests.testutils.test import io.element.android.tests.testutils.test
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
@ -169,7 +173,8 @@ class UserProfilePresenterTest {
@Test @Test
fun `present - BlockUser and UnblockUser without confirmation change the 'blocked' state`() = runTest { fun `present - BlockUser and UnblockUser without confirmation change the 'blocked' state`() = runTest {
val client = createFakeMatrixClient() val ignoredUsersFlow = MutableStateFlow(persistentListOf<UserId>())
val client = createFakeMatrixClient(ignoredUsersFlow = ignoredUsersFlow)
val presenter = createUserProfilePresenter( val presenter = createUserProfilePresenter(
client = client, client = client,
userId = A_USER_ID userId = A_USER_ID
@ -178,20 +183,21 @@ class UserProfilePresenterTest {
val initialState = awaitFirstItem() val initialState = awaitFirstItem()
initialState.eventSink(UserProfileEvents.BlockUser(needsConfirmation = false)) initialState.eventSink(UserProfileEvents.BlockUser(needsConfirmation = false))
assertThat(awaitItem().isBlocked.isLoading()).isTrue() assertThat(awaitItem().isBlocked.isLoading()).isTrue()
client.emitIgnoreUserList(listOf(A_USER_ID)) ignoredUsersFlow.emit(persistentListOf(A_USER_ID))
assertThat(awaitItem().isBlocked.dataOrNull()).isTrue() assertThat(awaitItem().isBlocked.dataOrNull()).isTrue()
initialState.eventSink(UserProfileEvents.UnblockUser(needsConfirmation = false)) initialState.eventSink(UserProfileEvents.UnblockUser(needsConfirmation = false))
assertThat(awaitItem().isBlocked.isLoading()).isTrue() assertThat(awaitItem().isBlocked.isLoading()).isTrue()
client.emitIgnoreUserList(listOf()) ignoredUsersFlow.emit(persistentListOf())
assertThat(awaitItem().isBlocked.dataOrNull()).isFalse() assertThat(awaitItem().isBlocked.dataOrNull()).isFalse()
} }
} }
@Test @Test
fun `present - BlockUser with error`() = runTest { fun `present - BlockUser with error`() = runTest {
val matrixClient = createFakeMatrixClient() val matrixClient = createFakeMatrixClient(
matrixClient.givenIgnoreUserResult(Result.failure(A_THROWABLE)) ignoreUserResult = { Result.failure(A_THROWABLE) }
)
val presenter = createUserProfilePresenter(client = matrixClient) val presenter = createUserProfilePresenter(client = matrixClient)
presenter.test { presenter.test {
val initialState = awaitFirstItem() val initialState = awaitFirstItem()
@ -207,8 +213,9 @@ class UserProfilePresenterTest {
@Test @Test
fun `present - UnblockUser with error`() = runTest { fun `present - UnblockUser with error`() = runTest {
val matrixClient = createFakeMatrixClient() val matrixClient = createFakeMatrixClient(
matrixClient.givenUnignoreUserResult(Result.failure(A_THROWABLE)) unIgnoreUserResult = { Result.failure(A_THROWABLE) }
)
val presenter = createUserProfilePresenter(client = matrixClient) val presenter = createUserProfilePresenter(client = matrixClient)
presenter.test { presenter.test {
val initialState = awaitFirstItem() val initialState = awaitFirstItem()
@ -374,10 +381,16 @@ class UserProfilePresenterTest {
private fun createFakeMatrixClient( private fun createFakeMatrixClient(
isUserVerified: Boolean = false, isUserVerified: Boolean = false,
ignoreUserResult: (UserId) -> Result<Unit> = { Result.success(Unit) },
unIgnoreUserResult: (UserId) -> Result<Unit> = { Result.success(Unit) },
ignoredUsersFlow: StateFlow<ImmutableList<UserId>> = MutableStateFlow(persistentListOf())
) = FakeMatrixClient( ) = FakeMatrixClient(
encryptionService = FakeEncryptionService( encryptionService = FakeEncryptionService(
isUserVerifiedResult = { Result.success(isUserVerified) } isUserVerifiedResult = { Result.success(isUserVerified) }
), ),
ignoreUserResult = ignoreUserResult,
unIgnoreUserResult = unIgnoreUserResult,
ignoredUsersFlow = ignoredUsersFlow
) )
private fun createUserProfilePresenter( private fun createUserProfilePresenter(

View file

@ -85,7 +85,10 @@ class FakeMatrixClient(
private val canDeactivateAccountResult: () -> Boolean = { lambdaError() }, private val canDeactivateAccountResult: () -> Boolean = { lambdaError() },
private val deactivateAccountResult: (String, Boolean) -> Result<Unit> = { _, _ -> lambdaError() }, private val deactivateAccountResult: (String, Boolean) -> Result<Unit> = { _, _ -> lambdaError() },
private val currentSlidingSyncVersionLambda: () -> Result<SlidingSyncVersion> = { lambdaError() }, private val currentSlidingSyncVersionLambda: () -> Result<SlidingSyncVersion> = { lambdaError() },
private val availableSlidingSyncVersionsLambda: () -> Result<List<SlidingSyncVersion>> = { lambdaError() } private val availableSlidingSyncVersionsLambda: () -> Result<List<SlidingSyncVersion>> = { lambdaError() },
private val ignoreUserResult: (UserId) -> Result<Unit> = { lambdaError() },
private var unIgnoreUserResult: (UserId)-> Result<Unit> = {Result.success(Unit)},
override val ignoredUsersFlow: StateFlow<ImmutableList<UserId>> = MutableStateFlow(persistentListOf()),
) : MatrixClient { ) : MatrixClient {
var setDisplayNameCalled: Boolean = false var setDisplayNameCalled: Boolean = false
private set private set
@ -96,10 +99,7 @@ class FakeMatrixClient(
private val _userProfile: MutableStateFlow<MatrixUser> = MutableStateFlow(MatrixUser(sessionId, userDisplayName, userAvatarUrl)) private val _userProfile: MutableStateFlow<MatrixUser> = MutableStateFlow(MatrixUser(sessionId, userDisplayName, userAvatarUrl))
override val userProfile: StateFlow<MatrixUser> = _userProfile override val userProfile: StateFlow<MatrixUser> = _userProfile
override val ignoredUsersFlow: MutableStateFlow<ImmutableList<UserId>> = MutableStateFlow(persistentListOf())
private var ignoreUserResult: Result<Unit> = Result.success(Unit)
private var unignoreUserResult: Result<Unit> = Result.success(Unit)
private var createRoomResult: Result<RoomId> = Result.success(A_ROOM_ID) private var createRoomResult: Result<RoomId> = Result.success(A_ROOM_ID)
private var createDmResult: Result<RoomId> = Result.success(A_ROOM_ID) private var createDmResult: Result<RoomId> = Result.success(A_ROOM_ID)
private var findDmResult: RoomId? = A_ROOM_ID private var findDmResult: RoomId? = A_ROOM_ID
@ -137,11 +137,11 @@ class FakeMatrixClient(
} }
override suspend fun ignoreUser(userId: UserId): Result<Unit> = simulateLongTask { override suspend fun ignoreUser(userId: UserId): Result<Unit> = simulateLongTask {
return ignoreUserResult return ignoreUserResult(userId)
} }
override suspend fun unignoreUser(userId: UserId): Result<Unit> = simulateLongTask { override suspend fun unignoreUser(userId: UserId): Result<Unit> = simulateLongTask {
return unignoreUserResult return unIgnoreUserResult(userId)
} }
override suspend fun createRoom(createRoomParams: CreateRoomParameters): Result<RoomId> = simulateLongTask { override suspend fun createRoom(createRoomParams: CreateRoomParameters): Result<RoomId> = simulateLongTask {
@ -239,10 +239,6 @@ class FakeMatrixClient(
return RoomMembershipObserver() return RoomMembershipObserver()
} }
suspend fun emitIgnoreUserList(users: List<UserId>) {
ignoredUsersFlow.emit(users.toImmutableList())
}
// Mocks // Mocks
fun givenCreateRoomResult(result: Result<RoomId>) { fun givenCreateRoomResult(result: Result<RoomId>) {
@ -253,14 +249,6 @@ class FakeMatrixClient(
createDmResult = result createDmResult = result
} }
fun givenIgnoreUserResult(result: Result<Unit>) {
ignoreUserResult = result
}
fun givenUnignoreUserResult(result: Result<Unit>) {
unignoreUserResult = result
}
fun givenFindDmResult(result: RoomId?) { fun givenFindDmResult(result: RoomId?) {
findDmResult = result findDmResult = result
} }