package handler import ( "os" "path/filepath" "testing" ) func TestTemplateNameFromFrontMatter(t *testing.T) { cases := []struct { name string src string want string }{ {"plain", "---\ntemplate: specification\n---\n\n# H\n", "specification"}, {"quoted", "---\ntemplate: \"letter\"\n---\n", "letter"}, {"absent", "---\ntitle: X\n---\n", ""}, {"no-frontmatter", "# Just a heading\n", ""}, {"traversal-rejected", "---\ntemplate: ../../etc/passwd\n---\n", ""}, {"slash-rejected", "---\ntemplate: a/b\n---\n", ""}, {"crlf", "---\r\ntemplate: report\r\n---\r\n", "report"}, {"dots-terminator", "---\ntemplate: letter\n...\nbody", "letter"}, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { if got := templateNameFromFrontMatter([]byte(c.src)); got != c.want { t.Errorf("templateNameFromFrontMatter(%q) = %q, want %q", c.src, got, c.want) } }) } } func TestResolveTemplateSet_DefaultsAndCascade(t *testing.T) { root := t.TempDir() party := filepath.Join(root, "working", "AcmeCo") if err := os.MkdirAll(party, 0o755); err != nil { t.Fatal(err) } // No overrides, no front matter → embedded report, partials present. ts := resolveTemplateSet(root, party, []byte("# Hi\n")) if ts.Name != "report.html" { t.Fatalf("default doctype: got %q, want report.html", ts.Name) } if ts.Files["_head.html"] == nil { t.Errorf("partial _head.html missing from default set") } embeddedReport := string(ts.Files["report.html"]) // Front matter selects a doctype. if ts := resolveTemplateSet(root, party, []byte("---\ntemplate: letter\n---\n")); ts.Name != "letter.html" { t.Errorf("front-matter doctype: got %q, want letter.html", ts.Name) } // Project-global override at /.zddc.d/templates/report.html. projDir := filepath.Join(root, ".zddc.d", "templates") if err := os.MkdirAll(projDir, 0o755); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(projDir, "report.html"), []byte("PROJECT-REPORT"), 0o644); err != nil { t.Fatal(err) } ts = resolveTemplateSet(root, party, []byte("# Hi\n")) if string(ts.Files["report.html"]) != "PROJECT-REPORT" { t.Errorf("project override not applied: %q", ts.Files["report.html"]) } if string(ts.Files["report.html"]) == embeddedReport { t.Errorf("override identical to embedded — overlay didn't happen") } // Party override wins over project-global. partyDir := filepath.Join(party, ".zddc.d", "templates") if err := os.MkdirAll(partyDir, 0o755); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(partyDir, "report.html"), []byte("PARTY-REPORT"), 0o644); err != nil { t.Fatal(err) } ts = resolveTemplateSet(root, party, []byte("# Hi\n")) if string(ts.Files["report.html"]) != "PARTY-REPORT" { t.Errorf("party override should win: got %q", ts.Files["report.html"]) } // A brand-new doctype provided only as an override is adopted as primary. if err := os.WriteFile(filepath.Join(partyDir, "memo.html"), []byte("MEMO-TEMPLATE"), 0o644); err != nil { t.Fatal(err) } ts = resolveTemplateSet(root, party, []byte("---\ntemplate: memo\n---\n")) if ts.Name != "memo.html" || string(ts.Files["memo.html"]) != "MEMO-TEMPLATE" { t.Errorf("custom doctype override: name=%q bytes=%q", ts.Name, ts.Files["memo.html"]) } if ts.Files["_head.html"] == nil { t.Errorf("partials should still ride along with a custom doctype override") } }