Skip to content

Commit dbdf68d

Browse files
committed
Unit Testing | Patch 23
1 parent 1c1b23b commit dbdf68d

File tree

6 files changed

+245
-3
lines changed

6 files changed

+245
-3
lines changed

presentation/src/main/java/com/shifthackz/aisdv1/presentation/screen/gallery/detail/GalleryDetailIntent.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ sealed interface GalleryDetailIntent : MviIntent {
1515
}
1616

1717
enum class Export : GalleryDetailIntent {
18-
1918
Image, Params;
2019
}
2120

presentation/src/main/java/com/shifthackz/aisdv1/presentation/screen/gallery/detail/GalleryDetailViewModel.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ class GalleryDetailViewModel(
7676

7777
GalleryDetailIntent.DismissDialog -> setActiveModal(Modal.None)
7878
}
79-
8079
}
8180

8281
private fun share() {
@@ -122,7 +121,7 @@ class GalleryDetailViewModel(
122121
}
123122

124123
private fun getGenerationResult(id: Long): Single<AiGenerationResult> {
125-
if (id <= 0) return getLastResultFromCacheUseCase.invoke()
124+
if (id <= 0) return getLastResultFromCacheUseCase()
126125
return getGenerationResultUseCase(id)
127126
}
128127
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.shifthackz.aisdv1.presentation.mocks
2+
3+
import com.shifthackz.aisdv1.domain.entity.AiGenerationResult
4+
import java.util.Date
5+
6+
val mockAiGenerationResult = AiGenerationResult(
7+
id = 5598L,
8+
image = "img",
9+
inputImage = "inp",
10+
createdAt = Date(0),
11+
type = AiGenerationResult.Type.IMAGE_TO_IMAGE,
12+
prompt = "prompt",
13+
negativePrompt = "negative",
14+
width = 512,
15+
height = 512,
16+
samplingSteps = 7,
17+
cfgScale = 0.7f,
18+
restoreFaces = true,
19+
sampler = "sampler",
20+
seed = "5598",
21+
subSeed = "1504",
22+
subSeedStrength = 5598f,
23+
denoisingStrength = 1504f,
24+
)
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.shifthackz.aisdv1.presentation.screen.debug
2+
3+
import com.shifthackz.aisdv1.domain.usecase.debug.DebugInsertBadBase64UseCase
4+
import com.shifthackz.aisdv1.presentation.core.CoreViewModelTest
5+
import com.shifthackz.aisdv1.presentation.navigation.router.main.MainRouter
6+
import com.shifthackz.aisdv1.presentation.stub.stubSchedulersProvider
7+
import io.mockk.every
8+
import io.mockk.mockk
9+
import io.mockk.verify
10+
import io.reactivex.rxjava3.core.Completable
11+
import org.junit.Test
12+
13+
class DebugMenuViewModelTest : CoreViewModelTest<DebugMenuViewModel>() {
14+
15+
private val stubDebugInsertBadBase64UseCase = mockk<DebugInsertBadBase64UseCase>()
16+
private val stubMainRouter = mockk<MainRouter>()
17+
18+
override fun initializeViewModel() = DebugMenuViewModel(
19+
debugInsertBadBase64UseCase = stubDebugInsertBadBase64UseCase,
20+
schedulersProvider = stubSchedulersProvider,
21+
mainRouter = stubMainRouter,
22+
)
23+
24+
@Test
25+
fun `given received NavigateBack intent, expected router navigateBack() method called`() {
26+
every {
27+
stubMainRouter.navigateBack()
28+
} returns Unit
29+
30+
viewModel.processIntent(DebugMenuIntent.NavigateBack)
31+
32+
verify {
33+
stubMainRouter.navigateBack()
34+
}
35+
}
36+
37+
@Test
38+
fun `given received InsertBadBase64 intent, expected debugInsertBadBase64UseCase() method called`() {
39+
every {
40+
stubDebugInsertBadBase64UseCase()
41+
} returns Completable.complete()
42+
43+
viewModel.processIntent(DebugMenuIntent.InsertBadBase64)
44+
45+
verify {
46+
stubDebugInsertBadBase64UseCase()
47+
}
48+
}
49+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.shifthackz.aisdv1.presentation.screen.drawer
2+
3+
import com.shifthackz.aisdv1.presentation.core.CoreViewModelTest
4+
import com.shifthackz.aisdv1.presentation.navigation.router.drawer.DrawerRouter
5+
import io.mockk.every
6+
import io.mockk.mockk
7+
import io.mockk.verify
8+
import org.junit.Test
9+
10+
class DrawerViewModelTest : CoreViewModelTest<DrawerViewModel>() {
11+
12+
private val stubDrawerRouter = mockk<DrawerRouter>()
13+
14+
override fun initializeViewModel() = DrawerViewModel(stubDrawerRouter)
15+
16+
@Test
17+
fun `given received Close intent, expected router closeDrawer() method called`() {
18+
every {
19+
stubDrawerRouter.closeDrawer()
20+
} returns Unit
21+
22+
viewModel.processIntent(DrawerIntent.Close)
23+
24+
verify {
25+
stubDrawerRouter.closeDrawer()
26+
}
27+
}
28+
29+
@Test
30+
fun `given received Open intent, expected router openDrawer() method called`() {
31+
every {
32+
stubDrawerRouter.openDrawer()
33+
} returns Unit
34+
35+
viewModel.processIntent(DrawerIntent.Open)
36+
37+
verify {
38+
stubDrawerRouter.openDrawer()
39+
}
40+
}
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package com.shifthackz.aisdv1.presentation.screen.gallery.detail
2+
3+
import android.graphics.Bitmap
4+
import com.shifthackz.aisdv1.core.imageprocessing.Base64ToBitmapConverter
5+
import com.shifthackz.aisdv1.core.model.asUiText
6+
import com.shifthackz.aisdv1.domain.usecase.caching.GetLastResultFromCacheUseCase
7+
import com.shifthackz.aisdv1.domain.usecase.gallery.DeleteGalleryItemUseCase
8+
import com.shifthackz.aisdv1.domain.usecase.generation.GetGenerationResultUseCase
9+
import com.shifthackz.aisdv1.presentation.core.CoreViewModelTest
10+
import com.shifthackz.aisdv1.presentation.core.GenerationFormUpdateEvent
11+
import com.shifthackz.aisdv1.presentation.extensions.mapToUi
12+
import com.shifthackz.aisdv1.presentation.mocks.mockAiGenerationResult
13+
import com.shifthackz.aisdv1.presentation.model.Modal
14+
import com.shifthackz.aisdv1.presentation.navigation.router.main.MainRouter
15+
import com.shifthackz.aisdv1.presentation.stub.stubSchedulersProvider
16+
import io.mockk.every
17+
import io.mockk.mockk
18+
import io.mockk.verify
19+
import io.reactivex.rxjava3.core.Completable
20+
import io.reactivex.rxjava3.core.Single
21+
import kotlinx.coroutines.flow.firstOrNull
22+
import kotlinx.coroutines.test.runTest
23+
import org.junit.Assert
24+
import org.junit.Before
25+
import org.junit.Test
26+
27+
class GalleryDetailViewModelTest : CoreViewModelTest<GalleryDetailViewModel>() {
28+
29+
private val stubBitmap = mockk<Bitmap>()
30+
private val stubGetGenerationResultUseCase = mockk<GetGenerationResultUseCase>()
31+
private val stubGetLastResultFromCacheUseCase = mockk<GetLastResultFromCacheUseCase>()
32+
private val stubDeleteGalleryItemUseCase = mockk<DeleteGalleryItemUseCase>()
33+
private val stubGalleryDetailBitmapExporter = mockk<GalleryDetailBitmapExporter>()
34+
private val stubBase64ToBitmapConverter = mockk<Base64ToBitmapConverter>()
35+
private val stubGenerationFormUpdateEvent = mockk<GenerationFormUpdateEvent>()
36+
private val stubMainRouter = mockk<MainRouter>()
37+
38+
override fun initializeViewModel() = GalleryDetailViewModel(
39+
itemId = 5598L,
40+
getGenerationResultUseCase = stubGetGenerationResultUseCase,
41+
getLastResultFromCacheUseCase = stubGetLastResultFromCacheUseCase,
42+
deleteGalleryItemUseCase = stubDeleteGalleryItemUseCase,
43+
galleryDetailBitmapExporter = stubGalleryDetailBitmapExporter,
44+
base64ToBitmapConverter = stubBase64ToBitmapConverter,
45+
schedulersProvider = stubSchedulersProvider,
46+
generationFormUpdateEvent = stubGenerationFormUpdateEvent,
47+
mainRouter = stubMainRouter,
48+
)
49+
50+
@Before
51+
override fun initialize() {
52+
super.initialize()
53+
54+
every {
55+
stubGetLastResultFromCacheUseCase()
56+
} returns Single.just(mockAiGenerationResult)
57+
58+
every {
59+
stubGetGenerationResultUseCase(any())
60+
} returns Single.just(mockAiGenerationResult)
61+
62+
every {
63+
stubBase64ToBitmapConverter(any())
64+
} returns Single.just(Base64ToBitmapConverter.Output(stubBitmap))
65+
}
66+
67+
@Test
68+
fun `initialized, loaded ai generation result, expected UI state is Content`() {
69+
runTest {
70+
val expected = GalleryDetailState.Content(
71+
tabs = GalleryDetailState.Tab.consume(mockAiGenerationResult.type),
72+
generationType = mockAiGenerationResult.type,
73+
id = mockAiGenerationResult.id,
74+
bitmap = stubBitmap,
75+
inputBitmap = stubBitmap,
76+
createdAt = mockAiGenerationResult.createdAt.toString().asUiText(),
77+
type = mockAiGenerationResult.type.key.asUiText(),
78+
prompt = mockAiGenerationResult.prompt.asUiText(),
79+
negativePrompt = mockAiGenerationResult.negativePrompt.asUiText(),
80+
size = "512 X 512".asUiText(),
81+
samplingSteps = mockAiGenerationResult.samplingSteps.toString().asUiText(),
82+
cfgScale = mockAiGenerationResult.cfgScale.toString().asUiText(),
83+
restoreFaces = mockAiGenerationResult.restoreFaces.mapToUi(),
84+
sampler = mockAiGenerationResult.sampler.asUiText(),
85+
seed = mockAiGenerationResult.seed.asUiText(),
86+
subSeed = mockAiGenerationResult.subSeed.asUiText(),
87+
subSeedStrength = mockAiGenerationResult.subSeedStrength.toString().asUiText(),
88+
denoisingStrength = mockAiGenerationResult.denoisingStrength.toString().asUiText(),
89+
)
90+
val actual = viewModel.state.value
91+
Assert.assertEquals(expected, actual)
92+
}
93+
}
94+
95+
@Test
96+
fun `given received CopyToClipboard intent, expected ShareClipBoard effect delivered to effect collector`() {
97+
viewModel.processIntent(GalleryDetailIntent.CopyToClipboard("text"))
98+
runTest {
99+
val expected = GalleryDetailEffect.ShareClipBoard("text")
100+
val actual = viewModel.effect.firstOrNull()
101+
Assert.assertEquals(expected, actual)
102+
}
103+
}
104+
105+
@Test
106+
fun `given received Delete_Request intent, expected modal field in UI state is DeleteImageConfirm`() {
107+
viewModel.processIntent(GalleryDetailIntent.Delete.Request)
108+
runTest {
109+
val expected = Modal.DeleteImageConfirm
110+
val actual = (viewModel.state.value as? GalleryDetailState.Content)?.screenModal
111+
Assert.assertEquals(expected, actual)
112+
}
113+
}
114+
115+
@Test
116+
fun `given received Delete_Confirm intent, expected modal field in UI state is None, deleteGalleryItemUseCase() method is called`() {
117+
every {
118+
stubDeleteGalleryItemUseCase(any())
119+
} returns Completable.complete()
120+
viewModel.processIntent(GalleryDetailIntent.Delete.Confirm)
121+
runTest {
122+
val expected = Modal.None
123+
val actual = (viewModel.state.value as? GalleryDetailState.Content)?.screenModal
124+
Assert.assertEquals(expected, actual)
125+
}
126+
verify {
127+
stubDeleteGalleryItemUseCase(5598L)
128+
}
129+
}
130+
}

0 commit comments

Comments
 (0)