From 0bfa30de9188cf77e9093aeacc347458ff96e58f Mon Sep 17 00:00:00 2001 From: Joe Julian Date: Sun, 29 Mar 2026 11:19:42 -0700 Subject: [PATCH] test: cover template CRUD UI flows --- main_test.go | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/main_test.go b/main_test.go index 62b4870..a815e8f 100644 --- a/main_test.go +++ b/main_test.go @@ -1044,6 +1044,111 @@ func TestUITemplateAndAttachmentActionsWorkThroughEditor(t *testing.T) { } } +func TestUITemplatesCanBeBrowsedCreatedEditedDeletedAndInstantiated(t *testing.T) { + t.Parallel() + + u := newUIWithModel("desktop", vault.Model{ + Templates: []vault.Entry{ + { + ID: "tpl-existing", + Title: "SSH Login", + Username: "root", + Password: "template-password", + Path: []string{"Templates", "Infra"}, + }, + }, + }) + + u.showTemplatesSection() + if got := u.childGroups(); !slices.Equal(got, []string{"Infra"}) { + t.Fatalf("childGroups() = %v, want [Infra] at template root", got) + } + + u.currentPath = []string{"Templates", "Infra"} + u.filter() + if got := u.filteredTitles(); !slices.Equal(got, []string{"SSH Login"}) { + t.Fatalf("filteredTitles() = %v, want [SSH Login] in template path", got) + } + + u.state.SelectedEntryID = "" + u.loadSelectedEntryIntoEditor() + u.entryID.SetText("tpl-web") + u.entryTitle.SetText("Website Login") + u.entryUsername.SetText("template-user") + u.entryPassword.SetText("template-password") + u.entryNotes.SetText("Reusable template for website accounts.") + u.entryTags.SetText("template, web") + u.entryPath.SetText("Templates / Web") + if err := u.saveTemplateAction(); err != nil { + t.Fatalf("saveTemplateAction(create) error = %v", err) + } + + u.currentPath = []string{"Templates", "Web"} + u.filter() + if got := u.filteredTitles(); !slices.Equal(got, []string{"Website Login"}) { + t.Fatalf("filteredTitles() after create = %v, want [Website Login]", got) + } + + u.loadSelectedEntryIntoEditor() + u.entryTitle.SetText("Website Login Updated") + u.entryFields.SetText("Environment=prod") + if err := u.saveTemplateAction(); err != nil { + t.Fatalf("saveTemplateAction(edit) error = %v", err) + } + + u.filter() + selected, ok := u.selectedEntry() + if !ok { + t.Fatal("selectedEntry() ok = false, want updated template") + } + if selected.Title != "Website Login Updated" { + t.Fatalf("selectedEntry().Title = %q, want %q", selected.Title, "Website Login Updated") + } + if selected.Fields["Environment"] != "prod" { + t.Fatalf("selectedEntry().Fields[Environment] = %q, want %q", selected.Fields["Environment"], "prod") + } + + u.entryID.SetText("entry-1") + u.entryTitle.SetText("Dynadot") + u.entryUsername.SetText("jjulian") + u.entryPassword.SetText("token-1") + u.entryURL.SetText("https://www.dynadot.com") + u.entryPath.SetText("Root / Internet") + if err := u.instantiateSelectedTemplateAction(); err != nil { + t.Fatalf("instantiateSelectedTemplateAction() error = %v", err) + } + + u.showEntriesSection() + u.currentPath = []string{"Root", "Internet"} + u.filter() + instantiated, ok := u.selectedEntry() + if !ok { + t.Fatal("selectedEntry() ok = false, want instantiated entry") + } + if instantiated.Title != "Dynadot" { + t.Fatalf("selectedEntry().Title = %q, want %q", instantiated.Title, "Dynadot") + } + if instantiated.Notes != "Reusable template for website accounts." { + t.Fatalf("selectedEntry().Notes = %q, want template notes", instantiated.Notes) + } + if instantiated.Fields["Environment"] != "prod" { + t.Fatalf("selectedEntry().Fields[Environment] = %q, want %q", instantiated.Fields["Environment"], "prod") + } + + u.showTemplatesSection() + u.currentPath = []string{"Templates", "Web"} + u.filter() + u.state.SelectedEntryID = "tpl-web" + if err := u.deleteSelectedTemplateAction(); err != nil { + t.Fatalf("deleteSelectedTemplateAction() error = %v", err) + } + + u.filter() + if got := u.filteredTitles(); len(got) != 0 { + t.Fatalf("filteredTitles() after delete = %v, want empty", got) + } +} + func TestUIRestoresSelectedEntryHistoryVersion(t *testing.T) { t.Parallel()