commit b38ccc3e956fe6303d661e44fb89211214fcf1cc
parent 81bd94667797153b7be8159d2144c2a1bcd61535
Author: triesap <tyson@radroots.org>
Date: Sat, 1 Aug 2026 18:29:15 +0000
test: prove the complete account action trace
- exercise every account workflow in one deterministic sequence
- validate state invariants after every transition
- cover idempotent status and typed failure recovery
- verify deterministic selection after confirmed removal
Diffstat:
1 file changed, 32 insertions(+), 0 deletions(-)
diff --git a/app/desktop/src/test/kotlin/org/radroots/studio/accounts/state/AccountsReducerTest.kt b/app/desktop/src/test/kotlin/org/radroots/studio/accounts/state/AccountsReducerTest.kt
@@ -9,6 +9,7 @@ import org.radroots.studio.accounts.model.AccountsAction
import org.radroots.studio.accounts.model.AccountsProblem
import org.radroots.studio.accounts.model.AccountsState
import org.radroots.studio.accounts.model.LoginStatus
+import org.radroots.studio.accounts.model.requireValid
import org.radroots.studio.accounts.testAccount
import org.radroots.studio.accounts.testAccountsState
@@ -280,6 +281,37 @@ class AccountsReducerTest {
assertEquals(null, finalAccount.pendingRemovalAccountId)
}
+ @Test
+ fun completeActionTracePreservesEveryStateInvariant() {
+ val reducer = reducerWithIds("account-1", "account-2")
+ val actions = listOf(
+ AccountsAction.EditAddDisplayName("First Account"),
+ AccountsAction.EditAddServerUrl("https://first.example.test"),
+ AccountsAction.SubmitAddAccount,
+ AccountsAction.EditAddDisplayName("Second Account"),
+ AccountsAction.EditAddServerUrl("https://second.example.test"),
+ AccountsAction.SubmitAddAccount,
+ AccountsAction.SelectAccount(AccountId("account-1")),
+ AccountsAction.LogIn(AccountId("account-1")),
+ AccountsAction.LogIn(AccountId("account-1")),
+ AccountsAction.LogOut(AccountId("account-1")),
+ AccountsAction.RequestRemoveAccount(AccountId("account-2")),
+ AccountsAction.CancelRemoveAccount,
+ AccountsAction.RequestRemoveAccount(AccountId("account-1")),
+ AccountsAction.ConfirmRemoveAccount(AccountId("account-1")),
+ AccountsAction.SelectAccount(AccountId("missing")),
+ AccountsAction.DismissProblem,
+ )
+
+ val result = actions.fold(AccountsState()) { state, action ->
+ reducer.reduce(state, action).requireValid()
+ }
+
+ assertEquals(listOf(AccountId("account-2")), result.accounts.map { it.id })
+ assertEquals(AccountId("account-2"), result.selectedAccountId)
+ assertEquals(null, result.problem)
+ }
+
private fun draftState(
displayName: String,
serverUrl: String,