Skip to content

Commit 342c694

Browse files
authored
Merge pull request #638 from code-payments/chore/test-coverage
chore: increase test coverage
2 parents 8d15780 + 86feebc commit 342c694

72 files changed

Lines changed: 6910 additions & 2 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/flipcash/core/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ android {
99
dependencies {
1010
testImplementation(kotlin("test"))
1111
testImplementation(libs.bundles.unit.testing)
12+
testImplementation(libs.robolectric)
1213

1314
implementation(libs.androidx.browser)
1415

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
package com.flipcash.app.core.cache
2+
3+
import kotlinx.coroutines.test.runTest
4+
import org.junit.Test
5+
import kotlin.test.assertEquals
6+
import kotlin.test.assertTrue
7+
8+
class CachePolicyHandlerTest {
9+
10+
private val handler = CachePolicyHandler<String, String>()
11+
12+
// region CacheOnly
13+
14+
@Test
15+
fun `CacheOnly with cache hit returns success with Cache origin`() = runTest {
16+
val result = handler.execute(
17+
cachePolicy = CachePolicy.CacheOnly,
18+
cacheLookup = { "cached" },
19+
persistNetworkData = { },
20+
networkRequest = { Result.success("network") },
21+
domainMapper = { it },
22+
)
23+
24+
assertTrue(result.isSuccess)
25+
val entry = result.getOrThrow()
26+
assertEquals("cached", entry.data)
27+
assertEquals(DataOrigin.Cache, entry.origin)
28+
}
29+
30+
@Test
31+
fun `CacheOnly with cache miss returns failure`() = runTest {
32+
val result = handler.execute(
33+
cachePolicy = CachePolicy.CacheOnly,
34+
cacheLookup = { null },
35+
persistNetworkData = { },
36+
networkRequest = { Result.success("network") },
37+
domainMapper = { it },
38+
)
39+
40+
assertTrue(result.isFailure)
41+
}
42+
43+
// endregion
44+
45+
// region CacheFirst
46+
47+
@Test
48+
fun `CacheFirst with cache hit returns success with Cache origin`() = runTest {
49+
val result = handler.execute(
50+
cachePolicy = CachePolicy.CacheFirst,
51+
cacheLookup = { "cached" },
52+
persistNetworkData = { },
53+
networkRequest = { Result.success("network") },
54+
domainMapper = { it },
55+
)
56+
57+
assertTrue(result.isSuccess)
58+
val entry = result.getOrThrow()
59+
assertEquals("cached", entry.data)
60+
assertEquals(DataOrigin.Cache, entry.origin)
61+
}
62+
63+
@Test
64+
fun `CacheFirst with cache miss and network success returns success with Network origin`() = runTest {
65+
val result = handler.execute(
66+
cachePolicy = CachePolicy.CacheFirst,
67+
cacheLookup = { null },
68+
persistNetworkData = { },
69+
networkRequest = { Result.success("network") },
70+
domainMapper = { it },
71+
)
72+
73+
assertTrue(result.isSuccess)
74+
val entry = result.getOrThrow()
75+
assertEquals("network", entry.data)
76+
assertEquals(DataOrigin.Network, entry.origin)
77+
}
78+
79+
@Test
80+
fun `CacheFirst with cache miss and network failure returns failure`() = runTest {
81+
val result = handler.execute(
82+
cachePolicy = CachePolicy.CacheFirst,
83+
cacheLookup = { null },
84+
persistNetworkData = { },
85+
networkRequest = { Result.failure(RuntimeException("network error")) },
86+
domainMapper = { it },
87+
)
88+
89+
assertTrue(result.isFailure)
90+
}
91+
92+
// endregion
93+
94+
// region NetworkFirst
95+
96+
@Test
97+
fun `NetworkFirst with network success returns success with Network origin`() = runTest {
98+
val result = handler.execute(
99+
cachePolicy = CachePolicy.NetworkFirst,
100+
cacheLookup = { "cached" },
101+
persistNetworkData = { },
102+
networkRequest = { Result.success("network") },
103+
domainMapper = { it },
104+
)
105+
106+
assertTrue(result.isSuccess)
107+
val entry = result.getOrThrow()
108+
assertEquals("network", entry.data)
109+
assertEquals(DataOrigin.Network, entry.origin)
110+
}
111+
112+
@Test
113+
fun `NetworkFirst with network failure and cache hit returns success with Cache origin`() = runTest {
114+
val result = handler.execute(
115+
cachePolicy = CachePolicy.NetworkFirst,
116+
cacheLookup = { "cached" },
117+
persistNetworkData = { },
118+
networkRequest = { Result.failure(RuntimeException("network error")) },
119+
domainMapper = { it },
120+
)
121+
122+
assertTrue(result.isSuccess)
123+
val entry = result.getOrThrow()
124+
assertEquals("cached", entry.data)
125+
assertEquals(DataOrigin.Cache, entry.origin)
126+
}
127+
128+
@Test
129+
fun `NetworkFirst with network failure and cache miss returns failure`() = runTest {
130+
val result = handler.execute(
131+
cachePolicy = CachePolicy.NetworkFirst,
132+
cacheLookup = { null },
133+
persistNetworkData = { },
134+
networkRequest = { Result.failure(RuntimeException("network error")) },
135+
domainMapper = { it },
136+
)
137+
138+
assertTrue(result.isFailure)
139+
}
140+
141+
// endregion
142+
143+
// region NetworkOnly
144+
145+
@Test
146+
fun `NetworkOnly with network success returns success with Network origin`() = runTest {
147+
val result = handler.execute(
148+
cachePolicy = CachePolicy.NetworkOnly,
149+
cacheLookup = { "cached" },
150+
persistNetworkData = { },
151+
networkRequest = { Result.success("network") },
152+
domainMapper = { it },
153+
)
154+
155+
assertTrue(result.isSuccess)
156+
val entry = result.getOrThrow()
157+
assertEquals("network", entry.data)
158+
assertEquals(DataOrigin.Network, entry.origin)
159+
}
160+
161+
@Test
162+
fun `NetworkOnly with network failure returns failure`() = runTest {
163+
val result = handler.execute(
164+
cachePolicy = CachePolicy.NetworkOnly,
165+
cacheLookup = { "cached" },
166+
persistNetworkData = { },
167+
networkRequest = { Result.failure(RuntimeException("network error")) },
168+
domainMapper = { it },
169+
)
170+
171+
assertTrue(result.isFailure)
172+
}
173+
174+
// endregion
175+
176+
// region persistNetworkData
177+
178+
@Test
179+
fun `persistNetworkData is called when network succeeds for NetworkOnly`() = runTest {
180+
var persisted: String? = null
181+
182+
handler.execute(
183+
cachePolicy = CachePolicy.NetworkOnly,
184+
cacheLookup = { null },
185+
persistNetworkData = { persisted = it },
186+
networkRequest = { Result.success("network-data") },
187+
domainMapper = { it },
188+
)
189+
190+
assertEquals("network-data", persisted)
191+
}
192+
193+
@Test
194+
fun `persistNetworkData is called when network succeeds for NetworkFirst`() = runTest {
195+
var persisted: String? = null
196+
197+
handler.execute(
198+
cachePolicy = CachePolicy.NetworkFirst,
199+
cacheLookup = { null },
200+
persistNetworkData = { persisted = it },
201+
networkRequest = { Result.success("network-data") },
202+
domainMapper = { it },
203+
)
204+
205+
assertEquals("network-data", persisted)
206+
}
207+
208+
@Test
209+
fun `persistNetworkData is called when CacheFirst falls back to network`() = runTest {
210+
var persisted: String? = null
211+
212+
handler.execute(
213+
cachePolicy = CachePolicy.CacheFirst,
214+
cacheLookup = { null },
215+
persistNetworkData = { persisted = it },
216+
networkRequest = { Result.success("network-data") },
217+
domainMapper = { it },
218+
)
219+
220+
assertEquals("network-data", persisted)
221+
}
222+
223+
// endregion
224+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package com.flipcash.app.core.data
2+
3+
import org.junit.Test
4+
import kotlin.test.assertEquals
5+
import kotlin.test.assertFalse
6+
import kotlin.test.assertNull
7+
import kotlin.test.assertTrue
8+
9+
class LoadableTest {
10+
11+
@Test
12+
fun `Loading state reports isLoading true`() {
13+
val state: Loadable<String> = Loadable.Loading()
14+
15+
assertTrue(state.isLoading())
16+
assertFalse(state.isLoaded())
17+
assertFalse(state.isError())
18+
}
19+
20+
@Test
21+
fun `Loaded state reports isLoaded true`() {
22+
val state: Loadable<String> = Loadable.Loaded("data")
23+
24+
assertTrue(state.isLoaded())
25+
assertFalse(state.isLoading())
26+
assertFalse(state.isError())
27+
}
28+
29+
@Test
30+
fun `Error state reports isError true`() {
31+
val state: Loadable<String> = Loadable.Error("something went wrong")
32+
33+
assertTrue(state.isError())
34+
assertFalse(state.isLoading())
35+
assertFalse(state.isLoaded())
36+
}
37+
38+
@Test
39+
fun `dataOrNull returns data for Loading with data`() {
40+
val state: Loadable<String> = Loadable.Loading(data = "partial")
41+
42+
assertEquals("partial", state.dataOrNull)
43+
}
44+
45+
@Test
46+
fun `dataOrNull returns null for Loading without data`() {
47+
val state: Loadable<String> = Loadable.Loading()
48+
49+
assertNull(state.dataOrNull)
50+
}
51+
52+
@Test
53+
fun `dataOrNull returns data for Loaded`() {
54+
val state: Loadable<String> = Loadable.Loaded("complete")
55+
56+
assertEquals("complete", state.dataOrNull)
57+
}
58+
59+
@Test
60+
fun `dataOrNull returns null for Error`() {
61+
val state: Loadable<String> = Loadable.Error("fail")
62+
63+
assertNull(state.dataOrNull)
64+
}
65+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.flipcash.app.core.extensions
2+
3+
import org.junit.Test
4+
import kotlin.test.assertEquals
5+
6+
class ListExtensionsTest {
7+
8+
@Test
9+
fun `filterIsNotInstance removes instances of specified type`() {
10+
val list: List<Any> = listOf("hello", 1, "world", 2, 3)
11+
12+
val result = list.filterIsNotInstance<String, Any>()
13+
14+
assertEquals(listOf(1, 2, 3), result)
15+
}
16+
17+
@Test
18+
fun `filterIsNotInstance keeps non-matching types`() {
19+
val list: List<Any> = listOf(1, 2, 3)
20+
21+
val result = list.filterIsNotInstance<String, Any>()
22+
23+
assertEquals(listOf(1, 2, 3), result)
24+
}
25+
26+
@Test
27+
fun `filterIsNotInstance on empty list returns empty`() {
28+
val list = emptyList<Any>()
29+
30+
val result = list.filterIsNotInstance<String, Any>()
31+
32+
assertEquals(emptyList(), result)
33+
}
34+
}

0 commit comments

Comments
 (0)