diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt index 119906a964..8c629e91d1 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt @@ -22,15 +22,18 @@ import io.element.android.features.messages.impl.actionlist.anActionListState import io.element.android.features.messages.impl.messagecomposer.AttachmentsState import io.element.android.features.messages.impl.messagecomposer.MessageComposerState import io.element.android.features.messages.impl.messagecomposer.aMessageComposerState +import io.element.android.features.messages.impl.timeline.TimelineState import io.element.android.features.messages.impl.timeline.aTimelineItemList import io.element.android.features.messages.impl.timeline.aTimelineState import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionEvents import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionState import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryEvents import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryState +import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetEvents import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetState import io.element.android.features.messages.impl.timeline.components.retrysendmenu.RetrySendMenuState import io.element.android.features.messages.impl.timeline.components.retrysendmenu.aRetrySendMenuState +import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent import io.element.android.features.messages.impl.typing.aTypingNotificationState import io.element.android.features.messages.impl.voicemessages.composer.VoiceMessageComposerState @@ -101,7 +104,11 @@ fun aMessagesState( mode = MessageComposerMode.Normal, ), voiceMessageComposerState: VoiceMessageComposerState = aVoiceMessageComposerState(), + timelineState: TimelineState = aTimelineState( + timelineItems = aTimelineItemList(aTimelineItemTextContent()), + ), retrySendMenuState: RetrySendMenuState = aRetrySendMenuState(), + readReceiptBottomSheetState: ReadReceiptBottomSheetState = aReadReceiptBottomSheetState(), actionListState: ActionListState = anActionListState(), customReactionState: CustomReactionState = aCustomReactionState(), reactionSummaryState: ReactionSummaryState = aReactionSummaryState(), @@ -120,15 +127,10 @@ fun aMessagesState( userHasPermissionToSendReaction = userHasPermissionToSendReaction, composerState = composerState, voiceMessageComposerState = voiceMessageComposerState, - timelineState = aTimelineState( - timelineItems = aTimelineItemList(aTimelineItemTextContent()), - ), typingNotificationState = aTypingNotificationState(), + timelineState = timelineState, retrySendMenuState = retrySendMenuState, - readReceiptBottomSheetState = ReadReceiptBottomSheetState( - selectedEvent = null, - eventSink = {}, - ), + readReceiptBottomSheetState = readReceiptBottomSheetState, actionListState = actionListState, customReactionState = customReactionState, reactionSummaryState = reactionSummaryState, @@ -158,3 +160,11 @@ fun aCustomReactionState( selectedEmoji = persistentSetOf(), eventSink = eventSink, ) + +fun aReadReceiptBottomSheetState( + selectedEvent: TimelineItem.Event? = null, + eventSink: (ReadReceiptBottomSheetEvents) -> Unit = {}, +) = ReadReceiptBottomSheetState( + selectedEvent = selectedEvent, + eventSink = eventSink, +) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt index 449e13e314..ede2f379ea 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineStateProvider.kt @@ -48,12 +48,13 @@ import kotlin.random.Random fun aTimelineState( timelineItems: ImmutableList = persistentListOf(), paginationState: MatrixTimeline.PaginationState = aPaginationState(), + renderReadReceipts: Boolean = false, eventSink: (TimelineEvents) -> Unit = {}, ) = TimelineState( timelineItems = timelineItems, timelineRoomInfo = aTimelineRoomInfo(), paginationState = paginationState, - renderReadReceipts = false, + renderReadReceipts = renderReadReceipts, highlightedEventId = null, newEventState = NewEventState.None, sessionState = aSessionState( @@ -196,9 +197,11 @@ internal fun aTimelineItemDebugInfo( latestEditedJson ) -internal fun aTimelineItemReadReceipts(): TimelineItemReadReceipts { +internal fun aTimelineItemReadReceipts( + receipts: List = emptyList(), +): TimelineItemReadReceipts { return TimelineItemReadReceipts( - receipts = emptyList().toImmutableList(), + receipts = receipts.toImmutableList(), ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/TimelineItemReadReceiptView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/TimelineItemReadReceiptView.kt index 8f3d8f3710..9f047742c8 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/TimelineItemReadReceiptView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/TimelineItemReadReceiptView.kt @@ -51,6 +51,8 @@ import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.utils.CommonDrawables import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState +import io.element.android.libraries.testtags.TestTags +import io.element.android.libraries.testtags.testTag import io.element.android.libraries.ui.strings.CommonPlurals import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.ImmutableList @@ -68,6 +70,7 @@ fun TimelineItemReadReceiptView( ReadReceiptsAvatars( receipts = state.receipts, modifier = Modifier + .testTag(TestTags.messageReadReceipts) .clip(RoundedCornerShape(4.dp)) .clickable { onReadReceiptsClicked() diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt index 841ea4ac2c..f6692bd0ff 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt @@ -27,6 +27,7 @@ import androidx.compose.ui.test.onAllNodesWithTag import androidx.compose.ui.test.onAllNodesWithText import androidx.compose.ui.test.onFirst import androidx.compose.ui.test.onNodeWithContentDescription +import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performTouchInput @@ -37,8 +38,13 @@ import io.element.android.features.messages.impl.actionlist.anActionListState import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction import io.element.android.features.messages.impl.attachments.Attachment import io.element.android.features.messages.impl.messagecomposer.aMessageComposerState +import io.element.android.features.messages.impl.timeline.aTimelineItemEvent +import io.element.android.features.messages.impl.timeline.aTimelineItemReadReceipts +import io.element.android.features.messages.impl.timeline.aTimelineState import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionEvents import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryEvents +import io.element.android.features.messages.impl.timeline.components.receipt.aReadReceiptData +import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetEvents import io.element.android.features.messages.impl.timeline.components.retrysendmenu.RetrySendMenuEvents import io.element.android.features.messages.impl.timeline.components.retrysendmenu.aRetrySendMenuState import io.element.android.features.messages.impl.timeline.model.TimelineItem @@ -200,6 +206,34 @@ class MessagesViewTest { ) } + @Test + fun `clicking on a read receipt list emits the expected Event`() { + val eventsRecorder = EventsRecorder() + val state = aMessagesState( + timelineState = aTimelineState( + renderReadReceipts = true, + timelineItems = persistentListOf( + aTimelineItemEvent( + readReceiptState = aTimelineItemReadReceipts( + receipts = listOf( + aReadReceiptData(0), + ), + ), + ), + ), + ), + readReceiptBottomSheetState = aReadReceiptBottomSheetState( + eventSink = eventsRecorder + ), + ) + val timelineItem = state.timelineState.timelineItems.first() as TimelineItem.Event + rule.setMessagesView( + state = state, + ) + rule.onNodeWithTag(TestTags.messageReadReceipts.value).performClick() + eventsRecorder.assertSingle(ReadReceiptBottomSheetEvents.EventSelected(timelineItem)) + } + @Test fun `clicking on send location invoke expected callback`() { val eventsRecorder = EventsRecorder(expectEvents = false) diff --git a/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt b/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt index a88f036fd5..ed93c19bc3 100644 --- a/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt +++ b/libraries/testtags/src/main/kotlin/io/element/android/libraries/testtags/TestTags.kt @@ -63,6 +63,11 @@ object TestTags { */ val messageBubble = TestTag("message_bubble") + /** + * Message Read Receipts. + */ + val messageReadReceipts = TestTag("message_read_receipts") + /** * Dialogs. */