adding tests around marking room as read

- fixes wrong message instance being used for filtering
This commit is contained in:
Adam Brown 2022-11-06 18:31:59 +00:00
parent aab6170caa
commit 6dc98ef8d3
3 changed files with 77 additions and 13 deletions

View File

@ -5,9 +5,7 @@ import app.dapk.st.matrix.common.EventId
import app.dapk.st.matrix.common.RoomId
import app.dapk.st.matrix.common.UserId
import app.dapk.st.matrix.room.RoomService
import app.dapk.st.matrix.sync.RoomEvent
import app.dapk.st.matrix.sync.RoomStore
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.*
@ -24,7 +22,7 @@ class ReadMarkingTimeline(
val credentials = credentialsStore.credentials()!!
roomStore.markRead(roomId)
emit(credentials)
}.flatMapMerge { credentials ->
}.flatMapConcat { credentials ->
var lastKnownReadEvent: EventId? = null
observeTimelineUseCase.invoke(roomId, credentials.userId).distinctUntilChanged().onEach { state ->
state.latestMessageEventFromOthers(self = credentials.userId)?.let {
@ -37,8 +35,9 @@ class ReadMarkingTimeline(
}
}
private suspend fun updateRoomReadStateAsync(latestReadEvent: EventId, state: MessengerPageState, isReadReceiptsDisabled: Boolean): Deferred<*> {
return coroutineScope {
@Suppress("DeferredResultUnused")
private suspend fun updateRoomReadStateAsync(latestReadEvent: EventId, state: MessengerPageState, isReadReceiptsDisabled: Boolean) {
coroutineScope {
async {
runCatching {
roomService.markFullyRead(state.roomState.roomOverview.roomId, latestReadEvent, isPrivate = isReadReceiptsDisabled)
@ -48,10 +47,9 @@ class ReadMarkingTimeline(
}
}
}
private fun MessengerPageState.latestMessageEventFromOthers(self: UserId) = this.roomState.events
.filterIsInstance<RoomEvent.Message>()
.filterNot { it.author.id == self }
.firstOrNull()
?.eventId
private fun MessengerPageState.latestMessageEventFromOthers(self: UserId) = this.roomState.events
.filterIsInstance<RoomEvent.Message>()
.filterNot { it.author.id == self }
.firstOrNull()
?.eventId
}

View File

@ -0,0 +1,66 @@
package app.dapk.st.engine
import app.dapk.st.matrix.common.RoomId
import app.dapk.st.matrix.common.UserId
import fake.FakeCredentialsStore
import fake.FakeRoomStore
import fixture.*
import io.mockk.every
import io.mockk.mockk
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flowOf
import org.amshove.kluent.shouldBeEqualTo
import org.junit.Test
import test.delegateReturn
import test.runExpectTest
private val A_ROOM_ID = aRoomId()
private val A_USER_CREDENTIALS = aUserCredentials()
private val A_ROOM_MESSAGE_FROM_OTHER_USER = aRoomMessageEvent(author = aRoomMember(id = aUserId("another-user")))
private val A_ROOM_MESSAGE_FROM_SELF = aRoomMessageEvent(author = aRoomMember(id = A_USER_CREDENTIALS.userId))
private val READ_RECEIPTS_ARE_DISABLED = true
class ReadMarkingTimelineTest {
private val fakeRoomStore = FakeRoomStore()
private val fakeCredentialsStore = FakeCredentialsStore().apply { givenCredentials().returns(A_USER_CREDENTIALS) }
private val fakeObserveTimelineUseCase = FakeObserveTimelineUseCase()
private val fakeRoomService = FakeRoomService()
private val readMarkingTimeline = ReadMarkingTimeline(
fakeRoomStore,
fakeCredentialsStore,
fakeObserveTimelineUseCase,
fakeRoomService,
)
@Test
fun `given a message from self, when fetching, then only marks room as read on initial launch`() = runExpectTest {
fakeRoomStore.expectUnit(times = 1) { it.markRead(A_ROOM_ID) }
val messengerState = aMessengerState(roomState = aRoomState(events = listOf(A_ROOM_MESSAGE_FROM_SELF)))
fakeObserveTimelineUseCase.given(A_ROOM_ID, A_USER_CREDENTIALS.userId).returns(flowOf(messengerState))
val result = readMarkingTimeline.fetch(A_ROOM_ID, isReadReceiptsDisabled = READ_RECEIPTS_ARE_DISABLED).first()
result shouldBeEqualTo messengerState
verifyExpects()
}
@Test
fun `given a message from other user, when fetching, then marks room as read`() = runExpectTest {
fakeRoomStore.expectUnit(times = 2) { it.markRead(A_ROOM_ID) }
fakeRoomService.expectUnit { it.markFullyRead(A_ROOM_ID, A_ROOM_MESSAGE_FROM_OTHER_USER.eventId, isPrivate = READ_RECEIPTS_ARE_DISABLED) }
val messengerState = aMessengerState(roomState = aRoomState(events = listOf(A_ROOM_MESSAGE_FROM_OTHER_USER)))
fakeObserveTimelineUseCase.given(A_ROOM_ID, A_USER_CREDENTIALS.userId).returns(flowOf(messengerState))
val result = readMarkingTimeline.fetch(A_ROOM_ID, isReadReceiptsDisabled = READ_RECEIPTS_ARE_DISABLED).first()
result shouldBeEqualTo messengerState
verifyExpects()
}
}
class FakeObserveTimelineUseCase : ObserveTimelineUseCase by mockk() {
fun given(roomId: RoomId, userId: UserId) = every { this@FakeObserveTimelineUseCase.invoke(roomId, userId) }.delegateReturn()
}

View File

@ -136,7 +136,7 @@ class FakeRoomService : RoomService by mockk() {
fun aMessengerState(
self: UserId = aUserId(),
roomState: app.dapk.st.engine.RoomState,
roomState: app.dapk.st.engine.RoomState = aRoomState(),
typing: Typing? = null,
isMuted: Boolean = IS_ROOM_MUTED,
) = MessengerPageState(self, roomState, typing, isMuted)