import * as fs from "fs"; import * as path from "path"; const TEMPLATES_DIR = path.resolve(__dirname, ".."); describe("day3-activation-feedback.txt", () => { const filePath = path.join(TEMPLATES_DIR, "day3-activation-feedback.txt"); let content: string; beforeAll(() => { if (!fs.existsSync(filePath)) { throw new Error( `Template file missing: ${filePath}. Expected file to exist at templates/emails/day3-activation-feedback.txt` ); } content = fs.readFileSync(filePath, "utf-8"); }); it("has a non-empty Subject line", () => { const match = content.match(/^Subject:\s*(.+)$/m); expect(match).not.toBeNull(); const subject = match![1].trim(); expect(subject.length).toBeGreaterThan(0); }); it("contains the {{first_name}} placeholder", () => { expect(content).toContain("{{first_name}}"); }); it("has a word count under 150", () => { // Strip the Subject line before counting body words const body = content.replace(/^Subject:.*$/m, "").trim(); const wordCount = body.split(/\s+/).filter((w) => w.length > 0).length; expect(wordCount).toBeLessThan(150); }); }); describe("day30-pmf-feedback.txt", () => { const filePath = path.join(TEMPLATES_DIR, "day30-pmf-feedback.txt"); let content: string; beforeAll(() => { if (!fs.existsSync(filePath)) { throw new Error( `Template file missing: ${filePath}. Expected file to exist at templates/emails/day30-pmf-feedback.txt` ); } content = fs.readFileSync(filePath, "utf-8"); }); it("has the required Subject line", () => { const match = content.match(/^Subject:\s*(.+)$/m); if (!match) { throw new Error( "Missing required element: Subject line not found. Expected a line starting with 'Subject:'" ); } const subject = match[1].trim(); if (subject.length === 0) { throw new Error( "Missing required element: Subject line is empty. Expected non-empty subject text" ); } expect(subject.length).toBeGreaterThan(0); }); it("contains the {{first_name}} placeholder", () => { if (!content.includes("{{first_name}}")) { throw new Error( "Missing required element: {{first_name}} placeholder not found in template" ); } expect(content).toContain("{{first_name}}"); }); it("contains Sean Ellis option a) Very disappointed", () => { if (!content.includes("a) Very disappointed")) { throw new Error( "Missing required element: Sean Ellis answer option 'a) Very disappointed' not found in template" ); } expect(content).toContain("a) Very disappointed"); }); it("contains Sean Ellis option b) Somewhat disappointed", () => { if (!content.includes("b) Somewhat disappointed")) { throw new Error( "Missing required element: Sean Ellis answer option 'b) Somewhat disappointed' not found in template" ); } expect(content).toContain("b) Somewhat disappointed"); }); it("contains Sean Ellis option c) Not disappointed", () => { if (!content.includes("c) Not disappointed")) { throw new Error( "Missing required element: Sean Ellis answer option 'c) Not disappointed' not found in template" ); } expect(content).toContain("c) Not disappointed"); }); it("has a word count under 200", () => { const body = content.replace(/^Subject:.*$/m, "").trim(); const wordCount = body.split(/\s+/).filter((w) => w.length > 0).length; if (wordCount >= 200) { throw new Error( `Missing required element: word count constraint violated. Body has ${wordCount} words but must be under 200` ); } expect(wordCount).toBeLessThan(200); }); }); describe("feedback-playbook.md", () => { const playbookPath = path.resolve(__dirname, "../../../docs/feedback-playbook.md"); let content: string; const REQUIRED_HEADINGS = [ "## Purpose", "## Templates", "## Trigger", "## Sending Instructions", "## Reading Responses", "## Future Automation", ]; beforeAll(() => { if (!fs.existsSync(playbookPath)) { throw new Error( `Playbook file missing: ${playbookPath}. Expected file to exist at docs/feedback-playbook.md` ); } content = fs.readFileSync(playbookPath, "utf-8"); }); it("contains all required section headings", () => { for (const heading of REQUIRED_HEADINGS) { if (!content.includes(heading)) { throw new Error( `Missing required section heading: "${heading}" not found in docs/feedback-playbook.md` ); } expect(content).toContain(heading); } }); });