adding missing image gallery reducer tests

This commit is contained in:
Adam Brown 2022-11-03 12:34:05 +00:00
parent 42761c0899
commit 6492afe063
3 changed files with 99 additions and 20 deletions

View File

@ -39,6 +39,8 @@ class ReducerTestScope<S, E>(
private val expectTestScope: ExpectTestScope
) : ExpectTestScope by expectTestScope, Reducer<S> {
private var invalidateCapturedState: Boolean = false
private val actionSideEffects = mutableMapOf<Action, () -> S>()
private var manualState: S? = null
private var capturedResult: S? = null
@ -47,6 +49,10 @@ class ReducerTestScope<S, E>(
override val coroutineScope = CoroutineScope(UnconfinedTestDispatcher())
override fun dispatch(action: Action) {
actionCaptures.add(action)
if (actionSideEffects.containsKey(action)) {
setState(actionSideEffects.getValue(action).invoke(), invalidateCapturedState = true)
}
}
override fun getState() = manualState ?: reducerFactory.initialState()
@ -54,15 +60,20 @@ class ReducerTestScope<S, E>(
private val reducer: Reducer<S> = reducerFactory.create(reducerScope)
override fun reduce(action: Action) = reducer.reduce(action).also {
capturedResult = it
capturedResult = if (invalidateCapturedState) manualState else it
}
fun setState(state: S) {
fun actionSideEffect(action: Action, handler: () -> S) {
actionSideEffects[action] = handler
}
fun setState(state: S, invalidateCapturedState: Boolean = false) {
manualState = state
this.invalidateCapturedState = invalidateCapturedState
}
fun setState(block: (S) -> S) {
manualState = block(reducerScope.getState())
setState(block(reducerScope.getState()))
}
fun assertInitialState(expected: S) {

View File

@ -46,7 +46,6 @@ fun imageGalleryReducer(
parent = ImageGalleryPage.Routes.folders,
state = ImageGalleryPage.Files(Lce.Loading(), action.folder)
)
dispatch(PageAction.GoTo(page))
jobBag.replace(ImageGalleryPage.Files::class, coroutineScope.launch {

View File

@ -1,54 +1,123 @@
package app.dapk.st.messenger.gallery.state
import android.net.Uri
import app.dapk.st.core.Lce
import app.dapk.st.core.page.PageAction
import app.dapk.st.core.page.PageContainer
import app.dapk.st.core.page.PageStateChange
import app.dapk.st.design.components.SpiderPage
import app.dapk.st.messenger.gallery.FetchMediaFoldersUseCase
import app.dapk.st.messenger.gallery.FetchMediaUseCase
import app.dapk.st.core.page.PageContainer
import app.dapk.st.messenger.gallery.Folder
import app.dapk.st.messenger.gallery.Media
import app.dapk.state.Combined2
import fake.FakeJobBag
import fake.FakeUri
import io.mockk.coEvery
import io.mockk.mockk
import org.junit.Test
import test.assertOnlyDispatches
import test.delegateReturn
import test.expect
import test.testReducer
private const val A_ROOM_NAME = "a room name"
private val A_FOLDER = Folder(
bucketId = "a-bucket-id",
title = "a title",
thumbnail = FakeUri().instance,
)
private val A_MEDIA_RESULT = listOf(aMedia())
private val A_FOLDERS_RESULT = listOf(aFolder())
private val AN_INITIAL_FILES_PAGE = SpiderPage(
route = ImageGalleryPage.Routes.files,
label = "Send to $A_ROOM_NAME",
parent = ImageGalleryPage.Routes.folders,
state = ImageGalleryPage.Files(Lce.Loading(), A_FOLDER)
)
private val AN_INITIAL_FOLDERS_PAGE = SpiderPage(
route = ImageGalleryPage.Routes.folders,
label = "Send to $A_ROOM_NAME",
parent = null,
state = ImageGalleryPage.Folders(Lce.Loading())
)
class ImageGalleryReducerTest {
private val fakeJobBag = FakeJobBag()
private val fakeFetchMediaFoldersUseCase = FakeFetchMediaFoldersUseCase()
private val fakeFetchMediaUseCase = FakeFetchMediaUseCase()
private val runReducerTest = testReducer { _: (Unit) -> Unit ->
imageGalleryReducer(
A_ROOM_NAME,
FakeFetchMediaFoldersUseCase().instance,
FakeFetchMediaUseCase().instance,
fakeFetchMediaFoldersUseCase.instance,
fakeFetchMediaUseCase.instance,
fakeJobBag.instance,
)
}
@Test
fun `initial state is folders page`() = runReducerTest {
assertInitialState(
Combined2(
state1 = PageContainer(
SpiderPage(
route = ImageGalleryPage.Routes.folders,
label = "Send to $A_ROOM_NAME",
parent = null,
state = ImageGalleryPage.Folders(Lce.Loading())
)
),
state2 = Unit
)
assertInitialState(pageState(AN_INITIAL_FOLDERS_PAGE))
}
@Test
fun `when Visible, then updates Folders content`() = runReducerTest {
fakeJobBag.instance.expect { it.replace(ImageGalleryPage.Folders::class, any()) }
fakeFetchMediaFoldersUseCase.givenFolders().returns(A_FOLDERS_RESULT)
reduce(ImageGalleryActions.Visible)
assertOnlyDispatches(
PageStateChange.UpdatePage(AN_INITIAL_FOLDERS_PAGE.state.copy(content = Lce.Content(A_FOLDERS_RESULT)))
)
}
@Test
fun `when SelectFolder, then goes to Folder page and fetches content`() = runReducerTest {
fakeJobBag.instance.expect { it.replace(ImageGalleryPage.Files::class, any()) }
fakeFetchMediaUseCase.givenMedia(A_FOLDER.bucketId).returns(A_MEDIA_RESULT)
val goToFolderPage = PageAction.GoTo(AN_INITIAL_FILES_PAGE)
actionSideEffect(goToFolderPage) { pageState(goToFolderPage.page) }
reduce(ImageGalleryActions.SelectFolder(A_FOLDER))
assertOnlyDispatches(
goToFolderPage,
PageStateChange.UpdatePage(goToFolderPage.page.state.copy(content = Lce.Content(A_MEDIA_RESULT)))
)
}
}
private fun <P> pageState(page: SpiderPage<out P>) = Combined2(PageContainer(page), Unit)
class FakeFetchMediaFoldersUseCase {
val instance = mockk<FetchMediaFoldersUseCase>()
fun givenFolders() = coEvery { instance.fetchFolders() }.delegateReturn()
}
class FakeFetchMediaUseCase {
val instance = mockk<FetchMediaUseCase>()
}
fun givenMedia(bucketId: String) = coEvery { instance.getMediaInBucket(bucketId) }.delegateReturn()
}
fun aMedia(
id: Long = 1L,
uri: Uri = FakeUri().instance,
mimeType: String = "image/png",
width: Int = 100,
height: Int = 250,
size: Long = 1000L,
dateModifiedEpochMillis: Long = 5000L,
) = Media(id, uri, mimeType, width, height, size, dateModifiedEpochMillis)
fun aFolder(
bucketId: String = "a-bucket-id",
title: String = "a title",
thumbnail: Uri = FakeUri().instance,
) = Folder(bucketId, title, thumbnail)