c5587842b9
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
230 lines
5.8 KiB
Go
230 lines
5.8 KiB
Go
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)
|
|
}
|
|
}
|