import { describe, expect, it } from "vitest";
import { renderToStaticMarkup } from "react-dom/server";
import { Primitive, withRenderProp } from "./Primitive";
const ALL_NODES = [
"a",
"button",
"div",
"form",
"h2",
"h3",
"img",
"input",
"label",
"li",
"nav",
"ol",
"p",
"select",
"span",
"svg",
"ul",
] as const;
// Void elements cannot have children
const VOID_ELEMENTS = new Set(["img", "input"]);
describe("Primitive", () => {
describe.each(ALL_NODES)("Primitive.%s", (node) => {
const Comp = Primitive[node];
it("renders the correct HTML tag", () => {
const html = VOID_ELEMENTS.has(node)
? renderToStaticMarkup()
: renderToStaticMarkup(content);
expect(html).toMatch(new RegExp(`^<${node}[\\s/>]`));
});
it("renders the render element instead of the default tag", () => {
// Use as render target — it won't collide with any Primitive node name
const html = VOID_ELEMENTS.has(node)
? renderToStaticMarkup(} />)
: renderToStaticMarkup(
}>content,
);
expect(html).toContain("]`));
});
if (!VOID_ELEMENTS.has(node)) {
it("render produces same markup as asChild", () => {
const renderHtml = renderToStaticMarkup(
} className="parent">
text
,
);
const asChildHtml = renderToStaticMarkup(
text
,
);
expect(renderHtml).toBe(asChildHtml);
});
}
});
describe("render prop edge cases", () => {
it("preserves a useful displayName on wrapped components", () => {
const Wrapped = withRenderProp(Primitive.div);
expect(Wrapped.displayName).toBe("Primitive.div");
});
it("uses render element's own children as fallback", () => {
const html = renderToStaticMarkup(
Fallback} />,
);
expect(html).toBe("Fallback");
});
it("outer children override render element's children", () => {
const html = renderToStaticMarkup(
Original}>Override,
);
expect(html).toBe("Override");
});
it("passes multiple children into the render element", () => {
const html = renderToStaticMarkup(
}>
A
B
,
);
expect(html).toContain("
");
expect(html).toContain("B
");
});
});
});