Add more tests

This commit is contained in:
Jorge Martín
2026-08-21 16:19:36 +02:00
parent e3b72446cc
commit b52ed580b1
2 changed files with 73 additions and 2 deletions
@@ -151,10 +151,11 @@ class GlobalSearchPresenter(
.mapNotNull { it } .mapNotNull { it }
searchResults = when { searchResults = when {
queryState.text.isEmpty() -> AsyncData.Uninitialized
mappedResults.isNotEmpty() -> { mappedResults.isNotEmpty() -> {
AsyncData.Success(GlobalSearchResults.MessageSearchResults(results = mappedResults.toImmutableList())) AsyncData.Success(GlobalSearchResults.MessageSearchResults(results = mappedResults.toImmutableList()))
} }
queryState.text.isNotEmpty() && paginationState is MessageSearchPaginationState.Idle && paginationState.endReached -> { paginationState is MessageSearchPaginationState.Idle && paginationState.endReached -> {
AsyncData.Success(GlobalSearchResults.MessageSearchResults(results = persistentListOf())) AsyncData.Success(GlobalSearchResults.MessageSearchResults(results = persistentListOf()))
} }
paginationState is MessageSearchPaginationState.Loading -> { paginationState is MessageSearchPaginationState.Loading -> {
@@ -139,13 +139,48 @@ class GlobalSearchPresenterTest {
testScheduler.advanceUntilIdle() testScheduler.advanceUntilIdle()
roomList.summaries.emit(listOf(aRoomSummary())) roomList.summaries.emit(listOf(aRoomSummary()))
val successState = consumeItemsUntilPredicate { it.results is AsyncData.Success }.last() // Wait for the presenter to emit a loading state before the success state
consumeItemsUntilPredicate { it.results is AsyncData.Loading }
val successState = awaitItem()
val results = (successState.results.dataOrNull() as GlobalSearchResults.RoomListResults).results val results = (successState.results.dataOrNull() as GlobalSearchResults.RoomListResults).results
assertThat(results).hasSize(1) assertThat(results).hasSize(1)
cancelAndIgnoreRemainingEvents() cancelAndIgnoreRemainingEvents()
} }
} }
@Test
fun `present - room search displays the uninitialized state when removing the query`() = runTest {
val roomList = FakeDynamicRoomList()
val roomListService = FakeRoomListService(createRoomListLambda = { roomList })
val presenter = createGlobalSearchPresenter(roomListService = roomListService)
presenter.test {
val initialState = awaitItem()
assertThat(initialState.results).isEqualTo(AsyncData.Uninitialized)
initialState.queryState.edit { append("A query") }
// Let the query be propagated to the data source before emitting results
testScheduler.advanceUntilIdle()
roomList.summaries.emit(listOf(aRoomSummary()))
// Wait for the presenter to emit a loading state before the success state
consumeItemsUntilPredicate { it.results is AsyncData.Loading }
val successState = awaitItem()
val results = (successState.results.dataOrNull() as GlobalSearchResults.RoomListResults).results
assertThat(results).hasSize(1)
// Remove the query
successState.queryState.edit { replace(0, length, "") }
// Skip the intermediate state where the query is empty but results are still present
skipItems(1)
// It's back to the uninitialized state
assertThat(awaitItem().results).isInstanceOf(AsyncData.Uninitialized::class.java)
// This happens even if for some reason the room results still contained any items
assertThat(roomList.summaries.value).isNotEmpty()
}
}
@Test @Test
fun `present - message search results are mapped when the message search emits`() = runTest { fun `present - message search results are mapped when the message search emits`() = runTest {
val messageSearch = FakeMessageSearch() val messageSearch = FakeMessageSearch()
@@ -173,6 +208,41 @@ class GlobalSearchPresenterTest {
} }
} }
@Test
fun `present - message search displays the uninitialized state after removing the query`() = runTest {
val messageSearch = FakeMessageSearch()
val matrixClient = FakeMatrixClient().apply {
getRoomInfoFlowLambda = { flowOf(Optional.of(aRoomInfo())) }
}
val presenter = createGlobalSearchPresenter(
messageSearchService = FakeMessageSearchService(messageSearch),
matrixClient = matrixClient,
)
presenter.test {
val initialState = awaitItem()
initialState.eventSink(GlobalSearchEvent.UpdateTarget(GlobalSearchTarget.MESSAGES))
initialState.queryState.edit { append("A query") }
testScheduler.advanceUntilIdle()
messageSearch.emitResults(persistentListOf(aMessageSearchResult()))
testScheduler.advanceUntilIdle()
val successState = consumeItemsUntilPredicate { it.results is AsyncData.Success }.last()
val results = (successState.results.dataOrNull() as GlobalSearchResults.MessageSearchResults).results
assertThat(results).hasSize(1)
assertThat(results.first()).isInstanceOf(MessageSearchResultItem.Message::class.java)
// Remove the query
successState.queryState.edit { replace(0, length, "") }
// Skip the intermediate state where the query is empty but results are still present
skipItems(1)
// It's back to the uninitialized state
assertThat(awaitItem().results).isInstanceOf(AsyncData.Uninitialized::class.java)
// This happens even if for some reason the message results still contained any items
assertThat(messageSearch.results.value).isNotEmpty()
}
}
@Test @Test
fun `present - UpdateVisibleRange triggers pagination for messages when near the end`() = runTest { fun `present - UpdateVisibleRange triggers pagination for messages when near the end`() = runTest {
val messageSearch = FakeMessageSearch() val messageSearch = FakeMessageSearch()