69 lines
2.8 KiB
TypeScript
69 lines
2.8 KiB
TypeScript
import { expect, test } from "bun:test";
|
|
import {
|
|
compilePlayground,
|
|
createPlaygroundHandler,
|
|
decodePlaygroundShare,
|
|
encodePlaygroundShare,
|
|
} from "../src/index.ts";
|
|
|
|
const source = `component Hello { props { name = "World" } view { <h1>Hello {name}</h1> } }`;
|
|
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 { <button @click="increment">{count}</button> }
|
|
}`,
|
|
);
|
|
expect(result.interactiveHtml).toContain('"operation":"++"');
|
|
expect(result.interactiveHtml).toContain("data-play-event-click");
|
|
});
|