Files
fn_registry/functions/infra/audit_e2e_coverage_test.go
egutierrez 7b0b697b18 feat(0121b): audit_e2e_coverage_go_infra + fn doctor e2e-coverage subcmd
- Crea functions/infra/audit_e2e_coverage.go: AuditE2ECoverage(roots) escanea
  app.md recursivamente, detecta e2e_checks: en frontmatter, retorna
  E2ECoverageReport{total, with_checks, missing, coverage_pct}.
- Crea functions/infra/e2e_coverage_report.go: tipo E2ECoverageReport con
  JSON tags (total, with_checks, missing, coverage_pct).
- Crea types/infra/e2e_coverage_report.md: metadata del tipo para registry.
- Crea functions/infra/audit_e2e_coverage.md: documentacion self-contained
  con Ejemplo, Cuando usarla, Gotchas.
- Crea functions/infra/audit_e2e_coverage_test.go: 3 tests (empty, all-covered,
  partial) — todos pasan.
- Edita cmd/fn/doctor.go: agrega case "e2e-coverage" -> doctorE2ECoverage().
  Output text (tabla tabwriter + lista de apps missing) y --json (E2ECoverageReport).

Acceptance verificado:
  fn doctor e2e-coverage --json -> {total, with_checks, missing, coverage_pct} OK
  fn doctor e2e-coverage        -> tabla text OK
  go test ./functions/infra/... -> 3/3 PASS
  fn show audit_e2e_coverage_go_infra -> indexada OK

task_run: task_d285372493cce2e6 iter 1

Co-authored-by: fn-orquestador <noreply@fn-registry>
2026-05-19 01:45:54 +02:00

117 lines
3.1 KiB
Go

package infra
import (
"math"
"os"
"path/filepath"
"testing"
)
func TestAuditE2ECoverage_EmptyRoot(t *testing.T) {
dir := t.TempDir()
// Empty directory — no app.md files.
report, err := AuditE2ECoverage([]string{dir})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if report.Total != 0 {
t.Errorf("Total: got %d, want 0", report.Total)
}
if report.WithChecks != 0 {
t.Errorf("WithChecks: got %d, want 0", report.WithChecks)
}
if report.CoveragePct != 0.0 {
t.Errorf("CoveragePct: got %f, want 0.0", report.CoveragePct)
}
if len(report.Missing) != 0 {
t.Errorf("Missing: got %v, want empty", report.Missing)
}
}
func TestAuditE2ECoverage_AllCovered(t *testing.T) {
dir := t.TempDir()
apps := []struct {
subdir string
content string
}{
{
"apps/registry_dashboard",
"---\nname: registry_dashboard\ne2e_checks:\n - id: build\n cmd: go build .\n---\n",
},
{
"apps/kanban",
"---\nname: kanban\ne2e_checks:\n - id: tests\n cmd: go test ./...\n---\n",
},
}
for _, a := range apps {
full := filepath.Join(dir, a.subdir)
if err := os.MkdirAll(full, 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(full, "app.md"), []byte(a.content), 0o644); err != nil {
t.Fatal(err)
}
}
report, err := AuditE2ECoverage([]string{filepath.Join(dir, "apps")})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if report.Total != 2 {
t.Errorf("Total: got %d, want 2", report.Total)
}
if report.WithChecks != 2 {
t.Errorf("WithChecks: got %d, want 2", report.WithChecks)
}
if report.CoveragePct != 100.0 {
t.Errorf("CoveragePct: got %f, want 100.0", report.CoveragePct)
}
if len(report.Missing) != 0 {
t.Errorf("Missing: got %v, want empty", report.Missing)
}
}
func TestAuditE2ECoverage_PartialCoverage(t *testing.T) {
dir := t.TempDir()
covered := filepath.Join(dir, "apps", "registry_dashboard")
uncovered := filepath.Join(dir, "apps", "legacy_app")
for _, d := range []string{covered, uncovered} {
if err := os.MkdirAll(d, 0o755); err != nil {
t.Fatal(err)
}
}
// app.md with e2e_checks
covContent := "---\nname: registry_dashboard\ne2e_checks:\n - id: smoke\n cmd: ./registry_dashboard --help\n---\n"
if err := os.WriteFile(filepath.Join(covered, "app.md"), []byte(covContent), 0o644); err != nil {
t.Fatal(err)
}
// app.md without e2e_checks
uncovContent := "---\nname: legacy_app\ndescription: A legacy app without e2e coverage.\n---\n"
if err := os.WriteFile(filepath.Join(uncovered, "app.md"), []byte(uncovContent), 0o644); err != nil {
t.Fatal(err)
}
report, err := AuditE2ECoverage([]string{filepath.Join(dir, "apps")})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if report.Total != 2 {
t.Errorf("Total: got %d, want 2", report.Total)
}
if report.WithChecks != 1 {
t.Errorf("WithChecks: got %d, want 1", report.WithChecks)
}
wantPct := 50.0
if math.Abs(report.CoveragePct-wantPct) > 0.01 {
t.Errorf("CoveragePct: got %f, want %f", report.CoveragePct, wantPct)
}
if len(report.Missing) != 1 {
t.Errorf("Missing len: got %d, want 1", len(report.Missing))
}
}