release: WRNexusJS 0.2.31

This commit is contained in:
2026-07-14 21:58:19 +05:30
parent 3cfdc747fa
commit 8b4b7ca5ac
58 changed files with 1152 additions and 196 deletions
+193
View File
@@ -243,3 +243,196 @@ layout AppLayout {
expect(output).toContain("export function render");
});
test("parses component lifecycle hooks", () => {
const ast = parse(`
component BackToTop {
state visible = false
lifecycle {
mount {
visible = true
}
update {
console.log(visible)
}
unmount {
visible = false
}
}
view {
<button>Top</button>
}
}
`);
expect(ast.lifecycle.mount).toContain("visible = true");
expect(ast.lifecycle.update).toContain("console.log(visible)");
expect(ast.lifecycle.unmount).toContain("visible = false");
});
test("parses state watchers", () => {
const ast = parse(`
component Menu {
state open = false
watch open {
console.log("Open changed", open)
}
view {
<button>{open}</button>
}
}
`);
expect(ast.watches).toEqual([
{
state: "open",
body: expect.stringContaining('console.log("Open changed", open)'),
},
]);
});
test("rejects watching an undeclared state", () => {
expect(() =>
parse(`
component Broken {
watch missing {
console.log(missing)
}
view {
<div>Broken</div>
}
}
`),
).toThrow("Cannot watch undeclared state 'missing'");
});
test("rejects unknown lifecycle hooks", () => {
expect(() =>
parse(`
component Broken {
lifecycle {
created {
console.log("invalid")
}
}
view {
<div>Broken</div>
}
}
`),
).toThrow("Unknown lifecycle hook 'created'");
});
test("component functions compile into browser behavior metadata", () => {
const output = generate(
parse(`
component Counter {
state count = 0
functions {
function increment() {
count += 1
}
}
view {
<button @click="increment()">
{count}
</button>
}
}
`),
);
expect(output).toContain("data-wrn-behavior");
expect(output).toContain("function increment()");
expect(output).toContain("export const __wrnexusBehavior");
});
test("component lifecycle hooks compile into behavior metadata", () => {
const output = generate(
parse(`
component LifecycleTest {
state ready = false
lifecycle {
mount {
ready = true
}
update {
console.log(ready)
}
unmount {
ready = false
}
}
view {
<div>{ready}</div>
}
}
`),
);
expect(output).toContain("&quot;mount&quot;");
expect(output).toContain("&quot;update&quot;");
expect(output).toContain("&quot;unmount&quot;");
});
test("component watchers compile into behavior metadata", () => {
const output = generate(
parse(`
component WatchTest {
state visible = false
watch visible {
console.log("changed", visible)
}
view {
<div>{visible}</div>
}
}
`),
);
expect(output).toContain("&quot;state&quot;:&quot;visible&quot;");
expect(output).toContain("console.log");
});
test("behavior-only components still receive a reactive scope", () => {
const output = generate(
parse(`
component BehaviorOnly {
functions {
function sayHello() {
console.log("hello")
}
}
lifecycle {
mount {
sayHello()
}
}
view {
<div>Hello</div>
}
}
`),
);
expect(output).toContain("data-scope");
expect(output).toContain("data-wrn-behavior");
});