Move pages to and from the vault
A page, including a journal day, can be moved into the unlocked vault with its id kept. Links to it elsewhere become [[locked:id]], shown as Locked Page until the vault is unlocked, so its title is kept only in the vault. Move out reverses it. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c08a8b8718
commit
994927c704
10 files changed
+443
-14
No files matched your search
@@ -576,3 +576,114 @@ func TestWrongKeyRefusesInsteadOfLosingPages(t *testing.T) {
|
||||
t.Fatal("opened with no key")
|
||||
}
|
||||
}
|
||||
|
||||
func openAt(t *testing.T, dir string, box *vault.Cipher) *Store {
|
||||
t.Helper()
|
||||
s, err := Open(dir, box)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func TestDetachRewritesLinksAndImportKeepsThePage(t *testing.T) {
|
||||
main, mdir := open(t)
|
||||
other := openAt(t, t.TempDir(), testBox(t))
|
||||
|
||||
secret := mk(t, main, "Secret", "the plan #hush")
|
||||
kid, _ := main.Create(NewNote{Title: "Kid", Parent: secret.ID})
|
||||
b := mk(t, main, "Notes", "see [[Secret]] and [[secret|the plan]]\n`[[Secret]]` in code\n```\n[[Secret]]\n```")
|
||||
gone := mk(t, main, "Old", "also [[Secret]]")
|
||||
if _, err := main.Trash(gone.ID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got, err := other.Import(secret)
|
||||
if err != nil || got.ID != secret.ID || got.Title != "Secret" || !got.Updated.Equal(secret.Updated) || got.Body != "the plan #hush" {
|
||||
t.Fatalf("import: %+v %v", got, err)
|
||||
}
|
||||
if _, err := other.Import(secret); !errors.Is(err, ErrExists) {
|
||||
t.Fatalf("a second import: %v", err)
|
||||
}
|
||||
if _, err := main.Detach(secret.ID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := main.Get(secret.ID); !errors.Is(err, ErrNotFound) {
|
||||
t.Fatalf("the page is still in the notebook: %v", err)
|
||||
}
|
||||
nb, _ := main.Get(b.ID)
|
||||
link := "[[" + LockedPrefix + secret.ID + "]]"
|
||||
want := "see " + link + " and " + link + "\n`" + link + "` in code\n```\n[[Secret]]\n```" // only a fenced block is left as typed
|
||||
if nb.Body != want {
|
||||
t.Fatalf("links:\n%q\nwant\n%q", nb.Body, want)
|
||||
}
|
||||
if og, _ := main.Get(gone.ID); og.Body != "also "+link {
|
||||
t.Fatalf("a link in the trash was left alone: %q", og.Body)
|
||||
}
|
||||
if k, _ := main.Get(kid.ID); k.Parent != "" {
|
||||
t.Fatalf("a subpage still points at the moved page: %q", k.Parent)
|
||||
}
|
||||
// and it is the same after a reload, with nothing of the title in the page that linked to it
|
||||
again := openAt(t, mdir, testBox(t))
|
||||
if n2, _ := again.Get(b.ID); n2.Body != want {
|
||||
t.Fatalf("after reload: %q", n2.Body)
|
||||
}
|
||||
if _, err := again.Get(secret.ID); !errors.Is(err, ErrNotFound) {
|
||||
t.Fatalf("the page came back from disk: %v", err)
|
||||
}
|
||||
|
||||
// coming back: the title is free again, and the links name it
|
||||
back, err := main.Import(got)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := main.Reveal(back.ID, back.Title); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if nb, _ := main.Get(b.ID); !strings.Contains(nb.Body, "see [[Secret]] and [[Secret]]") {
|
||||
t.Fatalf("links after coming back: %q", nb.Body)
|
||||
}
|
||||
if err := other.Discard(secret.ID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := other.Get(secret.ID); !errors.Is(err, ErrNotFound) {
|
||||
t.Fatal("discard left the page")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMovingAJournalDayAndATitleThatIsTaken(t *testing.T) {
|
||||
main, _ := open(t)
|
||||
other := openAt(t, t.TempDir(), testBox(t))
|
||||
|
||||
day, err := main.Daily("2026-10-31")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
day, _ = main.Update(day.ID, Change{Body: ptr("dear diary")}, time.Time{})
|
||||
ref := mk(t, main, "Index", "that day: [[2026-10-31]]")
|
||||
|
||||
got, err := other.Import(day)
|
||||
if err != nil || got.Daily != "2026-10-31" || got.Title != "2026-10-31" || got.Body != "dear diary" {
|
||||
t.Fatalf("import day: %+v %v", got, err)
|
||||
}
|
||||
if _, err := main.Detach(day.ID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if n, _ := main.Get(ref.ID); n.Body != "that day: [["+LockedPrefix+"daily-2026-10-31]]" {
|
||||
t.Fatalf("the link to the day: %q", n.Body)
|
||||
}
|
||||
again, _ := main.Daily("2026-10-31") // the day can be started afresh
|
||||
if _, err := other.Import(again); !errors.Is(err, ErrExists) {
|
||||
t.Fatalf("two pages for one day in the vault: %v", err)
|
||||
}
|
||||
|
||||
other.Create(NewNote{Title: "Plans"})
|
||||
p := mk(t, main, "Plans", "mine")
|
||||
got, err = other.Import(p)
|
||||
if err != nil || got.Title != "Plans 2" {
|
||||
t.Fatalf("a taken title: %+v %v", got, err)
|
||||
}
|
||||
}
|
||||
|
||||
func ptr[T any](v T) *T { return &v }
|
||||
Reference in new issue
Block a user