Issue#11 Create Turbine variant of Flow Tests
This commit is contained in:
parent
b52652ed67
commit
a71fa67de2
4 changed files with 428 additions and 50 deletions
|
|
@ -1,6 +1,5 @@
|
||||||
package org.fnives.test.showcase.core.content
|
package org.fnives.test.showcase.core.content
|
||||||
|
|
||||||
import app.cash.turbine.test
|
|
||||||
import kotlinx.coroutines.CompletableDeferred
|
import kotlinx.coroutines.CompletableDeferred
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.flow.take
|
import kotlinx.coroutines.flow.take
|
||||||
|
|
@ -147,28 +146,4 @@ internal class ContentRepositoryTest {
|
||||||
Assertions.assertFalse(actual.isCompleted)
|
Assertions.assertFalse(actual.isCompleted)
|
||||||
actual.cancel()
|
actual.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
@DisplayName("GIVEN content response THEN error WHEN fetched THEN only 4 items are emitted")
|
|
||||||
@Test
|
|
||||||
fun noAdditionalItemsEmittedWithTurbine() = runTest {
|
|
||||||
val exception = RuntimeException()
|
|
||||||
val expected = listOf(
|
|
||||||
Resource.Loading(),
|
|
||||||
Resource.Success(emptyList()),
|
|
||||||
Resource.Loading(),
|
|
||||||
Resource.Error<List<Content>>(UnexpectedException(exception))
|
|
||||||
)
|
|
||||||
var first = true
|
|
||||||
whenever(mockContentRemoteSource.get()).doAnswer {
|
|
||||||
if (first) emptyList<Content>().also { first = false } else throw exception
|
|
||||||
}
|
|
||||||
|
|
||||||
sut.contents.test {
|
|
||||||
sut.fetch()
|
|
||||||
expected.forEach { expectedItem ->
|
|
||||||
Assertions.assertEquals(expectedItem, awaitItem())
|
|
||||||
}
|
|
||||||
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
package org.fnives.test.showcase.core.content
|
package org.fnives.test.showcase.core.content
|
||||||
|
|
||||||
import app.cash.turbine.test
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.take
|
import kotlinx.coroutines.flow.take
|
||||||
import kotlinx.coroutines.flow.toList
|
import kotlinx.coroutines.flow.toList
|
||||||
|
import kotlinx.coroutines.test.advanceUntilIdle
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.fnives.test.showcase.core.storage.content.FavouriteContentLocalStorage
|
import org.fnives.test.showcase.core.storage.content.FavouriteContentLocalStorage
|
||||||
import org.fnives.test.showcase.model.content.Content
|
import org.fnives.test.showcase.model.content.Content
|
||||||
|
|
@ -151,15 +152,18 @@ internal class GetAllContentUseCaseTest {
|
||||||
Resource.Success(listOf(FavouriteContent(content, true)))
|
Resource.Success(listOf(FavouriteContent(content, true)))
|
||||||
)
|
)
|
||||||
|
|
||||||
sut.get().test {
|
val actual = async(coroutineContext) {
|
||||||
contentFlow.value = Resource.Success(listOf(content))
|
sut.get().take(3).toList()
|
||||||
favouriteContentIdFlow.value = listOf(ContentId("a"))
|
|
||||||
|
|
||||||
expected.forEach { expectedItem ->
|
|
||||||
Assertions.assertEquals(expectedItem, awaitItem())
|
|
||||||
}
|
|
||||||
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
|
||||||
}
|
}
|
||||||
|
advanceUntilIdle()
|
||||||
|
|
||||||
|
contentFlow.value = Resource.Success(listOf(content))
|
||||||
|
advanceUntilIdle()
|
||||||
|
|
||||||
|
favouriteContentIdFlow.value = listOf(ContentId("a"))
|
||||||
|
advanceUntilIdle()
|
||||||
|
|
||||||
|
Assertions.assertEquals(expected, actual.getCompleted())
|
||||||
}
|
}
|
||||||
|
|
||||||
@DisplayName("GIVEN loading then data then removed favourite WHEN observed THEN loading then correct favourites are returned")
|
@DisplayName("GIVEN loading then data then removed favourite WHEN observed THEN loading then correct favourites are returned")
|
||||||
|
|
@ -174,15 +178,18 @@ internal class GetAllContentUseCaseTest {
|
||||||
Resource.Success(listOf(FavouriteContent(content, false)))
|
Resource.Success(listOf(FavouriteContent(content, false)))
|
||||||
)
|
)
|
||||||
|
|
||||||
sut.get().test {
|
val actual = async(coroutineContext) {
|
||||||
contentFlow.value = Resource.Success(listOf(content))
|
sut.get().take(3).toList()
|
||||||
favouriteContentIdFlow.value = emptyList()
|
|
||||||
|
|
||||||
expected.forEach { expectedItem ->
|
|
||||||
Assertions.assertEquals(expectedItem, awaitItem())
|
|
||||||
}
|
|
||||||
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
|
||||||
}
|
}
|
||||||
|
advanceUntilIdle()
|
||||||
|
|
||||||
|
contentFlow.value = Resource.Success(listOf(content))
|
||||||
|
advanceUntilIdle()
|
||||||
|
|
||||||
|
favouriteContentIdFlow.value = emptyList()
|
||||||
|
advanceUntilIdle()
|
||||||
|
|
||||||
|
Assertions.assertEquals(expected, actual.getCompleted())
|
||||||
}
|
}
|
||||||
|
|
||||||
@DisplayName("GIVEN loading then data then loading WHEN observed THEN loading then correct favourites then loading are returned")
|
@DisplayName("GIVEN loading then data then loading WHEN observed THEN loading then correct favourites then loading are returned")
|
||||||
|
|
@ -197,14 +204,17 @@ internal class GetAllContentUseCaseTest {
|
||||||
Resource.Loading()
|
Resource.Loading()
|
||||||
)
|
)
|
||||||
|
|
||||||
sut.get().test {
|
val actual = async(coroutineContext) {
|
||||||
contentFlow.value = Resource.Success(listOf(content))
|
sut.get().take(3).toList()
|
||||||
contentFlow.value = Resource.Loading()
|
|
||||||
|
|
||||||
expected.forEach { expectedItem ->
|
|
||||||
Assertions.assertEquals(expectedItem, awaitItem())
|
|
||||||
}
|
|
||||||
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
|
||||||
}
|
}
|
||||||
|
advanceUntilIdle()
|
||||||
|
|
||||||
|
contentFlow.value = Resource.Success(listOf(content))
|
||||||
|
advanceUntilIdle()
|
||||||
|
|
||||||
|
contentFlow.value = Resource.Loading()
|
||||||
|
advanceUntilIdle()
|
||||||
|
|
||||||
|
Assertions.assertEquals(expected, actual.getCompleted())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,165 @@
|
||||||
|
package org.fnives.test.showcase.core.content
|
||||||
|
|
||||||
|
import app.cash.turbine.test
|
||||||
|
import kotlinx.coroutines.CompletableDeferred
|
||||||
|
import kotlinx.coroutines.flow.take
|
||||||
|
import kotlinx.coroutines.flow.toList
|
||||||
|
import kotlinx.coroutines.test.UnconfinedTestDispatcher
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import org.fnives.test.showcase.core.shared.UnexpectedException
|
||||||
|
import org.fnives.test.showcase.model.content.Content
|
||||||
|
import org.fnives.test.showcase.model.content.ContentId
|
||||||
|
import org.fnives.test.showcase.model.content.ImageUrl
|
||||||
|
import org.fnives.test.showcase.model.shared.Resource
|
||||||
|
import org.fnives.test.showcase.network.content.ContentRemoteSource
|
||||||
|
import org.junit.jupiter.api.Assertions
|
||||||
|
import org.junit.jupiter.api.BeforeEach
|
||||||
|
import org.junit.jupiter.api.DisplayName
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.mockito.kotlin.doAnswer
|
||||||
|
import org.mockito.kotlin.doReturn
|
||||||
|
import org.mockito.kotlin.doSuspendableAnswer
|
||||||
|
import org.mockito.kotlin.doThrow
|
||||||
|
import org.mockito.kotlin.mock
|
||||||
|
import org.mockito.kotlin.times
|
||||||
|
import org.mockito.kotlin.verify
|
||||||
|
import org.mockito.kotlin.verifyNoMoreInteractions
|
||||||
|
import org.mockito.kotlin.whenever
|
||||||
|
|
||||||
|
class TurbineContentRepositoryTest {
|
||||||
|
|
||||||
|
private lateinit var sut: ContentRepository
|
||||||
|
private lateinit var mockContentRemoteSource: ContentRemoteSource
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
fun setUp() {
|
||||||
|
mockContentRemoteSource = mock()
|
||||||
|
sut = ContentRepository(mockContentRemoteSource)
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("GIVEN no interaction THEN remote source is not called")
|
||||||
|
@Test
|
||||||
|
fun fetchingIsLazy() {
|
||||||
|
verifyNoMoreInteractions(mockContentRemoteSource)
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("GIVEN content response WHEN content observed THEN loading AND data is returned")
|
||||||
|
@Test
|
||||||
|
fun happyFlow() = runTest {
|
||||||
|
val expected = listOf(
|
||||||
|
Resource.Loading(),
|
||||||
|
Resource.Success(listOf(Content(ContentId("a"), "", "", ImageUrl(""))))
|
||||||
|
)
|
||||||
|
whenever(mockContentRemoteSource.get()).doReturn(
|
||||||
|
listOf(Content(ContentId("a"), "", "", ImageUrl("")))
|
||||||
|
)
|
||||||
|
|
||||||
|
sut.contents.test {
|
||||||
|
expected.forEach { expectedItem ->
|
||||||
|
Assertions.assertEquals(expectedItem, awaitItem())
|
||||||
|
}
|
||||||
|
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("GIVEN content error WHEN content observed THEN loading AND data is returned")
|
||||||
|
@Test
|
||||||
|
fun errorFlow() = runTest {
|
||||||
|
val exception = RuntimeException()
|
||||||
|
val expected = listOf(
|
||||||
|
Resource.Loading(),
|
||||||
|
Resource.Error<List<Content>>(UnexpectedException(exception))
|
||||||
|
)
|
||||||
|
whenever(mockContentRemoteSource.get()).doThrow(exception)
|
||||||
|
|
||||||
|
sut.contents.test {
|
||||||
|
expected.forEach { expectedItem ->
|
||||||
|
Assertions.assertEquals(expectedItem, awaitItem())
|
||||||
|
}
|
||||||
|
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("GIVEN saved cache WHEN collected THEN cache is returned")
|
||||||
|
@Test
|
||||||
|
fun verifyCaching() = runTest {
|
||||||
|
val content = Content(ContentId("1"), "", "", ImageUrl(""))
|
||||||
|
val expected = listOf(Resource.Success(listOf(content)))
|
||||||
|
whenever(mockContentRemoteSource.get()).doReturn(listOf(content))
|
||||||
|
sut.contents.take(2).toList()
|
||||||
|
|
||||||
|
sut.contents.test {
|
||||||
|
expected.forEach { expectedItem ->
|
||||||
|
Assertions.assertEquals(expectedItem, awaitItem())
|
||||||
|
}
|
||||||
|
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||||
|
}
|
||||||
|
verify(mockContentRemoteSource, times(1)).get()
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("GIVEN no response from remote source WHEN content observed THEN loading is returned")
|
||||||
|
@Test
|
||||||
|
fun loadingIsShownBeforeTheRequestIsReturned() = runTest {
|
||||||
|
val expected = listOf(Resource.Loading<List<Content>>())
|
||||||
|
val suspendedRequest = CompletableDeferred<Unit>()
|
||||||
|
whenever(mockContentRemoteSource.get()).doSuspendableAnswer {
|
||||||
|
suspendedRequest.await()
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
sut.contents.test {
|
||||||
|
expected.forEach { expectedItem ->
|
||||||
|
Assertions.assertEquals(expectedItem, awaitItem())
|
||||||
|
}
|
||||||
|
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||||
|
}
|
||||||
|
suspendedRequest.complete(Unit)
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("GIVEN content response THEN error WHEN fetched THEN returned states are loading data loading error")
|
||||||
|
@Test
|
||||||
|
fun whenFetchingRequestIsCalledAgain() = runTest(UnconfinedTestDispatcher()) {
|
||||||
|
val exception = RuntimeException()
|
||||||
|
val expected = listOf(
|
||||||
|
Resource.Loading(),
|
||||||
|
Resource.Success(emptyList()),
|
||||||
|
Resource.Loading(),
|
||||||
|
Resource.Error<List<Content>>(UnexpectedException(exception))
|
||||||
|
)
|
||||||
|
var first = true
|
||||||
|
whenever(mockContentRemoteSource.get()).doAnswer {
|
||||||
|
if (first) emptyList<Content>().also { first = false } else throw exception
|
||||||
|
}
|
||||||
|
|
||||||
|
sut.contents.test {
|
||||||
|
sut.fetch()
|
||||||
|
expected.forEach { expectedItem ->
|
||||||
|
Assertions.assertEquals(expectedItem, awaitItem())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("GIVEN content response THEN error WHEN fetched THEN only 4 items are emitted")
|
||||||
|
@Test
|
||||||
|
fun noAdditionalItemsEmitted() = runTest {
|
||||||
|
val exception = RuntimeException()
|
||||||
|
val expected = listOf(
|
||||||
|
Resource.Loading(),
|
||||||
|
Resource.Success(emptyList()),
|
||||||
|
Resource.Loading(),
|
||||||
|
Resource.Error<List<Content>>(UnexpectedException(exception))
|
||||||
|
)
|
||||||
|
var first = true
|
||||||
|
whenever(mockContentRemoteSource.get()).doAnswer {
|
||||||
|
if (first) emptyList<Content>().also { first = false } else throw exception
|
||||||
|
}
|
||||||
|
|
||||||
|
sut.contents.test {
|
||||||
|
sut.fetch()
|
||||||
|
expected.forEach { expectedItem ->
|
||||||
|
Assertions.assertEquals(expectedItem, awaitItem())
|
||||||
|
}
|
||||||
|
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,228 @@
|
||||||
|
package org.fnives.test.showcase.core.content
|
||||||
|
|
||||||
|
import app.cash.turbine.test
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import org.fnives.test.showcase.core.storage.content.FavouriteContentLocalStorage
|
||||||
|
import org.fnives.test.showcase.model.content.Content
|
||||||
|
import org.fnives.test.showcase.model.content.ContentId
|
||||||
|
import org.fnives.test.showcase.model.content.FavouriteContent
|
||||||
|
import org.fnives.test.showcase.model.content.ImageUrl
|
||||||
|
import org.fnives.test.showcase.model.shared.Resource
|
||||||
|
import org.junit.jupiter.api.Assertions
|
||||||
|
import org.junit.jupiter.api.BeforeEach
|
||||||
|
import org.junit.jupiter.api.DisplayName
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.mockito.kotlin.doReturn
|
||||||
|
import org.mockito.kotlin.mock
|
||||||
|
import org.mockito.kotlin.whenever
|
||||||
|
|
||||||
|
class TurbineGetAllContentUseCaseTest {
|
||||||
|
|
||||||
|
private lateinit var sut: GetAllContentUseCase
|
||||||
|
private lateinit var mockContentRepository: ContentRepository
|
||||||
|
private lateinit var mockFavouriteContentLocalStorage: FavouriteContentLocalStorage
|
||||||
|
private lateinit var contentFlow: MutableStateFlow<Resource<List<Content>>>
|
||||||
|
private lateinit var favouriteContentIdFlow: MutableStateFlow<List<ContentId>>
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
fun setUp() {
|
||||||
|
mockFavouriteContentLocalStorage = mock()
|
||||||
|
mockContentRepository = mock()
|
||||||
|
favouriteContentIdFlow = MutableStateFlow(emptyList())
|
||||||
|
contentFlow = MutableStateFlow(Resource.Loading())
|
||||||
|
whenever(mockFavouriteContentLocalStorage.observeFavourites()).doReturn(
|
||||||
|
favouriteContentIdFlow
|
||||||
|
)
|
||||||
|
whenever(mockContentRepository.contents).doReturn(contentFlow)
|
||||||
|
sut = GetAllContentUseCase(mockContentRepository, mockFavouriteContentLocalStorage)
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("GIVEN loading AND empty favourite WHEN observed THEN loading is shown")
|
||||||
|
@Test
|
||||||
|
fun loadingResourceWithNoFavouritesResultsInLoadingResource() = runTest {
|
||||||
|
favouriteContentIdFlow.value = emptyList()
|
||||||
|
contentFlow.value = Resource.Loading()
|
||||||
|
val expected = listOf(Resource.Loading<List<FavouriteContent>>())
|
||||||
|
|
||||||
|
sut.get().test {
|
||||||
|
expected.forEach { expectedItem ->
|
||||||
|
Assertions.assertEquals(expectedItem, awaitItem())
|
||||||
|
}
|
||||||
|
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("GIVEN loading AND listOfFavourite WHEN observed THEN loading is shown")
|
||||||
|
@Test
|
||||||
|
fun loadingResourceWithFavouritesResultsInLoadingResource() = runTest {
|
||||||
|
favouriteContentIdFlow.value = listOf(ContentId("a"))
|
||||||
|
contentFlow.value = Resource.Loading()
|
||||||
|
val expected = listOf(Resource.Loading<List<FavouriteContent>>())
|
||||||
|
|
||||||
|
sut.get().test {
|
||||||
|
expected.forEach { expectedItem ->
|
||||||
|
Assertions.assertEquals(expectedItem, awaitItem())
|
||||||
|
}
|
||||||
|
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("GIVEN error AND empty favourite WHEN observed THEN error is shown")
|
||||||
|
@Test
|
||||||
|
fun errorResourceWithNoFavouritesResultsInErrorResource() = runTest {
|
||||||
|
favouriteContentIdFlow.value = emptyList()
|
||||||
|
val exception = Throwable()
|
||||||
|
contentFlow.value = Resource.Error(exception)
|
||||||
|
val expected = listOf(Resource.Error<List<FavouriteContent>>(exception))
|
||||||
|
|
||||||
|
sut.get().test {
|
||||||
|
expected.forEach { expectedItem ->
|
||||||
|
Assertions.assertEquals(expectedItem, awaitItem())
|
||||||
|
}
|
||||||
|
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("GIVEN error AND listOfFavourite WHEN observed THEN error is shown")
|
||||||
|
@Test
|
||||||
|
fun errorResourceWithFavouritesResultsInErrorResource() = runTest {
|
||||||
|
favouriteContentIdFlow.value = listOf(ContentId("b"))
|
||||||
|
val exception = Throwable()
|
||||||
|
contentFlow.value = Resource.Error(exception)
|
||||||
|
val expected = listOf(Resource.Error<List<FavouriteContent>>(exception))
|
||||||
|
|
||||||
|
sut.get().test {
|
||||||
|
expected.forEach { expectedItem ->
|
||||||
|
Assertions.assertEquals(expectedItem, awaitItem())
|
||||||
|
}
|
||||||
|
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("GIVEN listOfContent AND empty favourite WHEN observed THEN favourites are returned")
|
||||||
|
@Test
|
||||||
|
fun successResourceWithNoFavouritesResultsInNoFavouritedItems() = runTest {
|
||||||
|
favouriteContentIdFlow.value = emptyList()
|
||||||
|
val content = Content(ContentId("a"), "b", "c", ImageUrl("d"))
|
||||||
|
contentFlow.value = Resource.Success(listOf(content))
|
||||||
|
val items = listOf(
|
||||||
|
FavouriteContent(content, false)
|
||||||
|
)
|
||||||
|
val expected = listOf(Resource.Success(items))
|
||||||
|
|
||||||
|
sut.get().test {
|
||||||
|
expected.forEach { expectedItem ->
|
||||||
|
Assertions.assertEquals(expectedItem, awaitItem())
|
||||||
|
}
|
||||||
|
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("GIVEN listOfContent AND other favourite id WHEN observed THEN favourites are returned")
|
||||||
|
@Test
|
||||||
|
fun successResourceWithDifferentFavouritesResultsInNoFavouritedItems() = runTest {
|
||||||
|
favouriteContentIdFlow.value = listOf(ContentId("x"))
|
||||||
|
val content = Content(ContentId("a"), "b", "c", ImageUrl("d"))
|
||||||
|
contentFlow.value = Resource.Success(listOf(content))
|
||||||
|
val items = listOf(
|
||||||
|
FavouriteContent(content, false)
|
||||||
|
)
|
||||||
|
val expected = listOf(Resource.Success(items))
|
||||||
|
|
||||||
|
sut.get().test {
|
||||||
|
expected.forEach { expectedItem ->
|
||||||
|
Assertions.assertEquals(expectedItem, awaitItem())
|
||||||
|
}
|
||||||
|
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("GIVEN listOfContent AND same favourite id WHEN observed THEN favourites are returned")
|
||||||
|
@Test
|
||||||
|
fun successResourceWithSameFavouritesResultsInFavouritedItems() = runTest {
|
||||||
|
favouriteContentIdFlow.value = listOf(ContentId("a"))
|
||||||
|
val content = Content(ContentId("a"), "b", "c", ImageUrl("d"))
|
||||||
|
contentFlow.value = Resource.Success(listOf(content))
|
||||||
|
val items = listOf(
|
||||||
|
FavouriteContent(content, true)
|
||||||
|
)
|
||||||
|
val expected = listOf(Resource.Success(items))
|
||||||
|
|
||||||
|
sut.get().test {
|
||||||
|
expected.forEach { expectedItem ->
|
||||||
|
Assertions.assertEquals(expectedItem, awaitItem())
|
||||||
|
}
|
||||||
|
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("GIVEN loading then data then added favourite WHEN observed THEN loading then correct favourites are returned")
|
||||||
|
@Test
|
||||||
|
fun whileLoadingAndAddingItemsReactsProperly() = runTest {
|
||||||
|
favouriteContentIdFlow.value = emptyList()
|
||||||
|
val content = Content(ContentId("a"), "b", "c", ImageUrl("d"))
|
||||||
|
contentFlow.value = Resource.Loading()
|
||||||
|
val expected = listOf(
|
||||||
|
Resource.Loading(),
|
||||||
|
Resource.Success(listOf(FavouriteContent(content, false))),
|
||||||
|
Resource.Success(listOf(FavouriteContent(content, true)))
|
||||||
|
)
|
||||||
|
|
||||||
|
sut.get().test {
|
||||||
|
contentFlow.value = Resource.Success(listOf(content))
|
||||||
|
favouriteContentIdFlow.value = listOf(ContentId("a"))
|
||||||
|
|
||||||
|
expected.forEach { expectedItem ->
|
||||||
|
Assertions.assertEquals(expectedItem, awaitItem())
|
||||||
|
}
|
||||||
|
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("GIVEN loading then data then removed favourite WHEN observed THEN loading then correct favourites are returned")
|
||||||
|
@Test
|
||||||
|
fun whileLoadingAndRemovingItemsReactsProperly() = runTest {
|
||||||
|
favouriteContentIdFlow.value = listOf(ContentId("a"))
|
||||||
|
val content = Content(ContentId("a"), "b", "c", ImageUrl("d"))
|
||||||
|
contentFlow.value = Resource.Loading()
|
||||||
|
val expected = listOf(
|
||||||
|
Resource.Loading(),
|
||||||
|
Resource.Success(listOf(FavouriteContent(content, true))),
|
||||||
|
Resource.Success(listOf(FavouriteContent(content, false)))
|
||||||
|
)
|
||||||
|
|
||||||
|
sut.get().test {
|
||||||
|
contentFlow.value = Resource.Success(listOf(content))
|
||||||
|
favouriteContentIdFlow.value = emptyList()
|
||||||
|
|
||||||
|
expected.forEach { expectedItem ->
|
||||||
|
Assertions.assertEquals(expectedItem, awaitItem())
|
||||||
|
}
|
||||||
|
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("GIVEN loading then data then loading WHEN observed THEN loading then correct favourites then loading are returned")
|
||||||
|
@Test
|
||||||
|
fun loadingThenDataThenLoadingReactsProperly() = runTest {
|
||||||
|
favouriteContentIdFlow.value = listOf(ContentId("a"))
|
||||||
|
val content = Content(ContentId("a"), "b", "c", ImageUrl("d"))
|
||||||
|
contentFlow.value = Resource.Loading()
|
||||||
|
val expected = listOf(
|
||||||
|
Resource.Loading(),
|
||||||
|
Resource.Success(listOf(FavouriteContent(content, true))),
|
||||||
|
Resource.Loading()
|
||||||
|
)
|
||||||
|
|
||||||
|
sut.get().test {
|
||||||
|
contentFlow.value = Resource.Success(listOf(content))
|
||||||
|
contentFlow.value = Resource.Loading()
|
||||||
|
|
||||||
|
expected.forEach { expectedItem ->
|
||||||
|
Assertions.assertEquals(expectedItem, awaitItem())
|
||||||
|
}
|
||||||
|
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue