Browse Source

Pinned events: add tests on PinnedMessagesBannerPresenter

pull/3275/head
ganfra 1 month ago
parent
commit
0390ede2ad
  1. 16
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt
  2. 157
      features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt

16
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt

@ -52,15 +52,15 @@ class PinnedMessagesBannerPresenter @Inject constructor( @@ -52,15 +52,15 @@ class PinnedMessagesBannerPresenter @Inject constructor(
@Composable
override fun present(): PinnedMessagesBannerState {
val isFeatureEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.PinnedEvents).collectAsState(initial = false)
var timelineFailed by rememberSaveable { mutableStateOf(false) }
var pinnedItems by remember {
mutableStateOf<ImmutableList<PinnedMessagesBannerItem>>(persistentListOf())
}
var hasTimelineFailedToLoad by rememberSaveable { mutableStateOf(false) }
var currentPinnedMessageIndex by rememberSaveable { mutableIntStateOf(0) }
val knownPinnedMessagesCount by remember {
room.roomInfoFlow.map { roomInfo -> roomInfo.pinnedEventIds.size }
}.collectAsState(initial = null)
var currentPinnedMessageIndex by rememberSaveable { mutableIntStateOf(0) }
var pinnedItems by remember {
mutableStateOf<ImmutableList<PinnedMessagesBannerItem>>(persistentListOf())
}
PinnedMessagesBannerItemsEffect(
isFeatureEnabled = isFeatureEnabled,
@ -72,7 +72,7 @@ class PinnedMessagesBannerPresenter @Inject constructor( @@ -72,7 +72,7 @@ class PinnedMessagesBannerPresenter @Inject constructor(
pinnedItems = newItems
},
onTimelineFail = { hasTimelineFailed ->
timelineFailed = hasTimelineFailed
hasTimelineFailedToLoad = hasTimelineFailed
}
)
@ -90,7 +90,7 @@ class PinnedMessagesBannerPresenter @Inject constructor( @@ -90,7 +90,7 @@ class PinnedMessagesBannerPresenter @Inject constructor(
return pinnedMessagesBannerState(
isFeatureEnabled = isFeatureEnabled,
hasTimelineFailed = timelineFailed,
hasTimelineFailed = hasTimelineFailedToLoad,
realPinnedMessagesCount = knownPinnedMessagesCount,
pinnedItems = pinnedItems,
currentPinnedMessageIndex = currentPinnedMessageIndex,
@ -117,7 +117,7 @@ class PinnedMessagesBannerPresenter @Inject constructor( @@ -117,7 +117,7 @@ class PinnedMessagesBannerPresenter @Inject constructor(
PinnedMessagesBannerState.Loaded(
currentPinnedMessage = currentPinnedMessage,
currentPinnedMessageIndex = currentPinnedMessageIndex,
knownPinnedMessagesCount = realPinnedMessagesCount,
knownPinnedMessagesCount = pinnedItems.size,
eventSink = eventSink
)
}

157
features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt

@ -17,13 +17,23 @@ @@ -17,13 +17,23 @@
package io.element.android.features.messages.impl.pinned.banner
import com.google.common.truth.Truth.assertThat
import io.element.android.features.networkmonitor.api.NetworkMonitor
import io.element.android.features.networkmonitor.test.FakeNetworkMonitor
import io.element.android.libraries.eventformatter.test.FakePinnedMessagesBannerFormatter
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.AN_EVENT_ID_2
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.libraries.matrix.test.timeline.FakeTimeline
import io.element.android.libraries.matrix.test.timeline.aMessageContent
import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem
import io.element.android.tests.testutils.test
import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Test
@ -31,23 +41,146 @@ import org.junit.Test @@ -31,23 +41,146 @@ import org.junit.Test
class PinnedMessagesBannerPresenterTest {
@Test
fun `present - initial state`() = runTest {
val presenter = createPinnedMessagesBannerPresenter()
val presenter = createPinnedMessagesBannerPresenter(isFeatureEnabled = true)
presenter.test {
val initialState = awaitItem()
assertThat(initialState.pinnedMessagesCount).isEqualTo(0)
assertThat(initialState.currentPinnedMessageIndex).isEqualTo(0)
assertThat(initialState.currentPinnedMessage).isNull()
assertThat(initialState).isEqualTo(PinnedMessagesBannerState.Hidden)
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - move to next pinned message when there is no pinned events`() = runTest {
val presenter = createPinnedMessagesBannerPresenter()
fun `present - feature disabled`() = runTest {
val presenter = createPinnedMessagesBannerPresenter(isFeatureEnabled = false)
presenter.test {
val initialState = awaitItem()
initialState.eventSink(PinnedMessagesBannerEvents.MoveToNextPinned)
// Nothing is emitted
ensureAllEventsConsumed()
assertThat(initialState).isEqualTo(PinnedMessagesBannerState.Hidden)
}
}
@Test
fun `present - loading state`() = runTest {
val room = FakeMatrixRoom(
pinnedEventsTimelineResult = { Result.success(FakeTimeline()) }
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
}
val presenter = createPinnedMessagesBannerPresenter(room = room)
presenter.test {
skipItems(1)
val loadingState = awaitItem()
assertThat(loadingState).isEqualTo(PinnedMessagesBannerState.Loading(1))
assertThat(loadingState.pinnedMessagesCount()).isEqualTo(1)
assertThat(loadingState.currentPinnedMessageIndex()).isEqualTo(0)
}
}
@Test
fun `present - loaded state`() = runTest {
val messageContent = aMessageContent("A message")
val pinnedEventsTimeline = FakeTimeline(
timelineItems = flowOf(
listOf(
MatrixTimelineItem.Event(
uniqueId = "FAKE_UNIQUE_ID",
event = anEventTimelineItem(
eventId = AN_EVENT_ID,
content = messageContent,
),
)
)
)
)
val room = FakeMatrixRoom(
pinnedEventsTimelineResult = { Result.success(pinnedEventsTimeline) }
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID, AN_EVENT_ID_2)))
}
val presenter = createPinnedMessagesBannerPresenter(room = room)
presenter.test {
skipItems(2)
val loadedState = awaitItem() as PinnedMessagesBannerState.Loaded
assertThat(loadedState.currentPinnedMessageIndex).isEqualTo(0)
assertThat(loadedState.knownPinnedMessagesCount).isEqualTo(1)
assertThat(loadedState.currentPinnedMessage.formatted.text).isEqualTo(messageContent.toString())
}
}
@Test
fun `present - loaded state - multiple pinned messages`() = runTest {
val messageContent1 = aMessageContent("A message")
val messageContent2 = aMessageContent("Another message")
val pinnedEventsTimeline = FakeTimeline(
timelineItems = flowOf(
listOf(
MatrixTimelineItem.Event(
uniqueId = "FAKE_UNIQUE_ID",
event = anEventTimelineItem(
eventId = AN_EVENT_ID,
content = messageContent1,
),
),
MatrixTimelineItem.Event(
uniqueId = "FAKE_UNIQUE_ID_2",
event = anEventTimelineItem(
eventId = AN_EVENT_ID_2,
content = messageContent2,
),
)
)
)
)
val room = FakeMatrixRoom(
pinnedEventsTimelineResult = { Result.success(pinnedEventsTimeline) }
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID, AN_EVENT_ID_2)))
}
val presenter = createPinnedMessagesBannerPresenter(room = room)
presenter.test {
skipItems(2)
awaitItem().also { loadedState ->
loadedState as PinnedMessagesBannerState.Loaded
assertThat(loadedState.currentPinnedMessageIndex).isEqualTo(0)
assertThat(loadedState.knownPinnedMessagesCount).isEqualTo(2)
assertThat(loadedState.currentPinnedMessage.formatted.text).isEqualTo(messageContent1.toString())
loadedState.eventSink(PinnedMessagesBannerEvents.MoveToNextPinned)
}
awaitItem().also { loadedState ->
loadedState as PinnedMessagesBannerState.Loaded
assertThat(loadedState.currentPinnedMessageIndex).isEqualTo(1)
assertThat(loadedState.knownPinnedMessagesCount).isEqualTo(2)
assertThat(loadedState.currentPinnedMessage.formatted.text).isEqualTo(messageContent2.toString())
loadedState.eventSink(PinnedMessagesBannerEvents.MoveToNextPinned)
}
awaitItem().also { loadedState ->
loadedState as PinnedMessagesBannerState.Loaded
assertThat(loadedState.currentPinnedMessageIndex).isEqualTo(0)
assertThat(loadedState.knownPinnedMessagesCount).isEqualTo(2)
assertThat(loadedState.currentPinnedMessage.formatted.text).isEqualTo(messageContent1.toString())
}
}
}
@Test
fun `present - timeline failed`() = runTest {
val room = FakeMatrixRoom(
pinnedEventsTimelineResult = { Result.failure(Exception()) }
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
}
val presenter = createPinnedMessagesBannerPresenter(room = room)
presenter.test {
skipItems(1)
awaitItem().also { loadingState ->
assertThat(loadingState).isEqualTo(PinnedMessagesBannerState.Loading(1))
assertThat(loadingState.pinnedMessagesCount()).isEqualTo(1)
assertThat(loadingState.currentPinnedMessageIndex()).isEqualTo(0)
}
awaitItem().also { failedState ->
assertThat(failedState).isEqualTo(PinnedMessagesBannerState.Hidden)
}
}
}
@ -56,9 +189,10 @@ class PinnedMessagesBannerPresenterTest { @@ -56,9 +189,10 @@ class PinnedMessagesBannerPresenterTest {
itemFactory: PinnedMessagesBannerItemFactory = PinnedMessagesBannerItemFactory(
coroutineDispatchers = testCoroutineDispatchers(),
formatter = FakePinnedMessagesBannerFormatter(
formatLambda = { event -> "Content ${event.content}" }
formatLambda = { event -> "${event.content}" }
)
),
networkMonitor: NetworkMonitor = FakeNetworkMonitor(),
isFeatureEnabled: Boolean = true,
): PinnedMessagesBannerPresenter {
val featureFlagService = FakeFeatureFlagService(
@ -69,7 +203,8 @@ class PinnedMessagesBannerPresenterTest { @@ -69,7 +203,8 @@ class PinnedMessagesBannerPresenterTest {
return PinnedMessagesBannerPresenter(
room = room,
itemFactory = itemFactory,
featureFlagService = featureFlagService
featureFlagService = featureFlagService,
networkMonitor = networkMonitor,
)
}
}

Loading…
Cancel
Save