From c1c9a9f853dc60b1477d2449f9db58711b8a4578 Mon Sep 17 00:00:00 2001 From: Jakub Zych Date: Thu, 1 Oct 2026 00:10:12 +0200 Subject: [PATCH] test(11.1-06): acceptance subtests per success criterion and the final docs gate - TestPhase11_1Acceptance asserts SC1 to SC5 on the real tree: sections and module pages, theme markers and no Node exec, AI outputs in sync, every go fence a src= copy run by go test, concept map and walkthrough - check-phase11.1.sh --named runs every named test of the phase by exact name (modules' TestDocs* and output Examples derived from source) and refuses failures, skips, missing or renamed tests and no tests to run - --all runs preconditions, deps, self-test, docs, forbidden, claude, named and the full go vet and go test --- cmd/summer/phase11_1_acceptance_test.go | 516 ++++++++++++++++++++++++ scripts/check-phase11.1.sh | 65 ++- 2 files changed, 580 insertions(+), 1 deletion(-) create mode 100644 cmd/summer/phase11_1_acceptance_test.go diff --git a/cmd/summer/phase11_1_acceptance_test.go b/cmd/summer/phase11_1_acceptance_test.go new file mode 100644 index 0000000..6c3f51c --- /dev/null +++ b/cmd/summer/phase11_1_acceptance_test.go @@ -0,0 +1,516 @@ +package main + +import ( + "bytes" + "go/ast" + "go/doc" + "go/parser" + "go/token" + "io/fs" + "os" + "os/exec" + "path/filepath" + "slices" + "strconv" + "strings" + "testing" + + "git.golem15.com/golem15/summercms/internal/docsite" + "git.golem15.com/golem15/summercms/modules/bonfire" +) + +// TestPhase11_1Acceptance asserts the Phase 11.1 success criteria on the +// real tree, one subtest per ROADMAP criterion. +func TestPhase11_1Acceptance(t *testing.T) { + opts := docsite.Options{Root: repoRoot, Commands: docsCommands()} + pages, loadProblems, err := docsite.Pages(opts) + if err != nil { + t.Fatal(err) + } + problems, err := docsite.Check(opts) + if err != nil { + t.Fatal(err) + } + out, _ := buildRealTree(t) + + // SC1: docs/ holds Markdown pages with frontmatter in the + // Winter-mirroring sections, and every framework module is reachable + // from the sidebar. + t.Run("SC1", func(t *testing.T) { + site, err := docsite.LoadSite(filepath.Join(repoRoot, "docs", "site.yaml")) + if err != nil { + t.Fatal(err) + } + var names []string + for _, s := range site.Sections { + names = append(names, s.Name) + } + if !slices.Equal(names, sectionOrder) { + t.Errorf("site.yaml sections = %v, want %v", names, sectionOrder) + } + for _, p := range append(slices.Clone(loadProblems), problems...) { + switch p.Rule { + case "frontmatter", "section", "site", "page", "readme": + t.Errorf("load problem: %s", p) + } + } + guides := 0 + for _, p := range pages { + if p.Module != "" { + continue + } + guides++ + if p.Title == "" || p.Description == "" || !strings.HasPrefix(p.Source, "docs/") || !strings.HasSuffix(p.Source, ".md") { + t.Errorf("page %s has incomplete frontmatter: %+v", p.URL, p) + } + if p.Section != "index" && (!slices.Contains(sectionOrder, p.Section) || p.Section == "api") { + t.Errorf("page %s is in section %q", p.URL, p.Section) + } + } + for _, sec := range sectionOrder[:len(sectionOrder)-1] { + if !slices.ContainsFunc(pages, func(p docsite.Page) bool { return p.Section == sec }) { + t.Errorf("section %s has no pages", sec) + } + } + if guides < len(requiredPages) { + t.Errorf("%d guide pages, want at least %d", guides, len(requiredPages)) + } + sidebar := sidebarOf(t, out, "setup/installation.html") + for _, m := range frameworkModules(t) { + if !slices.ContainsFunc(pages, func(p docsite.Page) bool { return p.URL == "api/"+m && p.Module == m }) { + t.Errorf("module %s has no api/%s page", m, m) + } + if !strings.Contains(sidebar, `href="/api/`+m+`.html"`) { + t.Errorf("the sidebar does not link api/%s", m) + } + } + }) + + // SC2: summer builds a self-contained static site with the UI-SPEC + // theme parts, search and dark mode, with no Node toolchain. + t.Run("SC2", func(t *testing.T) { + guide := readFile(t, filepath.Join(out, "setup", "installation.html")) + for _, marker := range []string{ + ``, + `