import { expect, test } from "bun:test"; import { diagnose, formatDiagnostic, parse } from "../src/index.ts"; test("parses WRN 0.3 execution, data, security, and reactivity blocks", () => { const ast = parse(`page Dashboard { runtime = "universal" hydrate = "visible" state count = 1 computed { doubled = count * 2 } effect { console.log(doubled) } security { auth = "required" csrf = "true" } load server { return { count: 1 } } load client { return { refreshed: true } } action save(input) { return input } view { } }`); expect(ast.runtime).toBe("universal"); expect(ast.hydrate).toBe("visible"); expect(ast.computed).toEqual([{ name: "doubled", expr: "count * 2" }]); expect(ast.effects).toHaveLength(1); expect(ast.security).toEqual({ auth: "required", csrf: "true" }); expect(ast.loads.map((load) => load.mode)).toEqual(["server", "client"]); expect(ast.actions).toEqual([expect.objectContaining({ name: "save", args: ["input"] })]); }); test("diagnoses server-only interactive roots and accessibility issues", () => { const diagnostics = diagnose( `component AvatarButton { runtime = "server" state open = false view { } }`, { file: "AvatarButton.wrn", accessibility: true }, ); expect(diagnostics.map((diagnostic) => diagnostic.code)).toContain( "WRN-RUNTIME-SERVER-INTERACTIVE", ); expect(diagnostics.map((diagnostic) => diagnostic.code)).toContain("WRN-A11Y-001"); }); test("formats parser diagnostics with stable codes and source locations", () => { const source = `page Broken { runtime = "worker"\n view {
} }`; const [diagnostic] = diagnose(source, { file: "Broken.wrn" }); expect(diagnostic?.code).toBe("WRN-RUNTIME-TARGET"); expect(formatDiagnostic(source, diagnostic!)).toContain("Broken.wrn"); }); test("parses keyed each blocks without changing legacy loop syntax", () => { const keyed = parse(`component Rows { props { rows = [] } view { {#each rows as row, index key row.id}

{index}: {row.name}

{/each} } }`); const loop = keyed.view.find((node) => node.type === "each"); expect(loop).toEqual( expect.objectContaining({ type: "each", list: "rows", item: "row", index: "index", key: "row.id", }), ); const legacy = parse(`component Rows { props { rows = [] } view { {#each rows as row}

{row.name}

{/each} } }`); expect(legacy.view.find((node) => node.type === "each")).toEqual( expect.objectContaining({ type: "each", key: undefined }), ); });