NavigationFlowTest.kt

5.6 KB · raw

1package com.peachpasswords.ui23import com.peachpasswords.ui.lock.postUnlockDestination4import com.peachpasswords.ui.onboarding.onboardingStartDestination5import com.peachpasswords.ui.vault.entryTapDestination6import com.peachpasswords.vault.VaultEntry7import org.junit.Assert.assertEquals8import org.junit.Test910/**11 * Navigation suite (brief Suite 9): route construction and the flow-decision12 * functions that route the app — onboarding gate, list-tap, and post-unlock.13 */14class NavigationFlowTest {1516    private fun login(id: String) = VaultEntry(id = id, title = id, type = "login", createdAt = 0, modifiedAt = 0)17    private fun note(id: String) = VaultEntry(id = id, title = id, type = "note", createdAt = 0, modifiedAt = 0)1819    // ── Route construction ────────────────────────────────────────────────────2021    @Test fun entry_detail_route_embeds_id() {22        assertEquals("entry/abc", PeachNav.EntryDetail("abc").route)23        assertEquals("entry/abc", PeachNav.EntryDetail.of("abc"))24        assertEquals("entry/{id}", PeachNav.EntryDetail.ROUTE)25    }2627    @Test fun notes_mode_route_embeds_id() {28        assertEquals("notes/n1", PeachNav.NotesMode("n1").route)29        assertEquals("notes/n1", PeachNav.NotesMode.of("n1"))30        assertEquals("notes/{id}", PeachNav.NotesMode.ROUTE)31    }3233    @Test fun entry_edit_route_handles_null_and_value() {34        assertEquals("edit?id=&prefillUrl=&prefillUsername=&prefillEmail=", PeachNav.EntryEdit(null).route)35        assertEquals("edit?id=x&prefillUrl=&prefillUsername=&prefillEmail=", PeachNav.EntryEdit("x").route)36        assertEquals("edit?id=&prefillUrl=&prefillUsername=&prefillEmail=", PeachNav.EntryEdit.of(null))37        assertEquals("edit?id=x&prefillUrl=&prefillUsername=&prefillEmail=", PeachNav.EntryEdit.of("x"))38    }3940    @Test fun entry_edit_route_carries_prefill_payload() {41        val route = PeachNav.EntryEdit.of(42            id = null,43            prefillUrl = "github.com",44            prefillUsername = "june",45            prefillEmail = "[email protected]",46        )47        assertEquals(48            "edit?id=&prefillUrl=github.com&prefillUsername=june&[email protected]",49            route,50        )51    }5253    @Test fun static_routes_are_stable() {54        assertEquals("onboarding", PeachNav.Onboarding.route)55        assertEquals("lock", PeachNav.Lock.route)56        assertEquals("vault", PeachNav.VaultList.route)57        assertEquals("settings", PeachNav.Settings.route)58    }5960    @Test fun locked_navigation_allows_only_pre_vault_surfaces() {61        listOf(62            PeachNav.Onboarding.route,63            PeachNav.Lock.route,64            PeachNav.AdoptVault.route,65            PeachNav.Import.route,66            PeachNav.CodexRestore.route,67            PeachNav.RecoveryEntry.route,68            PeachNav.Update.route,69        ).forEach { route ->70            assertEquals("$route should stay available while locked", false, requiresUnlockedVault(route))71        }7273        listOf(74            PeachNav.Settings.route,75            PeachNav.VaultList.route,76            PeachNav.EntryDetail.ROUTE,77            PeachNav.Export.route,78        ).forEach { route ->79            assertEquals("$route should redirect to Lock", true, requiresUnlockedVault(route))80        }81    }8283    // ── First-launch gate ─────────────────────────────────────────────────────8485    @Test fun first_launch_shows_onboarding() {86        assertEquals(PeachNav.Onboarding, onboardingStartDestination(hasVault = false, onboarded = false))87    }8889    @Test fun subsequent_launch_skips_onboarding() {90        assertEquals(PeachNav.Lock, onboardingStartDestination(hasVault = true, onboarded = true))91    }9293    // ── List tap ──────────────────────────────────────────────────────────────9495    @Test fun list_tap_login_opens_detail() {96        assertEquals(PeachNav.EntryDetail("l"), entryTapDestination(login("l")))97    }9899    @Test fun list_tap_note_opens_notes_mode() {100        assertEquals(PeachNav.NotesMode("n"), entryTapDestination(note("n")))101    }102103    // ── Post-unlock landing ───────────────────────────────────────────────────104105    @Test fun post_unlock_opens_last_viewed() {106        val entries = mapOf("a" to login("a"), "b" to login("b"))107        assertEquals(PeachNav.EntryDetail("b"), postUnlockDestination("b", entries::get, entries["a"]))108    }109110    @Test fun post_unlock_empty_vault_falls_to_list() {111        assertEquals(PeachNav.VaultList, postUnlockDestination(null, { null }, null))112    }113114    @Test fun vault_from_entry_uses_sheet_transition() {115        assertEquals(true, isVaultSheetTransition("entry/a", PeachNav.VaultList.route))116        assertEquals(true, isVaultSheetTransition("notes/n", PeachNav.VaultList.route))117        assertEquals(false, isVaultSheetTransition(PeachNav.Lock.route, PeachNav.VaultList.route))118    }119120    @Test fun vault_to_entry_uses_reverse_sheet_transition() {121        assertEquals(true, isVaultSheetTransition(PeachNav.VaultList.route, "entry/a", reverse = true))122        assertEquals(true, isVaultSheetTransition(PeachNav.VaultList.route, "notes/n", reverse = true))123        assertEquals(false, isVaultSheetTransition(PeachNav.VaultList.route, PeachNav.Settings.route, reverse = true))124    }125}