diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/polls/RoomPollsViewModel.kt b/vector/src/main/java/im/vector/app/features/roomprofile/polls/RoomPollsViewModel.kt index d7efab83ae..b634881f70 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/polls/RoomPollsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/RoomPollsViewModel.kt @@ -82,7 +82,6 @@ class RoomPollsViewModel @AssistedInject constructor( .launchIn(viewModelScope) } - // TODO add unit tests override fun handle(action: RoomPollsAction) { when (action) { RoomPollsAction.LoadMorePolls -> handleLoadMore() diff --git a/vector/src/test/java/im/vector/app/features/roomprofile/polls/RoomPollsViewModelTest.kt b/vector/src/test/java/im/vector/app/features/roomprofile/polls/RoomPollsViewModelTest.kt index 097b00e015..efb905c97f 100644 --- a/vector/src/test/java/im/vector/app/features/roomprofile/polls/RoomPollsViewModelTest.kt +++ b/vector/src/test/java/im/vector/app/features/roomprofile/polls/RoomPollsViewModelTest.kt @@ -17,13 +17,17 @@ package im.vector.app.features.roomprofile.polls import com.airbnb.mvrx.test.MavericksTestRule +import im.vector.app.features.roomprofile.polls.list.data.LoadedPollsStatus import im.vector.app.features.roomprofile.polls.list.domain.GetLoadedPollsStatusUseCase -import im.vector.app.features.roomprofile.polls.list.ui.PollSummary import im.vector.app.features.roomprofile.polls.list.domain.GetPollsUseCase import im.vector.app.features.roomprofile.polls.list.domain.LoadMorePollsUseCase import im.vector.app.features.roomprofile.polls.list.domain.SyncPollsUseCase +import im.vector.app.features.roomprofile.polls.list.ui.PollSummary import im.vector.app.test.test import im.vector.app.test.testDispatcher +import io.mockk.coEvery +import io.mockk.coJustRun +import io.mockk.coVerify import io.mockk.every import io.mockk.mockk import io.mockk.verify @@ -31,7 +35,7 @@ import kotlinx.coroutines.flow.flowOf import org.junit.Rule import org.junit.Test -private const val ROOM_ID = "room-id" +private const val A_ROOM_ID = "room-id" class RoomPollsViewModelTest { @@ -42,7 +46,7 @@ class RoomPollsViewModelTest { private val fakeGetLoadedPollsStatusUseCase = mockk() private val fakeLoadMorePollsUseCase = mockk() private val fakeSyncPollsUseCase = mockk() - private val initialState = RoomPollsViewState(ROOM_ID) + private val initialState = RoomPollsViewState(A_ROOM_ID) private fun createViewModel(): RoomPollsViewModel { return RoomPollsViewModel( @@ -55,11 +59,17 @@ class RoomPollsViewModelTest { } @Test - fun `given viewModel when created then polls list is observed and viewState is updated`() { + fun `given viewModel when created then polls list is observed, sync is launched and viewState is updated`() { // Given + val loadedPollsStatus = givenGetLoadedPollsStatusSuccess() + givenSyncPollsWithSuccess() val polls = listOf(givenAPollSummary()) - every { fakeGetPollsUseCase.execute(ROOM_ID) } returns flowOf(polls) - val expectedViewState = initialState.copy(polls = polls) + every { fakeGetPollsUseCase.execute(A_ROOM_ID) } returns flowOf(polls) + val expectedViewState = initialState.copy( + polls = polls, + canLoadMore = loadedPollsStatus.canLoadMore, + nbLoadedDays = loadedPollsStatus.nbLoadedDays, + ) // When val viewModel = createViewModel() @@ -70,11 +80,88 @@ class RoomPollsViewModelTest { .assertLatestState(expectedViewState) .finish() verify { - fakeGetPollsUseCase.execute(ROOM_ID) + fakeGetPollsUseCase.execute(A_ROOM_ID) } + coVerify { fakeSyncPollsUseCase.execute(A_ROOM_ID) } + } + + @Test + fun `given viewModel and error during sync process when created then error is raised in view event`() { + // Given + givenGetLoadedPollsStatusSuccess() + givenSyncPollsWithError(Exception()) + val polls = listOf(givenAPollSummary()) + every { fakeGetPollsUseCase.execute(A_ROOM_ID) } returns flowOf(polls) + + // When + val viewModel = createViewModel() + val viewModelTest = viewModel.test() + + // Then + viewModelTest + .assertEvents(RoomPollsViewEvent.LoadingError) + .finish() + coVerify { fakeSyncPollsUseCase.execute(A_ROOM_ID) } + } + + @Test + fun `given viewModel when handle load more action then viewState is updated`() { + // Given + val loadedPollsStatus = givenGetLoadedPollsStatusSuccess() + givenSyncPollsWithSuccess() + val polls = listOf(givenAPollSummary()) + every { fakeGetPollsUseCase.execute(A_ROOM_ID) } returns flowOf(polls) + val newLoadedPollsStatus = givenLoadMoreWithSuccess() + val viewModel = createViewModel() + val stateAfterInit = initialState.copy( + polls = polls, + canLoadMore = loadedPollsStatus.canLoadMore, + nbLoadedDays = loadedPollsStatus.nbLoadedDays, + ) + + // When + val viewModelTest = viewModel.test() + viewModel.handle(RoomPollsAction.LoadMorePolls) + + // Then + viewModelTest + .assertStatesChanges( + stateAfterInit, + { copy(isLoadingMore = true) }, + { copy(canLoadMore = newLoadedPollsStatus.canLoadMore, nbLoadedDays = newLoadedPollsStatus.nbLoadedDays) }, + { copy(isLoadingMore = false) }, + ) + .finish() + coVerify { fakeLoadMorePollsUseCase.execute(A_ROOM_ID) } } private fun givenAPollSummary(): PollSummary { return mockk() } + + private fun givenSyncPollsWithSuccess() { + coJustRun { fakeSyncPollsUseCase.execute(A_ROOM_ID) } + } + + private fun givenSyncPollsWithError(error: Exception) { + coEvery { fakeSyncPollsUseCase.execute(A_ROOM_ID) } throws error + } + + private fun givenLoadMoreWithSuccess(): LoadedPollsStatus { + val loadedPollsStatus = givenALoadedPollsStatus(canLoadMore = false, nbLoadedDays = 20) + coEvery { fakeLoadMorePollsUseCase.execute(A_ROOM_ID) } returns loadedPollsStatus + return loadedPollsStatus + } + + private fun givenGetLoadedPollsStatusSuccess(): LoadedPollsStatus { + val loadedPollsStatus = givenALoadedPollsStatus() + every { fakeGetLoadedPollsStatusUseCase.execute(A_ROOM_ID) } returns loadedPollsStatus + return loadedPollsStatus + } + + private fun givenALoadedPollsStatus(canLoadMore: Boolean = true, nbLoadedDays: Int = 10) = + LoadedPollsStatus( + canLoadMore = canLoadMore, + nbLoadedDays = nbLoadedDays, + ) }