99 lines
4.0 KiB
TypeScript
99 lines
4.0 KiB
TypeScript
import { expect, test } from "bun:test";
|
|
import { readFileSync } from "node:fs";
|
|
import { chartConfiguration, chartTypes } from "../src/chart-config";
|
|
import { renderComponent, mountHtml } from "../../test/src/index";
|
|
import { discoverPlugins, createPluginRunner } from "../../plugin/src/index";
|
|
import { resolve } from "node:path";
|
|
|
|
const source = readFileSync(new URL("../components/Chart.wrn", import.meta.url), "utf8");
|
|
for (const type of chartTypes) {
|
|
test(`Chart.js ${type} preserves native datasets`, () => {
|
|
const data = {
|
|
labels: ["A", "B"],
|
|
datasets: [
|
|
{
|
|
label: "Example",
|
|
data: type === "scatter" || type === "bubble" ? [{ x: 1, y: -2, r: 5 }] : [-20, 40],
|
|
},
|
|
],
|
|
};
|
|
const config = chartConfiguration({ type, data });
|
|
expect(config.type).toBe(type);
|
|
expect(config.data).toEqual(data);
|
|
expect(config.data).not.toBe(data);
|
|
if (["pie", "doughnut", "radar", "polarArea"].includes(type))
|
|
expect(config.options?.scales).toBeUndefined();
|
|
});
|
|
}
|
|
test("legacy rows preserve negatives, gaps, zero, and small decimal values", () => {
|
|
const config = chartConfiguration({
|
|
items: [
|
|
{ label: "Loss", value: -20 },
|
|
{ label: "Gap", value: null },
|
|
{ label: "Invalid", value: "oops" },
|
|
{ label: "Zero", value: 0 },
|
|
{ label: "Tiny", value: 0.0002 },
|
|
],
|
|
});
|
|
expect(config.data.datasets[0].data).toEqual([-20, null, null, 0, 0.0002]);
|
|
expect(config.data.labels).toEqual(["Loss", "Gap", "Invalid", "Zero", "Tiny"]);
|
|
});
|
|
test("native dataset options, mixed types, area fills, and stacked horizontal axes survive", () => {
|
|
const data = {
|
|
labels: ["A"],
|
|
datasets: [
|
|
{ type: "bar" as const, data: [20] },
|
|
{ type: "line" as const, data: [10], borderColor: "red" },
|
|
],
|
|
};
|
|
const options = {
|
|
indexAxis: "y",
|
|
scales: { x: { stacked: true }, y: { stacked: true } },
|
|
plugins: { legend: { display: false } },
|
|
};
|
|
const config = chartConfiguration({ type: "bar", data, options });
|
|
expect(config.data).toEqual(data);
|
|
expect(config.options?.indexAxis).toBe("y");
|
|
expect((config.options?.scales?.x as any)?.stacked).toBe(true);
|
|
expect(config.options?.plugins?.legend?.display).toBe(false);
|
|
const area = chartConfiguration({ type: "area", data: { datasets: [{ data: [1, 2] }] } });
|
|
expect(area.type).toBe("line");
|
|
expect((area.data.datasets[0] as any).fill).toBe(true);
|
|
expect(() => chartConfiguration({ type: "unknown" })).toThrow("Unsupported chart type");
|
|
});
|
|
test("separate datasets and custom legacy keys remain supported", () => {
|
|
expect(chartConfiguration({ labels: ["A"], datasets: [{ data: [3] }] }).data).toEqual({
|
|
labels: ["A"],
|
|
datasets: [{ data: [3] }],
|
|
});
|
|
expect(
|
|
chartConfiguration({ items: [{ name: "A", amount: -2 }], labelKey: "name", valueKey: "amount" })
|
|
.data.datasets[0].data,
|
|
).toEqual([-2]);
|
|
});
|
|
test("SSR safely carries native chart config and typed public outputs", async () => {
|
|
const data = { labels: ["<script>bad</script>"], datasets: [{ label: "Sample", data: [-2] }] };
|
|
const dom = mountHtml(await renderComponent(source, { type: "radar", data }));
|
|
const root = dom.querySelector('[data-ui-component="Chart"]') as HTMLElement;
|
|
expect(root.dataset.wrnexusRuntime).toBe("chartjs");
|
|
expect(JSON.parse(root.dataset.chartConfig!).data).toEqual(data);
|
|
expect(root.querySelector("canvas")?.getAttribute("role")).toBe("img");
|
|
expect(root.querySelector("script")).toBeNull();
|
|
});
|
|
test("UI package discovers its bundled Chart.js runtime automatically", async () => {
|
|
const plugins = await discoverPlugins(resolve("examples/component-showcase"), [], {
|
|
strict: true,
|
|
});
|
|
const runner = createPluginRunner(plugins, {
|
|
root: resolve("examples/component-showcase"),
|
|
mode: "development",
|
|
command: "dev",
|
|
metadata: new Map(),
|
|
warn: () => {},
|
|
});
|
|
const contributions = await runner.contributions();
|
|
expect(
|
|
contributions.clientRuntimes.some((runtime) => runtime.id === "chartjs" && runtime.bundle),
|
|
).toBe(true);
|
|
});
|