carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package docsite
2
3import "testing"
4
5// mainFile is the CLI's dispatch, relative to this package.
6const mainFile = "../../main.go"
7
8// cliPage is the page that must document all of it.
9const cliPage = "cli"
10
11// TestTopLevelCommandsReadsTheDispatch checks the scanner before the
12// gate that depends on it. A scanner that silently returns nothing
13// turns the gate below into a test that always passes.
14func TestTopLevelCommandsReadsTheDispatch(t *testing.T) {
15 cmds, err := TopLevelCommands(mainFile)
16 if err != nil {
17 t.Fatalf("scan: %v", err)
18 }
19 if len(cmds) < 20 {
20 t.Fatalf("found %d commands (%v) — the scanner is broken, not the docs", len(cmds), cmds)
21 }
22 for _, want := range []string{"ship", "promote", "deploy", "domains", "logs", "fleets"} {
23 if !contains(cmds, want) {
24 t.Errorf("scanner missed the %q command", want)
25 }
26 }
27 for _, unwanted := range []string{"-h", "--help", ""} {
28 if contains(cmds, unwanted) {
29 t.Errorf("scanner kept %q, which is not a command", unwanted)
30 }
31 }
32}
33
34func contains(xs []string, s string) bool {
35 for _, x := range xs {
36 if x == s {
37 return true
38 }
39 }
40 return false
41}
42
43// TestCLICommandsAreDocumented is the gate. It reads the dispatch
44// switch rather than the usage text on purpose: usage text is prose
45// someone can forget to update, so gating against it would only prove
46// the docs match a second copy of the docs. The switch is the CLI.
47//
48// It asks for a HEADING, not a substring of the body, and that is not
49// a stylistic preference. A substring check is defeated by prefixes:
50// "route" is a prefix of "routes", so the literal text "carlos routes"
51// anywhere on the page satisfies a Contains check for "route" — the
52// whole `### carlos route` section can be deleted with every test
53// still green (a reviewer did exactly that, 2026-08-25). The same
54// check also counts a mention inside another command's example fence,
55// or in a link, as documentation. A heading is the thing a reader can
56// actually land on, and `#carlos-route` and `#carlos-routes` are
57// distinct anchors. Do not "simplify" this back to Contains.
58func TestCLICommandsAreDocumented(t *testing.T) {
59 site, err := Load(root)
60 if err != nil {
61 t.Fatalf("load: %v", err)
62 }
63 page, ok := site.BySlug[cliPage]
64 if !ok {
65 t.Fatalf("no %s page — every command has to be documented somewhere", cliPage)
66 }
67 cmds, err := TopLevelCommands(mainFile)
68 if err != nil {
69 t.Fatalf("scan: %v", err)
70 }
71 for _, cmd := range cmds {
72 if !hasAnchor(page, Anchor("carlos "+cmd)) {
73 t.Errorf("%s.md has no heading for %q (expected a heading anchoring #%s)",
74 cliPage, cmd, Anchor("carlos "+cmd))
75 }
76 }
77}
78