Improve local vault open usability

This commit is contained in:
Joe Julian
2026-04-01 17:16:01 -07:00
parent 315988134b
commit cb1447e554
3 changed files with 388 additions and 72 deletions
+98
View File
@@ -105,6 +105,15 @@ func TestUIFiltersUsingVaultModelPathsAndSearch(t *testing.T) {
}
}
func TestUIMasterPasswordUsesPasswordInputHint(t *testing.T) {
t.Parallel()
u := newUIWithSession("phone", &session.Manager{})
if got := u.masterPassword.InputHint; got != key.HintPassword {
t.Fatalf("masterPassword.InputHint = %v, want %v", got, key.HintPassword)
}
}
func TestUISearchBehaviorIsConsistentAcrossDesktopAndPhoneLayouts(t *testing.T) {
t.Parallel()
@@ -268,6 +277,48 @@ func TestUIRunBackgroundActionIgnoresDuplicateWhileLoading(t *testing.T) {
}
}
func TestUICancelLifecycleBusyStateIgnoresLateResultAndKeepsRetryAvailable(t *testing.T) {
t.Parallel()
u := newUIWithSession("desktop", &session.Manager{})
u.vaultPath.SetText("/tmp/example.kdbx")
u.lastLifecycleAction = "open vault"
started := make(chan struct{})
release := make(chan struct{})
u.runBackgroundAction("open vault", func() (func() error, error) {
close(started)
<-release
return func() error {
u.state.StatusMessage = "should not apply"
return nil
}, nil
})
<-started
u.cancelLifecycleBusyState()
if got := u.loadingMessage; got != "" {
t.Fatalf("loadingMessage after cancel = %q, want empty", got)
}
if got := u.activeBackgroundAction; got != 0 {
t.Fatalf("activeBackgroundAction after cancel = %d, want 0", got)
}
if !u.requestMasterPassFocus {
t.Fatal("requestMasterPassFocus after cancel = false, want true")
}
close(release)
result := waitForBackgroundResult(t, u)
u.applyBackgroundResult(result)
if got := u.state.StatusMessage; got != "" {
t.Fatalf("StatusMessage after stale apply = %q, want empty", got)
}
if got := u.lastLifecycleAction; got != "open vault" {
t.Fatalf("lastLifecycleAction after cancel = %q, want open vault", got)
}
}
func TestUIChildGroupsComeFromVaultModel(t *testing.T) {
t.Parallel()
@@ -2695,6 +2746,43 @@ func TestUIBannerSurfacePrefersLoadingThenErrorThenStatus(t *testing.T) {
}
}
func TestUIBannerActionLabelsExposeCancelAndRetryForLifecycleOpen(t *testing.T) {
t.Parallel()
u := newUIWithSession("desktop", &session.Manager{})
u.loadingMessage = "Open vault..."
u.loadingActionLabel = "open vault"
primary, secondary := u.bannerActionLabels(u.bannerSurface())
if primary != "Cancel" || secondary != "" {
t.Fatalf("bannerActionLabels(loading) = %q/%q, want Cancel/empty", primary, secondary)
}
u.loadingMessage = ""
u.loadingActionLabel = ""
u.lastLifecycleAction = "open vault"
u.state.ErrorMessage = "open failed"
primary, secondary = u.bannerActionLabels(u.bannerSurface())
if primary != "Retry" || secondary != "Dismiss" {
t.Fatalf("bannerActionLabels(error) = %q/%q, want Retry/Dismiss", primary, secondary)
}
}
func TestCompactPathDirectorySummaryCollapsesLongPaths(t *testing.T) {
t.Parallel()
got := compactPathDirectorySummary("/home/julian/vaults/family/main.kdbx")
if got != "home/.../family" {
t.Fatalf("compactPathDirectorySummary() = %q, want %q", got, "home/.../family")
}
short := compactPathDirectorySummary("/tmp/main.kdbx")
if short != "/tmp" {
t.Fatalf("compactPathDirectorySummary(short) = %q, want %q", short, "/tmp")
}
}
func TestUIStatusToastExpiresAfterTimeout(t *testing.T) {
t.Parallel()
@@ -3304,6 +3392,7 @@ func TestSelectingRecentVaultSwitchesToLocalMode(t *testing.T) {
u := newUIWithSession("desktop", &session.Manager{})
u.lifecycleMode = "remote"
u.requestMasterPassFocus = false
u.recentVaults = []string{"/tmp/example.kdbx"}
u.recentVaultClicks = make([]widget.Clickable, 1)
u.recentVaultClicks[0].Click()
@@ -3313,6 +3402,7 @@ func TestSelectingRecentVaultSwitchesToLocalMode(t *testing.T) {
if 0 < len(u.recentVaults) {
u.lifecycleMode = "local"
u.vaultPath.SetText(u.recentVaults[0])
u.requestMasterPassFocus = true
}
}
@@ -3322,6 +3412,9 @@ func TestSelectingRecentVaultSwitchesToLocalMode(t *testing.T) {
if got := u.vaultPath.Text(); got != "/tmp/example.kdbx" {
t.Fatalf("vaultPath after recent vault click = %q, want /tmp/example.kdbx", got)
}
if !u.requestMasterPassFocus {
t.Fatal("requestMasterPassFocus after recent vault click = false, want true")
}
}
func TestSelectingRecentRemoteSwitchesToRemoteMode(t *testing.T) {
@@ -3329,6 +3422,7 @@ func TestSelectingRecentRemoteSwitchesToRemoteMode(t *testing.T) {
u := newUIWithSession("desktop", &session.Manager{})
u.lifecycleMode = "local"
u.requestMasterPassFocus = false
u.recentRemotes = []recentRemoteRecord{{
BaseURL: "https://dav.example.com",
Path: "vaults/home.kdbx",
@@ -3341,6 +3435,7 @@ func TestSelectingRecentRemoteSwitchesToRemoteMode(t *testing.T) {
if 0 < len(u.recentRemotes) {
u.lifecycleMode = "remote"
u.applyRecentRemoteRecord(u.recentRemotes[0])
u.requestMasterPassFocus = true
}
}
@@ -3350,6 +3445,9 @@ func TestSelectingRecentRemoteSwitchesToRemoteMode(t *testing.T) {
if got := u.remoteBaseURL.Text(); got != "https://dav.example.com" {
t.Fatalf("remoteBaseURL after recent remote click = %q, want https://dav.example.com", got)
}
if !u.requestMasterPassFocus {
t.Fatal("requestMasterPassFocus after recent remote click = false, want true")
}
}
func TestUILoadingDetailMessageUsesSelectedVault(t *testing.T) {