101 lines
4.0 KiB
TypeScript
101 lines
4.0 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import { formatWrn, parse } from "../src/index.ts";
|
|
|
|
const options = {
|
|
insertSpaces: true,
|
|
tabSize: 2,
|
|
printWidth: 70,
|
|
multilineAttributes: true,
|
|
} as const;
|
|
|
|
describe("canonical WRN formatter", () => {
|
|
test("formats declarations, structured values, markup, and imports idempotently", () => {
|
|
const source = `import Card from "@/components/Card.wrn"
|
|
component Demo {
|
|
props { title: string = "Hello" items = [{ id: 1, label: "One" }] }
|
|
view {
|
|
<Card title='{title}' items='{items}' class="very-long-utility-name another-long-utility-name"><strong>{title}</strong></Card>
|
|
}
|
|
}`;
|
|
const formatted = formatWrn(source, options);
|
|
|
|
expect(formatted).toContain('import Card from "@/components/Card.wrn"');
|
|
expect(formatted).toContain('props {\n title: string = "Hello"');
|
|
expect(formatted).toContain('items = [{ id: 1, label: "One" }]');
|
|
expect(formatted).toContain("<Card\n");
|
|
expect(formatWrn(formatted, options)).toBe(formatted);
|
|
expect(() => parse(formatted)).not.toThrow();
|
|
});
|
|
|
|
test("preserves comments and normalizes the final newline", () => {
|
|
const source = `// leading comment\r\npage Home {\r\nview { <!-- keep --> <p>Home</p> }\r\n}`;
|
|
const formatted = formatWrn(source, options);
|
|
|
|
expect(formatted.startsWith("// leading comment\n")).toBe(true);
|
|
expect(formatted).toContain("<!-- keep -->");
|
|
expect(formatted.endsWith("\n")).toBe(true);
|
|
expect(formatted).not.toContain("\r");
|
|
});
|
|
});
|
|
|
|
test("preserves preformatted code examples while formatting surrounding markup", () => {
|
|
const source = `page Docs {
|
|
view {
|
|
<section class="docs">
|
|
<pre><code><span class="code-muted">// One project, one language</span>
|
|
<span class="code-key">page</span> ProductDashboard {
|
|
<span class="code-key">state</span> count: number = 0
|
|
<button @click='count++'>Ship {count}</button>
|
|
}</code></pre>
|
|
</section>
|
|
}
|
|
}
|
|
`;
|
|
const formatted = formatWrn(source, options);
|
|
expect(formatted)
|
|
.toContain(`<pre><code><span class="code-muted">// One project, one language</span>
|
|
<span class="code-key">page</span> ProductDashboard {
|
|
<span class="code-key">state</span> count: number = 0`);
|
|
expect(formatWrn(formatted, options)).toBe(formatted);
|
|
expect(() => parse(formatted)).not.toThrow();
|
|
});
|
|
|
|
test("does not split an attribute-free opening tag delimiter", () => {
|
|
const source = `page Docs {
|
|
view {
|
|
<p>This is intentionally long documentation copy that should wrap as content without formatting the opening p tag as separate less-than and greater-than lines.</p>
|
|
}
|
|
}
|
|
`;
|
|
const formatted = formatWrn(source, options);
|
|
expect(formatted).toContain(" <p>\n");
|
|
expect(formatted).not.toContain(" <p\n >");
|
|
expect(formatWrn(formatted, options)).toBe(formatted);
|
|
});
|
|
|
|
test("preserves balanced compact sibling markup without indentation drift", () => {
|
|
const source = `page Compact {
|
|
view {
|
|
<div class="strip"><span>Page</span><b>→</b><span>API</span></div>
|
|
}
|
|
}\n`;
|
|
const formatted = formatWrn(source, { tabSize: 2, printWidth: 80 });
|
|
expect(formatted).toContain('<div class="strip"><span>Page</span><b>→</b><span>API</span></div>');
|
|
expect(formatWrn(formatted, { tabSize: 2, printWidth: 80 })).toBe(formatted);
|
|
});
|
|
|
|
test("formats large typed JSON prop defaults and remains idempotent", () => {
|
|
const source = `component Catalog {
|
|
props {
|
|
categories: unknown[] = [{"label":"Platform & Core","value":"platform","apps":[{"label":"WRNexus Home / Business Command Center","href":"/products/home","number":"01"},{"label":"SSO & Account","href":"/products/sso","number":"02"}]},{"label":"Sales & Customer","value":"sales","apps":[{"label":"CRM","href":"/products/crm","number":"11"}]}]
|
|
}
|
|
view { <div></div> }
|
|
}`;
|
|
const formatted = formatWrn(source, options);
|
|
|
|
expect(formatted).toContain(`categories: unknown[] = [\n {\n "label": "Platform & Core"`);
|
|
expect(formatted).toContain(`"apps": [\n {`);
|
|
expect(formatWrn(formatted, options)).toBe(formatted);
|
|
expect(() => parse(formatted)).not.toThrow();
|
|
});
|