Skip to content

Commit c5c0e12

Browse files
committed
test: add unit tests for uncovered classes
Add unit tests for previously untested classes: - Domain: connectivity, downloadable, gallery, report, settings, swarmmodel use cases - Data: FalAi endpoints, report data sources and repositories, MediaPipe repository - Presentation: InputHistory and OnBoarding view models - Fix EngineSelectionViewModelTest to include new MediaPipe use case dependency
1 parent 1f3dc38 commit c5c0e12

21 files changed

Lines changed: 1785 additions & 0 deletions
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
package dev.minios.pdaiv1.data.local
2+
3+
import dev.minios.pdaiv1.data.mocks.mockFalAiEndpoint
4+
import dev.minios.pdaiv1.data.mocks.mockFalAiEndpoints
5+
import dev.minios.pdaiv1.storage.db.persistent.dao.FalAiEndpointDao
6+
import dev.minios.pdaiv1.storage.db.persistent.entity.FalAiEndpointEntity
7+
import io.mockk.every
8+
import io.mockk.mockk
9+
import io.mockk.verify
10+
import io.reactivex.rxjava3.core.Completable
11+
import io.reactivex.rxjava3.core.Flowable
12+
import io.reactivex.rxjava3.core.Single
13+
import org.junit.Test
14+
15+
class FalAiEndpointLocalDataSourceTest {
16+
17+
private val stubException = Throwable("Database error")
18+
private val stubDao = mockk<FalAiEndpointDao>()
19+
20+
private val localDataSource = FalAiEndpointLocalDataSource(stubDao)
21+
22+
private val stubEntity = FalAiEndpointEntity(
23+
id = "fal-ai/flux/schnell",
24+
endpointId = "fal-ai/flux/schnell",
25+
title = "FLUX.1 [schnell]",
26+
description = "Fast text to image generation",
27+
category = "TEXT_TO_IMAGE",
28+
group = "FLUX",
29+
thumbnailUrl = "https://fal.ai/thumbnails/flux-schnell.jpg",
30+
playgroundUrl = "https://fal.ai/models/fal-ai/flux/schnell",
31+
documentationUrl = "https://fal.ai/models/fal-ai/flux/schnell/api",
32+
isCustom = true,
33+
schemaJson = """{"baseUrl":"https://queue.fal.run","submissionPath":"/fal-ai/flux/schnell","inputProperties":[{"name":"prompt","title":"Prompt","description":"The prompt","type":"STRING","default":"","minimum":null,"maximum":null,"enumValues":null,"isRequired":true,"isImageInput":false}],"requiredProperties":["prompt"],"propertyOrder":["prompt"]}""",
34+
)
35+
36+
@Test
37+
fun `given attempt to observe all, dao returns entities, expected domain models`() {
38+
every {
39+
stubDao.observeAll()
40+
} returns Flowable.just(listOf(stubEntity))
41+
42+
localDataSource
43+
.observeAll()
44+
.test()
45+
.assertNoErrors()
46+
.assertValue { endpoints -> endpoints.size == 1 }
47+
}
48+
49+
@Test
50+
fun `given attempt to observe all, dao returns empty list, expected empty domain list`() {
51+
every {
52+
stubDao.observeAll()
53+
} returns Flowable.just(emptyList())
54+
55+
localDataSource
56+
.observeAll()
57+
.test()
58+
.assertNoErrors()
59+
.assertValue { endpoints -> endpoints.isEmpty() }
60+
}
61+
62+
@Test
63+
fun `given attempt to get all, dao returns entities, expected domain models`() {
64+
every {
65+
stubDao.queryAll()
66+
} returns Single.just(listOf(stubEntity))
67+
68+
localDataSource
69+
.getAll()
70+
.test()
71+
.assertNoErrors()
72+
.assertValue { endpoints -> endpoints.size == 1 }
73+
.await()
74+
.assertComplete()
75+
}
76+
77+
@Test
78+
fun `given attempt to get all, dao throws exception, expected error value`() {
79+
every {
80+
stubDao.queryAll()
81+
} returns Single.error(stubException)
82+
83+
localDataSource
84+
.getAll()
85+
.test()
86+
.assertError(stubException)
87+
.await()
88+
.assertNotComplete()
89+
}
90+
91+
@Test
92+
fun `given attempt to get by id, dao returns entity, expected domain model`() {
93+
val id = "fal-ai/flux/schnell"
94+
95+
every {
96+
stubDao.queryById(id)
97+
} returns Single.just(stubEntity)
98+
99+
localDataSource
100+
.getById(id)
101+
.test()
102+
.assertNoErrors()
103+
.assertValue { endpoint -> endpoint.id == id }
104+
.await()
105+
.assertComplete()
106+
}
107+
108+
@Test
109+
fun `given attempt to get by id, dao throws exception, expected error value`() {
110+
val id = "nonexistent-id"
111+
112+
every {
113+
stubDao.queryById(id)
114+
} returns Single.error(stubException)
115+
116+
localDataSource
117+
.getById(id)
118+
.test()
119+
.assertError(stubException)
120+
.await()
121+
.assertNotComplete()
122+
}
123+
124+
@Test
125+
fun `given attempt to save endpoint, dao insert success, expected complete value`() {
126+
every {
127+
stubDao.insert(any())
128+
} returns Completable.complete()
129+
130+
localDataSource
131+
.save(mockFalAiEndpoint)
132+
.test()
133+
.assertNoErrors()
134+
.await()
135+
.assertComplete()
136+
137+
verify { stubDao.insert(any()) }
138+
}
139+
140+
@Test
141+
fun `given attempt to save endpoint, dao insert fails, expected error value`() {
142+
every {
143+
stubDao.insert(any())
144+
} returns Completable.error(stubException)
145+
146+
localDataSource
147+
.save(mockFalAiEndpoint)
148+
.test()
149+
.assertError(stubException)
150+
.await()
151+
.assertNotComplete()
152+
}
153+
154+
@Test
155+
fun `given attempt to delete endpoint, dao delete success, expected complete value`() {
156+
val id = "fal-ai/flux/schnell"
157+
158+
every {
159+
stubDao.deleteById(id)
160+
} returns Completable.complete()
161+
162+
localDataSource
163+
.delete(id)
164+
.test()
165+
.assertNoErrors()
166+
.await()
167+
.assertComplete()
168+
169+
verify { stubDao.deleteById(id) }
170+
}
171+
172+
@Test
173+
fun `given attempt to delete endpoint, dao delete fails, expected error value`() {
174+
val id = "nonexistent-id"
175+
176+
every {
177+
stubDao.deleteById(id)
178+
} returns Completable.error(stubException)
179+
180+
localDataSource
181+
.delete(id)
182+
.test()
183+
.assertError(stubException)
184+
.await()
185+
.assertNotComplete()
186+
}
187+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package dev.minios.pdaiv1.data.remote
2+
3+
import io.mockk.every
4+
import io.mockk.mockk
5+
import okhttp3.Call
6+
import okhttp3.OkHttpClient
7+
import okhttp3.Protocol
8+
import okhttp3.Request
9+
import okhttp3.Response
10+
import okhttp3.ResponseBody.Companion.toResponseBody
11+
import org.junit.Test
12+
13+
class FalAiEndpointRemoteDataSourceTest {
14+
15+
private val stubHttpClient = mockk<OkHttpClient>()
16+
private val stubCall = mockk<Call>()
17+
18+
private val remoteDataSource = FalAiEndpointRemoteDataSource(stubHttpClient)
19+
20+
@Test
21+
fun `given attempt to fetch from url, http returns error response, expected IllegalStateException`() {
22+
val url = "https://fal.ai/models/test-model/openapi.json"
23+
24+
val errorResponse = Response.Builder()
25+
.request(Request.Builder().url(url).build())
26+
.protocol(Protocol.HTTP_1_1)
27+
.code(404)
28+
.message("Not Found")
29+
.body("Not found".toResponseBody())
30+
.build()
31+
32+
every { stubHttpClient.newCall(any()) } returns stubCall
33+
every { stubCall.execute() } returns errorResponse
34+
35+
remoteDataSource
36+
.fetchFromUrl(url)
37+
.test()
38+
.assertError { error ->
39+
error is IllegalStateException &&
40+
error.message?.contains("Failed to fetch OpenAPI schema: 404") == true
41+
}
42+
.await()
43+
.assertNotComplete()
44+
}
45+
46+
@Test
47+
fun `given attempt to fetch from url, http returns empty body string, expected parse error`() {
48+
val url = "https://fal.ai/models/test-model/openapi.json"
49+
50+
val emptyResponse = Response.Builder()
51+
.request(Request.Builder().url(url).build())
52+
.protocol(Protocol.HTTP_1_1)
53+
.code(200)
54+
.message("OK")
55+
.body("".toResponseBody())
56+
.build()
57+
58+
every { stubHttpClient.newCall(any()) } returns stubCall
59+
every { stubCall.execute() } returns emptyResponse
60+
61+
remoteDataSource
62+
.fetchFromUrl(url)
63+
.test()
64+
.assertError { error -> error is Exception }
65+
.await()
66+
.assertNotComplete()
67+
}
68+
69+
@Test
70+
fun `given attempt to fetch from url, http call throws exception, expected error value`() {
71+
val url = "https://fal.ai/models/test-model/openapi.json"
72+
val stubException = RuntimeException("Network error")
73+
74+
every { stubHttpClient.newCall(any()) } returns stubCall
75+
every { stubCall.execute() } throws stubException
76+
77+
remoteDataSource
78+
.fetchFromUrl(url)
79+
.test()
80+
.assertError(stubException)
81+
.await()
82+
.assertNotComplete()
83+
}
84+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package dev.minios.pdaiv1.data.remote
2+
3+
import dev.minios.pdaiv1.domain.feature.MediaFileManager
4+
import dev.minios.pdaiv1.network.api.falai.FalAiApi
5+
import io.mockk.every
6+
import io.mockk.mockk
7+
import io.reactivex.rxjava3.core.Single
8+
import okhttp3.OkHttpClient
9+
import org.junit.Test
10+
11+
class FalAiGenerationRemoteDataSourceTest {
12+
13+
private val stubException = Throwable("API error")
14+
private val stubApi = mockk<FalAiApi>()
15+
private val stubHttpClient = mockk<OkHttpClient>()
16+
private val stubMediaFileManager = mockk<MediaFileManager>()
17+
18+
private val remoteDataSource = FalAiGenerationRemoteDataSource(
19+
api = stubApi,
20+
httpClient = stubHttpClient,
21+
mediaFileManager = stubMediaFileManager,
22+
)
23+
24+
@Test
25+
fun `given attempt to validate API key, api returns success, expected true value`() {
26+
val mockResponse = mockk<Any>()
27+
28+
every {
29+
stubApi.listModels(limit = 1)
30+
} returns Single.just(mockResponse)
31+
32+
remoteDataSource
33+
.validateApiKey()
34+
.test()
35+
.assertNoErrors()
36+
.assertValue(true)
37+
.await()
38+
.assertComplete()
39+
}
40+
41+
@Test
42+
fun `given attempt to validate API key, api returns error, expected false value`() {
43+
every {
44+
stubApi.listModels(limit = 1)
45+
} returns Single.error(stubException)
46+
47+
remoteDataSource
48+
.validateApiKey()
49+
.test()
50+
.assertNoErrors()
51+
.assertValue(false)
52+
.await()
53+
.assertComplete()
54+
}
55+
}

0 commit comments

Comments
 (0)