/**
* Ported from json-render's core/src/spec-validator.test.ts.
*
* Runs @json-render/core's validateSpec against Specs produced by jrx
* to prove structural correctness.
*/
import { describe, it, expect } from "bun:test";
import { validateSpec } from "@json-render/core";
import { render } from "./render";
import {
Stack,
Card,
Text,
Button,
Badge,
List,
ListItem,
Select,
} from "./test-components";
describe("validateSpec on jrx-produced specs", () => {
it("validates a simple single-element spec", () => {
const spec = render();
const result = validateSpec(spec);
expect(result.valid).toBe(true);
expect(result.issues).toHaveLength(0);
});
it("validates a parent-child spec", () => {
const spec = render(
,
);
const result = validateSpec(spec);
expect(result.valid).toBe(true);
expect(result.issues).toHaveLength(0);
});
it("validates a deep tree", () => {
const spec = render(
,
);
const result = validateSpec(spec);
expect(result.valid).toBe(true);
expect(result.issues).toHaveLength(0);
});
it("validates spec with visible at element level (not in props)", () => {
const spec = render(
,
);
const result = validateSpec(spec);
expect(result.issues.some((i) => i.code === "visible_in_props")).toBe(false);
});
it("validates spec with on at element level (not in props)", () => {
const spec = render(
,
);
const result = validateSpec(spec);
expect(result.issues.some((i) => i.code === "on_in_props")).toBe(false);
});
it("validates spec with repeat at element level (not in props)", () => {
const spec = render(
,
);
const result = validateSpec(spec);
expect(result.issues.some((i) => i.code === "repeat_in_props")).toBe(false);
});
it("validates spec with watch at element level (not in props)", () => {
const spec = render(
,
);
const result = validateSpec(spec);
expect(result.issues.some((i) => i.code === "watch_in_props")).toBe(false);
});
it("no orphaned elements in jrx output", () => {
const spec = render(
,
);
const result = validateSpec(spec, { checkOrphans: true });
expect(result.issues.some((i) => i.code === "orphaned_element")).toBe(false);
});
it("no missing children in jrx output", () => {
const spec = render(
,
);
const result = validateSpec(spec);
expect(result.issues.some((i) => i.code === "missing_child")).toBe(false);
expect(result.valid).toBe(true);
});
it("validates spec with state", () => {
const spec = render(, {
state: { count: 0, items: ["a", "b"] },
});
const result = validateSpec(spec);
expect(result.valid).toBe(true);
});
it("validates spec with all features combined", () => {
const spec = render(
,
{ state: { showHeader: true, items: [], country: "" } },
);
const result = validateSpec(spec);
expect(result.valid).toBe(true);
expect(result.issues).toHaveLength(0);
for (const el of Object.values(spec.elements)) {
const props = el.props as Record;
expect(props.visible).toBeUndefined();
expect(props.on).toBeUndefined();
expect(props.repeat).toBeUndefined();
expect(props.watch).toBeUndefined();
}
});
});