Files
go/cmd/docs/main_test.go
T
endandClaude Opus 5.5 cc482d9a9b
release / release (push) Successful in 17s
ci / check (push) Successful in 18s
feat: add docs checker for ADRs and implementation plans (#1)
Add cmd/docs, the first corestack component: `docs new adr|plan "Title"`
writes records from embedded templates, and `docs check` validates them
against the public format spec in docs/docs-format.md (timestamp IDs,
frontmatter keys and enums, separate decision and implementation status,
supersession symmetry, MADR 4 layout with required Consequences, plan
sections, and repo-root/durable references), reporting path:line errors.

Also adds the module skeleton (go.auvem.com/corestack, BSD-3-Clause,
README, AGENTS.md, CLAUDE.md), Gitea CI running tests and docs check,
a tag-triggered goreleaser release for darwin/linux binaries, and the
accepted ADR adopting the format.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 15:56:03 -07:00

81 lines
2.2 KiB
Go

package main
import (
"bytes"
"os"
"path/filepath"
"strings"
"testing"
"time"
)
var now = time.Date(2026, 10, 23, 20, 45, 12, 345_000_000, time.UTC)
func do(t *testing.T, args ...string) (code int, stdout, stderr string) {
t.Helper()
var out, errw bytes.Buffer
code = run(args, &out, &errw, now)
return code, out.String(), errw.String()
}
func TestCLI(t *testing.T) {
root := t.TempDir()
t.Chdir(root)
if code, out, _ := do(t, "check"); code != 0 || out != "ok: 0 records checked\n" {
t.Fatalf("empty check: %d %q", code, out)
}
code, out, _ := do(t, "new", "adr", "Use X")
if code != 0 || out != "docs/adr/20261023T204512345Z-use-x.md\n" {
t.Fatalf("new: %d %q", code, out)
}
code, out, _ = do(t, "check")
var want strings.Builder
for _, line := range []string{"6", "8", "20", "24", "28", "32"} { // numeric, not lexical, order
want.WriteString("docs/adr/20261023T204512345Z-use-x.md:" + line + ": unfinished placeholder {{docs:todo}}\n")
}
if code != 1 || out != want.String() {
t.Fatalf("check with markers: %d %q", code, out)
}
// --root checks another directory; the working directory is not used.
t.Chdir(t.TempDir())
if code, _, _ := do(t, "check", "--root", root); code != 1 {
t.Errorf("--root: %d", code)
}
if code, out, _ := do(t, "check"); code != 0 || !strings.HasPrefix(out, "ok: ") {
t.Errorf("cwd root: %d %q", code, out)
}
}
func TestCLIExitCodes(t *testing.T) {
t.Chdir(t.TempDir())
must := func(err error) {
t.Helper()
if err != nil {
t.Fatal(err)
}
}
must(os.MkdirAll("docs/adr", 0o755))
must(os.WriteFile(filepath.Join("docs", "adr", "bad.md"), nil, 0o644))
for _, tt := range []struct {
args []string
code int
}{
{nil, 2},
{[]string{"bogus"}, 2},
{[]string{"new"}, 2},
{[]string{"new", "adr"}, 2},
{[]string{"new", "note", "T"}, 2},
{[]string{"new", "adr", "T", "extra"}, 2},
{[]string{"new", "adr", "!!!"}, 1},
{[]string{"check", "--bogus"}, 2},
{[]string{"check", "extra"}, 2},
{[]string{"check", "--root", "missing-dir"}, 1},
{[]string{"check"}, 1}, // bad.md is not a valid name
} {
if code, _, stderr := do(t, tt.args...); code != tt.code {
t.Errorf("docs %v = %d, want %d (stderr %q)", tt.args, code, tt.code, stderr)
}
}
}