From 030e44b0278686fe9277524b0f64c16b2000ef15 Mon Sep 17 00:00:00 2001 From: Egutierrez Date: Mon, 18 May 2026 18:12:54 +0200 Subject: [PATCH] test(infra): audit_dod_schema covers valid/invalid/malformed/recurse (issue 0114) Co-Authored-By: Claude Opus 4.7 (1M context) --- functions/infra/audit_dod_schema_test.go | 229 +++++++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 functions/infra/audit_dod_schema_test.go diff --git a/functions/infra/audit_dod_schema_test.go b/functions/infra/audit_dod_schema_test.go new file mode 100644 index 00000000..6661c17d --- /dev/null +++ b/functions/infra/audit_dod_schema_test.go @@ -0,0 +1,229 @@ +package infra + +import ( + "os" + "path/filepath" + "strings" + "testing" +) + +// helper: write a file under tmp/dev/issues or tmp/dev/flows with given content. +func writeMD(t *testing.T, dir, name, body string) string { + t.Helper() + if err := os.MkdirAll(dir, 0o755); err != nil { + t.Fatalf("mkdir %s: %v", dir, err) + } + p := filepath.Join(dir, name) + if err := os.WriteFile(p, []byte(body), 0o644); err != nil { + t.Fatalf("write %s: %v", p, err) + } + return p +} + +func TestDodSchema_Valid(t *testing.T) { + tmp := t.TempDir() + issues := filepath.Join(tmp, "dev", "issues") + flows := filepath.Join(tmp, "dev", "flows") + + writeMD(t, issues, "0200-ok.md", `--- +id: "0200" +title: ok +dod_evidence_schema: + - id: surface_ui + kind: screenshot + expected: "kanban shows new card" + required: true + - id: backend_health + kind: cmd + expected: "curl -fsS http://localhost:8000/api/health" + required: false +--- +body +`) + + report, err := AuditDodSchema(issues, flows) + if err != nil { + t.Fatalf("AuditDodSchema: %v", err) + } + if report.TotalFiles != 1 { + t.Fatalf("TotalFiles = %d, want 1", report.TotalFiles) + } + if report.FilesWithItems != 1 { + t.Fatalf("FilesWithItems = %d, want 1", report.FilesWithItems) + } + if report.TotalItems != 2 { + t.Fatalf("TotalItems = %d, want 2", report.TotalItems) + } + if report.InvalidItems != 0 { + t.Fatalf("InvalidItems = %d, want 0; errors=%v", report.InvalidItems, report.Files[0].Errors) + } + f := report.Files[0] + if f.Type != "issue" { + t.Errorf("Type = %q, want issue", f.Type) + } + if f.Items[0].ID != "surface_ui" || f.Items[0].Kind != "screenshot" { + t.Errorf("item[0] = %+v", f.Items[0]) + } + if !f.Items[0].Required { + t.Errorf("item[0].Required = false, want true") + } + if f.Items[1].Required { + t.Errorf("item[1].Required = true, want false") + } +} + +func TestDodSchema_InvalidKind(t *testing.T) { + tmp := t.TempDir() + issues := filepath.Join(tmp, "dev", "issues") + writeMD(t, issues, "0201-badkind.md", `--- +id: "0201" +dod_evidence_schema: + - id: bad + kind: png + expected: "nope" +--- +`) + report, _ := AuditDodSchema(issues, "") + if len(report.Files) != 1 { + t.Fatalf("want 1 file, got %d", len(report.Files)) + } + errs := strings.Join(report.Files[0].Errors, "|") + if !strings.Contains(errs, "invalid kind 'png'") { + t.Errorf("expected invalid kind error, got %q", errs) + } + if report.InvalidItems != 1 { + t.Errorf("InvalidItems = %d, want 1", report.InvalidItems) + } +} + +func TestDodSchema_DuplicateID(t *testing.T) { + tmp := t.TempDir() + flows := filepath.Join(tmp, "dev", "flows") + writeMD(t, flows, "0001-dup.md", `--- +name: dup +dod_evidence_schema: + - id: surface_1 + kind: url + expected: "open dashboard" + - id: surface_1 + kind: cmd + expected: "other" +--- +`) + report, _ := AuditDodSchema("", flows) + errs := strings.Join(report.Files[0].Errors, "|") + if !strings.Contains(errs, "duplicate id") { + t.Errorf("expected duplicate id error, got %q", errs) + } + if report.Files[0].Type != "flow" { + t.Errorf("Type = %q, want flow", report.Files[0].Type) + } +} + +func TestDodSchema_EmptyExpected(t *testing.T) { + tmp := t.TempDir() + issues := filepath.Join(tmp, "dev", "issues") + writeMD(t, issues, "0202-noexpect.md", `--- +dod_evidence_schema: + - id: empty + kind: log + expected: "" +--- +`) + report, _ := AuditDodSchema(issues, "") + errs := strings.Join(report.Files[0].Errors, "|") + if !strings.Contains(errs, "empty expected") { + t.Errorf("expected empty expected error, got %q", errs) + } +} + +func TestDodSchema_MalformedYAML(t *testing.T) { + tmp := t.TempDir() + issues := filepath.Join(tmp, "dev", "issues") + writeMD(t, issues, "0203-bad.md", `--- +id: "0203 +dod_evidence_schema: + - id: x + kind: cmd + expected: nope +--- +`) + report, err := AuditDodSchema(issues, "") + if err != nil { + t.Fatalf("AuditDodSchema returned err on malformed: %v", err) + } + if len(report.Files) != 1 { + t.Fatalf("want 1 file, got %d", len(report.Files)) + } + errs := strings.Join(report.Files[0].Errors, "|") + if !strings.Contains(errs, "malformed") { + t.Errorf("expected malformed error, got %q", errs) + } +} + +func TestDodSchema_NoBlock(t *testing.T) { + tmp := t.TempDir() + issues := filepath.Join(tmp, "dev", "issues") + writeMD(t, issues, "0204-noblock.md", `--- +id: "0204" +title: no schema here +--- +body +`) + report, _ := AuditDodSchema(issues, "") + if len(report.Files) != 1 { + t.Fatalf("want 1 file, got %d", len(report.Files)) + } + if len(report.Files[0].Items) != 0 { + t.Errorf("Items=%d, want 0", len(report.Files[0].Items)) + } + if len(report.Files[0].Errors) != 0 { + t.Errorf("Errors=%v, want none", report.Files[0].Errors) + } + if report.FilesWithItems != 0 { + t.Errorf("FilesWithItems = %d, want 0", report.FilesWithItems) + } +} + +func TestDodSchema_SkipsConventionFiles(t *testing.T) { + tmp := t.TempDir() + issues := filepath.Join(tmp, "dev", "issues") + // README/INDEX/template/AGENT_GUIDE should be skipped even if they have a dod_evidence_schema block. + writeMD(t, issues, "README.md", `--- +dod_evidence_schema: + - id: x + kind: png + expected: "" +--- +`) + writeMD(t, issues, "0205-real.md", `--- +id: "0205" +--- +`) + report, _ := AuditDodSchema(issues, "") + if report.TotalFiles != 1 { + t.Fatalf("TotalFiles=%d, want 1 (README must be skipped)", report.TotalFiles) + } + if !strings.HasSuffix(report.Files[0].Path, "0205-real.md") { + t.Errorf("unexpected file scanned: %s", report.Files[0].Path) + } +} + +func TestDodSchema_RecurseCompleted(t *testing.T) { + tmp := t.TempDir() + issues := filepath.Join(tmp, "dev", "issues") + writeMD(t, filepath.Join(issues, "completed"), "0206-done.md", `--- +dod_evidence_schema: + - id: a + kind: url + expected: "http://localhost" +--- +`) + report, _ := AuditDodSchema(issues, "") + if report.TotalFiles != 1 { + t.Fatalf("TotalFiles=%d, want 1 (completed/ must be walked)", report.TotalFiles) + } + if report.TotalItems != 1 { + t.Errorf("TotalItems=%d, want 1", report.TotalItems) + } +}