fix (left room membership) : use correct membership change and add test
This commit is contained in:
parent
9097c3f622
commit
198bff9915
4 changed files with 120 additions and 14 deletions
|
|
@ -22,15 +22,12 @@ class RoomMembershipObserver {
|
||||||
private val _updates = MutableSharedFlow<RoomMembershipUpdate>(extraBufferCapacity = 10)
|
private val _updates = MutableSharedFlow<RoomMembershipUpdate>(extraBufferCapacity = 10)
|
||||||
val updates = _updates.asSharedFlow()
|
val updates = _updates.asSharedFlow()
|
||||||
|
|
||||||
suspend fun notifyUserLeftRoom(roomId: RoomId) {
|
suspend fun notifyUserLeftRoom(roomId: RoomId, membershipBeforeLeft: CurrentUserMembership) {
|
||||||
_updates.emit(RoomMembershipUpdate(roomId, false, MembershipChange.LEFT))
|
val membershipChange = when (membershipBeforeLeft) {
|
||||||
}
|
CurrentUserMembership.INVITED -> MembershipChange.INVITATION_REJECTED
|
||||||
|
CurrentUserMembership.KNOCKED -> MembershipChange.KNOCK_RETRACTED
|
||||||
suspend fun notifyUserDeclinedInvite(roomId: RoomId) {
|
else -> MembershipChange.LEFT
|
||||||
_updates.emit(RoomMembershipUpdate(roomId, false, MembershipChange.INVITATION_REJECTED))
|
}
|
||||||
}
|
_updates.emit(RoomMembershipUpdate(roomId, false, membershipChange))
|
||||||
|
|
||||||
suspend fun notifyUserCanceledKnock(roomId: RoomId) {
|
|
||||||
_updates.emit(RoomMembershipUpdate(roomId, false, MembershipChange.KNOCK_RETRACTED))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -137,10 +137,11 @@ class RustBaseRoom(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun leave(): Result<Unit> = withContext(roomDispatcher) {
|
override suspend fun leave(): Result<Unit> = withContext(roomDispatcher) {
|
||||||
|
val membershipBeforeLeft = roomInfoFlow.value.currentUserMembership
|
||||||
runCatching {
|
runCatching {
|
||||||
innerRoom.leave()
|
innerRoom.leave()
|
||||||
}.onSuccess {
|
}.onSuccess {
|
||||||
roomMembershipObserver.notifyUserLeftRoom(roomId)
|
roomMembershipObserver.notifyUserLeftRoom(roomId, membershipBeforeLeft)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ class FakeRustRoom(
|
||||||
private val roomId: RoomId = A_ROOM_ID,
|
private val roomId: RoomId = A_ROOM_ID,
|
||||||
private val getMembers: () -> RoomMembersIterator = { lambdaError() },
|
private val getMembers: () -> RoomMembersIterator = { lambdaError() },
|
||||||
private val getMembersNoSync: () -> RoomMembersIterator = { lambdaError() },
|
private val getMembersNoSync: () -> RoomMembersIterator = { lambdaError() },
|
||||||
|
private val leaveLambda: () -> Unit = { lambdaError() },
|
||||||
) : Room(NoPointer) {
|
) : Room(NoPointer) {
|
||||||
override fun id(): String {
|
override fun id(): String {
|
||||||
return roomId.value
|
return roomId.value
|
||||||
|
|
@ -31,6 +32,10 @@ class FakeRustRoom(
|
||||||
return getMembersNoSync()
|
return getMembersNoSync()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun leave() {
|
||||||
|
leaveLambda()
|
||||||
|
}
|
||||||
|
|
||||||
override fun close() {
|
override fun close() {
|
||||||
// No-op
|
// No-op
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,12 @@
|
||||||
|
|
||||||
package io.element.android.libraries.matrix.impl.room
|
package io.element.android.libraries.matrix.impl.room
|
||||||
|
|
||||||
|
import app.cash.turbine.test
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
|
||||||
|
import io.element.android.libraries.matrix.api.room.RoomInfo
|
||||||
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.MembershipChange
|
||||||
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoom
|
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoom
|
||||||
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoomListService
|
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoomListService
|
||||||
import io.element.android.libraries.matrix.test.A_DEVICE_ID
|
import io.element.android.libraries.matrix.test.A_DEVICE_ID
|
||||||
|
|
@ -16,6 +20,8 @@ import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||||
import io.element.android.libraries.matrix.test.room.aRoomInfo
|
import io.element.android.libraries.matrix.test.room.aRoomInfo
|
||||||
import io.element.android.tests.testutils.testCoroutineDispatchers
|
import io.element.android.tests.testutils.testCoroutineDispatchers
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
|
import kotlinx.coroutines.flow.shareIn
|
||||||
import kotlinx.coroutines.isActive
|
import kotlinx.coroutines.isActive
|
||||||
import kotlinx.coroutines.test.TestScope
|
import kotlinx.coroutines.test.TestScope
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
|
|
@ -33,23 +39,120 @@ class RustBaseRoomTest {
|
||||||
assertThat(rustBaseRoom.roomCoroutineScope.isActive).isFalse()
|
assertThat(rustBaseRoom.roomCoroutineScope.isActive).isFalse()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when currentUserMembership=JOINED and user leave room succeed then roomMembershipObserver emits change as LEFT`() = runTest {
|
||||||
|
val roomMembershipObserver = RoomMembershipObserver()
|
||||||
|
val rustBaseRoom = createRustBaseRoom(
|
||||||
|
sessionCoroutineScope = this,
|
||||||
|
initialRoomInfo = aRoomInfo(currentUserMembership = CurrentUserMembership.JOINED),
|
||||||
|
innerRoom = FakeRustRoom(
|
||||||
|
leaveLambda = {
|
||||||
|
// Simulate a successful leave
|
||||||
|
}
|
||||||
|
),
|
||||||
|
roomMembershipObserver = roomMembershipObserver,
|
||||||
|
)
|
||||||
|
val shared = roomMembershipObserver.updates.shareIn(scope = backgroundScope, started = SharingStarted.Eagerly, replay = 1)
|
||||||
|
rustBaseRoom.leave()
|
||||||
|
shared.test {
|
||||||
|
val membershipUpdate = awaitItem()
|
||||||
|
assertThat(membershipUpdate.roomId).isEqualTo(rustBaseRoom.roomId)
|
||||||
|
assertThat(membershipUpdate.isUserInRoom).isFalse()
|
||||||
|
assertThat(membershipUpdate.change).isEqualTo(MembershipChange.LEFT)
|
||||||
|
ensureAllEventsConsumed()
|
||||||
|
}
|
||||||
|
rustBaseRoom.destroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when currentUserMembership=KNOCKED and user leave room succeed then roomMembershipObserver emits change as KNOCK_RETRACTED`() = runTest {
|
||||||
|
val roomMembershipObserver = RoomMembershipObserver()
|
||||||
|
val rustBaseRoom = createRustBaseRoom(
|
||||||
|
sessionCoroutineScope = this,
|
||||||
|
initialRoomInfo = aRoomInfo(currentUserMembership = CurrentUserMembership.KNOCKED),
|
||||||
|
innerRoom = FakeRustRoom(
|
||||||
|
leaveLambda = {
|
||||||
|
// Simulate a successful leave
|
||||||
|
}
|
||||||
|
),
|
||||||
|
roomMembershipObserver = roomMembershipObserver,
|
||||||
|
)
|
||||||
|
val shared = roomMembershipObserver.updates.shareIn(scope = backgroundScope, started = SharingStarted.Eagerly, replay = 1)
|
||||||
|
rustBaseRoom.leave()
|
||||||
|
shared.test {
|
||||||
|
val membershipUpdate = awaitItem()
|
||||||
|
assertThat(membershipUpdate.roomId).isEqualTo(rustBaseRoom.roomId)
|
||||||
|
assertThat(membershipUpdate.isUserInRoom).isFalse()
|
||||||
|
assertThat(membershipUpdate.change).isEqualTo(MembershipChange.KNOCK_RETRACTED)
|
||||||
|
ensureAllEventsConsumed()
|
||||||
|
}
|
||||||
|
rustBaseRoom.destroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when currentUserMembership=INVITED and user leave room succeed then roomMembershipObserver emits change as INVITATION_REJECTED`() = runTest {
|
||||||
|
val roomMembershipObserver = RoomMembershipObserver()
|
||||||
|
val rustBaseRoom = createRustBaseRoom(
|
||||||
|
sessionCoroutineScope = this,
|
||||||
|
initialRoomInfo = aRoomInfo(currentUserMembership = CurrentUserMembership.INVITED),
|
||||||
|
innerRoom = FakeRustRoom(
|
||||||
|
leaveLambda = {
|
||||||
|
// Simulate a successful leave
|
||||||
|
}
|
||||||
|
),
|
||||||
|
roomMembershipObserver = roomMembershipObserver,
|
||||||
|
)
|
||||||
|
val shared = roomMembershipObserver.updates.shareIn(scope = backgroundScope, started = SharingStarted.Eagerly, replay = 1)
|
||||||
|
rustBaseRoom.leave()
|
||||||
|
shared.test {
|
||||||
|
val membershipUpdate = awaitItem()
|
||||||
|
assertThat(membershipUpdate.roomId).isEqualTo(rustBaseRoom.roomId)
|
||||||
|
assertThat(membershipUpdate.isUserInRoom).isFalse()
|
||||||
|
assertThat(membershipUpdate.change).isEqualTo(MembershipChange.INVITATION_REJECTED)
|
||||||
|
ensureAllEventsConsumed()
|
||||||
|
}
|
||||||
|
rustBaseRoom.destroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when user leave room fails then roomMembershipObserver emits nothing`() = runTest {
|
||||||
|
val roomMembershipObserver = RoomMembershipObserver()
|
||||||
|
val rustBaseRoom = createRustBaseRoom(
|
||||||
|
sessionCoroutineScope = this,
|
||||||
|
initialRoomInfo = aRoomInfo(currentUserMembership = CurrentUserMembership.INVITED),
|
||||||
|
innerRoom = FakeRustRoom(
|
||||||
|
leaveLambda = { error("Leave failed") }
|
||||||
|
),
|
||||||
|
roomMembershipObserver = roomMembershipObserver,
|
||||||
|
)
|
||||||
|
val shared = roomMembershipObserver.updates.shareIn(scope = backgroundScope, started = SharingStarted.Eagerly, replay = 1)
|
||||||
|
rustBaseRoom.leave()
|
||||||
|
shared.test {
|
||||||
|
ensureAllEventsConsumed()
|
||||||
|
}
|
||||||
|
rustBaseRoom.destroy()
|
||||||
|
}
|
||||||
|
|
||||||
private fun TestScope.createRustBaseRoom(
|
private fun TestScope.createRustBaseRoom(
|
||||||
sessionCoroutineScope: CoroutineScope,
|
sessionCoroutineScope: CoroutineScope,
|
||||||
|
initialRoomInfo: RoomInfo = aRoomInfo(),
|
||||||
|
innerRoom: FakeRustRoom = FakeRustRoom(),
|
||||||
|
roomMembershipObserver: RoomMembershipObserver = RoomMembershipObserver(),
|
||||||
): RustBaseRoom {
|
): RustBaseRoom {
|
||||||
val dispatchers = testCoroutineDispatchers()
|
val dispatchers = testCoroutineDispatchers()
|
||||||
return RustBaseRoom(
|
return RustBaseRoom(
|
||||||
sessionId = A_SESSION_ID,
|
sessionId = A_SESSION_ID,
|
||||||
deviceId = A_DEVICE_ID,
|
deviceId = A_DEVICE_ID,
|
||||||
innerRoom = FakeRustRoom(),
|
innerRoom = innerRoom,
|
||||||
coroutineDispatchers = dispatchers,
|
coroutineDispatchers = dispatchers,
|
||||||
roomSyncSubscriber = RoomSyncSubscriber(
|
roomSyncSubscriber = RoomSyncSubscriber(
|
||||||
roomListService = FakeRustRoomListService(),
|
roomListService = FakeRustRoomListService(),
|
||||||
dispatchers = dispatchers,
|
dispatchers = dispatchers,
|
||||||
),
|
),
|
||||||
roomMembershipObserver = RoomMembershipObserver(),
|
roomMembershipObserver = roomMembershipObserver,
|
||||||
sessionCoroutineScope = sessionCoroutineScope,
|
sessionCoroutineScope = sessionCoroutineScope,
|
||||||
roomInfoMapper = RoomInfoMapper(),
|
roomInfoMapper = RoomInfoMapper(),
|
||||||
initialRoomInfo = aRoomInfo(),
|
initialRoomInfo = initialRoomInfo,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue