import { expect, test } from "bun:test";
import {
compilePlayground,
createPlaygroundHandler,
decodePlaygroundShare,
encodePlaygroundShare,
} from "../src/index.ts";
const source = `component Hello { props { name = "World" } view {
Hello {name}
} }`;
test("playground exposes generated, client, SSR-shaped and diagnostic output", () => {
const result = compilePlayground(source);
expect(result.generated).toContain("export function render");
expect(result.client).toContain("Hello");
expect(result.html).toContain("Hello");
expect(result.interactiveHtml).toContain("Content-Security-Policy");
expect(result.diagnostics).toEqual([]);
});
test("share URLs round-trip Unicode and enforce bounds", () => {
const unicode = `${source}\n// नमस्ते`;
expect(decodePlaygroundShare(encodePlaygroundShare(unicode))).toBe(unicode);
expect(() => encodePlaygroundShare("x".repeat(70_000))).toThrow("WRN-PLAYGROUND-SHARE-LIMIT");
});
test("deployable handler compiles and serves a sandboxed CSP page", async () => {
const handler = createPlaygroundHandler();
const response = await handler(
new Request("https://play.test/api/compile", {
method: "POST",
body: JSON.stringify({ source }),
}),
);
expect(response.status).toBe(200);
expect(await response.json()).toHaveProperty("share");
const html = await handler(new Request("https://play.test/"));
expect(html.headers.get("content-security-policy")).toContain("script-src 'self'");
const page = await html.text();
expect(page).toContain('sandbox="allow-scripts"');
expect(page).toContain('id="compare"');
expect(page).toContain('id="examples"');
});
test("handler exposes examples and optional version comparisons", async () => {
const handler = createPlaygroundHandler({
examples: { hello: source },
versions: [{ version: "0.7.0", compile: async () => compilePlayground(source, "0.7.0") }],
});
const examples = await handler(new Request("https://play.test/api/examples"));
expect(await examples.json()).toEqual({ hello: source });
const comparison = await handler(
new Request("https://play.test/api/compile", {
method: "POST",
body: JSON.stringify({ source, versions: true }),
}),
);
const result = (await comparison.json()) as { comparisons: Array<{ version: string }> };
expect(result.comparisons[0]?.version).toBe("0.7.0");
});
test("reactive preview interprets only bounded state operations", () => {
const result = compilePlayground(
`component Counter {
state count = 0
functions { client function increment(): void { count++ } }
view { }
}`,
);
expect(result.interactiveHtml).toContain('"operation":"++"');
expect(result.interactiveHtml).toContain("data-play-event-click");
});