Make group navigation controller-driven

This commit is contained in:
Joe Julian
2026-03-29 11:21:38 -07:00
parent ea5c8b3c31
commit 24dcf9c8ad
6 changed files with 191 additions and 60 deletions
+121 -24
View File
@@ -31,7 +31,7 @@ func TestUIFiltersUsingVaultModelPathsAndSearch(t *testing.T) {
},
})
u.currentPath = []string{"Joe", "Internet"}
u.state.NavigateToPath([]string{"Joe", "Internet"})
u.filter()
if got := u.filteredTitles(); !slices.Equal(got, []string{"Dynadot", "Git Server"}) {
t.Fatalf("filteredTitles() = %v, want [Dynadot Git Server]", got)
@@ -137,7 +137,7 @@ func TestUIChildGroupsComeFromVaultModel(t *testing.T) {
},
})
u.currentPath = []string{"Joe"}
u.state.NavigateToPath([]string{"Joe"})
if got := u.childGroups(); !slices.Equal(got, []string{"Home Assistant", "Internet"}) {
t.Fatalf("childGroups() = %v, want [Home Assistant Internet]", got)
}
@@ -153,7 +153,7 @@ func TestUISelectedEntryFollowsApplicationStateSelection(t *testing.T) {
},
})
u.currentPath = []string{"Joe", "Internet"}
u.state.NavigateToPath([]string{"Joe", "Internet"})
u.filter()
u.state.SelectedEntryID = "2"
@@ -215,7 +215,7 @@ func TestUILifecycleActionsCreateSaveOpenLockAndUnlockLocalVault(t *testing.T) {
if err := u.lockAction(); err != nil {
t.Fatalf("lockAction() error = %v", err)
}
u.currentPath = []string{"Root", "Internet"}
u.state.NavigateToPath([]string{"Root", "Internet"})
u.filter()
if got := u.filteredTitles(); len(got) != 0 {
t.Fatalf("filteredTitles() = %v, want empty while locked", got)
@@ -235,7 +235,7 @@ func TestUILifecycleActionsCreateSaveOpenLockAndUnlockLocalVault(t *testing.T) {
if err := reopened.openVaultAction(); err != nil {
t.Fatalf("openVaultAction() error = %v", err)
}
reopened.currentPath = []string{"Root", "Internet"}
reopened.state.NavigateToPath([]string{"Root", "Internet"})
reopened.filter()
if got := reopened.filteredTitles(); !slices.Equal(got, []string{"Git Server"}) {
t.Fatalf("reopened filteredTitles() = %v, want [Git Server]", got)
@@ -322,7 +322,7 @@ func TestUIMasterKeyModesCreateOpenAndUnlockLocalVault(t *testing.T) {
if err := reopened.openVaultAction(); err != nil {
t.Fatalf("openVaultAction() error = %v", err)
}
reopened.currentPath = []string{"Root", "Internet"}
reopened.state.NavigateToPath([]string{"Root", "Internet"})
reopened.filter()
if got := reopened.filteredTitles(); !slices.Equal(got, []string{"Git Server"}) {
t.Fatalf("reopened filteredTitles() = %v, want [Git Server]", got)
@@ -395,7 +395,7 @@ func TestUIChangeMasterKeyModeForExistingVault(t *testing.T) {
if err := reopened.openVaultAction(); err != nil {
t.Fatalf("openVaultAction() with updated key error = %v", err)
}
reopened.currentPath = []string{"Root", "Internet"}
reopened.state.NavigateToPath([]string{"Root", "Internet"})
reopened.filter()
if got := reopened.filteredTitles(); !slices.Equal(got, []string{"Git Server"}) {
t.Fatalf("reopened filteredTitles() = %v, want [Git Server]", got)
@@ -706,13 +706,110 @@ func TestUISectionNavigationShowsTemplatesAndRecycleBin(t *testing.T) {
}
u.showEntriesSection()
u.currentPath = []string{"Root", "Internet"}
u.state.NavigateToPath([]string{"Root", "Internet"})
u.filter()
if got := u.filteredTitles(); !slices.Equal(got, []string{"Git Server"}) {
t.Fatalf("entry filteredTitles() = %v, want [Git Server]", got)
}
}
func TestUIGroupManagementAndPathNavigationAreControllerDriven(t *testing.T) {
t.Parallel()
u := newUIWithModel("desktop", vault.Model{
Entries: []vault.Entry{
{ID: "entry-1", Title: "Git Server", Path: []string{"Root", "Internet"}},
{ID: "entry-2", Title: "Home Assistant", Path: []string{"Root", "Home Assistant"}},
},
})
u.showEntriesSection()
u.state.NavigateToPath([]string{"Root"})
u.filter()
u.groupName.SetText("Finance")
if err := u.createGroupAction(); err != nil {
t.Fatalf("createGroupAction() error = %v", err)
}
if got := u.childGroups(); !slices.Equal(got, []string{"Finance", "Home Assistant", "Internet"}) {
t.Fatalf("childGroups() after create = %v, want [Finance Home Assistant Internet]", got)
}
u.state.EnterGroup("Finance")
u.filter()
u.groupName.SetText("Budget")
if err := u.renameGroupAction(); err != nil {
t.Fatalf("renameGroupAction() error = %v", err)
}
if !slices.Equal(u.state.CurrentPath, []string{"Root", "Budget"}) {
t.Fatalf("state.CurrentPath after rename = %v, want [Root Budget]", u.state.CurrentPath)
}
u.state.NavigateToPath([]string{"Root"})
u.filter()
if got := u.childGroups(); !slices.Equal(got, []string{"Budget", "Home Assistant", "Internet"}) {
t.Fatalf("childGroups() after rename = %v, want [Budget Home Assistant Internet]", got)
}
u.state.NavigateToPath([]string{"Root", "Budget"})
u.filter()
if err := u.deleteCurrentGroupAction(); err != nil {
t.Fatalf("deleteCurrentGroupAction() error = %v", err)
}
if !slices.Equal(u.state.CurrentPath, []string{"Root"}) {
t.Fatalf("state.CurrentPath after delete = %v, want [Root]", u.state.CurrentPath)
}
if got := u.childGroups(); !slices.Equal(got, []string{"Home Assistant", "Internet"}) {
t.Fatalf("childGroups() after delete = %v, want [Home Assistant Internet]", got)
}
}
func TestUISavingEntryWithDifferentPathMovesItBetweenGroups(t *testing.T) {
t.Parallel()
u := newUIWithModel("desktop", vault.Model{
Entries: []vault.Entry{
{
ID: "git-server",
Title: "Git Server",
Username: "joejulian",
Password: "token-1",
URL: "https://git.julianfamily.org",
Path: []string{"Root", "Internet"},
},
{
ID: "ha",
Title: "Home Assistant",
Username: "jjulian",
Password: "token-2",
URL: "https://ha.example.test",
Path: []string{"Root", "Home Assistant"},
},
},
})
u.showEntriesSection()
u.state.NavigateToPath([]string{"Root", "Internet"})
u.filter()
u.state.SelectedEntryID = "git-server"
u.loadSelectedEntryIntoEditor()
u.entryPath.SetText("Root / Home Assistant")
if err := u.saveEntryAction(); err != nil {
t.Fatalf("saveEntryAction() error = %v", err)
}
u.state.NavigateToPath([]string{"Root", "Internet"})
u.filter()
if got := u.filteredTitles(); len(got) != 0 {
t.Fatalf("filteredTitles() in source group = %v, want empty after move", got)
}
u.state.NavigateToPath([]string{"Root", "Home Assistant"})
u.filter()
if got := u.filteredTitles(); !slices.Equal(got, []string{"Git Server", "Home Assistant"}) {
t.Fatalf("filteredTitles() in destination group = %v, want [Git Server Home Assistant]", got)
}
}
func TestUISavesDuplicatesDeletesAndRestoresEntriesFromTheEditor(t *testing.T) {
t.Parallel()
@@ -729,7 +826,7 @@ func TestUISavesDuplicatesDeletesAndRestoresEntriesFromTheEditor(t *testing.T) {
},
})
u.showEntriesSection()
u.currentPath = []string{"Root", "Internet"}
u.state.NavigateToPath([]string{"Root", "Internet"})
u.filter()
u.state.SelectedEntryID = "git-server"
u.loadSelectedEntryIntoEditor()
@@ -764,7 +861,7 @@ func TestUISavesDuplicatesDeletesAndRestoresEntriesFromTheEditor(t *testing.T) {
t.Fatalf("restoreSelectedRecycleEntryAction() error = %v", err)
}
u.showEntriesSection()
u.currentPath = []string{"Root", "Internet"}
u.state.NavigateToPath([]string{"Root", "Internet"})
u.filter()
if got := u.filteredTitles(); !slices.Equal(got, []string{"Git Server", "Git Server (Copy)"}) {
t.Fatalf("filteredTitles() after restore = %v, want restored copy", got)
@@ -900,7 +997,7 @@ func TestUITemplateAndAttachmentActionsWorkThroughEditor(t *testing.T) {
}
u.showEntriesSection()
u.currentPath = []string{"Root", "Internet"}
u.state.NavigateToPath([]string{"Root", "Internet"})
u.filter()
u.state.SelectedEntryID = "entry-1"
u.loadSelectedEntryIntoEditor()
@@ -973,7 +1070,7 @@ func TestUIRestoresSelectedEntryHistoryVersion(t *testing.T) {
},
})
u.showEntriesSection()
u.currentPath = []string{"Root", "Internet"}
u.state.NavigateToPath([]string{"Root", "Internet"})
u.filter()
u.state.SelectedEntryID = "git-server"
u.loadSelectedEntryIntoEditor()
@@ -1038,7 +1135,7 @@ func TestUISelectingEntryHistoryVersionTracksSelectedVersion(t *testing.T) {
},
})
u.showEntriesSection()
u.currentPath = []string{"Root", "Internet"}
u.state.NavigateToPath([]string{"Root", "Internet"})
u.filter()
u.state.SelectedEntryID = "git-server"
u.loadSelectedEntryIntoEditor()
@@ -1080,7 +1177,7 @@ func TestUIKeyboardShortcutActionsDispatchExpectedCommands(t *testing.T) {
},
})
u.showEntriesSection()
u.currentPath = []string{"Root", "Internet"}
u.state.NavigateToPath([]string{"Root", "Internet"})
u.filter()
u.state.SelectedEntryID = "git-server"
u.loadSelectedEntryIntoEditor()
@@ -1124,7 +1221,7 @@ func TestUIKeyboardNavigationMovesAcrossBreadcrumbsListAndDetail(t *testing.T) {
},
})
u.showEntriesSection()
u.currentPath = []string{"Root", "Internet"}
u.state.NavigateToPath([]string{"Root", "Internet"})
u.filter()
if got := u.keyboardFocus; got != focusSearch {
@@ -1171,7 +1268,7 @@ func TestUIKeyboardNavigationActivatesBreadcrumbs(t *testing.T) {
},
})
u.showEntriesSection()
u.currentPath = []string{"Root", "Internet"}
u.state.NavigateToPath([]string{"Root", "Internet"})
u.filter()
u.keyboardFocus = breadcrumbFocusID(0)
@@ -1181,8 +1278,8 @@ func TestUIKeyboardNavigationActivatesBreadcrumbs(t *testing.T) {
}
u.handleKeyPress(key.NameReturn, 0)
if got := u.currentPath; !slices.Equal(got, []string{"Root"}) {
t.Fatalf("currentPath after breadcrumb activation = %v, want [Root]", got)
if got := u.state.CurrentPath; !slices.Equal(got, []string{"Root"}) {
t.Fatalf("state.CurrentPath after breadcrumb activation = %v, want [Root]", got)
}
}
@@ -1202,7 +1299,7 @@ func TestUIKeyboardShortcutsMoveFocusForSearchAndNewEntry(t *testing.T) {
},
})
u.showEntriesSection()
u.currentPath = []string{"Root", "Internet"}
u.state.NavigateToPath([]string{"Root", "Internet"})
u.filter()
u.state.SelectedEntryID = "git-server"
u.loadSelectedEntryIntoEditor()
@@ -1235,7 +1332,7 @@ func TestUIAccessibilityLabelsDescribeFocusableControls(t *testing.T) {
},
})
u.showEntriesSection()
u.currentPath = []string{"Root", "Internet"}
u.state.NavigateToPath([]string{"Root", "Internet"})
u.filter()
if got := u.accessibilityLabel(focusSearch); got != "Search vault" {
@@ -1294,7 +1391,7 @@ func TestUIActionErrorsAndStatusMessagesAreCapturedForDisplay(t *testing.T) {
},
})
u.showEntriesSection()
u.currentPath = []string{"Root", "Internet"}
u.state.NavigateToPath([]string{"Root", "Internet"})
u.filter()
u.state.SelectedEntryID = "git-server"
u.runAction("copy username", func() error { return u.copySelectedFieldAction(clipboard.TargetUsername) })
@@ -1444,7 +1541,7 @@ func TestUICopyActionsWriteExpectedClipboardContentsAndSanitizedFeedback(t *test
writer := &memoryClipboardWriter{}
u.clipboardWriter = writer
u.showEntriesSection()
u.currentPath = []string{"Root", "Internet"}
u.state.NavigateToPath([]string{"Root", "Internet"})
u.filter()
u.state.SelectedEntryID = "git-server"
@@ -1483,7 +1580,7 @@ func TestUICopyActionSanitizesClipboardBackendErrors(t *testing.T) {
})
u.clipboardWriter = failingClipboardWriter{err: os.ErrPermission}
u.showEntriesSection()
u.currentPath = []string{"Root", "Internet"}
u.state.NavigateToPath([]string{"Root", "Internet"})
u.filter()
u.state.SelectedEntryID = "git-server"
@@ -1515,7 +1612,7 @@ func TestUIPasswordRevealTogglesDisplayedPasswordAndLockResetsIt(t *testing.T) {
},
})
u.showEntriesSection()
u.currentPath = []string{"Root", "Internet"}
u.state.NavigateToPath([]string{"Root", "Internet"})
u.filter()
u.state.SelectedEntryID = "git-server"