Artifact 81a5e607aa2e6ae298abd2cbc66779f3d6410e4fd79df5afc2c1b36bc5e2ed03:
- File
internal/web/searchhit_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: 2868) [annotate] [blame] [check-ins using] [more...]
package web import ( "strings" "testing" "craftdesign.group/quarry/internal/index" ) // Every kind the index can return must produce a link. forum and // technote fell through hitOf's switch with no URL, so their titles // rendered as <a href="">, which a browser resolves to the current // page: clicking a forum result reloaded the search. The index found // them, the facet chips offered them, and the one step that turns a hit // into somewhere to go was missing. // // Driven by index.SearchKinds rather than a hand-written list, so a // kind added to the index without a link here fails instead of // shipping a dead result. func TestEverySearchKindLinksSomewhere(t *testing.T) { // Refs by kind, in the shape searchDoc actually files them: a // check-in by hash, a wiki page by title, a ticket by id, a forum // post by its THREAD ROOT, a technote by its EVENT id. ref := map[string]string{ "checkin": strings.Repeat("a", 64), "wiki": "Design Notes", "ticket": strings.Repeat("b", 40), "forum": strings.Repeat("c", 64), "technote": strings.Repeat("d", 40), "doc": "b8c7665e121b25c3/www/quickstart.wiki", "file": "b8c7665e121b25c3/src/main.c", } want := map[string]string{ "checkin": "/r/demo/checkin/", "wiki": "/r/demo/wiki/", "ticket": "/r/demo/ticket/", "forum": "/r/demo/forum/", "technote": "/r/demo/technote/", "doc": "/r/demo/doc/", "file": "/r/demo/file/", } for _, kind := range index.SearchKinds { r, ok := ref[kind] if !ok { t.Fatalf("index.SearchKinds gained %q and this test does not know its ref shape", kind) } t.Run(kind, func(t *testing.T) { h := hitOf("demo", kind, r, "A Label", "a ⟦match⟧ here") if h.URL == "" { t.Fatalf("%s hit has no URL — the title renders as href=\"\" "+ "and clicking it reloads the search", kind) } if !strings.HasPrefix(h.URL, want[kind]) { t.Errorf("%s URL = %q, want it under %q", kind, h.URL, want[kind]) } // A hit with no label must still be clickable and must not // render as an empty link. bare := hitOf("demo", kind, r, "", "") if bare.URL == "" || strings.TrimSpace(bare.Label) == "" { t.Errorf("%s with no label: url=%q label=%q — both must be filled", kind, bare.URL, bare.Label) } }) } } // The snippet's match markers become <mark> only AFTER escaping, so a // hit whose content carries markup stays inert. func TestSearchSnippetStaysInert(t *testing.T) { h := hitOf("demo", "checkin", strings.Repeat("a", 64), "L", "before ⟦<script>alert(1)</script>⟧ after") got := string(h.Snippet) if strings.Contains(got, "<script>") { t.Errorf("snippet passed markup through: %q", got) } if !strings.Contains(got, "<mark>") || !strings.Contains(got, "<script>") { t.Errorf("snippet = %q, want escaped content inside <mark>", got) } }