release: WRNexusJS 0.8.0
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
import { expect, test } from "bun:test";
|
||||
import { parse } from "../src/index.ts";
|
||||
|
||||
test("parses schema-backed server actions", () => {
|
||||
const ast = parse(`page Users {
|
||||
action createUser using CreateUserSchema { return { id: input.name } }
|
||||
view { <form @submit='createUser'><input name='name' /></form> }
|
||||
}`);
|
||||
expect(ast.actions[0]).toMatchObject({ name: "createUser", schema: "CreateUserSchema" });
|
||||
});
|
||||
@@ -0,0 +1,39 @@
|
||||
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");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
import { expect, test } from "bun:test";
|
||||
import { parse } from "../src/index.ts";
|
||||
|
||||
test("parses declarative navigation preservation", () => {
|
||||
const ast = parse(
|
||||
`page Users { navigation { preserve = ["filters", "pagination", "scroll"] } view { <main /> } }`,
|
||||
);
|
||||
expect(ast.navigation.preserve).toBe('["filters", "pagination", "scroll"]');
|
||||
});
|
||||
@@ -1,6 +1,37 @@
|
||||
import { expect, test } from "bun:test";
|
||||
import { diagnose, formatDiagnostic, parse } from "../src/index.ts";
|
||||
|
||||
test("parses explicit rendering modes and the never hydration alias", () => {
|
||||
const ast = parse(`page Marketing {
|
||||
render = "static"
|
||||
hydrate = "never"
|
||||
view { <h1>Fast</h1> }
|
||||
}`);
|
||||
expect(ast.renderMode).toBe("static");
|
||||
expect(ast.hydrate).toBe("none");
|
||||
expect(() => parse('page Invalid { render = "sometimes" view { <p>No</p> } }')).toThrow(
|
||||
"Unknown render mode",
|
||||
);
|
||||
});
|
||||
|
||||
test("parses a declarative cache policy", () => {
|
||||
const ast = parse(`page Dashboard {
|
||||
cache {
|
||||
strategy = "stale-while-revalidate"
|
||||
ttl = "5m"
|
||||
tags = ["users", "dashboard"]
|
||||
vary = ["tenant", "language"]
|
||||
}
|
||||
view { <h1>Dashboard</h1> }
|
||||
}`);
|
||||
expect(ast.cache).toEqual({
|
||||
strategy: "stale-while-revalidate",
|
||||
ttl: "5m",
|
||||
tags: '["users", "dashboard"]',
|
||||
vary: '["tenant", "language"]',
|
||||
});
|
||||
});
|
||||
|
||||
test("parses native array and object literals in state and component props", () => {
|
||||
const ast = parse(`
|
||||
component Navigation {
|
||||
@@ -111,7 +142,7 @@ test("diagnoses server-only interactive roots and accessibility issues", () => {
|
||||
});
|
||||
|
||||
test("formats parser diagnostics with stable codes and source locations", () => {
|
||||
const source = `page Broken { runtime = "worker"\n view { <main></main> } }`;
|
||||
const source = `page Broken { runtime = "quantum"\n view { <main></main> } }`;
|
||||
const [diagnostic] = diagnose(source, { file: "Broken.wrn" });
|
||||
|
||||
expect(diagnostic?.code).toBe("WRN-RUNTIME-TARGET");
|
||||
@@ -161,3 +192,11 @@ test("parses public component event declarations inside props", () => {
|
||||
expect(ast.props.map((prop) => prop.name)).toEqual(["value"]);
|
||||
expect(ast.events).toEqual([{ name: "search" }, { name: "clear" }]);
|
||||
});
|
||||
|
||||
test("parses edge and worker execution targets", () => {
|
||||
for (const runtime of ["edge", "worker", "service-worker"] as const) {
|
||||
expect(parse(`page Runtime { runtime = "${runtime}" view { <p>Hi</p> } }`).runtime).toBe(
|
||||
runtime,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user