120 lines
4.6 KiB
TypeScript
120 lines
4.6 KiB
TypeScript
import "../setup.ts";
|
|
import {
|
|
assert,
|
|
assertEquals,
|
|
assertFalse,
|
|
assertStringIncludes,
|
|
} from "@std/assert";
|
|
import { EmailKit, esc } from "../../mail/layout.ts";
|
|
import { EMAIL_STYLES } from "../../mail/styles.ts";
|
|
import { STYLE_NAMES } from "../../../shared/theme.ts";
|
|
|
|
const doc = (kit: EmailKit) =>
|
|
kit.render({
|
|
subject: "S <1>",
|
|
preheader: "P & Q",
|
|
markdown:
|
|
"# T\n\nbody\n\n## One\n\nfirst\n\n## Two\n\nsecond\n\n---\n\nwhy\n\n[Settings](https://x.test/?a=1&b=2)",
|
|
}).html;
|
|
|
|
Deno.test("esc: user text never becomes markup", () => {
|
|
assertEquals(
|
|
esc(`<b a="1">'&'</b>`),
|
|
"<b a="1">'&'</b>",
|
|
);
|
|
});
|
|
|
|
Deno.test("EmailKit: auto inlines light and recolors in a dark media block", () => {
|
|
const html = doc(new EmailKit({ style: "smooth", scheme: "auto" }));
|
|
const { light, dark } = EMAIL_STYLES.smooth;
|
|
assertStringIncludes(html, `background-color:${light.card}`);
|
|
assertStringIncludes(html, "@media (prefers-color-scheme:dark)");
|
|
assertStringIncludes(
|
|
html,
|
|
`.b-card{background-color:${dark.card}!important}`,
|
|
);
|
|
assertStringIncludes(html, `content="light dark"`);
|
|
// The subject, preheader and link are escaped where they land.
|
|
assertStringIncludes(html, "<title>S <1></title>");
|
|
assertStringIncludes(html, "P & Q");
|
|
assertStringIncludes(html, `href="https://x.test/?a=1&b=2"`);
|
|
});
|
|
|
|
Deno.test("EmailKit: a chosen scheme is the only one sent", () => {
|
|
const { light, dark } = EMAIL_STYLES.kanagawa;
|
|
const darkHtml = doc(
|
|
new EmailKit({ style: "kanagawa", scheme: "dark" }),
|
|
);
|
|
assertStringIncludes(darkHtml, `background-color:${dark.card}`);
|
|
assertFalse(darkHtml.includes(light.card));
|
|
assertFalse(darkHtml.includes("prefers-color-scheme"));
|
|
assertStringIncludes(darkHtml, `content="dark"`);
|
|
const lightHtml = doc(
|
|
new EmailKit({ style: "kanagawa", scheme: "light" }),
|
|
);
|
|
assertStringIncludes(lightHtml, `background-color:${light.card}`);
|
|
assertFalse(lightHtml.includes("prefers-color-scheme"));
|
|
});
|
|
|
|
Deno.test("EmailKit: every style draws its own card and font", () => {
|
|
for (const name of STYLE_NAMES) {
|
|
const style = EMAIL_STYLES[name];
|
|
const html = doc(new EmailKit({ style: name, scheme: "light" }));
|
|
assertStringIncludes(html, `background-color:${style.light.card}`);
|
|
assertStringIncludes(html, `font-family:${style.font}`);
|
|
assertEquals(html.includes("fonts.googleapis.com"), !!style.webFont, name);
|
|
}
|
|
// The rainbow and the hard shadow are what GeoCities and Brutalist look like.
|
|
const geo = new EmailKit({ style: "geocities", scheme: "light" });
|
|
assertStringIncludes(
|
|
geo.section("A", "", false),
|
|
"linear-gradient(90deg,#ff004d",
|
|
);
|
|
// On "auto" the dark rainbow replaces the light one, divider and bar alike.
|
|
const geoAuto = doc(new EmailKit({ style: "geocities", scheme: "auto" }));
|
|
assertStringIncludes(
|
|
geoAuto,
|
|
`.grad{background-color:#ff004d!important;background-image:linear-gradient(90deg,#ff004d`,
|
|
);
|
|
assertStringIncludes(geoAuto, `class="grad"`);
|
|
const brutal = doc(
|
|
new EmailKit({ style: "brutalist", scheme: "light" }),
|
|
);
|
|
assert(brutal.includes("box-shadow:5px 5px 0"));
|
|
});
|
|
|
|
Deno.test("EmailKit.render: the Markdown is the text part, and its blocks take the style", () => {
|
|
const kit = new EmailKit({ style: "smooth", scheme: "light" });
|
|
const markdown = [
|
|
"*Eyebrow*",
|
|
"# Title",
|
|
"## Section",
|
|
"**12** upvotes",
|
|
"- **@lou** said hi *Fri*\n > a quote",
|
|
"1.  [A dump](https://x.test/d) *yours* · by @lou",
|
|
"[Do it](https://x.test/go)",
|
|
"```\nhttps://x.test/raw\n```",
|
|
"*A note.*",
|
|
"---",
|
|
"Why you get this.",
|
|
].join("\n\n");
|
|
const { html, text } = kit.render({ subject: "S", preheader: "P", markdown });
|
|
assertEquals(text, markdown);
|
|
const { light } = EMAIL_STYLES.smooth;
|
|
assertStringIncludes(html, "text-transform:uppercase;margin:0 0 8px;");
|
|
assertStringIncludes(html, ">Title</h1>");
|
|
assertStringIncludes(html, `font-size:22px;`);
|
|
assertStringIncludes(html, "“a quote”");
|
|
assertStringIncludes(html, `>1</td>`);
|
|
assertStringIncludes(html, `width="64" height="48"`);
|
|
assertStringIncludes(html, `>A dump</a>`);
|
|
assertStringIncludes(html, `>yours</span>`);
|
|
assertStringIncludes(html, `>by @lou</div>`);
|
|
assertStringIncludes(html, `background-color:${light.accent};`);
|
|
assertStringIncludes(html, ">Do it</a></td></tr></table>");
|
|
assertStringIncludes(html, "word-break:break-all;");
|
|
assertStringIncludes(html, "Why you get this.</td>");
|
|
// A divider takes its color after the shorthand that would reset it.
|
|
assertFalse(html.includes(`border-color:${light.rule};border-top`));
|
|
});
|