Browse Source

Pinned events : add some ui testing

pull/3275/head
ganfra 1 month ago
parent
commit
04995cb26c
  1. 5
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt
  2. 2
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt
  3. 26
      features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt
  4. 87
      features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerViewTest.kt

5
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt

@ -74,6 +74,7 @@ import io.element.android.features.messages.impl.messagecomposer.MessageComposer @@ -74,6 +74,7 @@ import io.element.android.features.messages.impl.messagecomposer.MessageComposer
import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerState
import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerView
import io.element.android.features.messages.impl.pinned.banner.PinnedMessagesBannerViewDefaults
import io.element.android.features.messages.impl.timeline.FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS
import io.element.android.features.messages.impl.timeline.TimelineEvents
import io.element.android.features.messages.impl.timeline.TimelineView
import io.element.android.features.messages.impl.timeline.components.JoinCallMenuItem
@ -401,13 +402,13 @@ private fun MessagesViewContent( @@ -401,13 +402,13 @@ private fun MessagesViewContent(
nestedScrollConnection = scrollBehavior.nestedScrollConnection,
)
AnimatedVisibility(
visible = state.pinnedMessagesBannerState != PinnedMessagesBannerState.Hidden && scrollBehavior.isVisible,
visible = state.pinnedMessagesBannerState is PinnedMessagesBannerState.Visible && scrollBehavior.isVisible,
enter = expandVertically(),
exit = shrinkVertically(),
) {
fun focusOnPinnedEvent(eventId: EventId) {
state.timelineState.eventSink(
TimelineEvents.FocusOnEvent(eventId = eventId, debounce = 200.milliseconds)
TimelineEvents.FocusOnEvent(eventId = eventId, debounce = FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS.milliseconds)
)
}
PinnedMessagesBannerView(

2
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt

@ -57,6 +57,8 @@ import kotlinx.coroutines.flow.onEach @@ -57,6 +57,8 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
const val FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS = 200L
class TimelinePresenter @AssistedInject constructor(
private val timelineItemsFactory: TimelineItemsFactory,
private val timelineItemIndexer: TimelineItemIndexer,

26
features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesViewTest.kt

@ -33,6 +33,7 @@ import androidx.compose.ui.test.onNodeWithText @@ -33,6 +33,7 @@ import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performTouchInput
import androidx.compose.ui.test.swipeRight
import androidx.compose.ui.text.AnnotatedString
import androidx.test.ext.junit.runners.AndroidJUnit4
import io.element.android.emojibasebindings.Emoji
import io.element.android.emojibasebindings.EmojibaseCategory
@ -43,6 +44,10 @@ import io.element.android.features.messages.impl.actionlist.anActionListState @@ -43,6 +44,10 @@ 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.pinned.banner.PinnedMessagesBannerItem
import io.element.android.features.messages.impl.pinned.banner.aLoadedPinnedMessagesBannerState
import io.element.android.features.messages.impl.timeline.FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS
import io.element.android.features.messages.impl.timeline.TimelineEvents
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.aTimelineRoomInfo
@ -54,6 +59,7 @@ import io.element.android.features.messages.impl.timeline.components.receipt.aRe @@ -54,6 +59,7 @@ import io.element.android.features.messages.impl.timeline.components.receipt.aRe
import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetEvents
import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.testtags.TestTags
import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.tests.testutils.EnsureCalledOnceWithParam
@ -72,6 +78,7 @@ import org.junit.Test @@ -72,6 +78,7 @@ import org.junit.Test
import org.junit.rules.TestRule
import org.junit.runner.RunWith
import org.robolectric.annotation.Config
import kotlin.time.Duration.Companion.milliseconds
@RunWith(AndroidJUnit4::class)
class MessagesViewTest {
@ -458,6 +465,25 @@ class MessagesViewTest { @@ -458,6 +465,25 @@ class MessagesViewTest {
customReactionStateEventsRecorder.assertSingle(CustomReactionEvents.DismissCustomReactionSheet)
eventsRecorder.assertSingle(MessagesEvents.ToggleReaction(aUnicode, timelineItem.eventId!!))
}
@Test
fun `clicking on pinned messages banner emits the expected Event`() {
val eventsRecorder = EventsRecorder<TimelineEvents>()
val state = aMessagesState(
timelineState = aTimelineState(eventSink = eventsRecorder),
pinnedMessagesBannerState = aLoadedPinnedMessagesBannerState(
knownPinnedMessagesCount = 2,
currentPinnedMessageIndex = 0,
currentPinnedMessage = PinnedMessagesBannerItem(
eventId = AN_EVENT_ID,
formatted = AnnotatedString("This is a pinned message")
),
),
)
rule.setMessagesView(state = state)
rule.onNodeWithText("This is a pinned message").performClick()
eventsRecorder.assertSingle(TimelineEvents.FocusOnEvent(AN_EVENT_ID, debounce = FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS.milliseconds))
}
}
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setMessagesView(

87
features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerViewTest.kt

@ -0,0 +1,87 @@ @@ -0,0 +1,87 @@
/*
* Copyright (c) 2024 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.features.messages.impl.pinned.banner
import androidx.activity.ComponentActivity
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onRoot
import androidx.compose.ui.test.performClick
import androidx.test.ext.junit.runners.AndroidJUnit4
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.tests.testutils.EnsureNeverCalled
import io.element.android.tests.testutils.EnsureNeverCalledWithParam
import io.element.android.tests.testutils.EventsRecorder
import io.element.android.tests.testutils.clickOn
import io.element.android.tests.testutils.ensureCalledOnce
import io.element.android.tests.testutils.ensureCalledOnceWithParam
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TestRule
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class PinnedMessagesBannerViewTest {
@get:Rule val rule = createAndroidComposeRule<ComponentActivity>()
@Test
fun `clicking on the banner invoke expected callback`() {
val eventsRecorder = EventsRecorder<PinnedMessagesBannerEvents>()
val state = aLoadedPinnedMessagesBannerState(
eventSink = eventsRecorder
)
val pinnedEventId = state.currentPinnedMessage.eventId
ensureCalledOnceWithParam(pinnedEventId) { callback ->
rule.setPinnedMessagesBannerView(
state = state,
onClick = callback
)
rule.onRoot().performClick()
eventsRecorder.assertSingle(PinnedMessagesBannerEvents.MoveToNextPinned)
}
}
@Test
fun `clicking on view all emit the expected event`() {
val eventsRecorder = EventsRecorder<PinnedMessagesBannerEvents>(expectEvents = true)
val state = aLoadedPinnedMessagesBannerState(
eventSink = eventsRecorder
)
ensureCalledOnce { callback ->
rule.setPinnedMessagesBannerView(
state = state,
onViewAllClick = callback
)
rule.clickOn(CommonStrings.screen_room_pinned_banner_view_all_button_title)
}
}
}
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setPinnedMessagesBannerView(
state: PinnedMessagesBannerState,
onClick: (EventId) -> Unit = EnsureNeverCalledWithParam(),
onViewAllClick: () -> Unit = EnsureNeverCalled(),
) {
setContent {
PinnedMessagesBannerView(
state = state,
onClick = onClick,
onViewAllClick = onViewAllClick
)
}
}
Loading…
Cancel
Save