Artifact e303d836e5016c4de36c99a255bb3ff790fda41389b7eb43601e4d40d1ebfc81:
- File
internal/index/technote_test.go
— part of check-in
[24fdaa723a]
at
2026-08-25 19:05:45
on branch search-guards
— tests: the regression guards that were never added
Seven test files were written this session, reported as landed, and never committed: `zit commit` with no paths captures TRACKED files, and new files need `zit add` first. make check passed every time because they were on disk in the worktree, which proves nothing about what is in the check-in.
What was missing:
- search kinds, held in agreement across four places (the index list, two ops validators, the scope chips, hitOf). This is the guard that caught `doc` and again `file` the moment each was added; without it the validator silently refused a kind the chips offered. - technote edits collapsing to one timeline row, folded in three different orders, because a clone delivers artifacts in wire order. - wiki and technote search matching the CURRENT revision only, the "terrified" case. - Contributors(0) meaning every contributor rather than a silent 100. - the ops phase states, the stalled-store trap, and an empty fleet.
Verified by removing them and running the suite: it stays green, which is precisely the problem — trunk has been passing on their absence. (user: dmestas, size: 3935) [annotate] [blame] [check-ins using] [more...]
package index import ( "strconv" "strings" "testing" "craftdesign.group/quarry/internal/artifact" ) // A technote is ONE timeline row however often it is edited — fossil's // rule, and the one quarry broke. libfossil has 50 technote artifacts // under 26 event ids; fossil's timeline shows 26 and quarry showed 50, // which put a superseded title on the page five rows above its own // correction. // // The order matters as much as the count: a clone hands the fold // artifacts in wire order, so the newest edit is NOT reliably last. Each // case below folds the same three versions in a different order and // wants the same answer. func TestTechnoteEditsCollapseToOneRow(t *testing.T) { const ev = "e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1e1" // Three edits of one note. The E card (where the note is FILED) // stays put while the D card (when it was written) advances, which // is the shape libfossil's eight-edit note has. version := func(edited, title, body string) string { return "C " + strings.ReplaceAll(title, " ", `\s`) + "\nD " + edited + "\nE 2013-09-01T10:50:00 " + ev + "\nN text/x-markdown\nU stephan\nW " + strconv.Itoa(len(body)+1) + "\n" + body + "\n\n" } draft := version("2013-08-31T16:08:21", "Milestone: basic diff generation bits are in place", "First cut.") middle := version("2013-09-01T10:56:39", "Milestone: basic diff generation bits are in place", "Second cut.") final := version("2013-09-01T11:38:15", "Milestone: diff generation bits are in place", "It works.") orders := map[string][]string{ "in order": {draft, middle, final}, "newest first": {final, middle, draft}, "newest in the middle": {middle, final, draft}, } for name, bodies := range orders { t.Run(name, func(t *testing.T) { ix := openIndex(t) for i, body := range bodies { art, err := artifact.Parse(seal(body)) if err != nil || art == nil { t.Fatalf("version %d did not parse: %v", i, err) } hash := strings.Repeat(string(rune('a'+i)), 64) if err := ix.FoldNow([]Parsed{{Hash: hash, Art: art}}); err != nil { t.Fatalf("fold %d: %v", i, err) } } tl, _, err := ix.Timeline(TimelineFilter{Limit: 10, Kind: "e"}) if err != nil { t.Fatal(err) } if len(tl) != 1 { t.Fatalf("timeline rows = %d, want 1 — every edit is on the page: %+v", len(tl), tl) } // The WINNER's title. The draft's wording surviving here is // the exact bug: fossil shows the correction. if !strings.Contains(tl[0].Comment, "Technote: Milestone: diff generation") || strings.Contains(tl[0].Comment, "basic") { t.Errorf("timeline title = %q, want the newest edit's", tl[0].Comment) } if tl[0].Excerpt != "It works." { t.Errorf("excerpt = %q, want the newest edit's body", tl[0].Excerpt) } counts, err := ix.Counts(true) if err != nil { t.Fatal(err) } if counts.Technotes != 1 { t.Errorf("Counts.Technotes = %d, want 1 — the tab badge counts artifacts", counts.Technotes) } // The history keeps every version, which is the other half: // collapsing the timeline must not lose the record. hist, err := ix.TechnoteHistory(ev) if err != nil { t.Fatal(err) } if len(hist) != 3 { t.Fatalf("history = %d versions, want 3", len(hist)) } if hist[0].Edited != "2013-09-01T11:38:15" { t.Errorf("history[0] = %q, want newest first", hist[0].Edited) } if hist[2].Edited != "2013-08-31T16:08:21" { t.Errorf("history[2] = %q, want oldest last", hist[2].Edited) } // And a superseded version stays READABLE by its own hash, // the way a wiki revision is. n, ok, err := ix.TechnoteRevision(ev[:12], hist[2].Hash[:12]) if err != nil || !ok { t.Fatalf("superseded revision unreadable: ok=%v err=%v", ok, err) } if strings.TrimSpace(n.Body) != "First cut." { t.Errorf("revision body = %q, want the draft's", n.Body) } }) } }