Files
fn_registry/functions/infra/audit_dod_schema_test.go
T
2026-05-18 18:12:54 +02:00

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)
}
}