test(core): add T9 CompositionVariable font/image parse spec (before R1) (#1246)

* test(core): add T9 CompositionVariable font/image parse spec (before R1)

* fix(core): mark font+image spec tests as it.fails() — not yet implemented

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Vance Ingalls
2026-06-07 11:41:21 -07:00
committed by GitHub
co-authored by Claude Sonnet 4.6
parent 48fcf4ada5
commit 806b226b34
@@ -639,4 +639,108 @@ describe("extractCompositionMetadata", () => {
expect(meta.variables[1].id).toBe("count");
expect(meta.variables[1].type).toBe("number");
});
// T9 — CompositionVariable font/image parse (spec for R1).
// These tests are intentionally red until R1 adds "font" and "image" to
// CompositionVariableType and updates parseCompositionVariables accordingly.
// Currently failing (spec): tests 1, 2, 3 — filter rejects unknown types.
// Currently passing (baseline): test 4 — unknown type graceful rejection already works.
it.fails("[spec] parses a font variable (type: font) with name and source", () => {
const variables = JSON.stringify([
{
id: "brand-font-primary",
type: "font",
label: "Heading font",
default: "Inter",
source: "https://fonts.googleapis.com/css2?family=Inter",
default_name: "sans-serif",
default_source: "",
},
]);
const html = `<!DOCTYPE html>
<html data-composition-id="c" data-composition-duration="5" data-composition-variables='${variables}'>
<body></body></html>`;
const meta = extractCompositionMetadata(html);
const v = meta.variables.find((x) => x.id === "brand-font-primary");
expect(v).toBeDefined();
expect(v?.type).toBe("font");
// source, default_name, default_source are load-bearing for brand-kit font apply.
expect((v as Record<string, unknown>)?.source).toBe(
"https://fonts.googleapis.com/css2?family=Inter",
);
expect((v as Record<string, unknown>)?.default_name).toBe("sans-serif");
expect((v as Record<string, unknown>)?.default_source).toBe("");
});
it.fails("[spec] parses an image variable with brandRole logo:primary", () => {
const variables = JSON.stringify([
{ id: "brand-logo", type: "image", label: "Logo", default: "", brandRole: "logo:primary" },
]);
const html = `<!DOCTYPE html>
<html data-composition-id="c" data-composition-duration="5" data-composition-variables='${variables}'>
<body></body></html>`;
const meta = extractCompositionMetadata(html);
const v = meta.variables.find((x) => x.id === "brand-logo");
expect(v).toBeDefined();
expect(v?.type).toBe("image");
// TODO(R1): remove cast once ImageVariable.brandRole is typed
expect((v as Record<string, unknown>)?.brandRole).toBe("logo:primary");
});
it("[spec] parses a color variable with brandRole and preserves the brandRole field", () => {
const variables = JSON.stringify([
{
id: "brand-color-primary",
type: "color",
label: "Primary",
default: "#0066cc",
brandRole: "color:primary",
},
]);
const html = `<!DOCTYPE html>
<html data-composition-id="c" data-composition-duration="5" data-composition-variables='${variables}'>
<body></body></html>`;
const meta = extractCompositionMetadata(html);
const v = meta.variables.find((x) => x.id === "brand-color-primary");
expect(v).toBeDefined();
// TODO(R1): remove cast once ColorVariable.brandRole is typed
expect((v as Record<string, unknown>)?.brandRole).toBe("color:primary");
});
it("color variable without brandRole parses normally (brandRole is optional)", () => {
const variables = JSON.stringify([
{ id: "accent", type: "color", label: "Accent", default: "#ff0000" },
]);
const html = `<!DOCTYPE html>
<html data-composition-id="c" data-composition-duration="5" data-composition-variables='${variables}'>
<body></body></html>`;
const meta = extractCompositionMetadata(html);
const v = meta.variables.find((x) => x.id === "accent");
expect(v).toBeDefined();
expect(v?.type).toBe("color");
expect((v as Record<string, unknown>)?.brandRole).toBeUndefined();
});
it.todo(
"[spec] font variable without source field is rejected (source is required for brand-kit font apply)",
);
it.todo(
"[spec] image variable without default is rejected gracefully (default is required for image variables)",
);
it("unknown variable type is rejected gracefully (does not throw, variable is skipped)", () => {
const variables = JSON.stringify([
{ id: "ok", type: "string", label: "Ok", default: "yes" },
{ id: "x", type: "widget", label: "Unknown", default: null },
]);
const html = `<!DOCTYPE html>
<html data-composition-id="c" data-composition-duration="5" data-composition-variables='${variables}'>
<body></body></html>`;
expect(() => extractCompositionMetadata(html)).not.toThrow();
const meta = extractCompositionMetadata(html);
expect(meta.variables.find((v) => v.id === "x")).toBeUndefined();
expect(meta.variables.find((v) => v.id === "ok")).toBeDefined();
});
});