/** @jsxRuntime automatic @jsxImportSource react */
import "./test-preload.ts";
import { expect } from "@std/expect";
import { describe, test } from "@std/testing/bdd";
import { render } from "react-email";
import { Callout } from "../emails/_components/callout";
import { Footer, POSTAL_ADDRESS } from "../emails/_components/footer";
import { KeyValue } from "../emails/_components/key-value";
import { Layout, statusPageBrand } from "../emails/_components/layout";
import { renderMarkdown } from "../emails/_components/markdown";
import { Pill } from "../emails/_components/pill";
import { Steps } from "../emails/_components/steps";
import { tones } from "../emails/_components/styles";
import MonitorAlertEmail, {
type MonitorAlertProps,
monitorAlertPreheader,
monitorAlertSubject,
} from "../emails/monitor-alert";
import MonitorDeactivationEmail, {
monitorDeactivationSubject,
} from "../emails/monitor-deactivation";
import MonitorPausedEmail from "../emails/monitor-paused";
import PageSubscriptionEmail from "../emails/page-subscription";
import PrivateLocationAlertEmail, {
privateLocationAlertSubject,
} from "../emails/private-location-alert";
import StatusPageMagicLinkEmail from "../emails/status-page-magic-link";
import StatusReportEmail, {
type StatusReportProps,
statusReportPreheader,
} from "../emails/status-report";
import TeamInvitationEmail from "../emails/team-invitation";
const alert = {
type: "alert",
monitorId: 42,
name: "Ping Pong",
url: "https://openstatus.dev/ping",
method: "GET",
status: "503",
latency: "300 ms",
region: "Amsterdam, Netherlands",
timestamp: "2026-10-13T17:32:00Z",
firstSeen: "2026-10-13T17:29:00Z",
degradedAfter: 250,
message: "upstream response time 0.302s",
} satisfies MonitorAlertProps;
const report = {
pageTitle: "Acme",
reportTitle: "API unavailable",
status: "monitoring",
date: "2026-09-18T12:37:00Z",
reportStartedAt: "2026-09-18T10:23:00Z",
updateIndex: 3,
message: "We are on it.",
pageComponents: ["API", "Runners"],
componentImpacts: [
{ name: "API", impact: "partial_outage" },
{ name: "Runners", impact: "operational" },
],
statusPageUrl: "https://acme.openstatus.dev",
unsubscribeUrl: "https://acme.openstatus.dev/unsubscribe/t",
manageUrl: "https://acme.openstatus.dev/manage/t",
} satisfies StatusReportProps;
describe("primitives", () => {
test("pill maps tone to colour and uppercases its label", async () => {
for (const tone of ["danger", "warning", "success", "neutral"] as const) {
const html = await render(
x
', ); expect(html).not.toMatch(/<(script|img|p style="position)/); expect(html).toContain("<script>"); expect(html).toContain("<img src=x onerror=alert(1)>"); }); test("quotes in a link destination cannot break out of href", () => { for (const source of [ 'code<\/code>/);
});
test("images need https", () => {
expect(renderMarkdown("")).toContain(
'src="https://a.dev/i.png"',
);
expect(renderMarkdown("")).not.toContain("
{
test("region count replaces the single region", async () => {
const many = { ...alert, affectedRegions: 5, totalRegions: 6 };
const html = await render( );
expect(html).toContain("5/6");
expect(html).toContain("from 5/6 regions");
expect(monitorAlertSubject(many)).toContain("from 5/6 regions");
const one = await render(
,
);
expect(one).toContain("1/6");
expect(one).toContain(`from ${alert.region}`);
});
test("alert", async () => {
const html = await render( );
expect(html).toContain("Ping Pong is down");
expect(html).toContain("DOWN");
expect(html).not.toContain("retries");
expect(html).toContain("503");
expect(html).toContain("GET https://openstatus.dev/ping");
expect(html).toContain("Amsterdam, Netherlands");
expect(html).toContain("13 Oct, 17:29 UTC");
expect(html).toContain("13 Oct, 17:32 UTC");
expect(html).toContain("upstream response time 0.302s");
expect(html).toContain('href="https://app.openstatus.dev/monitors/42"');
expect(html).toContain(
'href="https://app.openstatus.dev/monitors/42/edit"',
);
expect(html).not.toContain("Alert rule");
});
test("degraded shows the threshold and the rule footer", async () => {
const html = await render(
,
);
expect(html).toContain("Ping Pong is answering slowly");
expect(html).toContain("DEGRADED");
expect(html).toContain("threshold 250 ms");
expect(html).toContain("latency > 250ms");
expect(html).toContain("Edit rule");
expect(html).toContain("still returning 200");
});
test("recovery", async () => {
const html = await render(
,
);
expect(html).toContain("Ping Pong is back up");
expect(html).toContain("RECOVERED");
expect(html).not.toContain("upstream response time");
});
test("optional rows disappear (TCP monitor, no incident)", async () => {
const html = await render(
,
);
expect(html).not.toContain("Response");
expect(html).not.toContain("Latency");
expect(html).not.toContain("First seen");
expect(html).not.toContain("Edit notifications");
expect(html).toContain('href="https://app.openstatus.dev/monitors"');
});
test("long messages are truncated", async () => {
const html = await render(
,
);
expect(html).toContain(`${"x".repeat(400)}…`);
expect(html).not.toContain("x".repeat(401));
});
test("subject and preheader", () => {
expect(monitorAlertSubject(alert)).toBe(
"Ping Pong is down — status 503 from Amsterdam, Netherlands",
);
expect(monitorAlertSubject({ ...alert, type: "degraded" })).toBe(
"Ping Pong is slow — 300 ms from Amsterdam, Netherlands",
);
expect(monitorAlertSubject({ ...alert, type: "recovery" })).toBe(
"Ping Pong recovered — 300 ms from Amsterdam, Netherlands",
);
expect(monitorAlertSubject({ type: "alert", region: "N/A" })).toBe(
"Your monitor is down — check failed",
);
expect(monitorAlertPreheader({ ...alert, type: "degraded" })).toBe(
"Above your 250 ms threshold.",
);
for (const type of ["alert", "degraded", "recovery"] as const) {
const props = { ...alert, type };
expect(monitorAlertPreheader(props)).not.toBe(monitorAlertSubject(props));
}
});
});
describe("private location alert", () => {
const base = {
locationName: "eu-west-private",
lastSeenAt: "2026-07-23T10:00:00Z",
};
test("error shows the checklist and skipped monitors", async () => {
const html = await render(
,
);
expect(html).toContain("UNHEALTHY");
expect(html).toContain("eu-west-private");
expect(html).toContain("are paused");
expect(html).toContain("23 Jul, 10:00 UTC");
expect(html).toContain("Checks skipped");
expect(html).toContain("4 monitors");
expect(html).toContain("Check, in this order");
expect(html).toContain("you are a member of this workspace");
expect(html).toContain("/settings/private-locations");
});
test("recovered drops the checklist; no monitors drops the row", async () => {
const html = await render(
,
);
expect(html).toContain("RECOVERED");
expect(html).toContain("are running again");
expect(html).not.toContain("Check, in this order");
expect(html).not.toContain("Checks resumed");
});
test("subject", () => {
expect(privateLocationAlertSubject({ ...base, status: "error" })).toBe(
'Checks paused — "eu-west-private" stopped reporting',
);
expect(privateLocationAlertSubject({ ...base, status: "recovered" })).toBe(
'Checks resumed — "eu-west-private" is reporting again',
);
});
});
describe("status report", () => {
test("eyebrow, components, markdown, links", async () => {
const html = await render( );
expect(html).toContain("Acme Status");
expect(html).toContain("MONITORING");
expect(html).toContain("Update 3 · 18 Sep, 12:37 UTC · 2h 14m in");
expect(html).toContain("API unavailable");
expect(html).toContain("Runners");
expect(html).toContain("Partial outage");
expect(html).toContain("Operational");
expect(html).not.toContain("●");
expect(html).toContain("We are on it.");
expect(html).toContain('href="https://acme.openstatus.dev"');
expect(html).toContain(`href="${report.unsubscribeUrl}"`);
expect(html).toContain(`href="${report.manageUrl}"`);
expect(html).not.toContain("openstatus.dev/assets/logos");
});
test("pill uses the status enum verbatim, one tone per status", async () => {
const expected = {
investigating: tones.danger,
identified: tones.warning,
monitoring: tones.info,
resolved: tones.success,
maintenance: tones.info,
};
for (const [status, tone] of Object.entries(expected)) {
const html = await render(
,
);
expect(html).toContain(status.toUpperCase());
expect(html).toContain(tone.bg);
}
});
test("unknown impact drops the value cell", async () => {
const html = await render(
,
);
expect(html).toContain("Runners");
expect(html).toContain('colSpan="2"');
expect(html).not.toContain("Operational");
expect(html).not.toContain("Partial outage");
});
test("optional blocks disappear", async () => {
const html = await render(
,
);
expect(html).not.toContain("Update 3");
expect(html).not.toContain("2h 14m in");
expect(html).not.toContain("Follow on the status page");
expect(html).not.toContain("●");
});
test("maintenance renders its window instead of a timestamp", async () => {
const html = await render(
,
);
expect(html).toContain("MAINTENANCE");
expect(html).toContain("Window");
expect(html).toContain("Mon 21 Sep, 10:00 - 12:00");
});
test("markdown headings and lists are styled, raw HTML is escaped", async () => {
const html = await render(
alert(1)
"
}
/>,
);
expect(html).toMatch(/");
expect(html).not.toContain("
{
const html = await render(
[x](javascript:alert(1))'
}
/>,
);
expect(html).not.toMatch(/\sonmouseover=/);
expect(html).not.toContain("javascript:");
expect(html).toContain(
'href="https://evil.com/x"onmouseover=alert(1)"',
);
});
test("autolinks and entities in the message survive escaping", async () => {
const html = await render(
,
);
expect(html).toContain('href="https://status.acme.dev/x"');
expect(html).toContain("R&D");
expect(html).not.toContain("&");
});
test("maintenance without eyebrow items renders no empty eyebrow", async () => {
const html = await render(
,
);
expect(html).not.toMatch(/]*letter-spacing:0\.12em[^>]*><\/p>/);
});
test("preheader never repeats the subject", () => {
expect(statusReportPreheader(report)).toBe("Monitoring: API, Runners.");
expect(statusReportPreheader({ ...report, status: "resolved" })).toBe(
"Resolved for API, Runners.",
);
expect(
statusReportPreheader({ ...report, pageComponents: [] }),
).not.toContain(report.reportTitle);
});
});
describe("inactivity pause", () => {
test("warning carries count, workspace, last sign-in, pause date and signature", async () => {
const html = await render(
,
);
expect(html).toContain("ACTION NEEDED");
expect(html).toContain("3 monitors will pause on Friday 25 September");
expect(html).toContain("Nothing gets deleted");
expect(html).toContain("acme-dev");
expect(html).toContain("Tue 21 Jul 2026");
expect(html).toContain("Fri 25 Sep 2026");
expect(html).toContain("Thibault");
expect(html).toContain("Co-founder, openstatus");
});
test("warning without context falls back and drops the rows", async () => {
const html = await render(
,
);
expect(html).toContain("Your monitors will pause on");
expect(html).not.toContain("Workspace");
expect(html).not.toContain("Last sign-in");
});
test("singular monitor", async () => {
const html = await render( );
expect(html).toContain("1 monitor has been paused");
});
test("paused", async () => {
const html = await render(
,
);
expect(html).toContain("3 monitors have been paused");
expect(html).toContain("Nothing was deleted");
expect(html).toContain("acme-dev");
const bare = await render( );
expect(bare).toContain("Your monitors have been paused");
expect(bare).not.toContain("Workspace");
});
test("subject", () => {
expect(
monitorDeactivationSubject({
deactivateAt: new Date("2026-09-25T00:00:00Z"),
}),
).toBe("Your monitors pause on 25 Sep — one sign-in stops it");
});
});
describe("account and status page mail", () => {
test("team invitation", async () => {
const html = await render(
,
);
expect(html).toContain("Join acme on openstatus");
expect(html).toContain("max@openstatus.dev");
expect(html).toContain(
'href="https://app.openstatus.dev/invite?token=tok"',
);
});
test("page subscription uses the page brand and logo", async () => {
const html = await render(
,
);
expect(html).toContain("Acme Status");
expect(html).toContain("https://acme.dev/logo.png");
expect(html).toContain('href="https://acme.openstatus.dev/verify/t"');
expect(html).not.toContain("every status report");
});
test("one-time links appear once, on the CTA only", async () => {
const link = "https://acme.openstatus.dev/verify/t";
for (const el of [
,
,
]) {
const html = await render(el);
expect(html.split(`href="${link}"`).length - 1).toBe(1);
expect(html).toContain('href="https://acme.openstatus.dev"');
}
});
test("team invitation falls back on an empty workspace name", async () => {
const html = await render(
,
);
expect(html).toContain("Join openstatus");
expect(html).not.toContain("on openstatus");
expect(html).not.toContain("Workspace");
});
test("magic link", async () => {
const html = await render(
,
);
expect(html).toContain("Sign in to Acme");
expect(html).toContain("24 hours");
expect(html).toContain('href="https://acme.openstatus.dev/verify/t"');
});
});
describe("every transactional template", () => {
const all = {
alert: ,
degraded: ,
recovery: ,
privateLocation: (
),
statusReport: ,
deactivation: (
),
paused: ,
invitation: ,
subscription: ,
magicLink: ,
};
for (const [name, element] of Object.entries(all)) {
test(`${name}: brand casing, no SVG data URIs, no flex/grid, 600px`, async () => {
const html = await render(element);
expect(html).not.toContain("OpenStatus<");
expect(html).not.toMatch(/>[^<]*OpenStatus[^<]*);
expect(html).not.toContain("data:image/svg");
expect(html).not.toMatch(/display:\s?(-webkit-)?(inline-)?(flex|grid)/);
expect(html).toContain("max-width:600px");
expect(html).toContain(POSTAL_ADDRESS);
});
}
});