@motion-proto/live-tokens 0.78.0 → 0.80.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/live-tokens-check-compliance/SKILL.md +49 -38
- package/.claude/skills/live-tokens-create-component/SKILL.md +23 -28
- package/.claude/skills/live-tokens-create-component/references/contract-tests.md +61 -0
- package/.claude/skills/live-tokens-create-component/references/sketch-mode.md +2 -2
- package/.claude/skills/live-tokens-create-component/references/token-naming.md +6 -15
- package/.claude/skills/live-tokens-create-page/SKILL.md +6 -4
- package/.claude/skills/live-tokens-create-theme/references/design-directions.md +1 -1
- package/.claude/skills/live-tokens-pick-component/SKILL.md +3 -3
- package/.claude/skills/live-tokens-set-colors/references/color-anchors.md +1 -1
- package/.claude/skills/live-tokens-set-geometry/SKILL.md +1 -1
- package/.claude/skills/live-tokens-set-geometry/references/geometry-anchors.md +1 -1
- package/CHANGELOG.md +271 -0
- package/README.md +10 -16
- package/bin/check-component.mjs +154 -551
- package/bin/check-page.mjs +57 -541
- package/bin/cli.mjs +93 -16
- package/bin/contractRunner.mjs +37 -91
- package/bin/lib/buildChecks.mjs +32 -0
- package/bin/lib/catalogue.mjs +161 -34
- package/bin/lib/componentSource.mjs +152 -0
- package/bin/lib/cssValues.mjs +9 -0
- package/bin/lib/dataDir.mjs +126 -0
- package/bin/lib/findings.mjs +103 -12
- package/bin/lib/fixers.mjs +64 -0
- package/bin/lib/geometry.mjs +92 -0
- package/bin/lib/pageSource.mjs +230 -0
- package/bin/lib/report.mjs +57 -59
- package/bin/lib/tokenVocabulary.mjs +104 -34
- package/bin/migrate-build-script.mjs +66 -0
- package/bin/migrate.mjs +5 -0
- package/bin/rules/componentStructure.mjs +344 -0
- package/bin/rules/componentUse.mjs +313 -0
- package/bin/rules/importsAndRoutes.mjs +136 -0
- package/bin/rules/testRuns.mjs +122 -0
- package/bin/rules/tokens.mjs +426 -0
- package/bin/setup-claude.mjs +1 -2
- package/dist-plugin/{chunk-PDNL4NC5.js → chunk-D4WRIKEZ.js} +7 -2
- package/dist-plugin/{chunk-SWXRVZKT.js → chunk-REBHE3ZM.js} +414 -1
- package/dist-plugin/index.cjs +470 -19
- package/dist-plugin/index.d.cts +1 -0
- package/dist-plugin/index.d.ts +1 -0
- package/dist-plugin/index.js +87 -55
- package/dist-plugin/migrateData/index.cjs +422 -4
- package/dist-plugin/migrateData/index.js +2 -2
- package/dist-plugin/setColors/index.cjs +414 -1
- package/dist-plugin/setColors/index.d.cts +1 -1
- package/dist-plugin/setColors/index.d.ts +1 -1
- package/dist-plugin/setColors/index.js +1 -1
- package/dist-plugin/setGeometry/index.cjs +423 -13
- package/dist-plugin/setGeometry/index.d.cts +3 -3
- package/dist-plugin/setGeometry/index.d.ts +3 -3
- package/dist-plugin/setGeometry/index.js +10 -13
- package/dist-plugin/setType/index.d.cts +1 -1
- package/dist-plugin/setType/index.d.ts +1 -1
- package/dist-plugin/{themeTypes-BxRtuN5V.d.cts → themeTypes-B8_Idrp4.d.cts} +2 -2
- package/dist-plugin/{themeTypes-BxRtuN5V.d.ts → themeTypes-B8_Idrp4.d.ts} +2 -2
- package/package.json +2 -2
- package/src/editor/component-editor/CalloutEditor.svelte +2 -2
- package/src/editor/component-editor/CollapsibleSectionEditor.svelte +14 -15
- package/src/editor/component-editor/CornerBadgeEditor.svelte +14 -14
- package/src/editor/component-editor/DialogEditor.svelte +5 -5
- package/src/editor/component-editor/InlineEditActionsEditor.svelte +2 -2
- package/src/editor/component-editor/RadioButtonEditor.svelte +21 -21
- package/src/editor/component-editor/SectionDividerEditor.svelte +7 -7
- package/src/editor/component-editor/SegmentedControlEditor.svelte +5 -5
- package/src/editor/component-editor/SideNavigationEditor.svelte +25 -25
- package/src/editor/component-editor/TabBarEditor.svelte +6 -6
- package/src/editor/component-editor/TableEditor.svelte +6 -6
- package/src/editor/component-editor/ToggleEditor.svelte +2 -2
- package/src/editor/component-editor/index.ts +3 -0
- package/src/editor/component-editor/registry.ts +57 -1
- package/src/editor/component-editor/scaffolding/TokenLayout.svelte +14 -14
- package/src/editor/component-editor/scaffolding/VariantGroup.svelte +3 -0
- package/src/editor/component-editor/scaffolding/types.ts +15 -0
- package/src/editor/core/components/adjustAliases.ts +4 -4
- package/src/editor/core/components/aliasKinds.ts +20 -19
- package/src/editor/core/sketch/sketchLayer.ts +3 -3
- package/src/editor/core/themes/migrateComponentConfig.ts +14 -6
- package/src/editor/core/themes/migrations/2026-09-13-badge-brand.ts +42 -0
- package/src/editor/core/themes/migrations/2026-09-13-collapsiblesection-open.ts +33 -0
- package/src/editor/core/themes/migrations/2026-09-13-cornerbadge-prefix.ts +70 -0
- package/src/editor/core/themes/migrations/2026-09-13-hairline.ts +92 -0
- package/src/editor/core/themes/migrations/2026-09-13-indicator.ts +54 -0
- package/src/editor/core/themes/migrations/2026-09-13-sectiondivider-surface.ts +36 -0
- package/src/editor/core/themes/migrations/2026-09-13-selected-state.ts +124 -0
- package/src/editor/core/themes/migrations/2026-09-13-toggle-label.ts +31 -0
- package/src/editor/core/themes/migrations/index.ts +16 -0
- package/src/editor/core/themes/themeService.ts +3 -3
- package/src/editor/core/themes/themeTypes.ts +13 -15
- package/src/editor/docs/Docs.svelte +1 -1
- package/src/editor/docs/content/light-and-dark.md +3 -3
- package/src/editor/docs/content.generated.ts +1 -1
- package/src/editor/index.ts +1 -0
- package/src/editor/overlay/LiveEditorOverlay.svelte +15 -0
- package/src/editor/skill-atlas/SkillAtlas.svelte +4 -4
- package/src/editor/skill-atlas/TreeNodeCard.svelte +4 -4
- package/src/editor/skill-atlas/skillSources.generated.ts +11 -14
- package/src/editor/skill-atlas/skillTrees.ts +1 -3
- package/src/editor/skill-atlas/trees/check-compliance.ts +37 -149
- package/src/editor/skill-atlas/trees/create-component.ts +62 -64
- package/src/editor/skill-atlas/trees/create-page.ts +38 -17
- package/src/editor/skill-atlas/trees/pick-component.ts +3 -3
- package/src/editor/skill-atlas/trees/set-geometry.ts +1 -1
- package/src/editor/ui/UIPaletteSelector.svelte +11 -15
- package/src/editor/ui/variantScales.ts +8 -8
- package/src/live-tokens/data/themes/autumn.json +188 -188
- package/src/live-tokens/data/themes/halloween.json +188 -188
- package/src/live-tokens/data/themes/midnight-study.json +245 -245
- package/src/live-tokens/data/themes/ocean.json +188 -188
- package/src/live-tokens/data/themes/royal-velvet.json +188 -188
- package/src/live-tokens/data/themes/sketchy.json +188 -188
- package/src/live-tokens/data/themes/spring-meadow.json +188 -188
- package/src/live-tokens/data/themes/sunset.json +188 -188
- package/src/system/components/Badge.svelte +27 -23
- package/src/system/components/Button.svelte +13 -7
- package/src/system/components/Callout.svelte +16 -11
- package/src/system/components/Card.svelte +22 -15
- package/src/system/components/CodeSnippet.svelte +10 -6
- package/src/system/components/CollapsibleSection.svelte +81 -76
- package/src/system/components/CornerBadge.svelte +78 -72
- package/src/system/components/Dialog.svelte +21 -18
- package/src/system/components/IconButton.svelte +13 -9
- package/src/system/components/Image.svelte +14 -8
- package/src/system/components/ImageLightbox.svelte +10 -6
- package/src/system/components/InlineEditActions.svelte +17 -14
- package/src/system/components/Input.svelte +13 -7
- package/src/system/components/MenuSelect.svelte +13 -7
- package/src/system/components/Notification.svelte +17 -11
- package/src/system/components/Panel.svelte +13 -6
- package/src/system/components/ProgressBar.svelte +10 -5
- package/src/system/components/RadioButton.svelte +33 -30
- package/src/system/components/SectionDivider.svelte +28 -21
- package/src/system/components/SegmentedControl.svelte +27 -23
- package/src/system/components/SideNavigation.svelte +175 -171
- package/src/system/components/Slider.svelte +11 -7
- package/src/system/components/TabBar.svelte +53 -49
- package/src/system/components/Table.svelte +20 -15
- package/src/system/components/Toggle.svelte +14 -10
- package/src/system/components/Tooltip.svelte +10 -6
- package/src/system/styles/CONVENTIONS.md +3 -4
- package/src/testing-js/chunk-3UKGXCDL.js +48 -0
- package/src/testing-js/chunk-3UKGXCDL.js.map +1 -0
- package/src/testing-js/{chunk-FAFOAWYL.js → chunk-Q3YIAAG3.js} +17 -3
- package/src/testing-js/chunk-Q3YIAAG3.js.map +1 -0
- package/src/testing-js/{chunk-GNIUPIU2.js → chunk-U7OJE5DU.js} +18 -18
- package/src/testing-js/chunk-U7OJE5DU.js.map +1 -0
- package/src/testing-js/{chunk-4JQX6WWL.js → chunk-ZMZQZ33J.js} +474 -166
- package/src/testing-js/chunk-ZMZQZ33J.js.map +1 -0
- package/src/testing-js/component-behavior.contract.js +155 -0
- package/src/testing-js/component-behavior.contract.js.map +1 -0
- package/src/testing-js/component-editor.contract.js +6 -4
- package/src/testing-js/component-editor.contract.js.map +1 -1
- package/src/testing-js/component-render.contract.js +14 -10
- package/src/testing-js/component-render.contract.js.map +1 -1
- package/src/testing-js/index.d.ts +44 -4
- package/src/testing-js/index.js +13 -7
- package/src/testing-js/index.js.map +1 -1
- package/src/testing-js/page-compliance.contract.js +48 -10
- package/src/testing-js/page-compliance.contract.js.map +1 -1
- package/src/testing-js/registry.contract.js +5 -3
- package/src/testing-js/registry.contract.js.map +1 -1
- package/src/testing-js/{vitest-C-wNWcoA.d.ts → vitest-BMLIbDs2.d.ts} +8 -2
- package/src/testing-js/vitest.d.ts +1 -1
- package/src/testing-js/vitest.js +2 -1
- package/template/package.json +1 -2
- package/template/vite.config.ts +3 -2
- package/.claude/skills/live-tokens-create-component/SKILL copy.md +0 -196
- package/.claude/skills/live-tokens-fix-findings/SKILL.md +0 -105
- package/src/editor/skill-atlas/trees/fix-findings.ts +0 -504
- package/src/testing-js/chunk-4JQX6WWL.js.map +0 -1
- package/src/testing-js/chunk-FAFOAWYL.js.map +0 -1
- package/src/testing-js/chunk-GNIUPIU2.js.map +0 -1
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
isInapplicable,
|
|
7
7
|
partLocator,
|
|
8
8
|
requiresInteraction
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-3UKGXCDL.js";
|
|
10
10
|
|
|
11
11
|
// src/testing/support/contractHarness.ts
|
|
12
12
|
import fs from "fs";
|
|
@@ -72,7 +72,7 @@ var ContractHarness = class _ContractHarness {
|
|
|
72
72
|
if (merged.state) {
|
|
73
73
|
const tab = this.page.locator(".variant-group:visible .tabs-states-block .state-tab-btn", { hasText: merged.state }).first();
|
|
74
74
|
if (await tab.count() === 0) {
|
|
75
|
-
this.fail("contract-
|
|
75
|
+
this.fail("contract-states", `no state tab labelled "${merged.state}"`);
|
|
76
76
|
}
|
|
77
77
|
await tab.click({ force: true });
|
|
78
78
|
await settle(this.page);
|
|
@@ -257,7 +257,7 @@ ${missing.join("\n")}`);
|
|
|
257
257
|
const named = new Set(this.contract.states.map((state) => state.state));
|
|
258
258
|
const unnamed = tabs.map((tab) => tab.trim()).filter((tab) => tab && !named.has(tab));
|
|
259
259
|
if (unnamed.length > 0) {
|
|
260
|
-
this.fail("contract-
|
|
260
|
+
this.fail("contract-states", `the editor renders state tabs the contract does not name: ${unnamed.join(", ")}`);
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
263
|
// ── 4. States, preview and interaction ───────────────────────────────────
|
|
@@ -281,7 +281,7 @@ ${missing.join("\n")}`);
|
|
|
281
281
|
if (isInapplicable(declared)) {
|
|
282
282
|
const tabs = await this.page.locator(".variant-group:visible .tabs-states-block .state-tab-btn").count();
|
|
283
283
|
if (tabs > 0) {
|
|
284
|
-
this.fail("contract-
|
|
284
|
+
this.fail("contract-states", `the editor renders ${tabs} state tabs but the contract marks states inapplicable: ${declared.reason}`);
|
|
285
285
|
}
|
|
286
286
|
return;
|
|
287
287
|
}
|
|
@@ -289,17 +289,17 @@ ${missing.join("\n")}`);
|
|
|
289
289
|
await this.selectView(state);
|
|
290
290
|
const classes = await this.locator(this.contract.root).evaluate((node) => [...node.classList]);
|
|
291
291
|
if (state.forceClass && !classes.includes(state.forceClass)) {
|
|
292
|
-
this.fail("contract-
|
|
292
|
+
this.fail("contract-states", `state "${state.state}" does not put "${state.forceClass}" on the preview`);
|
|
293
293
|
}
|
|
294
294
|
for (const [key, attributes] of Object.entries(state.attributes ?? {})) {
|
|
295
295
|
const observed = await this.locator(key).evaluate((node, names) => Object.fromEntries(names.map((name) => [name, node.getAttribute(name)])), Object.keys(attributes));
|
|
296
296
|
for (const [name, value] of Object.entries(attributes)) {
|
|
297
297
|
if (observed[name] !== value) {
|
|
298
|
-
this.fail("contract-
|
|
298
|
+
this.fail("contract-states", `state "${state.state}" has ${key}[${name}]="${observed[name]}", expected "${value}"`);
|
|
299
299
|
}
|
|
300
300
|
}
|
|
301
301
|
}
|
|
302
|
-
if (state.paints) await this.assertPaintMap(state.paints, "contract-
|
|
302
|
+
if (state.paints) await this.assertPaintMap(state.paints, "contract-states");
|
|
303
303
|
}
|
|
304
304
|
}
|
|
305
305
|
async roleOf(key) {
|
|
@@ -322,17 +322,17 @@ ${missing.join("\n")}`);
|
|
|
322
322
|
for (const key of Object.keys(this.contract.parts)) {
|
|
323
323
|
const role2 = await this.roleOf(key);
|
|
324
324
|
if (requiresInteraction(role2)) {
|
|
325
|
-
this.fail("contract-
|
|
325
|
+
this.fail("contract-interaction", `part "${key}" carries role "${role2}" but the contract marks interaction inapplicable: ${declared.reason}`);
|
|
326
326
|
}
|
|
327
327
|
}
|
|
328
328
|
return;
|
|
329
329
|
}
|
|
330
330
|
const role = await this.roleOf(declared.part);
|
|
331
331
|
if (role !== declared.role) {
|
|
332
|
-
this.fail("contract-
|
|
332
|
+
this.fail("contract-interaction", `part "${declared.part}" carries role "${role}", contract declares "${declared.role}"`);
|
|
333
333
|
}
|
|
334
334
|
if (declared.cases.length === 0) {
|
|
335
|
-
this.fail("contract-
|
|
335
|
+
this.fail("contract-interaction", `role "${declared.role}" is interactive and declares no action`);
|
|
336
336
|
}
|
|
337
337
|
for (const testCase of declared.cases) await this.runInteraction(testCase);
|
|
338
338
|
}
|
|
@@ -356,7 +356,7 @@ ${missing.join("\n")}`);
|
|
|
356
356
|
}
|
|
357
357
|
const from = await this.locator(action.part).boundingBox();
|
|
358
358
|
const along = await this.locator(action.along).boundingBox();
|
|
359
|
-
if (!from || !along) this.fail("contract-
|
|
359
|
+
if (!from || !along) this.fail("contract-interaction", `"${action.part}" or "${action.along}" has no box to drag along`);
|
|
360
360
|
await this.page.mouse.move(from.x + from.width / 2, from.y + from.height / 2);
|
|
361
361
|
await this.page.mouse.down();
|
|
362
362
|
await this.page.mouse.move(along.x + along.width * action.fraction, along.y + along.height / 2, { steps: 8 });
|
|
@@ -375,40 +375,40 @@ ${missing.join("\n")}`);
|
|
|
375
375
|
if (outcome.kind === "attribute") {
|
|
376
376
|
const actual = await this.locator(outcome.part).evaluate((node, name) => node.getAttribute(name), outcome.name);
|
|
377
377
|
if (actual !== outcome.value) {
|
|
378
|
-
this.fail("contract-
|
|
378
|
+
this.fail("contract-interaction", `${testCase.name}: ${outcome.part}[${outcome.name}] is "${actual}", expected "${outcome.value}"`);
|
|
379
379
|
}
|
|
380
380
|
return;
|
|
381
381
|
}
|
|
382
382
|
if (outcome.kind === "focused") {
|
|
383
383
|
const focused = await this.isFocused(outcome.part);
|
|
384
384
|
if (focused !== outcome.value) {
|
|
385
|
-
this.fail("contract-
|
|
385
|
+
this.fail("contract-interaction", `${testCase.name}: ${outcome.part} is ${focused ? "" : "not "}focused, expected ${outcome.value ? "" : "not "}focused`);
|
|
386
386
|
}
|
|
387
387
|
return;
|
|
388
388
|
}
|
|
389
389
|
const after = await this.valueOf(outcome.part);
|
|
390
390
|
if (outcome.kind === "valueHolds") {
|
|
391
391
|
if (after !== before) {
|
|
392
|
-
this.fail("contract-
|
|
392
|
+
this.fail("contract-interaction", `${testCase.name}: value moved from ${before} to ${after}`);
|
|
393
393
|
}
|
|
394
394
|
return;
|
|
395
395
|
}
|
|
396
396
|
if (outcome.kind === "valueChanges") {
|
|
397
397
|
if (after === before) {
|
|
398
|
-
this.fail("contract-
|
|
398
|
+
this.fail("contract-interaction", `${testCase.name}: value held at ${before}`);
|
|
399
399
|
}
|
|
400
400
|
return;
|
|
401
401
|
}
|
|
402
402
|
if (outcome.kind === "valueBecomes") {
|
|
403
403
|
if (after !== outcome.value) {
|
|
404
|
-
this.fail("contract-
|
|
404
|
+
this.fail("contract-interaction", `${testCase.name}: value is ${after}, expected ${outcome.value}`);
|
|
405
405
|
}
|
|
406
406
|
return;
|
|
407
407
|
}
|
|
408
408
|
const moved = Number(after) - Number(before);
|
|
409
409
|
const wanted = outcome.direction === "up" ? moved > 0 : moved < 0;
|
|
410
410
|
if (!wanted) {
|
|
411
|
-
this.fail("contract-
|
|
411
|
+
this.fail("contract-interaction", `${testCase.name}: value went ${before} -> ${after}, expected to move ${outcome.direction}`);
|
|
412
412
|
}
|
|
413
413
|
}
|
|
414
414
|
// ── 5. Persistence and reset ─────────────────────────────────────────────
|
|
@@ -773,4 +773,4 @@ function probeValueFor(css) {
|
|
|
773
773
|
export {
|
|
774
774
|
ContractHarness
|
|
775
775
|
};
|
|
776
|
-
//# sourceMappingURL=chunk-
|
|
776
|
+
//# sourceMappingURL=chunk-U7OJE5DU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../testing/support/contractHarness.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport type { Locator, Page } from '@playwright/test';\nimport {\n ContractViolation,\n isInapplicable,\n partLocator,\n requiresInteraction,\n type ComponentContract,\n type ContractRule,\n type ControlStep,\n type InteractionAction,\n type InteractionCase,\n type PaintMap,\n type PersistenceCase,\n type SketchExpectation,\n type ThemeExpectation,\n type View,\n} from '../componentContract';\nimport { openComponentsEditor } from './editor';\n\nconst STAGE = '.variant-group:visible .sketch-scope';\n\n/** A save or a reset is one file write on the dev server. Left implicit these\n * waits inherit the run's action timeout, which is sized for a click, and a\n * slow first write on a cold server would read as a missing response. */\nconst SERVER_WRITE_TIMEOUT_MS = 30_000;\n\n/**\n * Two frames for Svelte to flush and the browser to lay out, then every\n * in-flight transition jumped to its end. A colour read mid-interpolation is\n * neither the value the state left nor the one it is going to.\n *\n * The two frames after `finish()` are the other half: the browser dispatches\n * the `finish` event on a later turn, so a handler that ends a transition and\n * the Svelte flush it schedules both land after the call returns. Returning at\n * that point hands the next locator a DOM the animation is still leaving.\n */\nconst settle = (page: Page) => page.evaluate(async () => {\n const frame = () => new Promise<void>((resolve) => requestAnimationFrame(() => resolve()));\n await frame();\n await frame();\n for (const animation of document.getAnimations()) {\n // An editor spinner runs forever and has no end to jump to.\n try { animation.finish(); } catch { /* infinite effect */ }\n }\n await frame();\n await frame();\n});\n\n/** Contracts declare; this acts and observes, so mapping a new component stays\n * a declaration. */\nexport class ContractHarness {\n private constructor(\n readonly page: Page,\n readonly contract: ComponentContract,\n ) {}\n\n /** The editor page, with no component selected. The listing obligation runs\n * from here: an unregistered component has no preview to wait for. */\n static async attach(page: Page, contract: ComponentContract): Promise<ContractHarness> {\n await openComponentsEditor(page);\n return new ContractHarness(page, contract);\n }\n\n static async open(page: Page, contract: ComponentContract): Promise<ContractHarness> {\n const harness = await ContractHarness.attach(page, contract);\n await harness.selectComponent();\n return harness;\n }\n\n private fail(rule: ContractRule, message: string): never {\n throw new ContractViolation(rule, this.contract.id, message);\n }\n\n async selectComponent(): Promise<void> {\n await this.page.evaluate((id) => {\n const editor = window.__liveTokensEditor;\n if (!editor) throw new Error('window.__liveTokensEditor is not present on the components route');\n editor.selectComponent(id);\n }, this.contract.id);\n await this.page.locator('.variant-group').filter({ visible: true }).first().waitFor();\n await settle(this.page);\n await this.selectView(this.contract.view ?? {});\n }\n\n /** Open the variant group and state tab an obligation is declared against,\n * then run whatever has to happen before its parts exist. */\n async selectView(view: View): Promise<void> {\n const merged = { ...this.contract.view, ...view };\n if (merged.variant) {\n const tab = this.page.locator('.variant-tab-btn', { hasText: merged.variant }).first();\n if (await tab.count() === 0) {\n this.fail('contract-render', `no variant tab labelled \"${merged.variant}\"`);\n }\n await tab.click({ force: true });\n await settle(this.page);\n }\n if (merged.state) {\n const tab = this.page\n .locator('.variant-group:visible .tabs-states-block .state-tab-btn', { hasText: merged.state })\n .first();\n if (await tab.count() === 0) {\n this.fail('contract-states', `no state tab labelled \"${merged.state}\"`);\n }\n await tab.click({ force: true });\n await settle(this.page);\n }\n for (const step of merged.setup ?? []) {\n if (step.kind === 'control') await this.driveSetupControl(step);\n else await this.performAction(step);\n await settle(this.page);\n }\n }\n\n private async driveSetupControl(step: ControlStep): Promise<void> {\n const control = this.page.locator('.variant-group:visible').locator(step.selector).first();\n if (await control.count() === 0) {\n this.fail('contract-render', `no control matches \"${step.selector}\"`);\n }\n if (step.check !== undefined) await control.setChecked(step.check);\n else if (step.value !== undefined) await control.selectOption(step.value);\n else await control.click({ force: true });\n }\n\n locator(key: string): Locator {\n const locatorSpec = partLocator(this.contract, key);\n return locatorSpec.portal\n ? this.page.locator(locatorSpec.selector).first()\n : this.page.locator(STAGE).first().locator(locatorSpec.selector).first();\n }\n\n async requirePart(key: string, rule: ContractRule): Promise<Locator> {\n const element = this.locator(key);\n if (await element.count() === 0) {\n this.fail(rule, `part \"${key}\" (${partLocator(this.contract, key).selector}) is not in the preview`);\n }\n return element;\n }\n\n /** Computed values for one part: CSS properties and custom properties alike. */\n async read(key: string, properties: string[], rule: ContractRule = 'contract-render'): Promise<Record<string, string>> {\n const pseudo = partLocator(this.contract, key).pseudo ?? null;\n const element = await this.requirePart(key, rule);\n return element.evaluate((node, { names, on }) => {\n const style = getComputedStyle(node, on ?? undefined);\n return Object.fromEntries(names.map((name) => [\n name,\n (name.startsWith('--')\n ? style.getPropertyValue(name)\n : (style as unknown as Record<string, string>)[name] ?? '').trim(),\n ]));\n }, { names: properties, on: pseudo });\n }\n\n /**\n * A raw token value as the browser computes it for one CSS property, measured\n * beside the part so inherited font size and colour resolve the same way. A\n * token holding `#fff` and a computed `rgb(255, 255, 255)` are the same paint,\n * and only the browser can say so.\n */\n async normalize(key: string, css: string, rawValue: string): Promise<string> {\n return this.locator(key).evaluate((node, { property, raw }) => {\n const probe = document.createElement('div');\n probe.style.display = 'none';\n // A border width computes to 0 while the border style is `none`, so the\n // probe would answer 0px for every stroke thickness.\n probe.style.borderStyle = 'solid';\n probe.style.outlineStyle = 'solid';\n (node.parentElement ?? document.body).appendChild(probe);\n probe.style.setProperty(property.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`), raw);\n const computed = (getComputedStyle(probe) as unknown as Record<string, string>)[property];\n probe.remove();\n return (computed ?? '').trim();\n }, { property: css, raw: rawValue });\n }\n\n // ── 1. Listed ────────────────────────────────────────────────────────────\n\n async assertListed(): Promise<void> {\n const entry = await this.page.evaluate((id) => {\n const found = window.__liveTokensEditor?.getComponentRegistryEntries().find((e) => e.id === id);\n return found ? { id: found.id, origin: found.origin, label: found.label } : null;\n }, this.contract.id);\n if (!entry) this.fail('contract-listed', 'no registry entry');\n if (entry.origin !== this.contract.origin) {\n this.fail('contract-listed', `registry origin is \"${entry.origin}\", contract declares \"${this.contract.origin}\"`);\n }\n\n const placement = await this.page.evaluate((label) => {\n const children = [...document.querySelectorAll('.nav-items > *')];\n const divider = children.findIndex((el) => el.classList.contains('nav-divider'));\n const item = children.findIndex((el) =>\n el.classList.contains('nav-item') && el.textContent?.trim() === label);\n return { item, divider };\n }, entry.label);\n if (placement.item < 0) this.fail('contract-listed', `\"${entry.label}\" is not in the component rail`);\n const group = placement.divider >= 0 && placement.item > placement.divider ? 'custom' : 'system';\n if (group !== this.contract.origin) {\n this.fail('contract-listed', `rail lists \"${entry.label}\" under ${group}, contract declares ${this.contract.origin}`);\n }\n }\n\n // ── 2. Property projection ───────────────────────────────────────────────\n\n /**\n * Drive one design token to a probe value and require the declared part's\n * declared CSS property to adopt it. A repaint anywhere else in the preview\n * cannot satisfy this.\n */\n async assertPaintsFromToken(key: string, css: string, variable: string, rule: ContractRule): Promise<void> {\n await this.requirePart(key, rule);\n const probe = probeValueFor(css)\n ?? this.fail(rule, `no probe value for CSS property \"${css}\"; declare one in probeValueFor`);\n const expected = await this.normalize(key, css, probe);\n const before = (await this.read(key, [css]))[css];\n const restore = await this.page.evaluate(({ name, value }) => {\n const root = document.documentElement;\n const prior = { value: root.style.getPropertyValue(name), priority: root.style.getPropertyPriority(name) };\n root.style.setProperty(name, value, 'important');\n return prior;\n }, { name: variable, value: probe });\n await settle(this.page);\n const after = (await this.read(key, [css]))[css];\n await this.page.evaluate(({ name, prior }) => {\n const root = document.documentElement;\n if (prior.value) root.style.setProperty(name, prior.value, prior.priority);\n else root.style.removeProperty(name);\n }, { name: variable, prior: restore });\n await settle(this.page);\n if (after !== expected) {\n this.fail(rule, `${variable} set to ${probe} left ${key}.${css} at ${after} (was ${before}), expected ${expected}`);\n }\n }\n\n async assertProperties(): Promise<number> {\n let asserted = 0;\n for (const expectation of this.contract.properties) {\n await this.selectView(expectation);\n for (const [key, map] of Object.entries(expectation.paints)) {\n for (const [css, variable] of Object.entries(map)) {\n await this.assertPaintsFromToken(key, css, variable, 'contract-render');\n asserted++;\n }\n }\n }\n return asserted;\n }\n\n // ── 3. Alias resolution ──────────────────────────────────────────────────\n\n /** Every alias the component ships. The alias contract proves each one fans\n * out to the root; this proves each one resolves to a value once it is\n * there, which a fan-out cannot see. */\n shippedAliases(): string[] {\n const file = path.resolve(\n process.env.LIVE_TOKENS_DATA_DIR ?? 'src/live-tokens/data',\n 'component-configs',\n this.contract.id,\n 'default.json',\n );\n if (!fs.existsSync(file)) {\n this.fail('contract-alias', `no shipped config at ${file}`);\n }\n const data = JSON.parse(fs.readFileSync(file, 'utf8')) as { aliases?: Record<string, unknown> };\n return Object.keys(data.aliases ?? {}).sort();\n }\n\n async assertAliasesResolve(): Promise<void> {\n const aliases = this.shippedAliases();\n if (aliases.length === 0) this.fail('contract-alias', 'the shipped config declares no aliases');\n const unresolved = await this.page.evaluate((names) => {\n const style = getComputedStyle(document.documentElement);\n return names.filter((name) => style.getPropertyValue(name).trim() === '');\n }, aliases);\n if (unresolved.length > 0) {\n this.fail('contract-alias', `aliases resolve to nothing at the root: ${unresolved.join(', ')}`);\n }\n }\n\n /**\n * What the contract leaves out. Every shipped alias has to reach a paint map\n * or carry a reason it cannot, every declared part has to resolve, and every\n * state tab the editor renders has to be declared. Without this a contract\n * naming three tokens passes as completely as one naming all eighty.\n */\n async assertInventory(): Promise<void> {\n await this.selectView({});\n for (const key of Object.keys(this.contract.parts)) {\n await this.requirePart(key, 'contract-render');\n }\n\n const declared = new Set<string>(Object.keys(this.contract.uncovered ?? {}));\n const collect = (map: PaintMap) => {\n for (const properties of Object.values(map)) {\n for (const variable of Object.values(properties)) declared.add(variable);\n }\n };\n for (const expectation of this.contract.properties) collect(expectation.paints);\n if (!isInapplicable(this.contract.states)) {\n for (const state of this.contract.states) if (state.paints) collect(state.paints);\n }\n const missing = this.shippedAliases().filter((alias) => !declared.has(alias));\n if (missing.length > 0) {\n this.fail('contract-render', `${missing.length} shipped aliases reach no paint map and carry no reason:\\n${missing.join('\\n')}`);\n }\n\n const tabs = await this.page\n .locator('.variant-group:visible .tabs-states-block .tabs-selectors:first-of-type .state-tab-btn')\n .allTextContents();\n if (isInapplicable(this.contract.states)) return;\n const named = new Set(this.contract.states.map((state) => state.state));\n const unnamed = tabs.map((tab) => tab.trim()).filter((tab) => tab && !named.has(tab));\n if (unnamed.length > 0) {\n this.fail('contract-states', `the editor renders state tabs the contract does not name: ${unnamed.join(', ')}`);\n }\n }\n\n // ── 4. States, preview and interaction ───────────────────────────────────\n\n /** Computed-value equality between a part's CSS property and its token. */\n async assertPaintMap(map: PaintMap, rule: ContractRule): Promise<void> {\n for (const [key, properties] of Object.entries(map)) {\n const cssNames = Object.keys(properties);\n const observed = await this.read(key, [...cssNames, ...Object.values(properties)]);\n for (const [css, variable] of Object.entries(properties)) {\n const token = observed[variable];\n if (!token) this.fail(rule, `${variable} resolves to nothing on part \"${key}\"`);\n const expected = await this.normalize(key, css, token);\n if (observed[css] !== expected) {\n this.fail(rule, `${key}.${css} is ${observed[css]}, ${variable} resolves to ${expected}`);\n }\n }\n }\n }\n\n async assertStates(): Promise<void> {\n const declared = this.contract.states;\n if (isInapplicable(declared)) {\n const tabs = await this.page.locator('.variant-group:visible .tabs-states-block .state-tab-btn').count();\n if (tabs > 0) {\n this.fail('contract-states', `the editor renders ${tabs} state tabs but the contract marks states inapplicable: ${declared.reason}`);\n }\n return;\n }\n for (const state of declared) {\n await this.selectView(state);\n const classes = await this.locator(this.contract.root).evaluate((node) => [...node.classList]);\n if (state.forceClass && !classes.includes(state.forceClass)) {\n this.fail('contract-states', `state \"${state.state}\" does not put \"${state.forceClass}\" on the preview`);\n }\n for (const [key, attributes] of Object.entries(state.attributes ?? {})) {\n const observed = await this.locator(key).evaluate((node, names) =>\n Object.fromEntries(names.map((name) => [name, node.getAttribute(name)])), Object.keys(attributes));\n for (const [name, value] of Object.entries(attributes)) {\n if (observed[name] !== value) {\n this.fail('contract-states', `state \"${state.state}\" has ${key}[${name}]=\"${observed[name]}\", expected \"${value}\"`);\n }\n }\n }\n if (state.paints) await this.assertPaintMap(state.paints, 'contract-states');\n }\n }\n\n private async roleOf(key: string): Promise<string | null> {\n return this.locator(key).evaluate((node) => {\n const explicit = node.getAttribute('role');\n if (explicit) return explicit;\n const tag = node.tagName.toLowerCase();\n if (tag === 'button') return 'button';\n if (tag === 'a') return 'link';\n if (tag === 'input') {\n const type = (node as HTMLInputElement).type;\n return type === 'range' ? 'slider' : type === 'checkbox' ? 'checkbox' : 'textbox';\n }\n return null;\n });\n }\n\n async assertInteraction(): Promise<void> {\n const declared = this.contract.interaction;\n if (isInapplicable(declared)) {\n for (const key of Object.keys(this.contract.parts)) {\n const role = await this.roleOf(key);\n if (requiresInteraction(role)) {\n this.fail('contract-interaction', `part \"${key}\" carries role \"${role}\" but the contract marks interaction inapplicable: ${declared.reason}`);\n }\n }\n return;\n }\n const role = await this.roleOf(declared.part);\n if (role !== declared.role) {\n this.fail('contract-interaction', `part \"${declared.part}\" carries role \"${role}\", contract declares \"${declared.role}\"`);\n }\n if (declared.cases.length === 0) {\n this.fail('contract-interaction', `role \"${declared.role}\" is interactive and declares no action`);\n }\n for (const testCase of declared.cases) await this.runInteraction(testCase);\n }\n\n private async valueOf(key: string): Promise<string> {\n return this.locator(key).evaluate((node) =>\n (node as HTMLInputElement).value ?? node.getAttribute('aria-valuenow') ?? '');\n }\n\n private async performAction(action: InteractionAction): Promise<void> {\n if (action.kind === 'press') {\n // A disabled control refuses focus, which is part of what the disabled\n // case asserts. The outcome check decides whether that is right.\n await this.locator(action.part).focus().catch(() => undefined);\n await this.page.keyboard.press(action.key);\n return;\n }\n if (action.kind === 'click') {\n await this.locator(action.part).click({ force: true });\n return;\n }\n if (action.kind === 'type') {\n await this.locator(action.part).click({ force: true }).catch(() => undefined);\n await this.page.keyboard.type(action.text);\n return;\n }\n const from = await this.locator(action.part).boundingBox();\n const along = await this.locator(action.along).boundingBox();\n if (!from || !along) this.fail('contract-interaction', `\"${action.part}\" or \"${action.along}\" has no box to drag along`);\n await this.page.mouse.move(from.x + from.width / 2, from.y + from.height / 2);\n await this.page.mouse.down();\n await this.page.mouse.move(along.x + along.width * action.fraction, along.y + along.height / 2, { steps: 8 });\n await this.page.mouse.up();\n }\n\n private async isFocused(key: string): Promise<boolean> {\n return this.locator(key).evaluate((node) => document.activeElement === node);\n }\n\n private async runInteraction(testCase: InteractionCase): Promise<void> {\n await this.selectView(testCase);\n const outcome = testCase.expect;\n const tracksValue = outcome.kind === 'valueMoves'\n || outcome.kind === 'valueBecomes'\n || outcome.kind === 'valueChanges'\n || outcome.kind === 'valueHolds';\n const before = tracksValue ? await this.valueOf(outcome.part) : '';\n\n await this.performAction(testCase.action);\n await settle(this.page);\n\n if (outcome.kind === 'attribute') {\n const actual = await this.locator(outcome.part)\n .evaluate((node, name) => node.getAttribute(name), outcome.name);\n if (actual !== outcome.value) {\n this.fail('contract-interaction', `${testCase.name}: ${outcome.part}[${outcome.name}] is \"${actual}\", expected \"${outcome.value}\"`);\n }\n return;\n }\n if (outcome.kind === 'focused') {\n const focused = await this.isFocused(outcome.part);\n if (focused !== outcome.value) {\n this.fail('contract-interaction', `${testCase.name}: ${outcome.part} is ${focused ? '' : 'not '}focused, expected ${outcome.value ? '' : 'not '}focused`);\n }\n return;\n }\n\n const after = await this.valueOf(outcome.part);\n if (outcome.kind === 'valueHolds') {\n if (after !== before) {\n this.fail('contract-interaction', `${testCase.name}: value moved from ${before} to ${after}`);\n }\n return;\n }\n if (outcome.kind === 'valueChanges') {\n if (after === before) {\n this.fail('contract-interaction', `${testCase.name}: value held at ${before}`);\n }\n return;\n }\n if (outcome.kind === 'valueBecomes') {\n if (after !== outcome.value) {\n this.fail('contract-interaction', `${testCase.name}: value is ${after}, expected ${outcome.value}`);\n }\n return;\n }\n const moved = Number(after) - Number(before);\n const wanted = outcome.direction === 'up' ? moved > 0 : moved < 0;\n if (!wanted) {\n this.fail('contract-interaction', `${testCase.name}: value went ${before} -> ${after}, expected to move ${outcome.direction}`);\n }\n }\n\n // ── 5. Persistence and reset ─────────────────────────────────────────────\n\n /** Every alias and config value the component holds, for restoring the buffer. */\n async captureSlice(): Promise<unknown> {\n return this.page.evaluate((id) => {\n let slice: unknown;\n const stop = window.__liveTokensEditor!.editorState.subscribe((state) => {\n slice = structuredClone(state.components[id] ?? { aliases: {}, config: {} });\n });\n stop();\n return slice;\n }, this.contract.id);\n }\n\n async restoreSlice(slice: unknown): Promise<void> {\n await this.page.evaluate(({ id, value }) => {\n window.__liveTokensEditor!.mutate('contract: restore component slice', (state) => {\n (state.components as Record<string, unknown>)[id] = structuredClone(value);\n });\n }, { id: this.contract.id, value: slice });\n await settle(this.page);\n }\n\n async rootValue(variable: string): Promise<string> {\n return this.page.evaluate((name) =>\n document.documentElement.style.getPropertyValue(name).trim(), variable);\n }\n\n /** Drive one control the way a designer does, and return the value it wrote. */\n async driveControl(testCase: PersistenceCase): Promise<string> {\n await this.selectView(testCase);\n const group = this.page.locator('.variant-group:visible');\n if (testCase.shape === 'config' || testCase.shape === 'literal') {\n const control = group.locator(testCase.control!).first();\n if (await control.count() === 0) {\n this.fail('contract-persist', `no control matches \"${testCase.control}\"`);\n }\n const tag = await control.evaluate((element) => element.tagName.toLowerCase());\n if (tag === 'select') {\n const options = await control.locator('option').evaluateAll((elements) =>\n elements.map((element) => (element as HTMLOptionElement).value));\n const current = await control.inputValue();\n const next = options.find((option) => option !== current);\n if (!next) this.fail('contract-persist', `\"${testCase.control}\" offers no second option`);\n await control.selectOption(next);\n } else {\n await control.click({ force: true });\n }\n await settle(this.page);\n return testCase.shape === 'config'\n ? this.configValue(testCase.configKey!)\n : this.rootValue(testCase.variable!);\n }\n\n const variable = testCase.variable!;\n const selector = group\n .locator(`.ui-token-selector:visible[data-token-variable=\"${variable}\"]:not(.disabled):not(.locked)`)\n .first();\n if (testCase.shape === 'gradient') {\n const editor = group.locator(`.gradient-editor:visible[data-token-variable=\"${variable}\"]`).first();\n if (await editor.count() === 0) {\n this.fail('contract-persist', `no gradient editor for ${variable}`);\n }\n const solid = editor.getByRole('radio', { name: 'Solid' });\n if (await solid.count() && !await solid.isChecked()) await solid.check({ force: true });\n const picker = editor.locator('.picker-slot .ui-token-selector').first();\n await picker.locator('.ui-ts-trigger').click({ force: true });\n const swatch = picker.locator('.static-chip:not(.active):not(:disabled)').first();\n if (await swatch.count() === 0) this.fail('contract-persist', `gradient picker for ${variable} offers no stop colour`);\n await swatch.click({ force: true });\n await settle(this.page);\n return this.rootValue(variable);\n }\n\n if (await selector.count() === 0) {\n this.fail('contract-persist', `no editor control for ${variable}`);\n }\n if (testCase.shape === 'opacity') {\n await selector.locator('.ui-ts-trigger').click();\n const opacity = this.page.locator('.ui-ts-dropdown .opacity-input').first();\n if (await opacity.count() === 0) this.fail('contract-persist', `${variable} has no opacity control`);\n await opacity.fill('37');\n await opacity.blur();\n await settle(this.page);\n await this.page.keyboard.press('Escape');\n await settle(this.page);\n return this.rootValue(variable);\n }\n\n const before = await this.rootValue(variable);\n await selector.locator('.ui-ts-trigger').click();\n const option = this.page.locator(\n '.ui-ts-dropdown .static-chip:not(.active):not(:disabled), '\n + '.ui-ts-dropdown .ui-option-item:not(.active):not(:disabled), '\n + '.ui-ts-dropdown .font-size-row:not(.active):not(:disabled)',\n ).first();\n if (await option.count() === 0) this.fail('contract-persist', `${variable}'s control offers no other value`);\n await option.click();\n await settle(this.page);\n const after = await this.rootValue(variable);\n if (after === before) this.fail('contract-persist', `${variable}'s control did not write a new value`);\n return after;\n }\n\n async configValue(key: string): Promise<string> {\n const value = await this.page.evaluate(({ id, configKey }) => {\n let held: unknown;\n const stop = window.__liveTokensEditor!.editorState.subscribe((state) => {\n held = (state.components[id]?.config ?? {})[configKey];\n });\n stop();\n return held === undefined ? null : JSON.stringify(held);\n }, { id: this.contract.id, configKey: key });\n // An absent key would otherwise read the same before and after the edit,\n // and the readback below would compare one sentinel against another.\n if (value === null) this.fail('contract-persist', `nothing holds config key \"${key}\"`);\n return value;\n }\n\n /** File > Save, waiting for the working buffer to reach disk. */\n async save(): Promise<void> {\n await Promise.all([\n this.page.waitForResponse((response) =>\n response.url().includes(`/component-configs/${this.contract.id}/working`)\n && response.request().method() === 'PUT'\n && response.ok(), { timeout: SERVER_WRITE_TIMEOUT_MS }),\n (async () => {\n await this.page.locator('.file-menu button').first().click();\n await this.page.locator('.file-menu-item', { hasText: 'Save' }).first().click();\n })(),\n ]);\n await settle(this.page);\n }\n\n async reset(): Promise<void> {\n const button = this.page.locator('.cfm-bar button', { hasText: 'Reset' }).first();\n if (await button.isDisabled()) this.fail('contract-persist', 'Reset is disabled while the component is dirty');\n await Promise.all([\n this.page.waitForResponse((response) =>\n response.url().includes(`/component-configs/${this.contract.id}/active`) && response.ok(),\n { timeout: SERVER_WRITE_TIMEOUT_MS }),\n button.click(),\n ]);\n await settle(this.page);\n }\n\n /** Wait for a root variable to leave a value a repaint is about to replace. */\n private async awaitRootChange(variable: string, from: string): Promise<void> {\n await this.page.waitForFunction(({ name, previous }) =>\n getComputedStyle(document.documentElement).getPropertyValue(name).trim() !== previous,\n { name: variable, previous: from }, { timeout: 10_000 }).catch(() => undefined);\n await settle(this.page);\n }\n\n /** Re-open the route so the assertion reads the config off the server. */\n async reopen(): Promise<void> {\n await openComponentsEditor(this.page);\n await this.selectComponent();\n }\n\n /**\n * Every declared value shape, driven through its control, saved, and read\n * back after a reload; then Reset against the value the server holds.\n *\n * Reset restores the config the server holds, which is the working buffer\n * once one exists and the open theme's copy until then. The sequence saves\n * first, so the value the component booted with and the value the server\n * holds are different by the time Reset runs and a Reset landing on the\n * wrong one is visible.\n */\n async assertPersistence(): Promise<void> {\n const original = await this.captureSlice();\n try {\n const first = this.contract.persistence.cases[0];\n if (!first) this.fail('contract-persist', 'no persistence case is declared');\n const shipped = await this.rootValue(this.contract.persistence.resetVariable);\n\n for (const testCase of this.contract.persistence.cases) {\n await this.selectView(testCase);\n const { part, css } = testCase.observe;\n const before = (await this.read(part, [css]))[css];\n const written = await this.driveControl(testCase);\n const edited = (await this.read(part, [css]))[css];\n if (edited === before) {\n this.fail('contract-persist', `the ${testCase.shape} edit left ${part}.${css} at ${before}`);\n }\n await this.save();\n await this.reopen();\n await this.selectView(testCase);\n const stored = testCase.shape === 'config'\n ? await this.configValue(testCase.configKey!)\n : await this.rootValue(testCase.variable!);\n if (stored !== written) {\n this.fail('contract-persist', `the ${testCase.shape} edit read back as ${stored} after a reload, was ${written}`);\n }\n const reloaded = (await this.read(part, [css]))[css];\n if (reloaded !== edited) {\n this.fail('contract-persist', `the reloaded preview paints ${part}.${css} as ${reloaded}, was ${edited}`);\n }\n }\n\n const saved = await this.rootValue(this.contract.persistence.resetVariable);\n if (saved === shipped) {\n this.fail('contract-persist', `${this.contract.persistence.resetVariable} still holds its shipped value ${shipped}; Reset cannot tell the two baselines apart`);\n }\n // `first.setup` is about to replay a third time. A `ControlStep` is\n // idempotent (`setChecked` doesn't care what came before), but an\n // `InteractionAction` click that toggles something (a modal open/closed,\n // for instance) is not: replaying it against whatever state the loop\n // above happened to leave the page in can land on the wrong side of the\n // toggle. A fresh load puts every component back in the one state\n // `setup` was written against before it replays. `saved`, read above\n // from the server-backed root value, isn't invalidated by the reload.\n await this.reopen();\n await this.driveControl({\n variant: first.variant,\n state: first.state,\n setup: first.setup,\n shape: 'token',\n variable: this.contract.persistence.resetVariable,\n observe: first.observe,\n });\n const dirty = await this.rootValue(this.contract.persistence.resetVariable);\n if (dirty === saved) this.fail('contract-persist', 'the unsaved edit wrote nothing to reset');\n await this.reset();\n const restored = await this.rootValue(this.contract.persistence.resetVariable);\n if (restored !== saved) {\n this.fail('contract-persist', `Reset left ${this.contract.persistence.resetVariable} at ${restored}, the server holds ${saved}`);\n }\n } finally {\n await this.restoreSlice(original);\n await this.save();\n }\n }\n\n // ── 6. Theme projection ──────────────────────────────────────────────────\n\n /** `settleOn` is a variable the theme is expected to move, so the read that\n * follows lands after the repaint. */\n async previewTheme(slug: string, settleOn?: { variable: string; from: string }): Promise<void> {\n await this.page.locator('.theme-name-trigger').click();\n await this.page.locator('[role=\"dialog\"][aria-label=\"Theme Picker\"]').waitFor();\n const row = this.page.locator(`.load-item[data-file-name=\"theme:${slug}\"] .load-name-btn`);\n if (await row.count() === 0) this.fail('contract-theme', `the Theme Picker has no theme \"${slug}\"`);\n await Promise.all([\n this.page.waitForResponse((response) => response.url().includes('/themes/') && response.ok(),\n { timeout: SERVER_WRITE_TIMEOUT_MS }),\n row.click(),\n ]);\n await settle(this.page);\n if (settleOn) await this.awaitRootChange(settleOn.variable, settleOn.from);\n }\n\n async cancelThemePreview(settleOn?: { variable: string; from: string }): Promise<void> {\n const dialog = this.page.locator('[role=\"dialog\"][aria-label=\"Theme Picker\"]');\n await dialog.getByRole('button', { name: 'Cancel', exact: true }).click();\n await dialog.waitFor({ state: 'detached' });\n await settle(this.page);\n if (settleOn) await this.awaitRootChange(settleOn.variable, settleOn.from);\n }\n\n async rootValues(names: string[]): Promise<Record<string, string>> {\n return this.page.evaluate((variables) => {\n const style = getComputedStyle(document.documentElement);\n return Object.fromEntries(variables.map((name) => [name, style.getPropertyValue(name).trim()]));\n }, names);\n }\n\n async assertThemeProjection(expectation: ThemeExpectation): Promise<void> {\n await this.selectView(expectation);\n const watched = [\n ...expectation.changed,\n ...expectation.unchanged,\n ...Object.keys(expectation.aliasedTo),\n ...Object.values(expectation.aliasedTo),\n expectation.observe.variable,\n ];\n const before = await this.rootValues(watched);\n const moved = expectation.changed[0];\n if (!moved) this.fail('contract-theme', `${expectation.theme} is declared to change nothing`);\n await this.previewTheme(expectation.theme, { variable: moved, from: before[moved] });\n const after = await this.rootValues(watched);\n\n for (const name of expectation.changed) {\n if (after[name] === before[name]) {\n this.fail('contract-theme', `${expectation.theme} left ${name} at ${after[name]}`);\n }\n }\n for (const name of expectation.unchanged) {\n if (after[name] !== before[name]) {\n this.fail('contract-theme', `${expectation.theme} moved ${name} from ${before[name]} to ${after[name]}`);\n }\n }\n for (const [variable, token] of Object.entries(expectation.aliasedTo)) {\n if (after[variable] !== after[token]) {\n this.fail('contract-theme', `under ${expectation.theme} ${variable} is ${after[variable]}, ${token} is ${after[token]}`);\n }\n }\n await this.assertPaintMap(\n { [expectation.observe.part]: { [expectation.observe.css]: expectation.observe.variable } },\n 'contract-theme',\n );\n\n await this.cancelThemePreview({ variable: moved, from: after[moved] });\n const reverted = await this.rootValues(watched);\n for (const name of watched) {\n if (reverted[name] !== before[name]) {\n this.fail('contract-theme', `cancelling the ${expectation.theme} preview left ${name} at ${reverted[name]}, was ${before[name]}`);\n }\n }\n }\n\n // ── 7. Sketch paint ──────────────────────────────────────────────────────\n\n async setSketch(style: string | null): Promise<void> {\n await this.page.evaluate((id) => window.__liveTokensEditor!.setSketch(id), style);\n await settle(this.page);\n }\n\n /** The claim that a component is not drawn: toggling the effect changes\n * nothing about a part's own paint. A raw `'none'` check misreads a part\n * whose native content is never `'none'` (an icon font's glyph) as drawn,\n * so this compares against the part's real pre-toggle content instead, on\n * the pseudo-element the part actually declares (defaulting to `::before`,\n * where the sketch layer paints). */\n async assertNoSketchPaint(style: string): Promise<void> {\n const contentOf = async (part: string) => {\n const element = this.locator(part);\n if (await element.count() === 0) return null;\n const pseudo = partLocator(this.contract, part).pseudo ?? '::before';\n return element.evaluate((node, on) => getComputedStyle(node, on).content, pseudo);\n };\n const parts = Object.keys(this.contract.parts);\n const before: Record<string, string | null> = {};\n for (const part of parts) before[part] = await contentOf(part);\n\n await this.setSketch(style);\n try {\n for (const part of parts) {\n const drawn = await contentOf(part);\n if (drawn !== before[part]) {\n this.fail('contract-sketch', `part \"${part}\" is drawn under \"${style}\" but the contract marks Sketch inapplicable`);\n }\n }\n } finally {\n await this.setSketch(null);\n }\n }\n\n async assertSketchPaint(expectation: SketchExpectation): Promise<void> {\n await this.selectView(expectation);\n const watched = ['backgroundColor', 'borderTopColor', 'borderTopWidth', 'borderRadius'];\n const baseline: Record<string, Record<string, string>> = {};\n for (const { part } of expectation.parts) baseline[part] = await this.read(part, watched, 'contract-sketch');\n\n await this.setSketch(expectation.style);\n const scoped = await this.page.locator(STAGE).first().getAttribute('data-sketch');\n if (scoped === null) {\n this.fail('contract-sketch', `the preview stage carries no data-sketch under \"${expectation.style}\"`);\n }\n\n const fills = new Map<string, string>();\n for (const { part, fill, stroke } of expectation.parts) {\n const drawn = await (await this.requirePart(part, 'contract-sketch'))\n .evaluate((node) => getComputedStyle(node, '::before').content);\n if (drawn === 'none') this.fail('contract-sketch', `part \"${part}\" carries no drawn layer under \"${expectation.style}\"`);\n\n const names = ['--sketch-fill', '--sketch-stroke', ...(fill ? [fill] : []), ...(stroke ? [stroke] : [])];\n const observed = await this.read(part, names, 'contract-sketch');\n if (fill) {\n if (observed['--sketch-fill'] !== observed[fill]) {\n this.fail('contract-sketch', `part \"${part}\" draws its fill from ${observed['--sketch-fill']}, ${fill} is ${observed[fill]}`);\n }\n const twin = [...fills].find(([, value]) => value === observed['--sketch-fill'])?.[0];\n if (twin) {\n this.fail('contract-sketch', `parts \"${twin}\" and \"${part}\" are drawn in one colour, ${observed['--sketch-fill']}`);\n }\n fills.set(part, observed['--sketch-fill']);\n }\n if (stroke && observed['--sketch-stroke'] !== observed[stroke]) {\n this.fail('contract-sketch', `part \"${part}\" draws its stroke from ${observed['--sketch-stroke']}, ${stroke} is ${observed[stroke]}`);\n }\n }\n\n await this.setSketch(null);\n for (const { part } of expectation.parts) {\n const restored = await this.read(part, watched, 'contract-sketch');\n for (const property of watched) {\n if (restored[property] !== baseline[part][property]) {\n this.fail('contract-sketch', `leaving Sketch mode left ${part}.${property} at ${restored[property]}, was ${baseline[part][property]}`);\n }\n }\n }\n }\n}\n\nconst COLOUR = /(^|[a-z])(color|fill|stroke)$/i;\n// `height` also catches lineHeight, `spacing` letterSpacing.\nconst LENGTH = /(width|height|radius|padding|margin|gap|spacing|size|offset|inset|top|right|bottom|left)/i;\n\n/**\n * A value the CSS property adopts verbatim, so the assertion pins the mapping\n * to one part and one property. Returns null for a property no probe covers,\n * which fails the obligation.\n */\nexport function probeValueFor(css: string): string | null {\n if (css === 'fontWeight') return '850';\n if (css === 'fontFamily') return 'monospace';\n if (css === 'boxShadow') return 'rgb(1, 2, 3) 7px 9px 0px 3px';\n if (css === 'textTransform') return 'uppercase';\n if (css === 'opacity') return '0.37';\n if (css === 'backgroundImage') return 'linear-gradient(90deg, rgb(1, 2, 3), rgb(4, 5, 6))';\n if (COLOUR.test(css)) return 'rgb(1, 2, 3)';\n if (LENGTH.test(css)) return '37px';\n return null;\n}\n"],"mappings":"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","names":["role","option"]}
|