package engine import ( "context" "strings" "testing" "time" ) func TestRetractRebasesLaterDiffs(t *testing.T) { h := newHarness(t) ctx := context.Background() h.put("a.md", page("", "Alpha.")) h.after(time.Hour).put("a.md", page("Added beta.", "Alpha.\n\nBeta.")) h.after(time.Hour).put("a.md", page("Added gamma.", "Alpha.\n\nBeta.\n\nGamma.")) p, _ := h.e.Store.PageByPath(ctx, "folder", "a.md") if err := h.e.Retract(ctx, p.ID, 2, false); err != nil { t.Fatal(err) } // #3 is now compared with #1, so Beta shows as added too. if f := h.diffOf(h.revisions("a.md")[2]); f.Stats.BlocksChanged != 2 { t.Fatalf("after retract: %+v", f.Stats) } if last, _ := h.e.Store.LastRevision(ctx, p.ID); last.Number != 3 { t.Fatalf("last %d", last.Number) } if err := h.e.Retract(ctx, p.ID, 2, true); err != nil { t.Fatal(err) } if f := h.diffOf(h.revisions("a.md")[2]); f.Stats.BlocksChanged != 1 { t.Fatalf("after undo: %+v", f.Stats) } if err := h.e.Retract(ctx, p.ID, 1, false); err == nil { t.Fatal("the baseline must not be retractable") } } func TestPublishingAfterRetractionUsesANewNumber(t *testing.T) { h := newHarness(t) ctx := context.Background() h.put("a.md", page("", "Alpha.")) h.after(time.Hour).put("a.md", page("Oops.", "Alpha. Secret.")) p, _ := h.e.Store.PageByPath(ctx, "folder", "a.md") h.e.Retract(ctx, p.ID, 2, false) h.expect(h.after(time.Hour).put("a.md", page("Real change.", "Alpha. Public.")), Published, 3) if f := h.diffOf(h.revisions("a.md")[2]); strings.Contains(f.Ops[0].Segments[len(f.Ops[0].Segments)-1].S, "Secret") { t.Fatal("the new revision should be diffed against #1, not the retracted #2") } } func TestAmend(t *testing.T) { h := newHarness(t) ctx := context.Background() h.put("a.md", page("", "Alpha.")) h.after(time.Hour).put("a.md", page("Typo in nte.", "Beta.")) p, _ := h.e.Store.PageByPath(ctx, "folder", "a.md") if err := h.e.Amend(ctx, p.ID, 2, "Typo in note fixed.", "correction"); err != nil { t.Fatal(err) } r := h.revisions("a.md")[1] if r.Note != "Typo in note fixed." || r.Kind != "correction" { t.Fatalf("%+v", r) } if err := h.e.Amend(ctx, p.ID, 2, "", "rant"); err == nil { t.Fatal("invalid kind should fail") } } func TestBackfill(t *testing.T) { h := newHarness(t) ctx := context.Background() old := h.now.Add(-30 * 24 * time.Hour) if _, err := h.e.Backfill(ctx, "a.md", []byte(page("", "Very old text.")), old); err != nil { t.Fatal(err) } res, err := h.e.Backfill(ctx, "a.md", []byte(page("Rewrote the old text.", "Newer text.")), old.Add(24*time.Hour)) if err != nil || res.Action != Published { t.Fatalf("%+v %v", res, err) } if _, err := h.e.Backfill(ctx, "a.md", []byte("x"), old.Add(time.Hour)); err == nil { t.Fatal("backfilling before the latest snapshot must fail") } if _, err := h.e.Backfill(ctx, "a.md", []byte("x"), h.now.Add(time.Hour)); err == nil { t.Fatal("future times must fail") } revs := h.revisions("a.md") if !revs[1].PublishedAt.Equal(old.Add(24 * time.Hour)) { t.Fatalf("backfilled revision time %s", revs[1].PublishedAt) } } func TestRebuildDiffs(t *testing.T) { h := newHarness(t) ctx := context.Background() h.put("a.md", page("", "Alpha.")) h.after(time.Hour).put("a.md", page("Note.", "Beta.")) if n, err := h.e.RebuildDiffs(ctx, 0, false); err != nil || n != 0 { t.Fatalf("nothing to rebuild: %d %v", n, err) } if n, err := h.e.RebuildDiffs(ctx, 0, true); err != nil || n != 0 { t.Fatalf("forced rebuild of current diffs changes nothing: %d %v", n, err) } }