Restore entries tab state and preload recent vault

This commit is contained in:
Joe Julian
2026-03-30 14:31:06 -07:00
parent 88151dc780
commit 27fdd77aa1
2 changed files with 207 additions and 9 deletions
+106
View File
@@ -2227,6 +2227,45 @@ func TestUIShowEntriesSectionRestoresHiddenRootAfterLeavingEntries(t *testing.T)
}
}
func TestUIShowEntriesSectionRestoresEntriesViewState(t *testing.T) {
t.Parallel()
u := newUIWithModel("desktop", vault.Model{
Entries: []vault.Entry{
{ID: "amazon", Title: "Amazon", Username: "danny@crew.example.invalid", Path: []string{"keepass", "Crew", "Internet"}},
{ID: "aws", Title: "Amazon AWS", Username: "danny@crew.example.invalid", Path: []string{"keepass", "Crew", "Internet"}},
{ID: "git", Title: "Vault Console", Username: "dannyocean", Path: []string{"keepass", "Crew", "Internet"}},
},
})
u.showEntriesSection()
u.setCurrentPath([]string{"keepass", "Crew", "Internet"})
u.search.SetText("amazon")
u.filter()
u.state.SelectedEntryID = "amazon"
u.editingEntry = true
u.loadSelectedEntryIntoEditor()
u.showAPITokensSection()
u.showEntriesSection()
if got := u.currentPath; !slices.Equal(got, []string{"keepass", "Crew", "Internet"}) {
t.Fatalf("currentPath after returning to entries = %v, want [keepass Crew Internet]", got)
}
if got := u.search.Text(); got != "amazon" {
t.Fatalf("search text after returning to entries = %q, want amazon", got)
}
if got := u.state.SelectedEntryID; got != "amazon" {
t.Fatalf("SelectedEntryID after returning to entries = %q, want amazon", got)
}
if !u.editingEntry {
t.Fatal("editingEntry = false, want true after returning to entries")
}
if got := u.filteredTitles(); !slices.Equal(got, []string{"Amazon", "Amazon AWS"}) {
t.Fatalf("filteredTitles() after returning to entries = %v, want [Amazon Amazon AWS]", got)
}
}
func TestUINoteRecentVaultDeduplicatesAndOrdersMostRecentFirst(t *testing.T) {
t.Parallel()
@@ -2262,6 +2301,34 @@ func TestUILoadsRecentVaultsFromPersistedConfig(t *testing.T) {
}
}
func TestUIStartupPreselectsMostRecentLocalVault(t *testing.T) {
t.Parallel()
configPath := filepath.Join(t.TempDir(), "recent-vaults.json")
first := newUIWithSession("desktop", &session.Manager{})
first.recentVaultsPath = configPath
first.recentVaults = nil
first.recentVaultUsedAt = map[string]time.Time{}
first.now = func() time.Time { return time.Date(2026, 3, 30, 12, 0, 0, 0, time.UTC) }
first.noteRecentVault("/tmp/older.kdbx")
first.now = func() time.Time { return time.Date(2026, 3, 30, 13, 0, 0, 0, time.UTC) }
first.noteRecentVault("/tmp/newer.kdbx")
second := newUIWithSession("desktop", &session.Manager{}, statePaths{
DefaultSaveAsPath: filepath.Join(t.TempDir(), "vault.kdbx"),
RecentVaultsPath: configPath,
RecentRemotesPath: filepath.Join(t.TempDir(), "recent-remotes.json"),
UIPreferencesPath: filepath.Join(t.TempDir(), "ui-prefs.json"),
})
if got := second.lifecycleMode; got != "local" {
t.Fatalf("lifecycleMode = %q, want local", got)
}
if got := second.vaultPath.Text(); got != "/tmp/newer.kdbx" {
t.Fatalf("vaultPath = %q, want /tmp/newer.kdbx", got)
}
}
func TestUIRecentVaultsPersistLastOpenedGroupPerVault(t *testing.T) {
t.Parallel()
@@ -2382,6 +2449,44 @@ func TestUIRecentRemoteConnectionsPersistAndReload(t *testing.T) {
}
}
func TestUIStartupPreselectsNewestTargetAcrossLocalAndRemote(t *testing.T) {
t.Parallel()
dir := t.TempDir()
vaultsPath := filepath.Join(dir, "recent-vaults.json")
remotesPath := filepath.Join(dir, "recent-remotes.json")
paths := statePaths{
DefaultSaveAsPath: filepath.Join(dir, "vault.kdbx"),
RecentVaultsPath: vaultsPath,
RecentRemotesPath: remotesPath,
UIPreferencesPath: filepath.Join(dir, "ui-prefs.json"),
}
first := newUIWithSession("desktop", &session.Manager{}, paths)
first.now = func() time.Time { return time.Date(2026, 3, 30, 12, 0, 0, 0, time.UTC) }
first.noteRecentVault("/tmp/local.kdbx")
first.now = func() time.Time { return time.Date(2026, 3, 30, 13, 0, 0, 0, time.UTC) }
first.noteRecentRemote("https://dav.example.com", "vaults/home.kdbx", "alice", "secret-1", true)
second := newUIWithSession("desktop", &session.Manager{}, paths)
if got := second.lifecycleMode; got != "remote" {
t.Fatalf("lifecycleMode = %q, want remote", got)
}
if got := second.remoteBaseURL.Text(); got != "https://dav.example.com" {
t.Fatalf("remoteBaseURL = %q, want https://dav.example.com", got)
}
if got := second.remotePath.Text(); got != "vaults/home.kdbx" {
t.Fatalf("remotePath = %q, want vaults/home.kdbx", got)
}
if got := second.remoteUsername.Text(); got != "alice" {
t.Fatalf("remoteUsername = %q, want alice", got)
}
if got := second.remotePassword.Text(); got != "secret-1" {
t.Fatalf("remotePassword = %q, want secret-1", got)
}
}
func TestUIGroupToolsDisclosureStatePersists(t *testing.T) {
t.Parallel()
@@ -3106,6 +3211,7 @@ func TestUILocalLifecycleActionErrorsAreVisibleAndSpecific(t *testing.T) {
u := newUIWithSession("desktop", &session.Manager{})
u.masterPassword.SetText("correct horse battery staple")
u.vaultPath.SetText("")
u.runAction("open vault", u.openVaultAction)