feat: release design system engine, studio and component contracts
This commit is contained in:
1 parent
ff1065fb27
commit
3943b946d6
693 files changed
+175546
-3894
No files matched your search
@@ -115,12 +115,23 @@ test("marketing image dimensions reject invalid or injected values", async () =>
|
||||
});
|
||||
|
||||
test("video exports preserve thumbnail proportions, safe destination and accessible text", async () => {
|
||||
const draft = document("content.video", { title: "Watch & learn", href: "https://example.com/watch?a=1&b=2", thumbnail: "https://example.com/poster.png", alt: 'Demo & "preview"', width: "360", height: "240" });
|
||||
const draft = document("content.video", {
|
||||
title: "Watch & learn",
|
||||
href: "https://example.com/watch?a=1&b=2",
|
||||
thumbnail: "https://example.com/poster.png",
|
||||
alt: 'Demo & "preview"',
|
||||
width: "360",
|
||||
height: "240",
|
||||
});
|
||||
const before = JSON.stringify(draft);
|
||||
const result = await renderEmail(draft, { amp: true, mjml: true });
|
||||
expect(result.ok).toBe(true);
|
||||
if (!result.ok) return;
|
||||
for (const output of [result.value.parts.html.content, result.value.parts.amp?.content, result.value.exports?.mjml]) {
|
||||
for (const output of [
|
||||
result.value.parts.html.content,
|
||||
result.value.parts.amp?.content,
|
||||
result.value.exports?.mjml,
|
||||
]) {
|
||||
expect(output).toContain('href="https://example.com/watch?a=1&b=2"');
|
||||
expect(output).toContain('src="https://example.com/poster.png"');
|
||||
expect(output).toContain('alt="Demo & "preview""');
|
||||
@@ -128,29 +139,46 @@ test("video exports preserve thumbnail proportions, safe destination and accessi
|
||||
expect(result.value.parts.html.content).toContain('width="360" height="240"');
|
||||
expect(result.value.parts.amp?.content).toContain('width="360" height="240" layout="responsive"');
|
||||
expect(result.value.exports?.mjml).toContain('width="360px" height="240px"');
|
||||
expect(result.value.parts.text.content).toContain("Watch & learn: https://example.com/watch?a=1&b=2");
|
||||
expect(result.value.parts.text.content).toContain(
|
||||
"Watch & learn: https://example.com/watch?a=1&b=2",
|
||||
);
|
||||
expect(result.value.parts.amp?.validation.valid).toBe(true);
|
||||
expect(await validateMjml(result.value.exports!.mjml!)).toEqual([]);
|
||||
expect(JSON.stringify(draft)).toBe(before);
|
||||
});
|
||||
|
||||
test("social exports include only configured networks and retain safe links in plain text", async () => {
|
||||
const props = { label: "Follow & connect", facebook: "https://example.com/facebook?a=1&b=2", linkedin: "https://example.com/linkedin", instagram: "", x: "" };
|
||||
const props = {
|
||||
label: "Follow & connect",
|
||||
facebook: "https://example.com/facebook?a=1&b=2",
|
||||
linkedin: "https://example.com/linkedin",
|
||||
instagram: "",
|
||||
x: "",
|
||||
};
|
||||
const result = await renderEmail(document("content.social", props), { amp: true, mjml: true });
|
||||
expect(result.ok).toBe(true);
|
||||
if (!result.ok) return;
|
||||
for (const output of [result.value.parts.html.content, result.value.parts.amp?.content, result.value.exports?.mjml]) {
|
||||
for (const output of [
|
||||
result.value.parts.html.content,
|
||||
result.value.parts.amp?.content,
|
||||
result.value.exports?.mjml,
|
||||
]) {
|
||||
expect(output).toContain("Follow & connect");
|
||||
expect(output).toContain('href="https://example.com/facebook?a=1&b=2"');
|
||||
expect(output).toContain('href="https://example.com/linkedin"');
|
||||
expect(output).not.toContain(">Instagram</a>");
|
||||
expect(output).not.toContain(">X</a>");
|
||||
}
|
||||
expect(result.value.parts.text.content).toContain("Facebook: https://example.com/facebook?a=1&b=2");
|
||||
expect(result.value.parts.text.content).toContain(
|
||||
"Facebook: https://example.com/facebook?a=1&b=2",
|
||||
);
|
||||
expect(result.value.parts.text.content).toContain("LinkedIn: https://example.com/linkedin");
|
||||
expect(result.value.parts.amp?.validation.valid).toBe(true);
|
||||
expect(await validateMjml(result.value.exports!.mjml!)).toEqual([]);
|
||||
expect((await renderEmail(document("content.social", { ...props, facebook: "javascript:alert(1)" }))).ok).toBe(false);
|
||||
expect(
|
||||
(await renderEmail(document("content.social", { ...props, facebook: "javascript:alert(1)" })))
|
||||
.ok,
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
test("basic images, video thumbnails and spacers validate dimensions before rendering", async () => {
|
||||
|
||||
Reference in new issue
Block a user