Skip to content

Commit eba7b82

Browse files
committed
test: add dependency regression tests across 6 modules (60 tests)
Add targeted tests to catch regressions from major dependency updates (Kotlin 2.3.20, coroutines 1.10.2, Room/AndroidX, Hilt 2.58, etc.): - payments: StateFlow.update, SharedFlow.emit, sealed class dispatch (6) - authentication: structured concurrency, Result.fold, multi-dep orchestration (9) - persistence/db: Room KSP codegen, DAO queries, Flow emission (9) - core: BillState sealed interface, Duration API, BillController StateFlow (12) - workers: kotlinx-serialization, WorkerParameters validation (8) - cash: ViewModel state reducer, computed properties, Flow operators (16)
1 parent 61b3c50 commit eba7b82

12 files changed

Lines changed: 1497 additions & 0 deletions

File tree

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
package com.flipcash.app.core.bill
2+
3+
import com.getcode.opencode.model.financial.Fiat
4+
import com.getcode.opencode.model.financial.LocalFiat
5+
import com.getcode.opencode.model.financial.Rate
6+
import com.getcode.opencode.model.financial.MintMetadata
7+
import com.getcode.opencode.model.financial.Token
8+
import com.getcode.opencode.model.financial.HolderMetrics
9+
import com.getcode.opencode.model.financial.VmMetadata
10+
import com.getcode.solana.keys.Mint
11+
import com.getcode.solana.keys.PublicKey
12+
import kotlin.test.Test
13+
import kotlin.test.assertEquals
14+
import kotlin.test.assertFalse
15+
import kotlin.test.assertNull
16+
import kotlin.test.assertTrue
17+
import kotlin.time.Duration
18+
import kotlin.time.Duration.Companion.seconds
19+
20+
class BillStateTest {
21+
22+
private fun testToken(): Token = MintMetadata(
23+
address = Mint.usdf,
24+
decimals = 6,
25+
name = "Test",
26+
symbol = "TST",
27+
createdAt = null,
28+
description = "",
29+
imageUrl = "",
30+
vmMetadata = VmMetadata(
31+
vm = PublicKey.fromBase58("11111111111111111111111111111111"),
32+
authority = PublicKey.fromBase58("11111111111111111111111111111111"),
33+
lockDurationInDays = 21
34+
),
35+
launchpadMetadata = null,
36+
billCustomizations = null,
37+
socialLinks = emptyList(),
38+
holderMetrics = HolderMetrics.None,
39+
)
40+
41+
private fun testLocalFiat(): LocalFiat = LocalFiat(
42+
underlyingTokenAmount = Fiat(5.0),
43+
nativeAmount = Fiat(5.0),
44+
rate = Rate.oneToOne,
45+
mint = Mint.usdf,
46+
)
47+
48+
// region Default state
49+
50+
@Test
51+
fun `Default BillState has null bill and no toast`() {
52+
val state = BillState.Default
53+
54+
assertNull(state.bill)
55+
assertFalse(state.showToast)
56+
assertNull(state.toast)
57+
assertNull(state.valuation)
58+
assertNull(state.primaryAction)
59+
assertNull(state.secondaryAction)
60+
}
61+
62+
// endregion
63+
64+
// region canSwipeToDismiss
65+
66+
@Test
67+
fun `canSwipeToDismiss returns true when bill allows gestures`() {
68+
val bill = Bill.Cash(
69+
token = testToken(),
70+
amount = testLocalFiat(),
71+
disableGestures = false,
72+
)
73+
val state = BillState.Default.copy(bill = bill)
74+
75+
assertTrue(state.canSwipeToDismiss)
76+
}
77+
78+
@Test
79+
fun `canSwipeToDismiss returns false when bill disableGestures is true`() {
80+
val bill = Bill.Cash(
81+
token = testToken(),
82+
amount = testLocalFiat(),
83+
disableGestures = true,
84+
)
85+
val state = BillState.Default.copy(bill = bill)
86+
87+
assertFalse(state.canSwipeToDismiss)
88+
}
89+
90+
@Test
91+
fun `canSwipeToDismiss returns false when bill is null`() {
92+
val state = BillState.Default
93+
94+
assertFalse(state.canSwipeToDismiss)
95+
}
96+
97+
// endregion
98+
99+
// region confirmationDelayMillis
100+
101+
@Test
102+
fun `confirmationDelayMillis converts Duration correctly`() {
103+
val bill = Bill.Cash(
104+
token = testToken(),
105+
amount = testLocalFiat(),
106+
confirmationDelay = 3.seconds,
107+
)
108+
val state = BillState.Default.copy(bill = bill)
109+
110+
assertEquals(3000, state.confirmationDelayMillis)
111+
}
112+
113+
@Test
114+
fun `confirmationDelayMillis returns 0 for null bill`() {
115+
val state = BillState.Default
116+
117+
assertEquals(0, state.confirmationDelayMillis)
118+
}
119+
120+
// endregion
121+
122+
// region Bill.Cash metadata and canFlip
123+
124+
@Test
125+
fun `Bill Cash metadata extracts token and amount`() {
126+
val token = testToken()
127+
val amount = testLocalFiat()
128+
val data = listOf<Byte>(1, 2, 3)
129+
130+
val bill = Bill.Cash(
131+
token = token,
132+
amount = amount,
133+
data = data,
134+
)
135+
136+
val metadata = bill.metadata
137+
assertEquals(token, metadata.token)
138+
assertEquals(amount, metadata.amount)
139+
assertEquals(data, metadata.data)
140+
assertNull(metadata.request)
141+
}
142+
143+
@Test
144+
fun `Bill Cash canFlip is always false`() {
145+
val bill = Bill.Cash(
146+
token = testToken(),
147+
amount = testLocalFiat(),
148+
)
149+
150+
assertFalse(bill.canFlip)
151+
}
152+
153+
// endregion
154+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package com.flipcash.app.core.internal.bill
2+
3+
import com.flipcash.app.core.bill.BillState
4+
import com.flipcash.app.core.bill.BillToast
5+
import com.flipcash.app.userflags.UserFlagsCoordinator
6+
import com.getcode.opencode.managers.BillTransactionManager
7+
import com.getcode.opencode.model.financial.Fiat
8+
import io.mockk.mockk
9+
import io.mockk.verify
10+
import kotlin.test.Test
11+
import kotlin.test.assertEquals
12+
import kotlin.test.assertFalse
13+
import kotlin.test.assertNull
14+
import kotlin.test.assertTrue
15+
16+
class BillControllerTest {
17+
18+
private val transactionManager: BillTransactionManager = mockk(relaxed = true)
19+
private val userFlags: UserFlagsCoordinator = mockk(relaxed = true)
20+
21+
private val controller = BillController(
22+
transactionManager = transactionManager,
23+
userFlags = userFlags,
24+
)
25+
26+
// region initial state
27+
28+
@Test
29+
fun `initial state is Default`() {
30+
val state = controller.state.value
31+
32+
assertNull(state.bill)
33+
assertFalse(state.showToast)
34+
assertNull(state.toast)
35+
assertNull(state.valuation)
36+
assertNull(state.primaryAction)
37+
assertNull(state.secondaryAction)
38+
}
39+
40+
// endregion
41+
42+
// region update
43+
44+
@Test
45+
fun `update modifies state via function`() {
46+
val toast = BillToast(amount = Fiat(1.0), isDeposit = true)
47+
48+
controller.update { it.copy(showToast = true, toast = toast) }
49+
50+
val state = controller.state.value
51+
assertTrue(state.showToast)
52+
assertEquals(toast, state.toast)
53+
}
54+
55+
// endregion
56+
57+
// region reset
58+
59+
@Test
60+
fun `reset sets state to Default preserving toast`() {
61+
val toast = BillToast(amount = Fiat(2.0), isDeposit = false)
62+
controller.update { it.copy(showToast = true, toast = toast) }
63+
64+
controller.reset()
65+
66+
val state = controller.state.value
67+
assertNull(state.bill)
68+
assertFalse(state.showToast)
69+
assertEquals(toast, state.toast)
70+
assertNull(state.valuation)
71+
}
72+
73+
@Test
74+
fun `reset calls transactionManager reset`() {
75+
controller.reset()
76+
77+
verify(exactly = 1) { transactionManager.reset() }
78+
}
79+
80+
// endregion
81+
}

apps/flipcash/features/cash/build.gradle.kts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ android {
77
}
88

99
dependencies {
10+
testImplementation(kotlin("test"))
11+
testImplementation(libs.bundles.unit.testing)
12+
testImplementation(libs.mockito.kotlin)
13+
testImplementation(libs.robolectric)
14+
testImplementation(project(":libs:test-utils"))
15+
1016
implementation(libs.kotlin.stdlib)
1117
implementation(project(":apps:flipcash:shared:analytics"))
1218
implementation(project(":apps:flipcash:shared:onramp:common"))

0 commit comments

Comments
 (0)