-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Expand file tree
/
Copy pathapplyVariableBindings.test.ts
More file actions
123 lines (109 loc) · 5 KB
/
Copy pathapplyVariableBindings.test.ts
File metadata and controls
123 lines (109 loc) · 5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/**
* @vitest-environment jsdom
*/
import { describe, it, expect, beforeEach, afterEach } from "vitest";
import { applyVariableBindings } from "./applyVariableBindings";
import { getVariables } from "./getVariables";
type TestWindow = Window & {
__hfVariables?: unknown;
__hfVariablesByComp?: Record<string, Record<string, unknown>>;
__hyperframes?: { getVariables?: () => Record<string, unknown> };
};
const win = window as TestWindow;
beforeEach(() => {
win.__hyperframes = { getVariables };
});
afterEach(() => {
delete win.__hfVariables;
delete win.__hfVariablesByComp;
delete win.__hyperframes;
document.documentElement.removeAttribute("data-composition-variables");
document.body.innerHTML = "";
});
function setDeclared(decls: unknown[]): void {
document.documentElement.setAttribute("data-composition-variables", JSON.stringify(decls));
}
describe("applyVariableBindings", () => {
it("sets src from a string variable via data-var-src", () => {
setDeclared([{ id: "hero", type: "image", label: "Hero", default: "default.jpg" }]);
document.body.innerHTML = `
<div data-hf-root data-composition-id="c1">
<img id="img" data-var-src="hero" src="fallback.jpg" />
</div>`;
applyVariableBindings(document);
expect(document.getElementById("img")?.getAttribute("src")).toBe("default.jpg");
});
it("render-time overrides win, and {url} image values resolve", () => {
setDeclared([{ id: "hero", type: "image", label: "Hero", default: "default.jpg" }]);
win.__hfVariables = { hero: { url: "https://cdn/override.png" } };
document.body.innerHTML = `
<div data-hf-root><video data-var-src="hero" src="fallback.mp4"></video></div>`;
applyVariableBindings(document);
expect(document.querySelector("video")?.getAttribute("src")).toBe("https://cdn/override.png");
});
it("keeps the authored src when the variable resolves to nothing", () => {
document.body.innerHTML = `<div data-hf-root><img data-var-src="ghost" src="keep.jpg" /></div>`;
applyVariableBindings(document);
expect(document.querySelector("img")?.getAttribute("src")).toBe("keep.jpg");
});
it("sets text content from a scalar via data-var-text", () => {
setDeclared([{ id: "title", type: "string", label: "Title", default: "Hello" }]);
win.__hfVariables = { title: "Overridden" };
document.body.innerHTML = `<div data-hf-root><h1 data-var-text="title">Authored</h1></div>`;
applyVariableBindings(document);
expect(document.querySelector("h1")?.textContent).toBe("Overridden");
});
it("applies scalar variables as --{id} custom props on the root", () => {
setDeclared([
{ id: "accent", type: "color", label: "Accent", default: "#00C3FF" },
{ id: "count", type: "number", label: "Count", default: 3 },
]);
win.__hfVariables = { accent: "#ff0000" };
document.body.innerHTML = `<div id="root" data-hf-root></div>`;
applyVariableBindings(document);
const root = document.getElementById("root");
expect(root?.style.getPropertyValue("--accent")).toBe("#ff0000");
expect(root?.style.getPropertyValue("--count")).toBe("3");
});
it("applies a font value's family name, and skips other objects", () => {
win.__hfVariables = {
brandFont: { name: "Inter", source: "https://fonts" },
img: { url: "x" },
};
document.body.innerHTML = `<div id="root" data-hf-root></div>`;
applyVariableBindings(document);
const root = document.getElementById("root");
expect(root?.style.getPropertyValue("--brandFont")).toBe("Inter");
expect(root?.style.getPropertyValue("--img")).toBe("");
});
it("preserves element children when binding text on a container", () => {
win.__hfVariables = { title: "Replaced" };
document.body.innerHTML = `
<div data-hf-root>
<h1 data-var-text="title">Hello <em id="kid" class="clip">world</em></h1>
</div>`;
applyVariableBindings(document);
const h1 = document.querySelector("h1");
expect(document.getElementById("kid")?.textContent).toBe("world");
expect(h1?.childNodes[0]?.nodeValue).toBe("Replaced");
});
it("is idempotent across re-application (loader re-apply path)", () => {
win.__hfVariables = { title: "Once" };
document.body.innerHTML = `<div data-hf-root><h1 data-var-text="title">t</h1></div>`;
applyVariableBindings(document);
applyVariableBindings(document);
expect(document.querySelector("h1")?.textContent).toBe("Once");
});
it("resolves sub-composition elements against their scoped values", () => {
win.__hfVariablesByComp = { sub: { label: "Scoped" } };
win.__hfVariables = { label: "TopLevel" };
document.body.innerHTML = `
<div data-hf-root data-composition-id="main">
<p id="top" data-var-text="label">t</p>
<div data-composition-id="sub"><p id="inner" data-var-text="label">s</p></div>
</div>`;
applyVariableBindings(document);
expect(document.getElementById("inner")?.textContent).toBe("Scoped");
expect(document.getElementById("top")?.textContent).toBe("TopLevel");
});
});