@cssints/apg-specs 0.0.0-stage → 0.5.1
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/LICENSE +21 -0
- package/README.md +65 -2
- package/dist/apg/accordion.bridge.d.mts +35 -0
- package/dist/apg/accordion.bridge.mjs +326 -0
- package/dist/apg/accordion.model.json +8397 -0
- package/dist/apg/alert.bridge.d.mts +22 -0
- package/dist/apg/alert.bridge.mjs +86 -0
- package/dist/apg/alert.model.json +871 -0
- package/dist/apg/alertdialog.bridge.d.mts +21 -0
- package/dist/apg/alertdialog.bridge.mjs +221 -0
- package/dist/apg/alertdialog.model.json +5232 -0
- package/dist/apg/breadcrumb.bridge.d.mts +26 -0
- package/dist/apg/breadcrumb.bridge.mjs +120 -0
- package/dist/apg/breadcrumb.model.json +574 -0
- package/dist/apg/button.bridge.d.mts +35 -0
- package/dist/apg/button.bridge.mjs +208 -0
- package/dist/apg/button.model.json +5814 -0
- package/dist/apg/carousel.bridge.d.mts +44 -0
- package/dist/apg/carousel.bridge.mjs +262 -0
- package/dist/apg/carousel.model.json +8963 -0
- package/dist/apg/checkbox-group.bridge.d.mts +25 -0
- package/dist/apg/checkbox-group.bridge.mjs +276 -0
- package/dist/apg/checkbox-group.model.json +3863 -0
- package/dist/apg/checkbox.bridge.d.mts +34 -0
- package/dist/apg/checkbox.bridge.mjs +253 -0
- package/dist/apg/checkbox.model.json +3158 -0
- package/dist/apg/combobox-autocomplete.bridge.d.mts +14 -0
- package/dist/apg/combobox-autocomplete.bridge.mjs +326 -0
- package/dist/apg/combobox-autocomplete.model.json +11586 -0
- package/dist/apg/combobox-dialog.bridge.d.mts +17 -0
- package/dist/apg/combobox-dialog.bridge.mjs +250 -0
- package/dist/apg/combobox-dialog.model.json +8981 -0
- package/dist/apg/combobox-grid.bridge.d.mts +17 -0
- package/dist/apg/combobox-grid.bridge.mjs +227 -0
- package/dist/apg/combobox-grid.model.json +8554 -0
- package/dist/apg/combobox-select-only.bridge.d.mts +24 -0
- package/dist/apg/combobox-select-only.bridge.mjs +304 -0
- package/dist/apg/combobox-select-only.model.json +7846 -0
- package/dist/apg/combobox-tree.bridge.d.mts +17 -0
- package/dist/apg/combobox-tree.bridge.mjs +211 -0
- package/dist/apg/combobox-tree.model.json +9345 -0
- package/dist/apg/dialog-modal.bridge.d.mts +35 -0
- package/dist/apg/dialog-modal.bridge.mjs +186 -0
- package/dist/apg/dialog-modal.model.json +7580 -0
- package/dist/apg/disclosure.bridge.d.mts +25 -0
- package/dist/apg/disclosure.bridge.mjs +202 -0
- package/dist/apg/disclosure.model.json +4703 -0
- package/dist/apg/feed.bridge.d.mts +31 -0
- package/dist/apg/feed.bridge.mjs +246 -0
- package/dist/apg/feed.model.json +4523 -0
- package/dist/apg/grid-selection.bridge.d.mts +13 -0
- package/dist/apg/grid-selection.bridge.mjs +160 -0
- package/dist/apg/grid-selection.model.json +6974 -0
- package/dist/apg/grid-sort.bridge.d.mts +12 -0
- package/dist/apg/grid-sort.bridge.mjs +138 -0
- package/dist/apg/grid-sort.model.json +3799 -0
- package/dist/apg/grid.bridge.d.mts +54 -0
- package/dist/apg/grid.bridge.mjs +441 -0
- package/dist/apg/grid.model.json +3802 -0
- package/dist/apg/link.bridge.d.mts +24 -0
- package/dist/apg/link.bridge.mjs +126 -0
- package/dist/apg/link.model.json +694 -0
- package/dist/apg/listbox-multi.bridge.d.mts +10 -0
- package/dist/apg/listbox-multi.bridge.mjs +261 -0
- package/dist/apg/listbox-multi.model.json +10893 -0
- package/dist/apg/listbox-rearrangeable.bridge.d.mts +20 -0
- package/dist/apg/listbox-rearrangeable.bridge.mjs +237 -0
- package/dist/apg/listbox-rearrangeable.model.json +17592 -0
- package/dist/apg/listbox-shared.d.mts +58 -0
- package/dist/apg/listbox-shared.mjs +171 -0
- package/dist/apg/listbox-single.bridge.d.mts +10 -0
- package/dist/apg/listbox-single.bridge.mjs +196 -0
- package/dist/apg/listbox-single.model.json +8024 -0
- package/dist/apg/listbox-typeahead.bridge.d.mts +10 -0
- package/dist/apg/listbox-typeahead.bridge.mjs +153 -0
- package/dist/apg/listbox-typeahead.model.json +5615 -0
- package/dist/apg/menu-button.bridge.d.mts +29 -0
- package/dist/apg/menu-button.bridge.mjs +259 -0
- package/dist/apg/menu-button.model.json +5706 -0
- package/dist/apg/menu-checkable.bridge.d.mts +25 -0
- package/dist/apg/menu-checkable.bridge.mjs +226 -0
- package/dist/apg/menu-checkable.model.json +4277 -0
- package/dist/apg/menu-menubar.bridge.d.mts +27 -0
- package/dist/apg/menu-menubar.bridge.mjs +273 -0
- package/dist/apg/menu-menubar.model.json +9540 -0
- package/dist/apg/meter.bridge.d.mts +28 -0
- package/dist/apg/meter.bridge.mjs +159 -0
- package/dist/apg/meter.model.json +1185 -0
- package/dist/apg/player.bridge.d.mts +24 -0
- package/dist/apg/player.bridge.mjs +342 -0
- package/dist/apg/player.model.json +11013 -0
- package/dist/apg/radio.bridge.d.mts +35 -0
- package/dist/apg/radio.bridge.mjs +371 -0
- package/dist/apg/radio.model.json +5011 -0
- package/dist/apg/slider-multithumb.bridge.d.mts +34 -0
- package/dist/apg/slider-multithumb.bridge.mjs +365 -0
- package/dist/apg/slider-multithumb.model.json +5774 -0
- package/dist/apg/slider.bridge.d.mts +54 -0
- package/dist/apg/slider.bridge.mjs +359 -0
- package/dist/apg/slider.model.json +4881 -0
- package/dist/apg/spinbutton.bridge.d.mts +41 -0
- package/dist/apg/spinbutton.bridge.mjs +327 -0
- package/dist/apg/spinbutton.model.json +7571 -0
- package/dist/apg/switch.bridge.d.mts +30 -0
- package/dist/apg/switch.bridge.mjs +243 -0
- package/dist/apg/switch.model.json +3159 -0
- package/dist/apg/tabs.bridge.d.mts +41 -0
- package/dist/apg/tabs.bridge.mjs +294 -0
- package/dist/apg/tabs.model.json +7659 -0
- package/dist/apg/timeline.bridge.d.mts +36 -0
- package/dist/apg/timeline.bridge.mjs +265 -0
- package/dist/apg/timeline.model.json +6189 -0
- package/dist/apg/toolbar.bridge.d.mts +25 -0
- package/dist/apg/toolbar.bridge.mjs +307 -0
- package/dist/apg/toolbar.model.json +6616 -0
- package/dist/apg/tooltip.bridge.d.mts +36 -0
- package/dist/apg/tooltip.bridge.mjs +208 -0
- package/dist/apg/tooltip.model.json +8295 -0
- package/dist/apg/treegrid.bridge.d.mts +28 -0
- package/dist/apg/treegrid.bridge.mjs +311 -0
- package/dist/apg/treegrid.model.json +17358 -0
- package/dist/apg/treeview.bridge.d.mts +26 -0
- package/dist/apg/treeview.bridge.mjs +396 -0
- package/dist/apg/treeview.model.json +13745 -0
- package/dist/apg/windowsplitter.bridge.d.mts +36 -0
- package/dist/apg/windowsplitter.bridge.mjs +242 -0
- package/dist/apg/windowsplitter.model.json +6253 -0
- package/dist/canvas/camera.model.json +6568 -0
- package/dist/canvas/canvas.bridge.d.mts +190 -0
- package/dist/canvas/canvas.bridge.mjs +729 -0
- package/dist/canvas/pointer.model.json +17095 -0
- package/dist/scenario.d.mts +233 -0
- package/dist/scenario.mjs +313 -0
- package/package.json +57 -4
- package/scenarios/apg/README.md +221 -0
- package/scenarios/apg/accordion.base-ui.json +1005 -0
- package/scenarios/apg/accordion.react-aria.json +929 -0
- package/scenarios/apg/alert.base-ui.json +81 -0
- package/scenarios/apg/alert.react-aria.json +98 -0
- package/scenarios/apg/alertdialog.base-ui.json +331 -0
- package/scenarios/apg/alertdialog.react-aria.json +225 -0
- package/scenarios/apg/breadcrumb.react-aria.json +312 -0
- package/scenarios/apg/button.ariakit.json +136 -0
- package/scenarios/apg/button.base-ui.json +747 -0
- package/scenarios/apg/button.react-aria.json +443 -0
- package/scenarios/apg/carousel.apg.json +909 -0
- package/scenarios/apg/checkbox.ariakit.json +299 -0
- package/scenarios/apg/checkbox.base-ui.json +1126 -0
- package/scenarios/apg/checkbox.react-aria.json +518 -0
- package/scenarios/apg/combobox.ariakit.json +945 -0
- package/scenarios/apg/combobox.base-ui.json +2444 -0
- package/scenarios/apg/combobox.react-aria.json +845 -0
- package/scenarios/apg/dialog-modal.ariakit.json +1102 -0
- package/scenarios/apg/dialog-modal.base-ui.json +775 -0
- package/scenarios/apg/dialog-modal.react-aria.json +638 -0
- package/scenarios/apg/disclosure.apg.json +349 -0
- package/scenarios/apg/disclosure.ariakit.json +163 -0
- package/scenarios/apg/disclosure.base-ui.json +451 -0
- package/scenarios/apg/disclosure.react-aria.json +643 -0
- package/scenarios/apg/feed.apg.json +442 -0
- package/scenarios/apg/grid.ariakit.json +197 -0
- package/scenarios/apg/grid.base-ui.json +720 -0
- package/scenarios/apg/grid.react-aria.json +969 -0
- package/scenarios/apg/landmarks.ariakit.json +93 -0
- package/scenarios/apg/landmarks.react-aria.json +330 -0
- package/scenarios/apg/link.ariakit.json +83 -0
- package/scenarios/apg/link.base-ui.json +88 -0
- package/scenarios/apg/link.react-aria.json +186 -0
- package/scenarios/apg/listbox.ariakit.json +78 -0
- package/scenarios/apg/listbox.base-ui.json +163 -0
- package/scenarios/apg/listbox.react-aria.json +1118 -0
- package/scenarios/apg/menu-button.ariakit.json +924 -0
- package/scenarios/apg/menu-button.base-ui.json +1155 -0
- package/scenarios/apg/menu-button.react-aria.json +1080 -0
- package/scenarios/apg/menubar.ariakit.json +758 -0
- package/scenarios/apg/menubar.base-ui.json +673 -0
- package/scenarios/apg/meter.base-ui.json +243 -0
- package/scenarios/apg/meter.react-aria.json +201 -0
- package/scenarios/apg/radio.ariakit.json +459 -0
- package/scenarios/apg/radio.base-ui.json +581 -0
- package/scenarios/apg/radio.react-aria.json +576 -0
- package/scenarios/apg/slider-multithumb.base-ui.json +316 -0
- package/scenarios/apg/slider-multithumb.react-aria.json +363 -0
- package/scenarios/apg/slider.base-ui.json +544 -0
- package/scenarios/apg/slider.react-aria.json +456 -0
- package/scenarios/apg/spinbutton.base-ui.json +1688 -0
- package/scenarios/apg/spinbutton.react-aria.json +426 -0
- package/scenarios/apg/switch.base-ui.json +456 -0
- package/scenarios/apg/switch.react-aria.json +303 -0
- package/scenarios/apg/table.ariakit.json +65 -0
- package/scenarios/apg/table.react-aria.json +221 -0
- package/scenarios/apg/tabs.ariakit.json +329 -0
- package/scenarios/apg/tabs.base-ui.json +875 -0
- package/scenarios/apg/tabs.react-aria.json +644 -0
- package/scenarios/apg/toolbar.ariakit.json +595 -0
- package/scenarios/apg/toolbar.base-ui.json +1189 -0
- package/scenarios/apg/toolbar.react-aria.json +383 -0
- package/scenarios/apg/tooltip.ariakit.json +441 -0
- package/scenarios/apg/tooltip.base-ui.json +411 -0
- package/scenarios/apg/tooltip.react-aria.json +454 -0
- package/scenarios/apg/treegrid.apg.json +2558 -0
- package/scenarios/apg/treegrid.react-aria.json +5094 -0
- package/scenarios/apg/treeview.apg.json +928 -0
- package/scenarios/apg/windowsplitter.apg.json +557 -0
- package/scenarios/canvas/README.md +69 -0
- package/scenarios/canvas/camera.contract.json +237 -0
- package/scenarios/canvas/camera.excalidraw.json +57 -0
- package/scenarios/canvas/marquee.excalidraw.json +122 -0
- package/scenarios/canvas/pan.excalidraw.json +46 -0
- package/scenarios/canvas/pointer.contract.json +528 -0
- package/scenarios/parts.json +291 -0
- package/shared/aria.qnt +186 -0
- package/shared/details-group.qnt +50 -0
- package/shared/focusgroup.qnt +152 -0
- package/shared/invokers.qnt +81 -0
- package/shared/popover.qnt +71 -0
- package/specs/apg/STATIC.md +103 -0
- package/specs/apg/accordion.qnt +578 -0
- package/specs/apg/alert.qnt +131 -0
- package/specs/apg/alertdialog.qnt +455 -0
- package/specs/apg/breadcrumb.qnt +88 -0
- package/specs/apg/button.qnt +445 -0
- package/specs/apg/carousel.qnt +732 -0
- package/specs/apg/checkbox-group.qnt +388 -0
- package/specs/apg/checkbox.qnt +394 -0
- package/specs/apg/combobox-autocomplete.qnt +764 -0
- package/specs/apg/combobox-dialog.qnt +627 -0
- package/specs/apg/combobox-grid.qnt +632 -0
- package/specs/apg/combobox-select-only.qnt +626 -0
- package/specs/apg/combobox-tree.qnt +633 -0
- package/specs/apg/dialog-modal.qnt +499 -0
- package/specs/apg/disclosure.qnt +309 -0
- package/specs/apg/feed.qnt +485 -0
- package/specs/apg/grid-selection.qnt +512 -0
- package/specs/apg/grid-sort.qnt +330 -0
- package/specs/apg/grid.qnt +360 -0
- package/specs/apg/link.qnt +119 -0
- package/specs/apg/listbox-multi.qnt +799 -0
- package/specs/apg/listbox-rearrangeable.qnt +801 -0
- package/specs/apg/listbox-single.qnt +511 -0
- package/specs/apg/listbox-typeahead.qnt +396 -0
- package/specs/apg/menu-button.qnt +363 -0
- package/specs/apg/menu-checkable.qnt +304 -0
- package/specs/apg/menu-menubar.qnt +531 -0
- package/specs/apg/meter.qnt +129 -0
- package/specs/apg/player.qnt +1081 -0
- package/specs/apg/radio.qnt +394 -0
- package/specs/apg/slider-multithumb.qnt +441 -0
- package/specs/apg/slider.qnt +396 -0
- package/specs/apg/spinbutton.qnt +494 -0
- package/specs/apg/switch.qnt +389 -0
- package/specs/apg/tabs.qnt +412 -0
- package/specs/apg/timeline.qnt +612 -0
- package/specs/apg/toolbar.qnt +364 -0
- package/specs/apg/tooltip.qnt +553 -0
- package/specs/apg/treegrid.qnt +983 -0
- package/specs/apg/treeview.qnt +1004 -0
- package/specs/apg/windowsplitter.qnt +487 -0
- package/specs/canvas/camera.qnt +407 -0
- package/specs/canvas/pointer.qnt +841 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# APG scenarios — upstream tests ported as library-neutral data
|
|
2
|
+
|
|
3
|
+
One file per pattern and source: `<pattern>.<source>.json`, where `<source>` is
|
|
4
|
+
`ariakit`, `base-ui`, `react-aria` or `apg` (scenarios written by us from the APG
|
|
5
|
+
page). Each scenario is a port of one upstream test (no code copied; behaviour
|
|
6
|
+
restated) and is replayed against the Quint spec (`specs/apg/<pattern>*.qnt`) and
|
|
7
|
+
the Solid implementation by `src/scenario.ts`.
|
|
8
|
+
|
|
9
|
+
**This file is the one format spec (format v2).** The canvas scenarios
|
|
10
|
+
(`../canvas/README.md`) share the envelope and the `skipped` shape below but have
|
|
11
|
+
their own step/expectation vocabulary (pointer geometry, camera) and are not
|
|
12
|
+
decoded by `src/scenario.ts`; that README says so. `src/scenario.ts` is the
|
|
13
|
+
executable version of this document: every field named here is decoded and typed
|
|
14
|
+
there, and `test/apg/scenario-format.test.ts` checks every file in this
|
|
15
|
+
directory against it.
|
|
16
|
+
|
|
17
|
+
Pinned upstreams (shallow clones in the session temp dir `upstream/`):
|
|
18
|
+
|
|
19
|
+
| source | repo | commit | licence |
|
|
20
|
+
| ---------- | -------------------- | ------------------------------------------ | ---------- |
|
|
21
|
+
| ariakit | ariakit/ariakit | `404c72257b879569feb08465da4ff9915fd873da` | MIT |
|
|
22
|
+
| base-ui | mui/base-ui | `19511bb171f3b360b006c94cf6d07e53cb446505` | MIT |
|
|
23
|
+
| react-aria | adobe/react-spectrum | `99e610236887da619ad9d54a1cd87983166c043d` | Apache-2.0 |
|
|
24
|
+
|
|
25
|
+
## Envelope
|
|
26
|
+
|
|
27
|
+
```jsonc
|
|
28
|
+
{
|
|
29
|
+
"pattern": "tabs", // APG pattern slug (w3.org/WAI/ARIA/apg/patterns/<slug>/)
|
|
30
|
+
"source": "react-aria",
|
|
31
|
+
"commit": "99e6102…", // null for source "apg"
|
|
32
|
+
"license": "Apache-2.0",
|
|
33
|
+
"upstream": "https://…", // source "apg" only: the APG page
|
|
34
|
+
"retrieved": "2026-10-03", // source "apg" only
|
|
35
|
+
"fixture": {}, // optional, informational (shared fixture description); never passed to a driver
|
|
36
|
+
"notes": "optional, file level",
|
|
37
|
+
"skipped": [{ "upstream": "…", "upstreamTest": "…", "reason": "…" }],
|
|
38
|
+
"scenarios": [
|
|
39
|
+
{
|
|
40
|
+
"id": "tabs.react-aria.arrow-right-moves-focus", // unique, kebab-case, `<pattern>.<source>.<slug>`
|
|
41
|
+
"upstream": "https://github.com/adobe/react-spectrum/blob/<commit>/<path>#L<line>",
|
|
42
|
+
"upstreamTest": "Tabs > should focus the next tab on ArrowRight",
|
|
43
|
+
"apg": "keyboard", // APG section the behaviour comes from, or "extension" if not in APG
|
|
44
|
+
"config": {
|
|
45
|
+
"orientation": "horizontal",
|
|
46
|
+
"activation": "automatic",
|
|
47
|
+
"items": 3,
|
|
48
|
+
},
|
|
49
|
+
"steps": [
|
|
50
|
+
{ "event": "focus", "target": "tab:0" },
|
|
51
|
+
{ "event": "key", "key": "ArrowRight", "target": "tab:0" },
|
|
52
|
+
{
|
|
53
|
+
"expect": {
|
|
54
|
+
"focus": "tab:1",
|
|
55
|
+
"attrs": { "tab:1": { "aria-selected": "true" } },
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
"notes": "optional: divergence from APG, platform-specific behaviour",
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`skipped` is always present (use `[]`) and always the **object form**
|
|
66
|
+
`{ upstream?, upstreamTest?, reason, id? }`: `reason` is required; `upstream` /
|
|
67
|
+
`upstreamTest` say which upstream test was not ported when there is one; `id` names
|
|
68
|
+
the would-be scenario for `apg`-source files. Bare strings are not allowed.
|
|
69
|
+
|
|
70
|
+
## Steps
|
|
71
|
+
|
|
72
|
+
A step is **either** an action (has `event`) **or** an expectation (has only
|
|
73
|
+
`expect`). Never both: a step carrying `event` and `expect` is read as an action
|
|
74
|
+
with an unknown field and the scenario becomes unsupported, so write the check as
|
|
75
|
+
the following step.
|
|
76
|
+
|
|
77
|
+
Action fields (all decoded and typed in `ActionStep`):
|
|
78
|
+
|
|
79
|
+
| field | type | meaning |
|
|
80
|
+
| ------------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
81
|
+
| `event` | string | `focus` `blur` `click` `pointerdown` `pointermove` `pointerup` `hover` `unhover` `key` `type` `prop` `wait` … |
|
|
82
|
+
| `target` | target (grammar below) | the part the event is delivered to; `key`/`type` first focuses it, as a user would (a `phase: "up"` key does not) |
|
|
83
|
+
| `key` | string | `KeyboardEvent.key` (`Enter`, `ArrowDown`, `Tab`, `" "`; `Space` is accepted for `" "`) |
|
|
84
|
+
| `text` | string | text typed by a `type` event |
|
|
85
|
+
| `prop` | string | prop name for a `prop` event; with no `value` it is a trigger (`beforematch` fires the `beforematch` event on the target) |
|
|
86
|
+
| `value` | JSON | the new value for `prop`, or the value an event carries |
|
|
87
|
+
| `set` | object | `prop` event changing several props at once: `{ "event": "prop", "set": { "open": true } }` |
|
|
88
|
+
| `repeat` | `true` \| integer | `true`: this keydown is an auto-repeat (`KeyboardEvent.repeat`); `N`: the key is held for `N` repeat keydowns |
|
|
89
|
+
| `ms` | number | duration of a `wait` event (fake-timer milliseconds) |
|
|
90
|
+
| `position` | number 0..1 | where on the target track a pointer event lands, as a fraction of its length |
|
|
91
|
+
| `modifiers` | `Alt`\|`Control`\|`Meta`\|`Shift` array | held modifiers (a set; write them sorted). Never `shiftKey`, `ctrl`, `altKey`, … |
|
|
92
|
+
| `phase` | `down` \| `up` | which half of a `key` press (default: the full press); `down` holds the key for a later `up` step, so a blur can land between |
|
|
93
|
+
| `button` | number | `MouseEvent.button` (0 primary, 1 auxiliary, 2 secondary) |
|
|
94
|
+
| `buttons` | number | `MouseEvent.buttons` bitmask |
|
|
95
|
+
| `pointerType` | `mouse` \| `pen` \| `touch` | `PointerEvent.pointerType` (default `mouse`) |
|
|
96
|
+
| `pointerId` | number | `PointerEvent.pointerId` |
|
|
97
|
+
| `detail` | number | `UIEvent.detail` of a click |
|
|
98
|
+
| `count` | number | click count (`2` = double click) |
|
|
99
|
+
| `canceled` | boolean | the event is canceled (`preventDefault`) before the widget sees it |
|
|
100
|
+
| `defaultPrevented` | boolean | the event is expected to end with its default prevented (`true`) or not (`false`) |
|
|
101
|
+
| `isComposing` | boolean | `KeyboardEvent.isComposing` |
|
|
102
|
+
| `inputEvent` | string | origin of a `type` event (`paste`, `programmatic`) |
|
|
103
|
+
|
|
104
|
+
Any other field is **unknown**: it is preserved on decode and makes the scenario
|
|
105
|
+
`unsupported` (skipped, never silently replayed as a different step).
|
|
106
|
+
|
|
107
|
+
Typed is not the same as supported. The core fields (`event` `target` `key`
|
|
108
|
+
`text` `prop` `value` `repeat` `ms`) are understood by every bridge. The rest
|
|
109
|
+
(`EXTENDED_STEP_FIELDS` in `src/scenario.ts`) are decoded for everyone, but a
|
|
110
|
+
scenario using one is `unsupported` until the bridge lists it in
|
|
111
|
+
`SpecBridge.stepFields`, because a bridge that ignored `modifiers` would replay a
|
|
112
|
+
different step. A bridge that honours a field declares it; nothing else changes.
|
|
113
|
+
|
|
114
|
+
## Expectations
|
|
115
|
+
|
|
116
|
+
`{ "expect": { … } }` checks only what the upstream test checks:
|
|
117
|
+
|
|
118
|
+
| key | type | meaning |
|
|
119
|
+
| --------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
120
|
+
| `focus` | target \| `null` | the part holding focus (`null` = nothing in the widget) |
|
|
121
|
+
| `attrs` | `{ target: { name: string \| null } }` | attribute (or reflected property) values as strings; `null` = absent; booleans are `"true"`/`"false"` |
|
|
122
|
+
| `visible` | target[] | exactly these parts are visible |
|
|
123
|
+
| `hidden` | target[] | these parts are not visible (the others are unconstrained) |
|
|
124
|
+
| `value` | JSON | the pattern's observable value |
|
|
125
|
+
| `events` | `{ callback: payload[] }` | callbacks fired since mount, in order, one payload per call: `{ "onSelectionChange": ["tab:1"] }`; a sentinel is still a one-element list (`["all"]`) |
|
|
126
|
+
| `checked` | target \| `null` | the checked item of a single-selection group (radio) |
|
|
127
|
+
|
|
128
|
+
The engine currently **checks** `focus`, `attrs`, `visible`, `value`, `events`.
|
|
129
|
+
`hidden` and `checked` are decoded and typed but reported as skipped
|
|
130
|
+
(`expectation not supported by the replay engine`) until the engine implements
|
|
131
|
+
them. Unknown expectation keys are preserved and reported the same way.
|
|
132
|
+
|
|
133
|
+
**Symbolic relationship refs.** For the IDREF attributes (`aria-controls`,
|
|
134
|
+
`aria-labelledby`, `aria-describedby`, `aria-activedescendant`, `aria-owns`,
|
|
135
|
+
`aria-details`, `aria-errormessage`, `aria-flowto`) an `attrs` value of the form
|
|
136
|
+
`<part>:<index>` (a whitespace-separated list is allowed) is a reference to that
|
|
137
|
+
part, not a literal id: `"aria-controls": "tabpanel:1"`,
|
|
138
|
+
`"aria-activedescendant": "option:0"`, `"aria-describedby": "description:0 error:0"`.
|
|
139
|
+
The driver resolves it to the part's real id. Anything that is not a target is a
|
|
140
|
+
literal id (`"aria-labelledby": "custom-trigger-id"`).
|
|
141
|
+
|
|
142
|
+
## Target grammar
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
target = part [ ":" locator ] { "/" child }
|
|
146
|
+
part = name tab tabpanel popup nested-dialog
|
|
147
|
+
locator = index tab:1 option:0
|
|
148
|
+
| path row:0/1/2 treeitem:0/1 menuitem:1/0 (indices joined by "/")
|
|
149
|
+
| path "," index cell:<row>,<col> cell:0/3,2 (row may be a path)
|
|
150
|
+
| name checkbox:parent button:disabled input:hidden (non-indexed variant)
|
|
151
|
+
child = name [ ":" index ] /checkbox /chevron /link /child:0 (n-th child element of the part)
|
|
152
|
+
name = [A-Za-z][A-Za-z0-9-]*
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
A segment after `/` that starts with a digit continues the path; one that starts
|
|
156
|
+
with a letter is a child. `tab` and `tab:0` name the same single part. Paths are
|
|
157
|
+
always written with their part prefix (`row:0/1`, never a bare `0/1`).
|
|
158
|
+
|
|
159
|
+
## Part names
|
|
160
|
+
|
|
161
|
+
`target` uses **scenario names**; the specs use their own. The table maps them
|
|
162
|
+
(the machine-readable source is [`../parts.json`](../parts.json), which the bridges
|
|
163
|
+
should read instead of hard-coding aliases; the `.qnt` files are not renamed).
|
|
164
|
+
`← spec x` means the spec calls the part `x`. Names in the last column are
|
|
165
|
+
page/fixture parts of the scenarios (the page around the widget, helper controls);
|
|
166
|
+
they may appear in targets but carry no spec meaning. `test/apg/scenario-format.test.ts`
|
|
167
|
+
fails when a scenario uses a name that is in neither column.
|
|
168
|
+
|
|
169
|
+
| pattern | spec | parts (scenario name ← spec name) | fixture parts |
|
|
170
|
+
| ------------------- | ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------- |
|
|
171
|
+
| `accordion` | `accordion.qnt` | `trigger` ← spec `header`, `panel` ← spec `content`, `heading` | `menu`, `menuTrigger` |
|
|
172
|
+
| `alert` | `alert.qnt` | `alert`, `close` ← spec `dismiss` | `add`, `add-high`, `content`, `region`, `root`, `toast` |
|
|
173
|
+
| `alertdialog` | `alertdialog.qnt` | `trigger` ← spec `discard`, `dialog` ← spec `alertdialog`, `cancel` ← spec `no`, `confirm` ← spec `yes` | `backdrop`, `dismiss`, `secondary` |
|
|
174
|
+
| `breadcrumb` | `breadcrumb.qnt` | `item`, `link`, `nav` (no spec name), `breadcrumb` (no spec name) | — |
|
|
175
|
+
| `button` | `button.qnt` | `button`, `group` (no spec name), `text` (no spec name) | — |
|
|
176
|
+
| `carousel` | `carousel.qnt` | `carousel` (no spec name), `rotation`, `prev`, `next`, `tab`, `slide` | — |
|
|
177
|
+
| `checkbox` | `checkbox.qnt`, `checkbox-group.qnt` | `checkbox`, `group` (no spec name) | `button`, `input`, `label` |
|
|
178
|
+
| `combobox` | `combobox-autocomplete.qnt`, `combobox-dialog.qnt`, `combobox-grid.qnt`, `combobox-select-only.qnt`, `combobox-tree.qnt` | `input`, `trigger` ← spec `button`, `popup`, `option`, `gridcell` ← spec `cell`, `treeitem` ← spec `node` | `body`, `final-focus-button`, `label`, `next-button` |
|
|
179
|
+
| `dialog-modal` | `dialog-modal.qnt` | `trigger` ← spec `invoker`, `dialog`, `backdrop` (no spec name) | any kebab-case name |
|
|
180
|
+
| `disclosure` | `disclosure.qnt` | `trigger`, `panel`, `heading` (no spec name) | `disclosure` |
|
|
181
|
+
| `feed` | `feed.qnt` | `feed`, `article`, `before-feed` ← spec `before`, `after-feed` ← spec `after` | — |
|
|
182
|
+
| `grid` | `grid.qnt`, `grid-selection.qnt`, `grid-sort.qnt` | `cell`, `row`, `rowgroup` (no spec name), `columnheader` ← spec `header` | `after`, `body`, `checkbox`, `combobox`, `dialog`, `rowheader` |
|
|
183
|
+
| `landmarks` | — | `main` (no spec name), `navigation` (no spec name), `region` (no spec name), `button` (no spec name), `link` (no spec name), `listitem` (no spec name) | — |
|
|
184
|
+
| `link` | `link.qnt` | `link`, `button` (no spec name) | — |
|
|
185
|
+
| `listbox` | `listbox-single.qnt`, `listbox-multi.qnt`, `listbox-typeahead.qnt`, `listbox-rearrangeable.qnt` | `listbox`, `option` | `trigger` |
|
|
186
|
+
| `menu-button` | `menu-button.qnt`, `menu-checkable.qnt` | `trigger` ← spec `button`, `menu`, `menuitem` ← spec `item`, `submenu` (no spec name) | `after`, `body`, `dialog`, `dismiss`, `group`, `outside` |
|
|
187
|
+
| `menubar` | `menu-menubar.qnt` | `menubar`, `menu`, `menuitem` ← spec `item`, `submenu` | `body`, `outside` |
|
|
188
|
+
| `meter` | `meter.qnt` | `meter` | — |
|
|
189
|
+
| `radio` | `radio.qnt` | `radiogroup`, `radio` | — |
|
|
190
|
+
| `slider` | `slider.qnt` | `thumb`, `track` ← spec `rail` | `body` |
|
|
191
|
+
| `slider-multithumb` | `slider-multithumb.qnt` | `thumb`, `track` ← spec `rail` | `body` |
|
|
192
|
+
| `spinbutton` | `spinbutton.qnt` | `input`, `increment`, `decrement` | `description`, `error`, `group`, `label` |
|
|
193
|
+
| `switch` | `switch.qnt` | `switch` | `button`, `input`, `label` |
|
|
194
|
+
| `table` | — | `table` (no spec name), `rowgroup` (no spec name), `row` (no spec name), `columnheader` (no spec name), `rowheader` (no spec name), `gridcell` (no spec name), `caption` (no spec name), `colindex-cell` (no spec name), `colspan-cell` (no spec name) | — |
|
|
195
|
+
| `tabs` | `tabs.qnt` | `tablist`, `tab`, `tabpanel` | `link` |
|
|
196
|
+
| `toolbar` | `toolbar.qnt` | `toolbar`, `item` | `dialog`, `menuitem`, `option`, `popup` |
|
|
197
|
+
| `tooltip` | `tooltip.qnt` | `trigger`, `tooltip` | — |
|
|
198
|
+
| `treegrid` | `treegrid.qnt` | `treegrid` ← spec `grid`, `row`, `cell`, `chevron` ← spec `expander` | `checkbox`, `document`, `info`, `link`, `menu` |
|
|
199
|
+
| `treeview` | `treeview.qnt` | `tree`, `treeitem` ← spec `node` | — |
|
|
200
|
+
| `windowsplitter` | `windowsplitter.qnt` | `separator` ← spec `splitter`, `primary`, `secondary` | — |
|
|
201
|
+
|
|
202
|
+
Spec names are the names the `.qnt` header comments and action names use
|
|
203
|
+
(`click_header`, `click_button`, `focusSplitter`, …); where a spec encodes parts
|
|
204
|
+
as numbers (alertdialog/dialog-modal focus slots) the name is the role the
|
|
205
|
+
comment gives. `gridcell` and `treeitem` under `combobox` are reserved for the
|
|
206
|
+
grid/tree popups (no scenario uses them yet; the bridges already accept them).
|
|
207
|
+
`treegrid`'s `chevron` is a child part (`row:0/chevron`) that the spec calls
|
|
208
|
+
`expander`.
|
|
209
|
+
|
|
210
|
+
## Rules
|
|
211
|
+
|
|
212
|
+
- `target` uses APG part names (see the table). Rendering details, styling and
|
|
213
|
+
React-only APIs are out of scope; list them under `skipped`.
|
|
214
|
+
- Do not invent a field: if a step needs something not listed here, add it to
|
|
215
|
+
this file and to `ActionStep` in the same change.
|
|
216
|
+
- Units for `position` (fraction of the track) and `ms` (fake-timer time) are
|
|
217
|
+
fixed; `button`/`buttons`/`pointerId`/`detail` are the DOM values.
|
|
218
|
+
- When a scenario's expectation and a primitive disagree, the
|
|
219
|
+
[divergence policy](../../headless/README.md#divergence-policy) decides which
|
|
220
|
+
wins; a deliberate miss stays a negative test in the primitive's `DIVERGENCES`
|
|
221
|
+
map, and `notes` records why.
|