/**
* The complete email that each of the site's own templates sends.
*
* Every other check here reads for a fragment, so a render that kept the
* opening and lost the ticket link, a row, or a whole conditional block would
* still pass. These read the whole email, so nothing can go missing quietly.
*
* One booking of one ticket on a free listing, with nothing owed, which is the
* shape that leaves every conditional block out. The blocks themselves have
* their own checks in `render-content.test.ts`.
*/
import { assertStringIncludes } from "@std/assert";
import { expect } from "@std/expect";
import { describe, it as test } from "@std/testing/bdd";
import { renderEmailContent } from "#shared/email-renderer.ts";
import type { EmailContent } from "#templates/email/shared.ts";
import { makeTestEntry as makeEntry } from "#test-utils/factories.ts";
import type { EmailTemplateType } from "#types";
import { buildTestData, describeEmailRenderer } from "./test-helpers.ts";
const WHOLE_EMAIL = {
admin: {
html: `
New registration
- Name: Jane Doe
- Email: jane@example.com
- Phone: 555-1234
| Listing | Qty | Price |
| Test Listing | 1 | |
`,
subject: "New registration: Jane Doe for Test Listing",
text: `New registration
Name: Jane Doe
Email: jane@example.com
Phone: 555-1234
Test Listing: 1 ticket`,
},
confirmation: {
html: `
Thanks for registering!
You're confirmed for Test Listing.
| Listing | Qty | Price |
| Test Listing | 1 | |
View your tickets
Or copy this link: https://example.com/t/ABC
`,
subject: "Your tickets for Test Listing",
text: `Thanks for registering!
You're confirmed for Test Listing.
Test Listing: 1 ticket
View your tickets: https://example.com/t/ABC`,
},
} as const satisfies Record;
const EVERY_PART = ["subject", "html", "text"] as const;
describeEmailRenderer(() => {
describe("the whole email the site's own wording sends", () => {
for (const [which, whole] of Object.entries(WHOLE_EMAIL)) {
for (const part of EVERY_PART) {
test(`the ${which} email's ${part}, whole`, async () => {
const data = await buildTestData([makeEntry()]);
const sent = await renderEmailContent(
which as EmailTemplateType,
data,
);
expect(sent[part]).toBe(whole[part]);
});
}
}
});
});
describe("the whole email the site's own wording sends with answers", () => {
describeEmailRenderer(() => {
const data = () =>
buildTestData([makeEntry()], {
answerLines: new Map([
[
42,
new Map([
[
1,
[
{
question: "Any allergies?",
text: "Peanuts and nuts",
},
],
],
]),
],
]),
});
test("the confirmation prints each answer", async () => {
const sent = await renderEmailContent("confirmation", await data());
assertStringIncludes(
sent.text,
"Any allergies?: Peanuts and nuts",
);
assertStringIncludes(
sent.html,
"Any allergies?: Peanuts <b>and</b> nuts",
);
});
test("the admin notification prints each answer with its listing", async () => {
const sent = await renderEmailContent("admin", await data());
assertStringIncludes(
sent.text,
"Any allergies? (Test Listing): Peanuts and nuts",
);
assertStringIncludes(
sent.html,
"Any allergies? (Test Listing): Peanuts <b>and</b> nuts",
);
});
});
});