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
@@ -3,18 +3,40 @@ import { importMjml, renderEmail } from "../src/index.ts";
|
||||
|
||||
const parse = (columns: string) => {
|
||||
let id = 0;
|
||||
return importMjml(`<mjml><mj-body><mj-section>${columns}</mj-section></mj-body></mjml>`, { subject: "Imported", id: () => `n${++id}` });
|
||||
return importMjml(`<mjml><mj-body><mj-section>${columns}</mj-section></mj-body></mjml>`, {
|
||||
subject: "Imported",
|
||||
id: () => `n${++id}`,
|
||||
});
|
||||
};
|
||||
|
||||
test("imported columns form one native row with preserved order and exact width totals", async () => {
|
||||
for (const widths of [["", ""], ["33%", ""], ["", "", ""], ["25%", "75%"]]) {
|
||||
const result = parse(widths.map((width, index) => `<mj-column${width ? ` width="${width}"` : ""}><mj-text>Column ${index}</mj-text></mj-column>`).join(""));
|
||||
for (const widths of [
|
||||
["", ""],
|
||||
["33%", ""],
|
||||
["", "", ""],
|
||||
["25%", "75%"],
|
||||
]) {
|
||||
const result = parse(
|
||||
widths
|
||||
.map(
|
||||
(width, index) =>
|
||||
`<mj-column${width ? ` width="${width}"` : ""}><mj-text>Column ${index}</mj-text></mj-column>`,
|
||||
)
|
||||
.join(""),
|
||||
);
|
||||
expect(result.ok).toBe(true);
|
||||
if (!result.ok) continue;
|
||||
const row = result.value.root.slots.content[0]!.slots.content[0]!;
|
||||
expect(row.type).toBe("layout.columns");
|
||||
expect(row.slots.columns.map(column => column.slots.content[0]!.props.text)).toEqual(widths.map((_, index) => `Column ${index}`));
|
||||
expect(row.slots.columns.reduce((sum, column) => sum + Number.parseFloat(String(column.props.width)), 0)).toBeCloseTo(100, 8);
|
||||
expect(row.slots.columns.map((column) => column.slots.content[0]!.props.text)).toEqual(
|
||||
widths.map((_, index) => `Column ${index}`),
|
||||
);
|
||||
expect(
|
||||
row.slots.columns.reduce(
|
||||
(sum, column) => sum + Number.parseFloat(String(column.props.width)),
|
||||
0,
|
||||
),
|
||||
).toBeCloseTo(100, 8);
|
||||
const rendered = await renderEmail(result.value, { mjml: true });
|
||||
expect(rendered.ok).toBe(true);
|
||||
if (rendered.ok) expect(rendered.value.exports?.mjml).toContain("<mj-column");
|
||||
@@ -27,12 +49,23 @@ test("import rejects invalid URLs, dimensions, widths, and native slot limits",
|
||||
'<mj-column><mj-image src="https://example.com/x.png" width="99999px" /></mj-column>',
|
||||
'<mj-column width="75%"></mj-column><mj-column width="75%"></mj-column>',
|
||||
'<mj-column width="400px"></mj-column>',
|
||||
Array(5).fill('<mj-column><mj-text>X</mj-text></mj-column>').join(""),
|
||||
]) expect(parse(input).ok).toBe(false);
|
||||
Array(5).fill("<mj-column><mj-text>X</mj-text></mj-column>").join(""),
|
||||
])
|
||||
expect(parse(input).ok).toBe(false);
|
||||
});
|
||||
|
||||
test("import enforces depth limits and rejects repeated instance IDs", () => {
|
||||
const nested = '<mjml><mj-body>' + '<mj-wrapper>'.repeat(100) + '<mj-section><mj-column><mj-text>X</mj-text></mj-column></mj-section>' + '</mj-wrapper>'.repeat(100) + '</mj-body></mjml>';
|
||||
const nested =
|
||||
"<mjml><mj-body>" +
|
||||
"<mj-wrapper>".repeat(100) +
|
||||
"<mj-section><mj-column><mj-text>X</mj-text></mj-column></mj-section>" +
|
||||
"</mj-wrapper>".repeat(100) +
|
||||
"</mj-body></mjml>";
|
||||
expect(importMjml(nested, { subject: "Depth", id: () => "id" }).ok).toBe(false);
|
||||
expect(importMjml('<mjml><mj-body><mj-section><mj-column><mj-text>X</mj-text></mj-column></mj-section></mj-body></mjml>', { subject: "IDs", id: () => "same" }).ok).toBe(false);
|
||||
expect(
|
||||
importMjml(
|
||||
"<mjml><mj-body><mj-section><mj-column><mj-text>X</mj-text></mj-column></mj-section></mj-body></mjml>",
|
||||
{ subject: "IDs", id: () => "same" },
|
||||
).ok,
|
||||
).toBe(false);
|
||||
});
|
||||
Reference in new issue
Block a user