adding tests around marking room as read
- fixes wrong message instance being used for filtering
This commit is contained in:
parent
aab6170caa
commit
6dc98ef8d3
|
@ -5,9 +5,7 @@ import app.dapk.st.matrix.common.EventId
|
||||||
import app.dapk.st.matrix.common.RoomId
|
import app.dapk.st.matrix.common.RoomId
|
||||||
import app.dapk.st.matrix.common.UserId
|
import app.dapk.st.matrix.common.UserId
|
||||||
import app.dapk.st.matrix.room.RoomService
|
import app.dapk.st.matrix.room.RoomService
|
||||||
import app.dapk.st.matrix.sync.RoomEvent
|
|
||||||
import app.dapk.st.matrix.sync.RoomStore
|
import app.dapk.st.matrix.sync.RoomStore
|
||||||
import kotlinx.coroutines.Deferred
|
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.coroutineScope
|
import kotlinx.coroutines.coroutineScope
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
|
@ -24,7 +22,7 @@ class ReadMarkingTimeline(
|
||||||
val credentials = credentialsStore.credentials()!!
|
val credentials = credentialsStore.credentials()!!
|
||||||
roomStore.markRead(roomId)
|
roomStore.markRead(roomId)
|
||||||
emit(credentials)
|
emit(credentials)
|
||||||
}.flatMapMerge { credentials ->
|
}.flatMapConcat { credentials ->
|
||||||
var lastKnownReadEvent: EventId? = null
|
var lastKnownReadEvent: EventId? = null
|
||||||
observeTimelineUseCase.invoke(roomId, credentials.userId).distinctUntilChanged().onEach { state ->
|
observeTimelineUseCase.invoke(roomId, credentials.userId).distinctUntilChanged().onEach { state ->
|
||||||
state.latestMessageEventFromOthers(self = credentials.userId)?.let {
|
state.latestMessageEventFromOthers(self = credentials.userId)?.let {
|
||||||
|
@ -37,8 +35,9 @@ class ReadMarkingTimeline(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun updateRoomReadStateAsync(latestReadEvent: EventId, state: MessengerPageState, isReadReceiptsDisabled: Boolean): Deferred<*> {
|
@Suppress("DeferredResultUnused")
|
||||||
return coroutineScope {
|
private suspend fun updateRoomReadStateAsync(latestReadEvent: EventId, state: MessengerPageState, isReadReceiptsDisabled: Boolean) {
|
||||||
|
coroutineScope {
|
||||||
async {
|
async {
|
||||||
runCatching {
|
runCatching {
|
||||||
roomService.markFullyRead(state.roomState.roomOverview.roomId, latestReadEvent, isPrivate = isReadReceiptsDisabled)
|
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>()
|
||||||
private fun MessengerPageState.latestMessageEventFromOthers(self: UserId) = this.roomState.events
|
.filterNot { it.author.id == self }
|
||||||
.filterIsInstance<RoomEvent.Message>()
|
.firstOrNull()
|
||||||
.filterNot { it.author.id == self }
|
?.eventId
|
||||||
.firstOrNull()
|
}
|
||||||
?.eventId
|
|
|
@ -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()
|
||||||
|
}
|
|
@ -136,7 +136,7 @@ class FakeRoomService : RoomService by mockk() {
|
||||||
|
|
||||||
fun aMessengerState(
|
fun aMessengerState(
|
||||||
self: UserId = aUserId(),
|
self: UserId = aUserId(),
|
||||||
roomState: app.dapk.st.engine.RoomState,
|
roomState: app.dapk.st.engine.RoomState = aRoomState(),
|
||||||
typing: Typing? = null,
|
typing: Typing? = null,
|
||||||
isMuted: Boolean = IS_ROOM_MUTED,
|
isMuted: Boolean = IS_ROOM_MUTED,
|
||||||
) = MessengerPageState(self, roomState, typing, isMuted)
|
) = MessengerPageState(self, roomState, typing, isMuted)
|
Loading…
Reference in New Issue