105 lines
3.7 KiB
TypeScript
105 lines
3.7 KiB
TypeScript
import "../setup.ts";
|
|
import { assert, assertFalse, assertStringIncludes } from "@std/assert";
|
|
import { type DigestContent, renderDigestEmail } from "../../mail/digest.ts";
|
|
|
|
const links = {
|
|
notifications: "https://g.test/notifications",
|
|
followed: "https://g.test/~/followed",
|
|
chat: "https://g.test/?chat=open",
|
|
settings: "https://g.test/users/ann/~/settings",
|
|
unsubscribe: "https://g.test/unsubscribe?token=t",
|
|
};
|
|
const dump = (title: string, over = {}) => ({
|
|
title,
|
|
url: "https://g.test/dumps/x",
|
|
poster: "bob",
|
|
domain: "example.com",
|
|
thumbnail: "https://g.test/api/dumps/x/thumbnail?v=1",
|
|
votes: 1,
|
|
comments: 0,
|
|
mine: false,
|
|
...over,
|
|
});
|
|
|
|
Deno.test("renderDigestEmail: the weekly digest escapes what users wrote and links to unsubscribe", () => {
|
|
const content: DigestContent = {
|
|
cadence: "weekly",
|
|
from: new Date("2026-09-27T08:00:00Z"),
|
|
to: new Date("2026-10-04T08:00:00Z"),
|
|
reader: "ann",
|
|
activity: {
|
|
counts: { upvotes: 12, followers: 1 },
|
|
highlights: [{
|
|
kind: "comment",
|
|
who: "bob",
|
|
target: { title: "<script>x</script>", url: "https://g.test/dumps/y" },
|
|
quote: "a <b>bold</b> claim",
|
|
at: new Date("2026-09-30T10:00:00Z"),
|
|
}],
|
|
total: 13,
|
|
},
|
|
network: { dumps: [dump("Net & work")], more: 2 },
|
|
top: [dump("Mine", { mine: true, votes: 4 })],
|
|
community: null,
|
|
links,
|
|
};
|
|
const email = renderDigestEmail(content, { style: "smooth", scheme: "auto" });
|
|
assertStringIncludes(email.subject, "Your week on gerbeur, Sep 27");
|
|
assertFalse(email.html.includes("<script>x"));
|
|
assertStringIncludes(email.html, "<script>x</script>");
|
|
assertStringIncludes(email.html, "a <b>bold</b> claim");
|
|
assertStringIncludes(email.html, "Net & work");
|
|
assertStringIncludes(email.html, "2 more on your Followed feed");
|
|
assertStringIncludes(email.html, ">yours</span>");
|
|
assertStringIncludes(email.html, `href="${links.unsubscribe}"`);
|
|
assertStringIncludes(
|
|
email.html,
|
|
"12 upvotes, 1 new follower, and 3 new dumps",
|
|
);
|
|
// The plain-text part is Markdown, with what users wrote escaped.
|
|
assertStringIncludes(email.text, "# Your week, ann");
|
|
assertStringIncludes(email.text, "## From people you follow");
|
|
assertStringIncludes(
|
|
email.text,
|
|
"[Turn off weekly digests](https://g.test/unsubscribe?token=t)",
|
|
);
|
|
assertStringIncludes(
|
|
email.text,
|
|
"[\\<script\\>x\\</script\\>](https://g.test/dumps/y)",
|
|
);
|
|
assertStringIncludes(email.text, " > a \\<b\\>bold\\</b\\> claim");
|
|
assertFalse(email.html.includes("Community"));
|
|
});
|
|
|
|
Deno.test("renderDigestEmail: the monthly recap leads with a wide image and the month's totals", () => {
|
|
const content: DigestContent = {
|
|
cadence: "monthly",
|
|
from: new Date("2026-09-04T08:00:00Z"),
|
|
to: new Date("2026-10-04T08:00:00Z"),
|
|
reader: "ann",
|
|
activity: null,
|
|
network: null,
|
|
top: [dump("First"), dump("Second"), dump("Third"), dump("Fourth")],
|
|
community: {
|
|
members: [{ username: "cy", invitedBy: "ann" }],
|
|
membersMore: 0,
|
|
playlists: [],
|
|
playlistsMore: 0,
|
|
chatMessages: 1284,
|
|
totals: { dumps: 203, upvotes: 911, comments: 402 },
|
|
},
|
|
links,
|
|
};
|
|
const email = renderDigestEmail(content, {
|
|
style: "melange",
|
|
scheme: "light",
|
|
});
|
|
assertStringIncludes(email.subject, "The month on gerbeur");
|
|
assertStringIncludes(email.html, `width="528"`);
|
|
assertStringIncludes(email.html, "1,284");
|
|
assertStringIncludes(email.html, "invited by you");
|
|
assertStringIncludes(email.html, "Turn off monthly recaps");
|
|
// Only #2 and #3 get a thumbnail beside the hero.
|
|
assert(email.html.match(/<img[^>]*width="64"/g)?.length === 2);
|
|
});
|