@@ -40,6 +40,7 @@ import io.getstream.chat.android.models.Message
4040import io.getstream.chat.android.models.MessageType
4141import io.getstream.chat.android.models.MessagesState
4242import io.getstream.chat.android.models.Reaction
43+ import io.getstream.chat.android.models.SyncStatus
4344import io.getstream.chat.android.models.TypingEvent
4445import io.getstream.chat.android.models.User
4546import io.getstream.chat.android.models.Vote
@@ -308,9 +309,9 @@ internal class MessageListControllerTests {
308309 fun `When repetitive markLastMessageRead calls appear only single API call should be sent` () = runTest {
309310 val chatClient: ChatClient = mock()
310311 val messages = arrayListOf (
311- randomMessage(id = " 1" ),
312- randomMessage(id = " 2" ),
313- randomMessage(id = " 3" ),
312+ randomMessage(id = " 1" , syncStatus = SyncStatus . COMPLETED ),
313+ randomMessage(id = " 2" , syncStatus = SyncStatus . COMPLETED ),
314+ randomMessage(id = " 3" , syncStatus = SyncStatus . COMPLETED ),
314315 )
315316 val messagesState = MutableStateFlow (messages)
316317 val controller = Fixture (chatClient = chatClient)
@@ -334,6 +335,68 @@ internal class MessageListControllerTests {
334335 verify(chatClient, times(1 )).markRead(any(), any())
335336 }
336337
338+ @Test
339+ fun `When current user's last message is COMPLETED markLastMessageRead should invoke markRead` () = runTest {
340+ val chatClient: ChatClient = mock()
341+ val messagesState = MutableStateFlow (
342+ listOf (randomMessage(id = " 1" , user = user1, syncStatus = SyncStatus .COMPLETED )),
343+ )
344+ val controller = Fixture (chatClient = chatClient)
345+ .givenCurrentUser()
346+ .givenChannelQuery()
347+ .givenMarkRead()
348+ .givenChannelState(messagesState = messagesState)
349+ .get()
350+
351+ controller.markLastMessageRead()
352+ delay(1000 )
353+
354+ verify(chatClient, times(1 )).markRead(eq(CHANNEL_TYPE ), eq(CHANNEL_ID ))
355+ controller.lastSeenMessageId `should be equal to` " 1"
356+ }
357+
358+ @Test
359+ fun `When current user's last message is not COMPLETED markLastMessageRead should not invoke markRead` () = runTest {
360+ val chatClient: ChatClient = mock()
361+ val messagesState = MutableStateFlow (
362+ listOf (randomMessage(id = " 1" , user = user1, syncStatus = SyncStatus .IN_PROGRESS )),
363+ )
364+ val controller = Fixture (chatClient = chatClient)
365+ .givenCurrentUser()
366+ .givenChannelQuery()
367+ .givenMarkRead()
368+ .givenChannelState(messagesState = messagesState)
369+ .get()
370+
371+ controller.markLastMessageRead()
372+ delay(1000 )
373+
374+ verify(chatClient, times(0 )).markRead(any(), any())
375+ controller.lastSeenMessageId.shouldBeNull()
376+ }
377+
378+ @Test
379+ fun `When peer's last message is not COMPLETED markLastMessageRead should still invoke markRead` () = runTest {
380+ // syncStatus is local-only and not on the wire. Peer messages inherit the data
381+ // class default — the gate must not block them on that.
382+ val chatClient: ChatClient = mock()
383+ val messagesState = MutableStateFlow (
384+ listOf (randomMessage(id = " 1" , user = user2, syncStatus = SyncStatus .IN_PROGRESS )),
385+ )
386+ val controller = Fixture (chatClient = chatClient)
387+ .givenCurrentUser()
388+ .givenChannelQuery()
389+ .givenMarkRead()
390+ .givenChannelState(messagesState = messagesState)
391+ .get()
392+
393+ controller.markLastMessageRead()
394+ delay(1000 )
395+
396+ verify(chatClient, times(1 )).markRead(eq(CHANNEL_TYPE ), eq(CHANNEL_ID ))
397+ controller.lastSeenMessageId `should be equal to` " 1"
398+ }
399+
337400 @Test
338401 fun `When channelData changes the updated Channel instance must be emitted` () = runTest {
339402 val chatClient: ChatClient = mock()
@@ -1320,12 +1383,18 @@ internal class MessageListControllerTests {
13201383 @OptIn(ExperimentalCoroutinesApi ::class )
13211384 private fun nowDate () = Date (testCoroutines.dispatcher.scheduler.currentTime)
13221385
1323- private fun nowMessage (author : User , type : String , text : String = randomString()): Message {
1386+ private fun nowMessage (
1387+ author : User ,
1388+ type : String ,
1389+ text : String = randomString(),
1390+ syncStatus : SyncStatus = SyncStatus .COMPLETED ,
1391+ ): Message {
13241392 val nowDate = nowDate()
13251393 return randomMessage(
13261394 user = author,
13271395 type = type,
13281396 text = text,
1397+ syncStatus = syncStatus,
13291398 createdAt = nowDate,
13301399 updatedAt = nowDate,
13311400 deletedAt = null ,
0 commit comments