@motion-proto/live-tokens 0.97.0 → 0.99.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 +5 -0
- package/.claude/skills/live-tokens-create-component/SKILL.md +4 -3
- package/.claude/skills/live-tokens-create-component/references/contract-tests.md +71 -11
- package/CHANGELOG.md +339 -0
- package/README.md +2 -2
- package/bin/check-component.mjs +8 -0
- package/bin/check-page.mjs +6 -0
- package/bin/cli.mjs +36 -6
- package/bin/contractRunner.mjs +144 -19
- package/bin/lib/findings.mjs +20 -4
- package/bin/rules/a11y.mjs +53 -0
- package/dist-plugin/{chunk-A4TBP4MM.js → chunk-SLICH4IH.js} +2 -2
- package/dist-plugin/index.cjs +204 -3
- package/dist-plugin/index.js +306 -105
- package/dist-plugin/setColors/index.js +1 -1
- package/package.json +47 -2
- package/src/demo/LabeledSelect.svelte +1 -1
- package/src/editor/bootstrap.ts +5 -1
- package/src/editor/component-editor/BadgeEditor.svelte +13 -0
- package/src/editor/component-editor/ButtonEditor.svelte +33 -2
- package/src/editor/component-editor/CalloutEditor.svelte +13 -0
- package/src/editor/component-editor/CardEditor.svelte +12 -2
- package/src/editor/component-editor/CodeSnippetEditor.svelte +11 -1
- package/src/editor/component-editor/CollapsibleSectionEditor.svelte +18 -1
- package/src/editor/component-editor/CornerBadgeEditor.svelte +13 -0
- package/src/editor/component-editor/DialogEditor.svelte +15 -0
- package/src/editor/component-editor/IconButtonEditor.svelte +29 -1
- package/src/editor/component-editor/ImageEditor.svelte +20 -9
- package/src/editor/component-editor/ImageLightboxEditor.svelte +44 -0
- package/src/editor/component-editor/InlineEditActionsEditor.svelte +13 -1
- package/src/editor/component-editor/InputEditor.svelte +23 -0
- package/src/editor/component-editor/MenuSelectEditor.svelte +27 -1
- package/src/editor/component-editor/NotificationEditor.svelte +15 -0
- package/src/editor/component-editor/PanelEditor.svelte +1 -1
- package/src/editor/component-editor/ProgressBarEditor.svelte +13 -0
- package/src/editor/component-editor/RadioButtonEditor.svelte +20 -1
- package/src/editor/component-editor/SectionDividerEditor.svelte +40 -13
- package/src/editor/component-editor/SegmentedControlEditor.svelte +29 -1
- package/src/editor/component-editor/SideNavigationEditor.svelte +40 -1
- package/src/editor/component-editor/SlidePagerEditor.svelte +20 -0
- package/src/editor/component-editor/SliderEditor.svelte +33 -0
- package/src/editor/component-editor/TabBarEditor.svelte +23 -2
- package/src/editor/component-editor/TableEditor.svelte +14 -0
- package/src/editor/component-editor/ToggleEditor.svelte +17 -0
- package/src/editor/component-editor/TooltipEditor.svelte +11 -2
- package/src/editor/component-editor/VideoFrameEditor.svelte +8 -0
- package/src/editor/component-editor/VideoLightboxEditor.svelte +10 -0
- package/src/editor/component-editor/registration.ts +2 -1
- package/src/editor/component-editor/registry.ts +69 -27
- package/src/editor/component-editor/scaffolding/DemoHeader.svelte +2 -0
- package/src/editor/component-editor/scaffolding/StateBlock.svelte +19 -8
- package/src/editor/component-editor/scaffolding/TokenLayout.svelte +3 -0
- package/src/editor/component-editor/scaffolding/VariantGroup.svelte +70 -3
- package/src/editor/component-editor/scaffolding/editorContext.ts +7 -0
- package/src/editor/core/a11y/a11yReport.ts +164 -0
- package/src/editor/core/a11y/a11yReportTypes.ts +77 -0
- package/src/editor/core/a11y/contrastFailures.ts +22 -0
- package/src/editor/core/a11y/contrastFixes.ts +41 -0
- package/src/editor/core/components/contrastPairRegistry.ts +18 -0
- package/src/editor/core/palettes/contrast.ts +44 -0
- package/src/editor/core/palettes/contrastPairs.ts +82 -0
- package/src/editor/core/palettes/resolveColor.ts +77 -0
- package/src/editor/core/store/editorStore.ts +4 -0
- package/src/editor/core/store/editorViewStore.ts +2 -2
- package/src/editor/core/store/unsavedEdits.ts +10 -0
- package/src/editor/core/themes/liveStateStream.ts +7 -1
- package/src/editor/core/themes/parsers/gradient.ts +5 -2
- package/src/editor/docs/chapters.ts +1 -0
- package/src/editor/docs/content/accessibility.md +411 -0
- package/src/editor/docs/content/editing-tokens.md +32 -1
- package/src/editor/docs/content.generated.ts +2 -1
- package/src/editor/pages/ComponentEditorPage.svelte +11 -1
- package/src/editor/pages/EditorShell.svelte +98 -10
- package/src/editor/skill-atlas/skillSources.generated.ts +3 -3
- package/src/editor/skill-atlas/trees/check-compliance.ts +3 -3
- package/src/editor/skill-atlas/trees/create-component.ts +12 -12
- package/src/editor/styles/ui-editor.css +2 -0
- package/src/editor/ui/EditorViewSwitcher.svelte +15 -2
- package/src/editor/ui/GradientEditor.svelte +9 -1
- package/src/editor/ui/ThemePanel.svelte +4 -4
- package/src/editor/ui/UIContrastReadout.svelte +186 -0
- package/src/editor/ui/UIInfoPopover.svelte +16 -2
- package/src/editor/ui/UIPaletteSelector.svelte +9 -0
- package/src/editor/ui/UITokenSelector.svelte +26 -2
- package/src/editor/ui/a11y/A11yByEye.svelte +264 -0
- package/src/editor/ui/a11y/A11yComponentIssues.svelte +121 -0
- package/src/editor/ui/a11y/A11yFindingRow.svelte +119 -0
- package/src/editor/ui/a11y/A11yIssueRow.svelte +152 -0
- package/src/editor/ui/a11y/A11yOverview.svelte +246 -0
- package/src/editor/ui/a11y/A11yPanel.svelte +153 -0
- package/src/editor/ui/a11y/A11yPropertyMark.svelte +84 -0
- package/src/editor/ui/a11y/A11yRailMark.svelte +41 -0
- package/src/editor/ui/a11y/AccessibilityTab.svelte +321 -0
- package/src/editor/ui/a11y/a11yView.ts +257 -0
- package/src/editor/ui/contrastReadout.ts +45 -0
- package/src/live-tokens/data/colors-and-type/halloween.json +1 -1
- package/src/live-tokens/data/themes/autumn.json +35 -35
- package/src/live-tokens/data/themes/halloween.json +36 -36
- package/src/live-tokens/data/themes/midnight-study.json +35 -35
- package/src/live-tokens/data/themes/ocean.json +35 -35
- package/src/live-tokens/data/themes/royal-velvet.json +35 -35
- package/src/live-tokens/data/themes/sketchy.json +35 -35
- package/src/live-tokens/data/themes/spring-meadow.json +35 -35
- package/src/live-tokens/data/themes/sunset.json +35 -35
- package/src/system/components/Badge.svelte +3 -3
- package/src/system/components/Button.svelte +12 -6
- package/src/system/components/CodeSnippet.svelte +8 -1
- package/src/system/components/CornerBadge.svelte +3 -3
- package/src/system/components/Dialog.svelte +43 -14
- package/src/system/components/IconButton.svelte +1 -1
- package/src/system/components/Image.svelte +7 -0
- package/src/system/components/ImageLightbox.svelte +18 -25
- package/src/system/components/InlineEditActions.svelte +1 -1
- package/src/system/components/Input.svelte +9 -2
- package/src/system/components/MenuSelect.svelte +31 -3
- package/src/system/components/Notification.svelte +1 -1
- package/src/system/components/ProgressBar.svelte +7 -1
- package/src/system/components/RadioButton.svelte +36 -3
- package/src/system/components/SegmentedControl.svelte +36 -2
- package/src/system/components/SlidePager.svelte +3 -3
- package/src/system/components/Slider.svelte +19 -15
- package/src/system/components/TabBar.svelte +33 -3
- package/src/system/components/Toggle.svelte +3 -3
- package/src/system/components/VideoFrame.svelte +1 -1
- package/src/system/components/VideoLightbox.svelte +2 -2
- package/src/system/internal/focusTrap.ts +35 -0
- package/src/testing-js/__aria__/badge.yml +40 -0
- package/src/testing-js/__aria__/button.yml +88 -0
- package/src/testing-js/__aria__/callout.yml +12 -0
- package/src/testing-js/__aria__/card.yml +8 -0
- package/src/testing-js/__aria__/codesnippet.yml +21 -0
- package/src/testing-js/__aria__/collapsiblesection.yml +23 -0
- package/src/testing-js/__aria__/cornerbadge.yml +24 -0
- package/src/testing-js/__aria__/dialog.yml +42 -0
- package/src/testing-js/__aria__/iconbutton.yml +57 -0
- package/src/testing-js/__aria__/image.yml +10 -0
- package/src/testing-js/__aria__/imagelightbox.yml +50 -0
- package/src/testing-js/__aria__/inlineeditactions.yml +16 -0
- package/src/testing-js/__aria__/input.yml +61 -0
- package/src/testing-js/__aria__/menuselect.yml +30 -0
- package/src/testing-js/__aria__/notification.yml +30 -0
- package/src/testing-js/__aria__/panel.yml +2 -0
- package/src/testing-js/__aria__/progressbar.yml +2 -0
- package/src/testing-js/__aria__/radiobutton.yml +20 -0
- package/src/testing-js/__aria__/sectiondivider.yml +9 -0
- package/src/testing-js/__aria__/segmentedcontrol.yml +35 -0
- package/src/testing-js/__aria__/sidenavigation.yml +304 -0
- package/src/testing-js/__aria__/slidepager.yml +72 -0
- package/src/testing-js/__aria__/slider.yml +28 -0
- package/src/testing-js/__aria__/tabbar.yml +35 -0
- package/src/testing-js/__aria__/table.yml +144 -0
- package/src/testing-js/__aria__/toggle.yml +12 -0
- package/src/testing-js/__aria__/tooltip.yml +2 -0
- package/src/testing-js/__aria__/videoframe.yml +6 -0
- package/src/testing-js/__aria__/videolightbox.yml +12 -0
- package/src/testing-js/{chunk-WIZ6W7UT.js → chunk-3WCLMOM7.js} +2 -2
- package/src/testing-js/{chunk-NB3NZRBM.js → chunk-7CM5D7PF.js} +5 -1
- package/src/testing-js/chunk-7CM5D7PF.js.map +1 -0
- package/src/testing-js/{chunk-X6KHEVIG.js → chunk-7QXUJRSO.js} +97 -29
- package/src/testing-js/chunk-7QXUJRSO.js.map +1 -0
- package/src/testing-js/chunk-GZKUYLDW.js +193 -0
- package/src/testing-js/chunk-GZKUYLDW.js.map +1 -0
- package/src/testing-js/chunk-RTZQLW3F.js +649 -0
- package/src/testing-js/chunk-RTZQLW3F.js.map +1 -0
- package/src/testing-js/{chunk-SHBYZUPD.js → chunk-RWOT2XDB.js} +212 -15
- package/src/testing-js/chunk-RWOT2XDB.js.map +1 -0
- package/src/testing-js/{chunk-GKO27NGN.js → chunk-THWGMSRH.js} +2 -2
- package/src/testing-js/{chunk-3UKGXCDL.js → chunk-YVVR3GJZ.js} +1 -1
- package/src/testing-js/chunk-YVVR3GJZ.js.map +1 -0
- package/src/testing-js/component-a11y.contract.js +313 -0
- package/src/testing-js/component-a11y.contract.js.map +1 -0
- package/src/testing-js/component-alias.contract.js +2 -2
- package/src/testing-js/component-behavior.contract.js +2 -2
- package/src/testing-js/component-editor.contract.js +6 -5
- package/src/testing-js/component-editor.contract.js.map +1 -1
- package/src/testing-js/component-render.contract.js +10 -6
- package/src/testing-js/component-render.contract.js.map +1 -1
- package/src/testing-js/index.d.ts +44 -16
- package/src/testing-js/index.js +11 -11
- package/src/testing-js/index.js.map +1 -1
- package/src/testing-js/page-compliance.contract.js +132 -13
- package/src/testing-js/page-compliance.contract.js.map +1 -1
- package/src/testing-js/vitest.js +3 -3
- package/template/_gitignore +3 -0
- package/template/package.json +9 -0
- package/src/testing-js/chunk-3UKGXCDL.js.map +0 -1
- package/src/testing-js/chunk-NB3NZRBM.js.map +0 -1
- package/src/testing-js/chunk-SHBYZUPD.js.map +0 -1
- package/src/testing-js/chunk-X6KHEVIG.js.map +0 -1
- /package/src/testing-js/{chunk-WIZ6W7UT.js.map → chunk-3WCLMOM7.js.map} +0 -0
- /package/src/testing-js/{chunk-GKO27NGN.js.map → chunk-THWGMSRH.js.map} +0 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"preview": |
|
|
2
|
+
- switch "Enable feature"
|
|
3
|
+
"default": |
|
|
4
|
+
- switch "Enable feature"
|
|
5
|
+
"hover": |
|
|
6
|
+
- switch "Enable feature"
|
|
7
|
+
"on": |
|
|
8
|
+
- switch "Enable feature" [checked]
|
|
9
|
+
"on hover": |
|
|
10
|
+
- switch "Enable feature" [checked]
|
|
11
|
+
"disabled": |
|
|
12
|
+
- switch "Enable feature" [disabled]
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"preview": |
|
|
2
|
+
- 'button "Play video: Navigation running on a smartwatch"'
|
|
3
|
+
- button "Close"
|
|
4
|
+
"hover": |
|
|
5
|
+
- 'button "Play video: Navigation running on a smartwatch"'
|
|
6
|
+
- button "Close"
|
|
7
|
+
"default": |
|
|
8
|
+
- 'button "Play video: Navigation running on a smartwatch"'
|
|
9
|
+
- button "Close"
|
|
10
|
+
"preview (click closeButton)": |
|
|
11
|
+
- 'button "Play video: Navigation running on a smartwatch"'
|
|
12
|
+
- button "Close"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
COMPONENTS_PATH_ENV,
|
|
3
3
|
DEFAULT_COMPONENTS_PATH
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-7CM5D7PF.js";
|
|
5
5
|
|
|
6
6
|
// src/testing/support/editor.ts
|
|
7
7
|
function componentsPath() {
|
|
@@ -20,4 +20,4 @@ async function openComponentsEditor(page, path = componentsPath()) {
|
|
|
20
20
|
export {
|
|
21
21
|
openComponentsEditor
|
|
22
22
|
};
|
|
23
|
-
//# sourceMappingURL=chunk-
|
|
23
|
+
//# sourceMappingURL=chunk-3WCLMOM7.js.map
|
|
@@ -9,6 +9,8 @@ var DEFAULT_COMPONENTS_PATH = "/live-tokens/components";
|
|
|
9
9
|
var TESTING_CONFIG_FILE = "live-tokens.testing.ts";
|
|
10
10
|
var COMPONENTS_PATH_ENV = "LIVE_TOKENS_COMPONENTS_PATH";
|
|
11
11
|
var COMPONENT_ENV = "LIVE_TOKENS_COMPONENT";
|
|
12
|
+
var A11Y_THEMES_ENV = "LIVE_TOKENS_A11Y_THEMES";
|
|
13
|
+
var UPDATE_ARIA_ENV = "LIVE_TOKENS_UPDATE_ARIA";
|
|
12
14
|
var PAGES_ENV = "LIVE_TOKENS_PAGES";
|
|
13
15
|
var PAGE_VIEWPORTS_ENV = "LIVE_TOKENS_PAGE_VIEWPORTS";
|
|
14
16
|
var DEFAULT_PAGE_VIEWPORTS = [
|
|
@@ -54,6 +56,8 @@ export {
|
|
|
54
56
|
TESTING_CONFIG_FILE,
|
|
55
57
|
COMPONENTS_PATH_ENV,
|
|
56
58
|
COMPONENT_ENV,
|
|
59
|
+
A11Y_THEMES_ENV,
|
|
60
|
+
UPDATE_ARIA_ENV,
|
|
57
61
|
PAGES_ENV,
|
|
58
62
|
PAGE_VIEWPORTS_ENV,
|
|
59
63
|
DEFAULT_PAGE_VIEWPORTS,
|
|
@@ -61,4 +65,4 @@ export {
|
|
|
61
65
|
resolveTestingConfig,
|
|
62
66
|
devServerCommand
|
|
63
67
|
};
|
|
64
|
-
//# sourceMappingURL=chunk-
|
|
68
|
+
//# sourceMappingURL=chunk-7CM5D7PF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../testing/config.ts","../editor/core/routing/ownedRoutes.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { DEFAULT_COMPONENTS_PATH } from '../editor/core/routing/ownedRoutes';\n\n/** The file a project puts its shared test settings in, at the project root. */\nexport const TESTING_CONFIG_FILE = 'live-tokens.testing.ts';\n\n/** The components route the run drives, published from the settings so the\n * suites need no argument. */\nexport const COMPONENTS_PATH_ENV = 'LIVE_TOKENS_COMPONENTS_PATH';\n\n/** Narrows a run to one component. */\nexport const COMPONENT_ENV = 'LIVE_TOKENS_COMPONENT';\n\n/** `all` repeats each component accessibility scan under the eight preset\n * themes. The repository's own contract run sets it; a consumer run scans\n * the active theme alone. */\nexport const A11Y_THEMES_ENV = 'LIVE_TOKENS_A11Y_THEMES';\n\n/** Rewrites each component's recorded accessibility tree. */\nexport const UPDATE_ARIA_ENV = 'LIVE_TOKENS_UPDATE_ARIA';\n\n/** The page targets a run opens, as JSON: `[{ source, route }]`. */\nexport const PAGES_ENV = 'LIVE_TOKENS_PAGES';\n\n/** The viewports every page rule runs at, as JSON: `[{ width, height }]`. */\nexport const PAGE_VIEWPORTS_ENV = 'LIVE_TOKENS_PAGE_VIEWPORTS';\n\nexport interface PageViewport {\n width: number;\n height: number;\n}\n\n/** The contract project's own desktop size, and the phone the text styles\n * carry media overrides for. Nothing here is derived from a page. */\nexport const DEFAULT_PAGE_VIEWPORTS: PageViewport[] = [\n { width: 1280, height: 900 },\n { width: 390, height: 844 },\n];\n\n/** What `resolveDataDirs` falls back to, restated because that resolver is\n * plugin-side and the tarball ships the plugin built rather than as source.\n * `vite-plugin/testingConfig.test.ts` pins the two together. */\nconst DEFAULT_DATA_DIR = 'src/live-tokens/data';\n\nconst DEFAULT_DEV_COMMAND = 'npm run dev -- --host {host} --port {port}';\n\nexport interface LiveTokensTestingConfig {\n /** Vite config a generated Vitest config merges. Default `vite.config.ts`. */\n viteConfig?: string;\n /** Command that starts the dev server. `{host}` and `{port}` are substituted.\n * Default `npm run dev -- --host {host} --port {port}`. */\n devCommand?: string;\n /** Fixed port for the dev server. Omitted, the run takes a free one. */\n port?: number;\n /** The components route, when `editorRoutes` moved it off the owned default. */\n componentsPath?: string;\n /** The plugin's data directory. Default: `dataDir` from\n * `live-tokens.config.json`, else `src/live-tokens/data`. The run never uses\n * it directly; it is the tree the isolated copy is made from. */\n dataDir?: string;\n /** Module that registers the project's components without mounting the app.\n * The registry contract imports it before it selects entries. */\n registrySetup?: string;\n /** Module exporting the `ComponentContract[]` a custom component adds to the\n * shipped list (default export or a named `contracts` export). The suite\n * files are static Playwright entry points, so an env var naming this path\n * plus a dynamic import inside `selectedContracts()` is the only way a\n * custom contract reaches them. */\n contractsModule?: string;\n /** Page source path to the concrete URL that renders it, for a route the\n * `pages` object cannot express: one served by `resolve()`, or one whose\n * parameters only the project knows. Page paths are relative to the\n * project root. */\n pageRoutes?: Record<string, string>;\n /** Replaces the two sizes every page rule runs at. */\n pageViewports?: PageViewport[];\n}\n\nexport interface ResolvedTestingConfig {\n root: string;\n viteConfig: string;\n devCommand: string;\n port?: number;\n componentsPath: string;\n dataDir: string;\n registrySetup?: string;\n contractsModule?: string;\n pageRoutes: Record<string, string>;\n pageViewports: PageViewport[];\n}\n\n/** Types the settings file without importing the interface by hand. */\nexport function defineTestingConfig(config: LiveTokensTestingConfig): LiveTokensTestingConfig {\n return config;\n}\n\n/** `dataDir` as the plugin resolves it, from the same file the plugin reads. */\nfunction configuredDataDir(root: string): string {\n try {\n const parsed = JSON.parse(fs.readFileSync(path.join(root, 'live-tokens.config.json'), 'utf-8'));\n if (parsed && typeof parsed === 'object' && typeof parsed.dataDir === 'string') {\n return path.resolve(root, parsed.dataDir);\n }\n } catch {\n // Missing or unparseable reads as absent, matching `readLiveTokensConfig`.\n }\n return path.resolve(root, DEFAULT_DATA_DIR);\n}\n\nexport function resolveTestingConfig(\n config: LiveTokensTestingConfig = {},\n root: string = process.cwd(),\n): ResolvedTestingConfig {\n const projectRoot = path.resolve(root);\n return {\n root: projectRoot,\n viteConfig: path.resolve(projectRoot, config.viteConfig ?? 'vite.config.ts'),\n devCommand: config.devCommand ?? DEFAULT_DEV_COMMAND,\n port: config.port,\n componentsPath: config.componentsPath ?? DEFAULT_COMPONENTS_PATH,\n dataDir: config.dataDir ? path.resolve(projectRoot, config.dataDir) : configuredDataDir(projectRoot),\n registrySetup: config.registrySetup\n ? path.resolve(projectRoot, config.registrySetup)\n : undefined,\n contractsModule: config.contractsModule\n ? path.resolve(projectRoot, config.contractsModule)\n : undefined,\n pageRoutes: config.pageRoutes ?? {},\n pageViewports: config.pageViewports?.length ? config.pageViewports : DEFAULT_PAGE_VIEWPORTS,\n };\n}\n\nexport function devServerCommand(command: string, host: string, port: number): string {\n return command.replaceAll('{host}', host).replaceAll('{port}', String(port));\n}\n","// The package's dev-only editor surfaces live under a reserved `/live-tokens/*`\n// namespace so they can never collide with a consumer's own routes — the\n// consumer owns the rest of the URL space. Keeping the defaults in one place\n// is the guard against the nav rail and the dispatcher drifting onto different\n// paths (the collision/shadow class these constants exist to prevent).\n//\n// A consumer relocates or disables each surface via the `editorRoutes` prop on\n// <LiveTokensRouter>; these are only the defaults.\nexport const DEFAULT_EDITOR_PATH = '/live-tokens/editor';\nexport const DEFAULT_COMPONENTS_PATH = '/live-tokens/components';\nexport const DEFAULT_COLORS_PATH = '/live-tokens/colors';\nexport const DEFAULT_DOCS_PATH = '/live-tokens/docs';\n"],"mappings":";AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;;;ACQV,IAAM,0BAA0B;;;ADJhC,IAAM,sBAAsB;AAI5B,IAAM,sBAAsB;AAG5B,IAAM,gBAAgB;AAKtB,IAAM,kBAAkB;AAGxB,IAAM,kBAAkB;AAGxB,IAAM,YAAY;AAGlB,IAAM,qBAAqB;AAS3B,IAAM,yBAAyC;AAAA,EACpD,EAAE,OAAO,MAAM,QAAQ,IAAI;AAAA,EAC3B,EAAE,OAAO,KAAK,QAAQ,IAAI;AAC5B;AAKA,IAAM,mBAAmB;AAEzB,IAAM,sBAAsB;AAgDrB,SAAS,oBAAoB,QAA0D;AAC5F,SAAO;AACT;AAGA,SAAS,kBAAkB,MAAsB;AAC/C,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,GAAG,aAAa,KAAK,KAAK,MAAM,yBAAyB,GAAG,OAAO,CAAC;AAC9F,QAAI,UAAU,OAAO,WAAW,YAAY,OAAO,OAAO,YAAY,UAAU;AAC9E,aAAO,KAAK,QAAQ,MAAM,OAAO,OAAO;AAAA,IAC1C;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO,KAAK,QAAQ,MAAM,gBAAgB;AAC5C;AAEO,SAAS,qBACd,SAAkC,CAAC,GACnC,OAAe,QAAQ,IAAI,GACJ;AACvB,QAAM,cAAc,KAAK,QAAQ,IAAI;AACrC,SAAO;AAAA,IACL,MAAM;AAAA,IACN,YAAY,KAAK,QAAQ,aAAa,OAAO,cAAc,gBAAgB;AAAA,IAC3E,YAAY,OAAO,cAAc;AAAA,IACjC,MAAM,OAAO;AAAA,IACb,gBAAgB,OAAO,kBAAkB;AAAA,IACzC,SAAS,OAAO,UAAU,KAAK,QAAQ,aAAa,OAAO,OAAO,IAAI,kBAAkB,WAAW;AAAA,IACnG,eAAe,OAAO,gBAClB,KAAK,QAAQ,aAAa,OAAO,aAAa,IAC9C;AAAA,IACJ,iBAAiB,OAAO,kBACpB,KAAK,QAAQ,aAAa,OAAO,eAAe,IAChD;AAAA,IACJ,YAAY,OAAO,cAAc,CAAC;AAAA,IAClC,eAAe,OAAO,eAAe,SAAS,OAAO,gBAAgB;AAAA,EACvE;AACF;AAEO,SAAS,iBAAiB,SAAiB,MAAc,MAAsB;AACpF,SAAO,QAAQ,WAAW,UAAU,IAAI,EAAE,WAAW,UAAU,OAAO,IAAI,CAAC;AAC7E;","names":[]}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
openComponentsEditor
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-3WCLMOM7.js";
|
|
4
|
+
import {
|
|
5
|
+
recordA11y
|
|
6
|
+
} from "./chunk-RTZQLW3F.js";
|
|
4
7
|
import {
|
|
5
8
|
ContractViolation,
|
|
6
9
|
isInapplicable,
|
|
7
10
|
partLocator,
|
|
8
11
|
requiresInteraction
|
|
9
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-YVVR3GJZ.js";
|
|
10
13
|
|
|
11
14
|
// src/testing/support/contractHarness.ts
|
|
12
15
|
import fs from "fs";
|
|
@@ -14,6 +17,8 @@ import path from "path";
|
|
|
14
17
|
var STAGE_GROUP = ".variant-group";
|
|
15
18
|
var STAGE_SCOPE = ".sketch-scope";
|
|
16
19
|
var STAGE = `${STAGE_GROUP}:visible ${STAGE_SCOPE}`;
|
|
20
|
+
var THEME_PICKER = '[role="dialog"][aria-label="Theme Picker"]';
|
|
21
|
+
var KEYBOARD_PATTERNS_URL = "https://www.w3.org/WAI/ARIA/apg/patterns/";
|
|
17
22
|
var SERVER_WRITE_TIMEOUT_MS = 3e4;
|
|
18
23
|
var settle = (page) => page.evaluate(async () => {
|
|
19
24
|
const frame = () => new Promise((resolve) => requestAnimationFrame(() => resolve()));
|
|
@@ -158,6 +163,19 @@ var ContractHarness = class _ContractHarness {
|
|
|
158
163
|
this.fail("contract-listed", `rail lists "${entry.label}" under ${group}, contract declares ${this.contract.origin}`);
|
|
159
164
|
}
|
|
160
165
|
}
|
|
166
|
+
/** Every variable a property row of the component can set: its schema
|
|
167
|
+
* tokens and its intrinsics. */
|
|
168
|
+
async propertyVariables() {
|
|
169
|
+
const names = await this.page.evaluate((id) => {
|
|
170
|
+
const entry = window.__liveTokensEditor?.getComponentRegistryEntries().find((e) => e.id === id);
|
|
171
|
+
if (!entry) throw new Error(`no registry entry for "${id}"`);
|
|
172
|
+
return [
|
|
173
|
+
...entry.schema.map((token) => token.variable),
|
|
174
|
+
...(entry.intrinsics ?? []).flatMap((spec) => spec.variants.map((variant) => spec.variable(variant)))
|
|
175
|
+
];
|
|
176
|
+
}, this.contract.id);
|
|
177
|
+
return new Set(names);
|
|
178
|
+
}
|
|
161
179
|
// ── 2. Property projection ───────────────────────────────────────────────
|
|
162
180
|
/**
|
|
163
181
|
* Drive one design token to a probe value and require the declared part's
|
|
@@ -372,7 +390,7 @@ ${missing.join("\n")}`);
|
|
|
372
390
|
}
|
|
373
391
|
async performAction(action) {
|
|
374
392
|
if (action.kind === "press") {
|
|
375
|
-
await this.locator(action.part).focus().catch(() => void 0);
|
|
393
|
+
if (action.part) await this.locator(action.part).focus().catch(() => void 0);
|
|
376
394
|
await this.page.keyboard.press(action.key);
|
|
377
395
|
return;
|
|
378
396
|
}
|
|
@@ -398,49 +416,68 @@ ${missing.join("\n")}`);
|
|
|
398
416
|
}
|
|
399
417
|
async runInteraction(testCase) {
|
|
400
418
|
await this.selectView(testCase);
|
|
419
|
+
const gap = await this.interactionGap(testCase);
|
|
420
|
+
if (gap === null) return;
|
|
421
|
+
if (testCase.rule !== "a11y-keyboard") this.fail("contract-interaction", `${testCase.name}: ${gap}`);
|
|
422
|
+
const element = this.locator(testCase.expect.part);
|
|
423
|
+
const merged = { ...this.contract.view, ...testCase };
|
|
424
|
+
const view = [merged.variant, merged.state].filter(Boolean).join(" / ");
|
|
425
|
+
recordA11y([{
|
|
426
|
+
rule: "a11y-keyboard",
|
|
427
|
+
engineRule: testCase.name,
|
|
428
|
+
impact: null,
|
|
429
|
+
target: testCase.expect.part,
|
|
430
|
+
html: await element.count() ? await element.evaluate((node) => node.outerHTML.slice(0, 300)) : "",
|
|
431
|
+
help: gap,
|
|
432
|
+
helpUrl: KEYBOARD_PATTERNS_URL,
|
|
433
|
+
...view ? { view } : {}
|
|
434
|
+
}]);
|
|
435
|
+
}
|
|
436
|
+
/** What the case observed against what it expects, or null when they agree. */
|
|
437
|
+
async interactionGap(testCase) {
|
|
401
438
|
const outcome = testCase.expect;
|
|
402
439
|
const tracksValue = outcome.kind === "valueMoves" || outcome.kind === "valueBecomes" || outcome.kind === "valueChanges" || outcome.kind === "valueHolds";
|
|
403
440
|
const before = tracksValue ? await this.valueOf(outcome.part) : "";
|
|
441
|
+
if (outcome.kind === "activated") {
|
|
442
|
+
await this.locator(outcome.part).evaluate((node) => {
|
|
443
|
+
const marked = node;
|
|
444
|
+
marked.__contractActivated = false;
|
|
445
|
+
node.addEventListener("click", () => {
|
|
446
|
+
marked.__contractActivated = true;
|
|
447
|
+
}, { once: true });
|
|
448
|
+
});
|
|
449
|
+
}
|
|
404
450
|
await this.performAction(testCase.action);
|
|
405
451
|
await settle(this.page);
|
|
406
452
|
if (outcome.kind === "attribute") {
|
|
407
453
|
const actual = await this.locator(outcome.part).evaluate((node, name) => node.getAttribute(name), outcome.name);
|
|
408
|
-
|
|
409
|
-
this.fail("contract-interaction", `${testCase.name}: ${outcome.part}[${outcome.name}] is "${actual}", expected "${outcome.value}"`);
|
|
410
|
-
}
|
|
411
|
-
return;
|
|
454
|
+
return actual === outcome.value ? null : `${outcome.part}[${outcome.name}] is "${actual}", expected "${outcome.value}"`;
|
|
412
455
|
}
|
|
413
456
|
if (outcome.kind === "focused") {
|
|
414
457
|
const focused = await this.isFocused(outcome.part);
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
458
|
+
return focused === outcome.value ? null : `${outcome.part} is ${focused ? "" : "not "}focused, expected ${outcome.value ? "" : "not "}focused`;
|
|
459
|
+
}
|
|
460
|
+
if (outcome.kind === "activated") {
|
|
461
|
+
const activated = await this.locator(outcome.part).evaluate((node) => node.__contractActivated === true);
|
|
462
|
+
return activated ? null : `${outcome.part} received no click, expected the key to activate it`;
|
|
463
|
+
}
|
|
464
|
+
if (outcome.kind === "present") {
|
|
465
|
+
const present = await this.locator(outcome.part).count() > 0;
|
|
466
|
+
return present === outcome.value ? null : `${outcome.part} is ${present ? "still" : "not"} in the document, expected it ${outcome.value ? "present" : "gone"}`;
|
|
419
467
|
}
|
|
420
468
|
const after = await this.valueOf(outcome.part);
|
|
421
469
|
if (outcome.kind === "valueHolds") {
|
|
422
|
-
|
|
423
|
-
this.fail("contract-interaction", `${testCase.name}: value moved from ${before} to ${after}`);
|
|
424
|
-
}
|
|
425
|
-
return;
|
|
470
|
+
return after === before ? null : `value moved from ${before} to ${after}`;
|
|
426
471
|
}
|
|
427
472
|
if (outcome.kind === "valueChanges") {
|
|
428
|
-
|
|
429
|
-
this.fail("contract-interaction", `${testCase.name}: value held at ${before}`);
|
|
430
|
-
}
|
|
431
|
-
return;
|
|
473
|
+
return after === before ? `value held at ${before}` : null;
|
|
432
474
|
}
|
|
433
475
|
if (outcome.kind === "valueBecomes") {
|
|
434
|
-
|
|
435
|
-
this.fail("contract-interaction", `${testCase.name}: value is ${after}, expected ${outcome.value}`);
|
|
436
|
-
}
|
|
437
|
-
return;
|
|
476
|
+
return after === outcome.value ? null : `value is ${after}, expected ${outcome.value}`;
|
|
438
477
|
}
|
|
439
478
|
const moved = Number(after) - Number(before);
|
|
440
479
|
const wanted = outcome.direction === "up" ? moved > 0 : moved < 0;
|
|
441
|
-
|
|
442
|
-
this.fail("contract-interaction", `${testCase.name}: value went ${before} -> ${after}, expected to move ${outcome.direction}`);
|
|
443
|
-
}
|
|
480
|
+
return wanted ? null : `value went ${before} -> ${after}, expected to move ${outcome.direction}`;
|
|
444
481
|
}
|
|
445
482
|
// ── 5. Persistence and reset ─────────────────────────────────────────────
|
|
446
483
|
/** Every alias and config value the component holds, for restoring the buffer. */
|
|
@@ -646,7 +683,7 @@ ${missing.join("\n")}`);
|
|
|
646
683
|
* follows lands after the repaint. */
|
|
647
684
|
async previewTheme(slug, settleOn) {
|
|
648
685
|
await this.page.locator(".theme-name-trigger").click();
|
|
649
|
-
await this.page.locator(
|
|
686
|
+
await this.page.locator(THEME_PICKER).waitFor();
|
|
650
687
|
const row = this.page.locator(`.load-item[data-file-name="theme:${slug}"] .load-name-btn`);
|
|
651
688
|
if (await row.count() === 0) this.fail("contract-theme", `the Theme Picker has no theme "${slug}"`);
|
|
652
689
|
await Promise.all([
|
|
@@ -660,12 +697,43 @@ ${missing.join("\n")}`);
|
|
|
660
697
|
if (settleOn) await this.awaitRootChange(settleOn.variable, settleOn.from);
|
|
661
698
|
}
|
|
662
699
|
async cancelThemePreview(settleOn) {
|
|
663
|
-
const dialog = this.page.locator(
|
|
700
|
+
const dialog = this.page.locator(THEME_PICKER);
|
|
664
701
|
await dialog.getByRole("button", { name: "Cancel", exact: true }).click();
|
|
665
702
|
await dialog.waitFor({ state: "detached" });
|
|
666
703
|
await settle(this.page);
|
|
667
704
|
if (settleOn) await this.awaitRootChange(settleOn.variable, settleOn.from);
|
|
668
705
|
}
|
|
706
|
+
/** A theme preview that leaves the stage in view, for a check that reads the
|
|
707
|
+
* stage's own paint: the Theme Picker's backdrop covers it while the
|
|
708
|
+
* preview lasts. Each click is dispatched on its element, because a
|
|
709
|
+
* portaled overlay such as ImageLightbox's sits over the picker trigger. */
|
|
710
|
+
async previewThemeUncovered(slug) {
|
|
711
|
+
await this.page.locator(".theme-name-trigger").dispatchEvent("click");
|
|
712
|
+
await this.page.locator(THEME_PICKER).waitFor();
|
|
713
|
+
const row = this.page.locator(`.load-item[data-file-name="theme:${slug}"] .load-name-btn`);
|
|
714
|
+
if (await row.count() === 0) this.fail("contract-theme", `the Theme Picker has no theme "${slug}"`);
|
|
715
|
+
await Promise.all([
|
|
716
|
+
this.page.waitForResponse(
|
|
717
|
+
(response) => response.url().includes("/themes/") && response.ok(),
|
|
718
|
+
{ timeout: SERVER_WRITE_TIMEOUT_MS }
|
|
719
|
+
),
|
|
720
|
+
row.dispatchEvent("click")
|
|
721
|
+
]);
|
|
722
|
+
await settle(this.page);
|
|
723
|
+
await this.showThemePicker(false);
|
|
724
|
+
}
|
|
725
|
+
async cancelUncoveredPreview() {
|
|
726
|
+
await this.showThemePicker(true);
|
|
727
|
+
const dialog = this.page.locator(THEME_PICKER);
|
|
728
|
+
await dialog.getByRole("button", { name: "Cancel", exact: true }).dispatchEvent("click");
|
|
729
|
+
await dialog.waitFor({ state: "detached" });
|
|
730
|
+
await settle(this.page);
|
|
731
|
+
}
|
|
732
|
+
async showThemePicker(shown) {
|
|
733
|
+
await this.page.locator(THEME_PICKER).evaluate((dialog, visible) => {
|
|
734
|
+
dialog.closest(".ui-dialog-backdrop").style.visibility = visible ? "" : "hidden";
|
|
735
|
+
}, shown);
|
|
736
|
+
}
|
|
669
737
|
async rootValues(names) {
|
|
670
738
|
return this.page.evaluate((variables) => {
|
|
671
739
|
const style = getComputedStyle(document.documentElement);
|
|
@@ -804,4 +872,4 @@ function probeValueFor(css) {
|
|
|
804
872
|
export {
|
|
805
873
|
ContractHarness
|
|
806
874
|
};
|
|
807
|
-
//# sourceMappingURL=chunk-
|
|
875
|
+
//# sourceMappingURL=chunk-7QXUJRSO.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 { recordA11y } from './a11y';\nimport { openComponentsEditor } from './editor';\n\nconst STAGE_GROUP = '.variant-group';\nconst STAGE_SCOPE = '.sketch-scope';\nconst STAGE = `${STAGE_GROUP}:visible ${STAGE_SCOPE}`;\nconst THEME_PICKER = '[role=\"dialog\"][aria-label=\"Theme Picker\"]';\nconst KEYBOARD_PATTERNS_URL = 'https://www.w3.org/WAI/ARIA/apg/patterns/';\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 /** Every variable a property row of the component can set: its schema\n * tokens and its intrinsics. */\n async propertyVariables(): Promise<Set<string>> {\n const names = await this.page.evaluate((id) => {\n const entry = window.__liveTokensEditor?.getComponentRegistryEntries().find((e) => e.id === id);\n if (!entry) throw new Error(`no registry entry for \"${id}\"`);\n return [\n ...entry.schema.map((token) => token.variable),\n ...(entry.intrinsics ?? []).flatMap((spec) => spec.variants.map((variant) => spec.variable(variant))),\n ];\n }, this.contract.id);\n return new Set(names);\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. Each view runs in one browser call: a call per\n * property cost more in round trips than the paint it proved.\n */\n async assertProperties(): Promise<number> {\n let asserted = 0;\n for (const expectation of this.contract.properties) {\n await this.selectView(expectation);\n const cases = Object.entries(expectation.paints).flatMap(([key, map]) =>\n Object.entries(map).map(([css, variable]) => ({\n key,\n css,\n variable,\n ...partLocator(this.contract, key),\n probe: probeValueFor(css)\n ?? this.fail('contract-render', `no probe value for CSS property \"${css}\"; declare one in probeValueFor`),\n })));\n const failure = await this.page.evaluate(async ({ cases, stage }) => {\n const frame = () => new Promise<void>((resolve) => requestAnimationFrame(() => resolve()));\n const settle = async () => {\n await frame();\n await frame();\n for (const animation of document.getAnimations()) {\n try { animation.finish(); } catch { /* infinite effect */ }\n }\n await frame();\n await frame();\n };\n const stageRoot = [...document.querySelectorAll<HTMLElement>(stage.group)]\n .find((group) => group.checkVisibility())\n ?.querySelector<HTMLElement>(stage.scope);\n const root = document.documentElement;\n for (const c of cases) {\n const node = c.portal ? document.querySelector(c.selector) : stageRoot?.querySelector(c.selector);\n if (!node) return { kind: 'missing' as const, key: c.key, selector: c.selector };\n const read = () =>\n ((getComputedStyle(node, c.pseudo ?? undefined) as unknown as Record<string, string>)[c.css] ?? '').trim();\n const probe = document.createElement('div');\n probe.style.display = 'none';\n probe.style.borderStyle = 'solid';\n probe.style.outlineStyle = 'solid';\n (node.parentElement ?? document.body).appendChild(probe);\n probe.style.setProperty(c.css.replace(/[A-Z]/g, (ch) => `-${ch.toLowerCase()}`), c.probe);\n const expected = ((getComputedStyle(probe) as unknown as Record<string, string>)[c.css] ?? '').trim();\n probe.remove();\n const before = read();\n const prior = { value: root.style.getPropertyValue(c.variable), priority: root.style.getPropertyPriority(c.variable) };\n root.style.setProperty(c.variable, c.probe, 'important');\n await settle();\n const after = read();\n if (prior.value) root.style.setProperty(c.variable, prior.value, prior.priority);\n else root.style.removeProperty(c.variable);\n if (after !== expected) {\n await settle();\n return { kind: 'unpainted' as const, key: c.key, css: c.css, variable: c.variable, probe: c.probe, before, after, expected };\n }\n }\n await settle();\n return null;\n }, { cases, stage: { group: STAGE_GROUP, scope: STAGE_SCOPE } });\n if (failure?.kind === 'missing') {\n this.fail('contract-render', `part \"${failure.key}\" (${failure.selector}) is not in the preview`);\n }\n if (failure) {\n this.fail('contract-render', `${failure.variable} set to ${failure.probe} left ${failure.key}.${failure.css} at ${failure.after} (was ${failure.before}), expected ${failure.expected}`);\n }\n asserted += cases.length;\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 if (action.part) 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 gap = await this.interactionGap(testCase);\n if (gap === null) return;\n if (testCase.rule !== 'a11y-keyboard') this.fail('contract-interaction', `${testCase.name}: ${gap}`);\n const element = this.locator(testCase.expect.part);\n const merged = { ...this.contract.view, ...testCase };\n const view = [merged.variant, merged.state].filter(Boolean).join(' / ');\n recordA11y([{\n rule: 'a11y-keyboard',\n engineRule: testCase.name,\n impact: null,\n target: testCase.expect.part,\n html: await element.count() ? await element.evaluate((node) => node.outerHTML.slice(0, 300)) : '',\n help: gap,\n helpUrl: KEYBOARD_PATTERNS_URL,\n ...(view ? { view } : {}),\n }]);\n }\n\n /** What the case observed against what it expects, or null when they agree. */\n private async interactionGap(testCase: InteractionCase): Promise<string | null> {\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 if (outcome.kind === 'activated') {\n await this.locator(outcome.part).evaluate((node) => {\n const marked = node as HTMLElement & { __contractActivated?: boolean };\n marked.__contractActivated = false;\n node.addEventListener('click', () => { marked.__contractActivated = true; }, { once: true });\n });\n }\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 return actual === outcome.value ? null : `${outcome.part}[${outcome.name}] is \"${actual}\", expected \"${outcome.value}\"`;\n }\n if (outcome.kind === 'focused') {\n const focused = await this.isFocused(outcome.part);\n return focused === outcome.value\n ? null\n : `${outcome.part} is ${focused ? '' : 'not '}focused, expected ${outcome.value ? '' : 'not '}focused`;\n }\n if (outcome.kind === 'activated') {\n const activated = await this.locator(outcome.part).evaluate((node) =>\n (node as HTMLElement & { __contractActivated?: boolean }).__contractActivated === true);\n return activated ? null : `${outcome.part} received no click, expected the key to activate it`;\n }\n if (outcome.kind === 'present') {\n const present = await this.locator(outcome.part).count() > 0;\n return present === outcome.value\n ? null\n : `${outcome.part} is ${present ? 'still' : 'not'} in the document, expected it ${outcome.value ? 'present' : 'gone'}`;\n }\n\n const after = await this.valueOf(outcome.part);\n if (outcome.kind === 'valueHolds') {\n return after === before ? null : `value moved from ${before} to ${after}`;\n }\n if (outcome.kind === 'valueChanges') {\n return after === before ? `value held at ${before}` : null;\n }\n if (outcome.kind === 'valueBecomes') {\n return after === outcome.value ? null : `value is ${after}, expected ${outcome.value}`;\n }\n const moved = Number(after) - Number(before);\n const wanted = outcome.direction === 'up' ? moved > 0 : moved < 0;\n return wanted ? null : `value went ${before} -> ${after}, expected to move ${outcome.direction}`;\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(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(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 /** A theme preview that leaves the stage in view, for a check that reads the\n * stage's own paint: the Theme Picker's backdrop covers it while the\n * preview lasts. Each click is dispatched on its element, because a\n * portaled overlay such as ImageLightbox's sits over the picker trigger. */\n async previewThemeUncovered(slug: string): Promise<void> {\n await this.page.locator('.theme-name-trigger').dispatchEvent('click');\n await this.page.locator(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.dispatchEvent('click'),\n ]);\n await settle(this.page);\n await this.showThemePicker(false);\n }\n\n async cancelUncoveredPreview(): Promise<void> {\n await this.showThemePicker(true);\n const dialog = this.page.locator(THEME_PICKER);\n await dialog.getByRole('button', { name: 'Cancel', exact: true }).dispatchEvent('click');\n await dialog.waitFor({ state: 'detached' });\n await settle(this.page);\n }\n\n private async showThemePicker(shown: boolean): Promise<void> {\n await this.page.locator(THEME_PICKER).evaluate((dialog, visible) => {\n dialog.closest<HTMLElement>('.ui-dialog-backdrop')!.style.visibility = visible ? '' : 'hidden';\n }, shown);\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":["cases","settle","role","option"]}
|