Add key field to UElement (ADR-004)

This commit is contained in:
2026-05-18 16:39:14 +00:00
parent c9c32a6aa6
commit 822ded6cf1
3 changed files with 61 additions and 2 deletions

View File

@@ -1,7 +1,8 @@
import { describe, it, expect } from "vitest";
import { h, createRoot, createComponent, Fragment, jsx, jsxs, jsxDEV } from "../src/core/h.js";
import { isUElement, isURoot, isUPrimitive } from "../src/core/schema.js";
import { isUElement, isURoot, isUPrimitive, UJSX } from "../src/core/schema.js";
import type { UNode, UElement } from "../src/core/schema.js";
import { Value } from "@alkdev/typebox/value";
import { Context } from "../src/core/context.js";
import { TransformRegistry, childCtx, ctx as transformCtx } from "../src/transform/registry.js";
import type { Direction } from "../src/core/context.js";
@@ -98,6 +99,60 @@ describe("type guards", () => {
});
});
describe("UElement key field", () => {
it("h() extracts key from props and promotes to element level", () => {
const el = h("div", { key: "item-1", class: "test" }, "hello");
expect(isUElement(el)).toBe(true);
if (isUElement(el)) {
expect(el.key).toBe("item-1");
expect(el.props.key).toBeUndefined();
expect(el.props.class).toBe("test");
}
});
it("h() without key does not add key field", () => {
const el = h("div", { class: "test" }, "hello");
expect(isUElement(el)).toBe(true);
if (isUElement(el)) {
expect(el.key).toBeUndefined();
}
});
it("h() with null props has no key", () => {
const el = h("div", null, "hello");
expect(isUElement(el)).toBe(true);
if (isUElement(el)) {
expect(el.key).toBeUndefined();
}
});
it("UElement with key validates against TypeBox schema", () => {
const UElementSchema = UJSX.Import("UElement");
const el = h("li", { key: "a" }, "item");
expect(Value.Check(UElementSchema, el)).toBe(true);
});
it("UElement without key validates against TypeBox schema (backward compat)", () => {
const UElementSchema = UJSX.Import("UElement");
const el = h("li", { class: "item" }, "item");
expect(Value.Check(UElementSchema, el)).toBe(true);
});
it("URoot does not have a key field", () => {
const root = createRoot("r");
expect("key" in root).toBe(false);
});
it("h() with root type does not promote key to URoot", () => {
const root = h("root", { key: "should-not-appear", id: "test" }, "child");
expect(isURoot(root)).toBe(true);
if (isURoot(root)) {
expect("key" in root).toBe(false);
expect(root.props.key).toBeUndefined();
}
});
});
describe("Context", () => {
it("stores and updates values", () => {
const ctx = new Context({ density: "full", target: "markdown" });