@orkestrel/scaffold 0.0.103 → 0.0.104
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/dist/agents/skills/orkestrel-dispatch/scripts/helpers.js +84 -1
- package/dist/agents/skills/orkestrel-dispatch/scripts/launch.js +21 -6
- package/dist/agents/skills/orkestrel-harden/scripts/titles.js +338 -0
- package/dist/agents/skills/orkestrel-publish/scripts/swap.js +3 -39
- package/dist/agents/skills/orkestrel-publish/scripts/wave.js +433 -47
- package/dist/agents/skills/orkestrel-publish/scripts/window.js +2 -1
- package/dist/bin/main.js +16 -9
- package/dist/bin/main.js.map +1 -1
- package/dist/host/agents/orchestration.md +3 -3
- package/dist/host/agents/skills/enterprise-bootstrap/references/components.md +2 -2
- package/dist/host/agents/skills/enterprise-bootstrap/references/inspection.md +1 -1
- package/dist/host/agents/skills/orkestrel-build/SKILL.md +2 -2
- package/dist/host/agents/skills/orkestrel-debrief/SKILL.md +2 -2
- package/dist/host/agents/skills/orkestrel-debrief/references/field-testing.md +1 -1
- package/dist/host/agents/skills/orkestrel-debrief/references/instruction-audit.md +3 -3
- package/dist/host/agents/skills/orkestrel-dispatch/SKILL.md +10 -10
- package/dist/host/agents/skills/orkestrel-dispatch/references/launch.md +1 -0
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/helpers.ts +100 -1
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/launch.ts +27 -6
- package/dist/host/agents/skills/orkestrel-falsify/SKILL.md +4 -4
- package/dist/host/agents/skills/orkestrel-falsify/agents/openai.yaml +1 -1
- package/dist/host/agents/skills/orkestrel-falsify/references/brief.md +8 -7
- package/dist/host/agents/skills/orkestrel-falsify/references/reconcile.md +6 -6
- package/dist/host/agents/skills/orkestrel-harden/SKILL.md +6 -1
- package/dist/host/agents/skills/orkestrel-harden/references/bindings.md +1700 -0
- package/dist/host/agents/skills/orkestrel-harden/references/contract.md +2 -2
- package/dist/host/agents/skills/orkestrel-harden/references/equivalence.md +48 -0
- package/dist/host/agents/skills/orkestrel-harden/references/hardening.md +4 -2
- package/dist/host/agents/skills/orkestrel-harden/scripts/titles.ts +425 -0
- package/dist/host/agents/skills/orkestrel-journey/SKILL.md +2 -2
- package/dist/host/agents/skills/orkestrel-journey/references/captures.md +9 -8
- package/dist/host/agents/skills/orkestrel-polish/SKILL.md +3 -3
- package/dist/host/agents/skills/orkestrel-publish/SKILL.md +2 -2
- package/dist/host/agents/skills/orkestrel-publish/references/release.md +1 -0
- package/dist/host/agents/skills/orkestrel-publish/references/wave.md +56 -13
- package/dist/host/agents/skills/orkestrel-publish/references/window.md +6 -6
- package/dist/host/agents/skills/orkestrel-publish/scripts/swap.ts +5 -49
- package/dist/host/agents/skills/orkestrel-publish/scripts/wave.ts +646 -49
- package/dist/host/agents/skills/orkestrel-publish/scripts/window.ts +2 -1
- package/dist/host/agents/transports/codex.md +1 -1
- package/dist/host/claude/agents/orkestrel.md +54 -53
- package/dist/host/claude/agents/reviewer.md +4 -4
- package/dist/host/claude/rules/documentation.md +2 -1
- package/dist/host/claude/rules/patterns.md +1 -1
- package/dist/host/claude/rules/quality.md +2 -2
- package/dist/host/claude/rules/styles.md +1 -1
- package/dist/host/claude/rules/tests.md +34 -8
- package/dist/host/claude/rules/typescript.md +29 -0
- package/dist/host/claude/rules/workspace.md +32 -22
- package/dist/host/claude/rules/writing.md +34 -26
- package/dist/host/claude/settings.json +2 -0
- package/dist/host/claude/skills/orkestrel-debrief/SKILL.md +1 -1
- package/dist/host/claude/skills/orkestrel-falsify/SKILL.md +1 -1
- package/dist/host/codex/agents/analyst.toml +3 -3
- package/dist/host/codex/agents/reviewer.toml +4 -4
- package/dist/host/configs/policy.ts +13 -2
- package/dist/host/dotfiles/editorconfig +0 -1
- package/dist/host/dotfiles/gitattributes +0 -1
- package/dist/host/dotfiles/gitignore +0 -1
- package/dist/host/dotfiles/oxlintrc.json +24 -0
- package/dist/host/guides/agent.md +1638 -598
- package/dist/host/guides/budget.md +89 -29
- package/dist/host/guides/form.md +477 -91
- package/dist/host/guides/mcp.md +14 -2
- package/dist/host/guides/ollama.md +97 -73
- package/dist/host/guides/probe.md +1 -1
- package/dist/host/guides/scaffold.md +158 -101
- package/dist/host/guides/study.md +2635 -0
- package/dist/host/guides/table.md +225 -15
- package/dist/host/guides/terminal.md +22 -20
- package/dist/host/guides/test.md +689 -255
- package/dist/host/manifest.json +87 -63
- package/dist/host/tests/config.test.ts +136 -82
- package/dist/host/tests/policy.test.ts +39 -1
- package/dist/host/tests/setupPolicy.ts +86 -28
- package/dist/src/core/index.cjs +1387 -611
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +35 -20
- package/dist/src/core/index.d.ts +35 -20
- package/dist/src/core/index.js +1385 -612
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +12 -12
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +12 -12
- package/dist/src/server/index.d.ts +12 -12
- package/dist/src/server/index.js +12 -12
- package/dist/src/server/index.js.map +1 -1
- package/package.json +4 -4
package/dist/host/guides/test.md
CHANGED
|
@@ -137,6 +137,14 @@ Each interface's call-signature members are listed under [Methods](#methods). `R
|
|
|
137
137
|
and `Failure` come from `@orkestrel/contract` (mirrored at [`contract.md`](contract.md)) and are not
|
|
138
138
|
re-exported; `retryUntil` reads `Result` internally.
|
|
139
139
|
|
|
140
|
+
The chooser wire contract is shared by the browser journey and its server command.
|
|
141
|
+
|
|
142
|
+
| Type | Kind | Shape | Summary |
|
|
143
|
+
| ---------------- | --------- | ------------------------------------------ | ------------------------------------------------------------------------------------- |
|
|
144
|
+
| `FixtureFile` | interface | `{ name, mime, bytes }` | Represents one fixture file as a name, media type, and immutable bytes. |
|
|
145
|
+
| `ChoiceOptions` | interface | `{ keyboard?, budget? }` | Configures native file-picker activation and its bounded provider wait. |
|
|
146
|
+
| `ChooserRequest` | interface | `ChoiceOptions` plus `{ selector, files }` | Carries a resolved file-input selector and fixture selection to the browser provider. |
|
|
147
|
+
|
|
140
148
|
#### Constants
|
|
141
149
|
|
|
142
150
|
A `Shape` cell holds the constant's declared type.
|
|
@@ -177,36 +185,47 @@ instead of propagating.
|
|
|
177
185
|
|
|
178
186
|
#### Helpers
|
|
179
187
|
|
|
180
|
-
| API
|
|
181
|
-
|
|
|
182
|
-
| `waitForCondition`
|
|
183
|
-
| `retryUntil`
|
|
184
|
-
| `waitForEvent`
|
|
185
|
-
| `waitForText`
|
|
186
|
-
| `checkBounds`
|
|
187
|
-
| `buildRetryExhausted`
|
|
188
|
-
| `buildRefusal`
|
|
189
|
-
| `dropRegistration`
|
|
190
|
-
| `decodeJSONLines`
|
|
191
|
-
| `
|
|
192
|
-
| `
|
|
193
|
-
| `
|
|
194
|
-
| `
|
|
195
|
-
| `
|
|
196
|
-
| `
|
|
197
|
-
| `
|
|
198
|
-
| `
|
|
199
|
-
| `
|
|
200
|
-
| `
|
|
201
|
-
| `
|
|
202
|
-
| `
|
|
203
|
-
| `
|
|
188
|
+
| API | Kind | Signature | Summary |
|
|
189
|
+
| ------------------------ | -------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
190
|
+
| `waitForCondition` | function | `(description, condition, options?) => Promise<void>` | Waits until a condition holds within an elapsed-time budget. |
|
|
191
|
+
| `retryUntil` | function | `(description, produce, satisfied, options?) => Promise<T>` | Repeats a producer until one produced value satisfies a predicate. |
|
|
192
|
+
| `waitForEvent` | function | `(subscribe, description, options?) => Promise<TArgs>` | Waits for the first delivery from an event subscription. |
|
|
193
|
+
| `waitForText` | function | `(description, read, text, options?) => Promise<string>` | Waits until a reading of text carries an expected sentence. |
|
|
194
|
+
| `checkBounds` | function | `(subject: string, budget: number, interval: number) => void` | Checks the resolved bounds one bounded wait runs under. |
|
|
195
|
+
| `buildRetryExhausted` | function | `(description, budget, elapsed, last, cause) => Error` | Builds the error `retryUntil` raises when its elapsed-time budget runs out. |
|
|
196
|
+
| `buildRefusal` | function | `(name: string, cause: unknown) => Error` | Builds the error a refused fixture build raises, named for the row it was building for. |
|
|
197
|
+
| `dropRegistration` | function | `(registrations: SignalRegistration[], installed) => SignalRegistration \| undefined` | Drops the registration an instrumented signal installed for one listener. |
|
|
198
|
+
| `decodeJSONLines` | function | `(text: string) => readonly unknown[]` | Decodes newline-delimited JSON values. |
|
|
199
|
+
| `collectSelectorClasses` | function | `(selector: string) => readonly string[]` | Collects the class names one selector text names, decoded and without repeats. |
|
|
200
|
+
| `waitForDelay` | function | `(ms?: number) => Promise<void>` | Waits for a host timer to elapse. |
|
|
201
|
+
| `waitForAbort` | function | `(signal: AbortSignal) => Promise<void>` | Waits until an abort signal is aborted. |
|
|
202
|
+
| `captureError` | function | `(thunk: () => unknown) => unknown` | Captures the value thrown by a thunk. |
|
|
203
|
+
| `requireValue` | function | `<T>(value: T \| null \| undefined, message?: string) => T` | Narrows a value away from `null` and `undefined`, throwing when it is absent. |
|
|
204
|
+
| `collect` | function | `<T>(source: AsyncIterable<T>) => Promise<readonly T[]>` | Collects every value from an async iterable. |
|
|
205
|
+
| `collectStream` | function | `<T>(stream: ReadableStream<T>) => Promise<readonly T[]>` | Collects every value from a readable stream. |
|
|
206
|
+
| `roundTripJSON` | function | `<T>(value: T & JSONSafe<T>) => T` | Copies a JSON value through serialization and parsing. |
|
|
207
|
+
| `invokeUnchecked` | function | `<T>(target: unknown, method: unknown, args: readonly unknown[]) => T` | Invokes an unknown method through an explicit unchecked result contract. |
|
|
208
|
+
| `readProperty` | function | `<T>(target: unknown, key: PropertyKey) => T` | Reads a property from an unknown object or function. |
|
|
209
|
+
| `flattenHeaders` | function | `(init: HeadersSource) => Readonly<Record<string, string>>` | Normalizes headers into a frozen plain record. |
|
|
210
|
+
| `resolveRoot` | function | `(meta: ImportMeta) => URL` | Resolves the parent directory of a calling module, which is the workspace root when called from the conventional `tests/setup.ts` location. |
|
|
211
|
+
| `executeScenario` | function | `(scenario, context) => Promise<void>` | Drives one statechart scenario through its arrange, act, and assert phases. |
|
|
212
|
+
| `executeScenarios` | function | `(scenarios, build) => Promise<void>` | Drives a statechart table row by row, each row against a context of its own. |
|
|
204
213
|
|
|
205
214
|
`dropRegistration` is the mechanic `createSignal`'s one-shot and scope-abort paths share, exported
|
|
206
215
|
because both of them call it rather than because a consumer was expected to. Reaching it takes a
|
|
207
216
|
`SignalRegistration` list of your own: `createSignal` hands back `SignalInterface`, whose members are
|
|
208
217
|
`controller`, `signal`, and `count`, so nothing this package returns carries the list to pass.
|
|
209
218
|
|
|
219
|
+
`collectSelectorClasses` reads the class names out of a selector's text, and the browser's
|
|
220
|
+
`readCascade` reads every loaded rule through it. It reads tokens, not the selector grammar: text
|
|
221
|
+
inside a quoted string, a comment, or an attribute block names no class, so `[title=".card"]`
|
|
222
|
+
contributes nothing, and an escaped name decodes to the class it means, so `.sm\:flex` names
|
|
223
|
+
`sm:flex`. A name may open with an underscore, a hyphen, two hyphens, a non-ASCII letter, or an
|
|
224
|
+
escape. Text it cannot read whole — an open or doubled quote, comment, attribute block, or
|
|
225
|
+
parenthesis, a cut-short escape, a class name opening with a digit, or a character outside the
|
|
226
|
+
selector alphabet such as a declaration block's braces — throws an `Error` reading
|
|
227
|
+
`Unreadable selector: <selector>`.
|
|
228
|
+
|
|
210
229
|
#### Factories
|
|
211
230
|
|
|
212
231
|
| API | Kind | Signature | Summary |
|
|
@@ -220,10 +239,37 @@ because both of them call it rather than because a consumer was expected to. Rea
|
|
|
220
239
|
|
|
221
240
|
### Browser
|
|
222
241
|
|
|
223
|
-
Imported from `@orkestrel/test/browser`. Every journey verb here resolves its own target from
|
|
224
|
-
|
|
225
|
-
takes an element, a component instance, or a selector for the thing it
|
|
226
|
-
a journey a description of what a person does rather than of what the
|
|
242
|
+
Imported from `@orkestrel/test/browser`. Every journey verb here resolves its own target from an
|
|
243
|
+
accessible name and, where the platform supplies one, a role, and drives it through the installed
|
|
244
|
+
Vitest provider. None of them takes an element, a component instance, or a selector for the thing it
|
|
245
|
+
acts on. That is what keeps a journey a description of what a person does rather than of what the
|
|
246
|
+
markup happens to be.
|
|
247
|
+
|
|
248
|
+
The low-level `sendTouch` and `tapTouch` instruments take an element for coordinate projection, as
|
|
249
|
+
`readProtocolPoint` does. `sendFileDrag` resolves a rendered role-and-name target without requiring
|
|
250
|
+
focus reachability, so a status or region can receive an external file drag.
|
|
251
|
+
|
|
252
|
+
Native file inputs carry no ARIA role. Their journey uses the label resolver and the same visibility,
|
|
253
|
+
enabled-state, focus-order, uniqueness, and active-modal checks as the other controls.
|
|
254
|
+
|
|
255
|
+
| API | Kind | Signature | Summary |
|
|
256
|
+
| ------------------ | -------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
|
|
257
|
+
| `resolveFileInput` | function | `(name: string) => HTMLInputElement` | Resolves one visible, enabled, focus-reachable native file input by its exact label. |
|
|
258
|
+
| `chooseAccessible` | function | `(name: string, files: readonly FixtureFile[], options?: ChoiceOptions) => Promise<void>` | Activates a labeled native file input and fulfills its observed chooser with fixture bytes. |
|
|
259
|
+
|
|
260
|
+
Register the server entry's `chooseFiles` function as the `chooseFiles` command in the workspace's
|
|
261
|
+
`configs/commands.ts`, the module the root configuration passes to every browser project as
|
|
262
|
+
Vitest's `test.browser.commands`. A package that declares `@orkestrel/test` imports `chooseFiles`
|
|
263
|
+
from `@orkestrel/test/server` there and freezes `{ chooseFiles }` as its exported `commands`
|
|
264
|
+
record. Pass fixture filenames, media types, and byte arrays to `chooseAccessible`; `keyboard: true`
|
|
265
|
+
reaches the input through Tab before pressing Enter, and the default activates it with a native
|
|
266
|
+
pointer click. Run selections sequentially on a page. The server arms its chooser observer before
|
|
267
|
+
activation, checks the event's input identity, and supplies the bytes through the real Playwright
|
|
268
|
+
chooser. A missing or wrong chooser rejects. Observers and input handles are released after
|
|
269
|
+
success, activation failure, timeout, and page closure. Each provider wait defaults to a positive
|
|
270
|
+
1000 ms budget. An empty fixture selection clears the input; it does not prove a manual OS Cancel
|
|
271
|
+
gesture. This proves browser-native chooser activation and fixture selection in Chromium, not
|
|
272
|
+
manual OS dialog interaction, OS drag, or network upload.
|
|
227
273
|
|
|
228
274
|
The fixture builders, the readers, and the field writers do take an element, and none of them is a
|
|
229
275
|
journey verb. `build` creates a node, `mount` attaches one, and `render` does both from
|
|
@@ -232,16 +278,22 @@ back the root it mounted; `buildContrast`, `buildEscapes`, and `buildCensus` eac
|
|
|
232
278
|
a detached control the caller appends where it is reading; `clearStorage` takes nothing at all, and
|
|
233
279
|
`removeDatabase` takes a database name. The predicates, the element readers, and the describers name
|
|
234
280
|
a node the caller already has — `isRendered`, `isReachable`, `readHit`, `readText`, `readRole`,
|
|
235
|
-
`readName`, `readStates`, `
|
|
236
|
-
`
|
|
237
|
-
|
|
281
|
+
`readName`, `readStates`, `readProtocolPoint`, `readProtocolNode`, `readAccessibilityNode`,
|
|
282
|
+
`readActiveElement`, `countElements`, `containsNode`, `readCensus`, `describeTree`, `describeFocus`, `extractOrphans`,
|
|
283
|
+
`readRows`, `readStyle`, `readToken`, `readPixels`, `readContrast`, `readColorContrast`,
|
|
284
|
+
`readLayers`, `readBackdrop`, `readRing`, `readAnimations`, `readClippedBlock`, and
|
|
285
|
+
`collectScrollRegions` — and each reads that node rather than acting on a target it was handed.
|
|
238
286
|
`waitForAnimations` takes one too, and waiting for a browser to stop painting it changes nothing
|
|
239
287
|
about it. `captureFrame` and `place` take an
|
|
240
288
|
element as well, and photographing one is a reading too: neither moves focus, dispatches an event,
|
|
241
|
-
or changes what the element renders. `
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
and
|
|
289
|
+
or changes what the element renders. `readShotPixel` takes one for the same reason and reads one
|
|
290
|
+
pixel of the provider's shot of it. `settleCapture` takes no element: it parks the pointer the way
|
|
291
|
+
`parkPointer` does and holds the document's endless animations until the resume it returns runs.
|
|
292
|
+
`sendTouch` and `tapTouch` act on an element through protocol coordinates. `typeInput` and
|
|
293
|
+
`commitInput` also take an element: they write into the field they are given, as the synthetic
|
|
294
|
+
counterpart of `typeAccessible` for a component that listens for `input`. The color leaves, the
|
|
295
|
+
cascade readers, the pane verbs, and the whole-document readers take a value or nothing at all, so
|
|
296
|
+
they name no target either, and neither does `stepFocus`, which takes a limit and presses Tab.
|
|
245
297
|
|
|
246
298
|
#### Types
|
|
247
299
|
|
|
@@ -252,6 +304,7 @@ a union's arms escaped as `\|`.
|
|
|
252
304
|
| Type | Kind | Shape | Summary |
|
|
253
305
|
| --------------------- | --------- | ------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
254
306
|
| `Color` | type | `readonly [red, green, blue, alpha]` | Represents one rendered color as straight sRGB channels and its alpha. |
|
|
307
|
+
| `ContrastOptions` | interface | `{ floor?, opacity? }` | Configures one color contrast reading: the surface the backdrop walk ends on, and the opacity the painted color is shown at. |
|
|
255
308
|
| `ElementOptions` | interface | `{ classes?, text?, attributes? }` | Configures one built element: its class list, its text, and its attributes. |
|
|
256
309
|
| `FrameOptions` | interface | `{ path, width, height, element? }` | Configures one captured frame: where it is written, the viewport it is shot at, and what it shoots. |
|
|
257
310
|
| `FrameOffset` | interface | `{ top, left }` | Represents how far an element frame moves the tester frame from the runner window's origin for the shot, in CSS pixels. |
|
|
@@ -262,7 +315,13 @@ a union's arms escaped as `\|`.
|
|
|
262
315
|
| `JournalStep` | interface | `{ action, trigger, result }` | Represents one scripted step a journal recorded, and what the surface did about it. |
|
|
263
316
|
| `JournalInterface` | interface | `{ steps, output }` plus `start` / `stop` / `record` | Records one scenario: every step it took and everything the page said while it ran. |
|
|
264
317
|
| `StateOptions` | interface | `WaitOptions` plus `{ absent? }` | Configures a bounded wait over the states a control announces. |
|
|
265
|
-
| `
|
|
318
|
+
| `SettleOptions` | interface | `WaitOptions` plus `{ pointer? }` | Configures one capture settle: the time bounds of `WaitOptions` and whether the pointer parks first. |
|
|
319
|
+
| `AnimationReading` | interface | `{ finite, endless }` | Represents the animations running on one element and its subtree, split by whether each one ends. |
|
|
320
|
+
| `MediaOptions` | interface | `{ print?, motion?, forced?, pointer? }` | Configures the tester's print medium, motion preference, forced colours, and pointer precision. |
|
|
321
|
+
| `StabilityOptions` | interface | `WaitOptions` plus `{ frames? }` | Configures how long a reading must hold still: the time bounds of `WaitOptions` and the count of reads it must agree across. |
|
|
322
|
+
| `AccessibilityNode` | interface | `{ role, name, properties }` | Represents the accessibility node the browser computed for one element. |
|
|
323
|
+
| `SheetAdoption` | interface | `{ sheet: CSSStyleSheet, release() }` | Describes an adopted stylesheet and its idempotent release operation. |
|
|
324
|
+
| `ProtocolPoint` | interface | `{ x, y }` | Represents one point in the coordinates of the browser's top-level viewport, the space a DevTools input command addresses. |
|
|
266
325
|
| `StorageOptions` | interface | `{ values?, reads?, writes?, quota? }` | Configures an inert `Storage`: its seed, which operations the host permits, and its quota. |
|
|
267
326
|
| `WebStorageInterface` | interface | `Storage` plus `{}` plus `permit` | Holds a store the host can withhold and later grant. |
|
|
268
327
|
| `CensusReading` | interface | `{ elements, tokens, undeclared }` | Reports an authored-class census: the population walked, the tokens found, and the undeclared. |
|
|
@@ -292,113 +351,145 @@ A `Shape` cell holds the constant's declared type.
|
|
|
292
351
|
|
|
293
352
|
#### Helpers
|
|
294
353
|
|
|
295
|
-
| API | Kind | Signature
|
|
296
|
-
| -------------------------- | -------- |
|
|
297
|
-
| `resolveAccessible` | function | `(name: string) => HTMLElement` / `(role: string, name: string) => HTMLElement`
|
|
298
|
-
| `resolveAccessibleWithin` | function | `(region: string, role: string, name: string) => HTMLElement`
|
|
299
|
-
| `resolveRendered` | function | `(first: string, second?: string) => HTMLElement`
|
|
300
|
-
| `computeNamePattern` | function | `(name: string) => RegExp`
|
|
301
|
-
| `isOutsideViewport` | function | `(rectangle: DOMRectReadOnly) => boolean`
|
|
302
|
-
| `isRendered` | function | `(element: Element) => boolean`
|
|
303
|
-
| `isReachable` | function | `(element: Element) => boolean`
|
|
304
|
-
| `readHit` | function | `(element: Element) => Element \| undefined`
|
|
305
|
-
| `clickAccessible` | function | `(name: string) => Promise<void>` / `(role: string, name: string) => Promise<void>`
|
|
306
|
-
| `clickAccessibleWithin` | function | `(region: string, role: string, name: string) => Promise<void>`
|
|
307
|
-
| `clickDisclosure` | function | `(name: string) => Promise<void>`
|
|
308
|
-
| `sendProtocol` | function | `(method: string, params
|
|
309
|
-
| `
|
|
310
|
-
| `
|
|
311
|
-
| `
|
|
312
|
-
| `
|
|
313
|
-
| `
|
|
314
|
-
| `
|
|
315
|
-
| `
|
|
316
|
-
| `
|
|
317
|
-
| `
|
|
318
|
-
| `
|
|
319
|
-
| `
|
|
320
|
-
| `
|
|
321
|
-
| `
|
|
322
|
-
| `
|
|
323
|
-
| `
|
|
324
|
-
| `
|
|
325
|
-
| `
|
|
326
|
-
| `
|
|
327
|
-
| `
|
|
328
|
-
| `
|
|
329
|
-
| `
|
|
330
|
-
| `
|
|
331
|
-
| `
|
|
332
|
-
| `
|
|
333
|
-
| `
|
|
334
|
-
| `
|
|
335
|
-
| `
|
|
336
|
-
| `
|
|
337
|
-
| `
|
|
338
|
-
| `
|
|
339
|
-
| `
|
|
340
|
-
| `
|
|
341
|
-
| `
|
|
342
|
-
| `
|
|
343
|
-
| `
|
|
344
|
-
| `
|
|
345
|
-
| `
|
|
346
|
-
| `
|
|
347
|
-
| `
|
|
348
|
-
| `
|
|
349
|
-
| `
|
|
350
|
-
| `
|
|
351
|
-
| `
|
|
352
|
-
| `
|
|
353
|
-
| `
|
|
354
|
-
| `
|
|
355
|
-
| `
|
|
356
|
-
| `
|
|
357
|
-
| `
|
|
358
|
-
| `
|
|
359
|
-
| `
|
|
360
|
-
| `
|
|
361
|
-
| `
|
|
362
|
-
| `
|
|
363
|
-
| `
|
|
364
|
-
| `
|
|
365
|
-
| `
|
|
366
|
-
| `
|
|
367
|
-
| `
|
|
368
|
-
| `
|
|
369
|
-
| `
|
|
370
|
-
| `
|
|
371
|
-
| `
|
|
372
|
-
| `
|
|
373
|
-
| `
|
|
374
|
-
| `
|
|
375
|
-
| `
|
|
376
|
-
| `
|
|
377
|
-
| `
|
|
378
|
-
| `
|
|
379
|
-
| `
|
|
380
|
-
| `
|
|
381
|
-
| `
|
|
382
|
-
| `
|
|
383
|
-
| `
|
|
384
|
-
| `
|
|
385
|
-
| `
|
|
386
|
-
| `
|
|
387
|
-
| `
|
|
388
|
-
| `
|
|
389
|
-
| `
|
|
354
|
+
| API | Kind | Signature | Summary |
|
|
355
|
+
| -------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
356
|
+
| `resolveAccessible` | function | `(name: string) => HTMLElement` / `(role: string, name: string) => HTMLElement` | Resolves one visible, focus-reachable interactive element by its exact accessible name. A wholly-off-viewport target is scrolled into view before reachability is measured. |
|
|
357
|
+
| `resolveAccessibleWithin` | function | `(region: string, role: string, name: string) => HTMLElement` | Resolves one human-reachable control by role and accessible-name text inside a named region. |
|
|
358
|
+
| `resolveRendered` | function | `(first: string, second?: string) => HTMLElement` | Resolves one rendered, focus-reachable interactive element without requiring it to intersect the viewport yet. |
|
|
359
|
+
| `computeNamePattern` | function | `(name: string) => RegExp` | Computes the pattern that matches one accessible name a decorative glyph may sit beside. |
|
|
360
|
+
| `isOutsideViewport` | function | `(rectangle: DOMRectReadOnly) => boolean` | Determines whether a rectangle lies wholly outside the browser viewport. |
|
|
361
|
+
| `isRendered` | function | `(element: Element) => boolean` | Determines whether the accessibility tree presents one element at all. |
|
|
362
|
+
| `isReachable` | function | `(element: Element) => boolean` | Determines whether a person can click one element where it sits. |
|
|
363
|
+
| `readHit` | function | `(element: Element) => Element \| undefined` | Reads the topmost element at one element's bounding-box centre. |
|
|
364
|
+
| `clickAccessible` | function | `(name: string) => Promise<void>` / `(role: string, name: string) => Promise<void>` | Clicks one visible, focus-reachable control by its accessible name through the browser provider. |
|
|
365
|
+
| `clickAccessibleWithin` | function | `(region: string, role: string, name: string) => Promise<void>` | Clicks one human-reachable control by role and accessible-name text inside a named region. |
|
|
366
|
+
| `clickDisclosure` | function | `(name: string) => Promise<void>` | Opens or closes one native details disclosure by its rendered summary. |
|
|
367
|
+
| `sendProtocol` | function | `(method: string, params?: Readonly<Record<string, unknown>>) => Promise<unknown>` | Sends one DevTools protocol command through the browser provider. |
|
|
368
|
+
| `readProtocolPoint` | function | `(element: Element, offset?: ProtocolPoint) => ProtocolPoint` | Projects a point of one element through every frame that holds it into the browser's top-level viewport. |
|
|
369
|
+
| `readProtocolNode` | function | `(element: Element) => Promise<number>` | Resolves one element to the node the browser's DOM tree holds for it. |
|
|
370
|
+
| `readAccessibilityNode` | function | `(element: Element) => Promise<AccessibilityNode>` | Reads the accessibility node the browser computed for one element. |
|
|
371
|
+
| `hoverAccessible` | function | `(name: string) => Promise<void>` / `(role: string, name: string) => Promise<void>` | Hovers one visible, focus-reachable control by its accessible name through the browser provider. |
|
|
372
|
+
| `holdAccessible` | function | `(name: string) => Promise<void>` / `(role: string, name: string) => Promise<void>` | Holds the primary pointer button on one visible, focus-reachable control by its accessible name. |
|
|
373
|
+
| `holdAccessibleWithin` | function | `(region: string, role: string, name: string) => Promise<void>` | Holds the primary pointer button on one control by role and accessible-name text inside a named region. |
|
|
374
|
+
| `driveHold` | function | `(resolve: () => HTMLElement, name: string) => Promise<void>` | Holds the primary pointer button on the control a resolver returns, through the browser provider. |
|
|
375
|
+
| `parkPointer` | function | `() => Promise<void>` | Parks the pointer outside the page and waits for the parked pointer's frame to paint. |
|
|
376
|
+
| `releasePointer` | function | `() => Promise<void>` | Releases a held pointer and parks it outside the page, clearing hover. |
|
|
377
|
+
| `typeAccessible` | function | `(name: string, text: string) => Promise<void>` | Replaces a named field's value through focus, select-all, deletion, and real keystrokes. |
|
|
378
|
+
| `fillAccessible` | function | `(name: string, text: string) => Promise<void>` | Replaces a named field's value in one operation, for text too long to type key by key. |
|
|
379
|
+
| `traverseAccessible` | function | `(name: string) => Promise<HTMLElement>` | Reaches a named control only through natural forward Tab traversal from the current focus. |
|
|
380
|
+
| `traverseAccessibleWithin` | function | `(region: string, role: string, name: string) => Promise<HTMLElement>` | Reaches a control by role and accessible-name text inside a named region, only through natural forward Tab traversal from the current focus. |
|
|
381
|
+
| `readActiveElement` | function | `(root?: Document \| ShadowRoot) => HTMLElement \| undefined` | Reads the HTML element that holds focus, following it into open shadow roots and same-origin frames. |
|
|
382
|
+
| `countElements` | function | `(root?: Document \| ShadowRoot) => number` | Counts the elements a tree holds, descending into open shadow roots and same-origin frames. |
|
|
383
|
+
| `containsNode` | function | `(root: Node, node: Node) => boolean` | Determines whether a node sits inside a root, through open shadow roots and frames. |
|
|
384
|
+
| `stepFocus` | function | `(limit: number) => AsyncGenerator<HTMLElement \| undefined, void, undefined>` | Presses Tab and yields the element focus lands on, once per press, up to a limit. |
|
|
385
|
+
| `driveTraversal` | function | `(resolve: () => HTMLElement, name: string) => Promise<HTMLElement>` | Reaches the control a resolver returns, only through natural forward Tab traversal from the current focus. |
|
|
386
|
+
| `walkFocus` | function | `(stop?: (element: HTMLElement) => boolean) => Promise<readonly HTMLElement[]>` | Walks forward by real Tab presses from the focused element until a predicate accepts a stop or the Tab order ends. |
|
|
387
|
+
| `collectTabStops` | function | `(root: Element, start: HTMLElement) => Promise<readonly HTMLElement[]>` | Collects the elements of a region that a forward Tab walk reaches from a starting element. |
|
|
388
|
+
| `pressKeys` | function | `(keys: string) => Promise<void>` | Sends a key sequence to whatever holds focus, and refuses to send it to nothing. |
|
|
389
|
+
| `readPerception` | function | `(name: string) => string` | Reads the normalized visible text of one named region, dialog, table, tab panel, or alert. |
|
|
390
|
+
| `readPage` | function | `() => string` | Reads the normalized visible text of the whole page. |
|
|
391
|
+
| `readFocus` | function | `() => string \| undefined` | Reads the rendered text of the element that holds focus. |
|
|
392
|
+
| `readValue` | function | `(role: string, name: string) => string` | Reads the value a resolved control renders. |
|
|
393
|
+
| `readRefusal` | function | `(name: string) => string \| undefined` / `(role: string, name: string) => string \| undefined` | Reads the refusal one named target answers with, or nothing when it resolves. |
|
|
394
|
+
| `readText` | function | `(element: Element) => string` | Reads one element's rendered text the way a name computation reads it. |
|
|
395
|
+
| `readRole` | function | `(element: Element) => string \| undefined` | Reads the role one element carries in the accessibility tree. |
|
|
396
|
+
| `readName` | function | `(element: Element) => string` | Reads the accessible name one element is announced under. |
|
|
397
|
+
| `readStates` | function | `(element: Element) => readonly string[]` | Reads the states one element is announced in. |
|
|
398
|
+
| `describeTree` | function | `(element: Element) => string` | Describes the accessible tree one rendered element presents. |
|
|
399
|
+
| `describeFocus` | function | `(element: Element) => string` | Describes the order sequential keyboard navigation visits one element's controls in. |
|
|
400
|
+
| `waitForFrame` | function | `() => Promise<void>` | Waits for one animation frame to settle pending browser paint work. |
|
|
401
|
+
| `waitForState` | function | `(name, state, options?) => Promise<readonly string[]>` / `(role, name, state, options?) => Promise<readonly string[]>` | Waits until one named control announces a state, or stops announcing it. |
|
|
402
|
+
| `waitForAnimations` | function | `(element: Element, options?: WaitOptions) => Promise<void>` | Waits until every finite animation on one element and its subtree has stopped moving. |
|
|
403
|
+
| `readAnimations` | function | `(element: Element) => AnimationReading` | Reads the animations running on one element and its subtree, split by whether each one ends. |
|
|
404
|
+
| `settleCapture` | function | `(options?: SettleOptions) => Promise<() => void>` | Settles the page for one capture: parks the pointer, waits out every finite animation, and holds each endless animation at its first frame. |
|
|
405
|
+
| `collectScrollRegions` | function | `(root: Element, axis?: 'inline' \| 'block') => readonly HTMLElement[]` | Collects the rendered boxes a person can scroll. |
|
|
406
|
+
| `describeScrollRegions` | function | `(regions: readonly HTMLElement[]) => string` | Describes the window's scroll position and each scroll region's offsets and extents. |
|
|
407
|
+
| `build` | function | `<K extends keyof HTMLElementTagNameMap>(tag: K, options?: ElementOptions) => HTMLElementTagNameMap[K]` | Builds one unmounted element of a known tag, wearing the classes, text, and attributes asked for. |
|
|
408
|
+
| `mount` | function | `<T extends Element>(element: T) => T` | Puts one element into the document and hands it straight back. |
|
|
409
|
+
| `typeInput` | function | `(element: HTMLInputElement \| HTMLTextAreaElement, text: string) => void` | Sets one field's value and announces it the way typing into the field does. |
|
|
410
|
+
| `commitInput` | function | `(element: HTMLInputElement \| HTMLTextAreaElement, text: string) => void` | Sets one field's value and commits it, the way typing and then leaving the field does. |
|
|
411
|
+
| `render` | function | `(markup: string) => HTMLDivElement` / `(tag: K, classes: string) => HTMLElementTagNameMap[K]` | Renders one fixture into the document from trusted markup. |
|
|
412
|
+
| `clearStorage` | function | `() => void` | Clears both browser storage surfaces. |
|
|
413
|
+
| `removeDatabase` | function | `(name: string) => Promise<void>` | Deletes one IndexedDB database and reports what the request actually did. |
|
|
414
|
+
| `convertSRGB` | function | `(red: number, green: number, blue: number, alpha?: number) => Color` | Converts normalized encoded sRGB channels to the clipped paint scale. |
|
|
415
|
+
| `convertLinearSRGB` | function | `(red: number, green: number, blue: number, alpha?: number) => Color` | Converts linear sRGB channels to encoded, clipped paint channels. |
|
|
416
|
+
| `convertXYZD65` | function | `(x: number, y: number, z: number, alpha?: number) => Color` | Converts D65 XYZ coordinates to clipped sRGB paint channels. |
|
|
417
|
+
| `convertXYZD50` | function | `(x: number, y: number, z: number, alpha?: number) => Color` | Converts D50 XYZ coordinates to clipped sRGB paint channels. |
|
|
418
|
+
| `convertOKLab` | function | `(lightness: number, a: number, b: number, alpha?: number) => Color` | Converts OKLab coordinates to clipped sRGB paint channels. |
|
|
419
|
+
| `convertLab` | function | `(lightness: number, a: number, b: number, alpha?: number) => Color` | Converts CIE Lab coordinates relative to D50 to clipped sRGB paint channels. |
|
|
420
|
+
| `convertDisplayP3` | function | `(red: number, green: number, blue: number, alpha?: number) => Color` | Converts encoded Display P3 channels to clipped sRGB paint channels. |
|
|
421
|
+
| `convertA98RGB` | function | `(red: number, green: number, blue: number, alpha?: number) => Color` | Converts encoded A98 RGB channels to clipped sRGB paint channels. |
|
|
422
|
+
| `convertProPhotoRGB` | function | `(red: number, green: number, blue: number, alpha?: number) => Color` | Converts encoded ProPhoto RGB channels to clipped sRGB paint channels. |
|
|
423
|
+
| `convertRec2020` | function | `(red: number, green: number, blue: number, alpha?: number) => Color` | Converts encoded Rec. 2020 channels to clipped sRGB paint channels. |
|
|
424
|
+
| `parseColor` | function | `(value: string) => Color \| undefined` | Parses computed CSS Color 4 values into clipped straight sRGB channels. |
|
|
425
|
+
| `parseCSSColor` | function | `(value: string, scope?: Element) => Color \| undefined` | Resolves any CSS color expression to straight sRGB channels, by asking the browser. |
|
|
426
|
+
| `matchesColor` | function | `(first: string \| Color, second: string \| Color) => boolean` | Determines whether two colors render the same, within the rounding a browser does. |
|
|
427
|
+
| `blendColor` | function | `(front: Color, back: Color) => Color` | Composites one color over another. |
|
|
428
|
+
| `measureLuminance` | function | `(color: Color) => number` | Measures one opaque color's WCAG relative luminance. |
|
|
429
|
+
| `measureContrast` | function | `(front: Color, back: Color) => number` | Measures the WCAG 2.x contrast ratio between two opaque colors. |
|
|
430
|
+
| `readLayers` | function | `(element: Element) => readonly Color[]` | Collects readable background color layers and refuses an unreadable painted layer. |
|
|
431
|
+
| `readBackdrop` | function | `(element: Element, floor: Color) => Color` | Resolves the opaque color standing behind one element. |
|
|
432
|
+
| `readColorContrast` | function | `(element: Element, color: string, options?: ContrastOptions) => number` | Measures the WCAG 2.x contrast ratio one color reaches when painted over an element's backdrop. |
|
|
433
|
+
| `readContrast` | function | `(element: Element, floor?: Color) => number` | Measures the WCAG 2.x contrast ratio between an element's computed text and background colors. |
|
|
434
|
+
| `readRing` | function | `(control: Element, worn?: Element) => number \| undefined` | Measures the contrast the focus chrome painted on one control reaches against its own backdrop. |
|
|
435
|
+
| `readClipEdge` | function | `(element: Element) => number \| undefined` | Measures the row a clipping element cuts its content off at, in document coordinates. |
|
|
436
|
+
| `readClipMargin` | function | `(element: Element) => number` | Measures how far past its own box a clipping element lets its content show. |
|
|
437
|
+
| `readClippedBlock` | function | `(element: Element) => number` | Measures the block size an element shows after every clipping ancestor cuts it. |
|
|
438
|
+
| `collectClippingAncestors` | function | `(element: Element) => readonly Element[]` | Collects the ancestors of an element that clip their descendants' overflow. |
|
|
439
|
+
| `clipsOverflow` | function | `(element: Element) => boolean` | Reports whether an element clips its descendants' overflow. |
|
|
440
|
+
| `measureContent` | function | `() => number` | Measures the row the document's own content ends on, in document coordinates. |
|
|
441
|
+
| `stagePane` | function | `(width: number, height: number) => Promise<void>` | Sets the tester's viewport and renders the runner's pane at the size that viewport claims. |
|
|
442
|
+
| `releasePane` | function | `() => Promise<void>` | Hands the tester pane back to the runner's own layout, at the viewport it had before staging. |
|
|
443
|
+
| `computeOffset` | function | `(box: DOMRectReadOnly, width: number, height: number) => FrameOffset` | Computes how far an element frame moves the tester frame so the element is shot inside the runner's window. |
|
|
444
|
+
| `stageMedia` | function | `(options: MediaOptions) => Promise<void>` | Stages the tester's print medium, motion preference, forced colours, and pointer precision through the browser provider. |
|
|
445
|
+
| `releaseMedia` | function | `() => Promise<void>` | Restores the media readings observed before the first stage as explicit emulation. With nothing staged, clears every override and waits for a stable reading, not a proved engine baseline. Checks the budget between polls, so a frame that never paints is not bounded by it. |
|
|
446
|
+
| `waitForStability` | function | `(description: string, read: () => string, options?: StabilityOptions) => Promise<void>` | Waits for a reading to hold across its last `frames + 1` reads, each later read taken after a painted frame, with the interval slept between polls. Checks the budget between reads, so a frame that never paints is not bounded by it. |
|
|
447
|
+
| `captureFrame` | function | `(options: FrameOptions) => Promise<string>` | Shoots one frame at one viewport size and proves the file on disk holds this run's bytes. |
|
|
448
|
+
| `paintImage` | function | `(encoded: string) => Promise<OffscreenCanvasRenderingContext2D \| undefined>` | Decodes a base64 PNG and paints it, unscaled, onto a fresh offscreen 2D canvas. |
|
|
449
|
+
| `readFrame` | function | `(path: string) => Promise<FrameReading>` | Reads one written frame back and reports its size and the color its bottom row paints. |
|
|
450
|
+
| `readShotPixel` | function | `(element: Element, x: number, y: number) => Promise<Color>` | Reads one painted pixel of an element's screenshot. |
|
|
451
|
+
| `readCascade` | function | `() => ReadonlySet<string>` | Collects every class token the stylesheets loaded into this document actually define. |
|
|
452
|
+
| `readClasses` | function | `(root: ParentNode) => ReadonlySet<string>` | Collects every class token the markup under one root carries. |
|
|
453
|
+
| `readCensus` | function | `(root: ParentNode) => CensusReading` | Takes the authored-class census of one subtree against the cascade this document loaded. |
|
|
454
|
+
| `sendTouch` | function | `(type: 'touchStart' \| 'touchMove' \| 'touchEnd' \| 'touchCancel', element?: Element, point?: ProtocolPoint) => Promise<void>` | Sends one emulated touch event through the browser protocol. |
|
|
455
|
+
| `tapTouch` | function | `(element: Element, options?: StabilityOptions) => Promise<void>` | Taps an element's centre with emulated touch after its box settles. |
|
|
456
|
+
| `releaseTouch` | function | `() => Promise<void>` | Cancels emulated touch input, disables touch emulation, and parks the pointer. |
|
|
457
|
+
| `sendFileDrag` | function | `(type: 'dragEnter' \| 'dragOver' \| 'dragCancel', role: string, name: string, names: readonly string[]) => Promise<void>` | Carries files from outside the page over a rendered target named by role and accessible name. |
|
|
458
|
+
| `adoptSheet` | function | `(text: string) => SheetAdoption` | Adopts CSS text into the document with an idempotent release operation. |
|
|
459
|
+
| `readLayerNames` | function | `(source: CSSStyleSheet \| CSSGroupingRule \| CSSStyleRule, layer?: string) => readonly string[]` | Reads layer statements and blocks in declaration order, including repeated names. |
|
|
460
|
+
| `readRules` | function | `() => readonly CSSRule[]` | Collects every rule the stylesheets loaded into this document hold, nested grouping rules included. |
|
|
461
|
+
| `findRule` | function | `(selector: string) => CSSStyleRule \| undefined` | Finds the first style rule in the cascade whose selector carries a fragment. |
|
|
462
|
+
| `findKeyframes` | function | `(name: string) => CSSKeyframesRule \| undefined` | Finds the animation the cascade declares under one name. |
|
|
463
|
+
| `readRows` | function | `(root: ParentNode, selector: string) => readonly string[]` | Reads the normalized visible text of every element a selector matches, in document order. |
|
|
464
|
+
| `extractOrphans` | function | `(root: ParentNode, child: string, parent: string) => readonly string[]` | Collects every element carrying a component class rendered outside the container it belongs to. |
|
|
465
|
+
| `extractStyles` | function | `(root: ParentNode) => readonly string[]` | Collects the markup of every element carrying a non-empty `style` attribute and of every `<style>` element, in document order, `root` included in both populations when it is an `Element`. |
|
|
466
|
+
| `readStyle` | function | `(element: Element, property: string, pseudo?: string) => string` | Reads one resolved CSS property from a real browser element or a named pseudo-element. |
|
|
467
|
+
| `readToken` | function | `(element: Element, name: string) => string` | Reads one custom property from an element's resolved style. |
|
|
468
|
+
| `readRootToken` | function | `(name: string) => string` | Reads one custom property from the document element. |
|
|
469
|
+
| `readPixels` | function | `(element: Element, property: string, pseudo?: string) => number` | Reads one resolved CSS length as a number of pixels. |
|
|
470
|
+
| `expandCaptures` | function | `(states: readonly string[], variants: readonly CaptureVariant[]) => readonly string[]` | Expands a capture registry across every variant into the filenames a complete portfolio holds. |
|
|
471
|
+
| `buildDenial` | function | `(operation: string, key?: string) => DOMException` | Builds the refusal a host withholding a storage operation raises. |
|
|
472
|
+
| `buildContrast` | function | `(bar: number) => ContrastFixture` | Builds a detached translucent stack whose composited and flat contrast readings straddle one bar. |
|
|
473
|
+
| `buildEscapes` | function | `(permitted: string) => EscapeFixture` | Builds detached markup carrying one style escape of each kind, plus the sheet a project allows. |
|
|
474
|
+
| `buildCensus` | function | `() => CensusFixture` | Builds detached markup carrying one undeclared class token on HTML and another on SVG. |
|
|
390
475
|
|
|
391
476
|
#### Factories
|
|
392
477
|
|
|
393
|
-
| API
|
|
394
|
-
|
|
|
395
|
-
| `
|
|
396
|
-
| `
|
|
397
|
-
| `
|
|
398
|
-
| `
|
|
399
|
-
| `
|
|
400
|
-
| `
|
|
401
|
-
| `
|
|
478
|
+
| API | Kind | Signature | Summary |
|
|
479
|
+
| --------------------- | -------- | --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
|
|
480
|
+
| `createPortfolio` | function | `(options: PortfolioOptions) => PortfolioInterface` | Creates the capture portfolio one run places its screenshots through; a disabled run still refuses. |
|
|
481
|
+
| `createChannel` | function | `(name: string, output: string[], forward: (...data: unknown[]) => void) => (...data: unknown[]) => void` | Creates one console channel that records every call it receives and hands that call on unchanged. |
|
|
482
|
+
| `createJournal` | function | `() => JournalInterface` | Creates the journal one scenario records its steps and the page's own output into. |
|
|
483
|
+
| `createStorage` | function | `(options?: StorageOptions) => WebStorageInterface` | Creates an inert `Storage` a host can withhold, grant, and run out of room in. |
|
|
484
|
+
| `createHarness` | function | `(options: HarnessOptions<TState, TEvent, TContext>) => HarnessInterface` | Creates a mounted statechart harness that renders one transition table and drives it row by row. |
|
|
485
|
+
| `createPointerEvent` | function | `(name: string, options?: PointerEventInit) => PointerEvent` | Creates one real pointer event, ready to dispatch. |
|
|
486
|
+
| `createDragEvent` | function | `(name: string, options?: DragEventInit) => DragEvent` | Creates one real drag event carrying a live data transfer, ready to dispatch. |
|
|
487
|
+
| `createKeyboardEvent` | function | `(name: string, options?: KeyboardEventInit) => KeyboardEvent` | Creates one real keyboard event, ready to dispatch. |
|
|
488
|
+
|
|
489
|
+
`createPointerEvent` and `createDragEvent` default to `composed: true` from 0.0.27, where 0.0.26
|
|
490
|
+
left it `false`. An event dispatched inside an open shadow root stayed there in 0.0.26, and a
|
|
491
|
+
listener outside that root heard nothing; a listener outside it hears the event from 0.0.27. Pass
|
|
492
|
+
`{ composed: false }` to restore the 0.0.26 boundary behavior.
|
|
402
493
|
|
|
403
494
|
`resolveAccessible` counts a match as reachable only when every condition holds: it is connected; it
|
|
404
495
|
passes a visibility check honouring opacity and CSS; its box has non-zero width and height; its
|
|
@@ -498,12 +589,26 @@ clipped to 0–255 after conversion; this reader does not perform perceptual gam
|
|
|
498
589
|
Alpha is clipped to 0–1.
|
|
499
590
|
|
|
500
591
|
`parseCSSColor` is the live half of the pair `parseColor` opens. `parseColor` reads text and speaks
|
|
501
|
-
only the computed syntaxes a cascade hands back; `parseCSSColor`
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
`finally`. Refusal is the CSSOM's: an expression it will not parse
|
|
506
|
-
naming an undeclared custom property is not refused, and
|
|
592
|
+
only the computed syntaxes a cascade hands back; `parseCSSColor` hands the expression to the real
|
|
593
|
+
cascade and reads back what the engine computed — which is the only way a keyword, a hex triple, a
|
|
594
|
+
`var()` reference, or a `color-mix()` becomes channels at all. With no scope the expression resolves
|
|
595
|
+
on a probe that is a child of the body, mounted so a `var()` reference resolves against the tokens
|
|
596
|
+
`:root` declares, and removed in a `finally`. Refusal is the CSSOM's: an expression it will not parse
|
|
597
|
+
returns `undefined`. A `var()` naming an undeclared custom property is not refused, and
|
|
598
|
+
[Limits](#limits) states what that costs. The optional `scope` argument resolves the expression on
|
|
599
|
+
that same body-mounted probe, which carries the scope's computed context onto its own inline style:
|
|
600
|
+
the computed value of every custom property the expression names, a fallback's included, the
|
|
601
|
+
scope's computed `color`, and its computed `color-scheme`. The expression is written into
|
|
602
|
+
`background-color`, so `currentColor` is the carried `color`, and a system color or `light-dark()`
|
|
603
|
+
answers as the scope's scheme. The element's own and inherited custom properties apply, a registered
|
|
604
|
+
property that does not inherit included, and an `input`, an SVG element, or any other element
|
|
605
|
+
resolves like any other. A custom property is named by letters, digits, `_`, and `-` after its `--`,
|
|
606
|
+
and a name the scope leaves undeclared is not carried, so its `var()` fallback still applies. The
|
|
607
|
+
scope element is never written: the probe is new, so it has no earlier style to start a transition
|
|
608
|
+
from, a transition running on the scope keeps running and `currentColor` reads the color the scope
|
|
609
|
+
shows at that moment, and the scope's geometry and scroll position stay as they were. No attribute,
|
|
610
|
+
style, or child of the scope changes, so a `MutationObserver` on it records nothing. A disconnected
|
|
611
|
+
scope computes no style and returns `undefined`.
|
|
507
612
|
|
|
508
613
|
`matchesColor` compares two colors as a browser renders them. Each string side resolves through
|
|
509
614
|
`parseCSSColor`, so a keyword, a token reference, and the `rgb()` an engine computes for either
|
|
@@ -522,6 +627,21 @@ or the color a fragment is really mounted onto — and the same stack composites
|
|
|
522
627
|
being refused. A detached element is refused either way, because its computed foreground color does
|
|
523
628
|
not exist.
|
|
524
629
|
|
|
630
|
+
`readColorContrast` is the same measurement with the color handed in, for paint that is not the
|
|
631
|
+
element's own text: a separator grip, a placeholder, a checkbox mark. `readContrast` and `readRing`
|
|
632
|
+
both measure through it. A computed color value parses directly, and any other expression — a
|
|
633
|
+
keyword, a hex triple, a `var()` reference — resolves through `parseCSSColor` at the element's own
|
|
634
|
+
scope: a token reads as the element and its ancestors declare it, and `currentColor` is the
|
|
635
|
+
element's own text color, not the body's. The read carries the element's computed custom
|
|
636
|
+
properties, `color`, and `color-scheme` onto a probe, so an `input` and a registered token that does
|
|
637
|
+
not inherit resolve as they do on any other element, and the element itself is never written. A
|
|
638
|
+
disconnected element computes no style, so it refuses such an expression as unreadable; hand it a
|
|
639
|
+
computed color such as `rgb(255, 255, 255)`. `floor` takes the
|
|
640
|
+
part `readContrast`'s second argument takes, with the same refusal and the same voice when it is
|
|
641
|
+
omitted. `opacity` multiplies the color's own alpha before it is composited, for a mark painted
|
|
642
|
+
inside an element whose `opacity` is below `1`, and a value outside `0` to `1` is refused rather than
|
|
643
|
+
read.
|
|
644
|
+
|
|
525
645
|
`readLayers` is the reading that refusal turns on. It hands back the painted layers themselves,
|
|
526
646
|
element first and the deepest last, so a walk that ended on a real surface is the one whose last
|
|
527
647
|
layer has an alpha of `1`. A composited color cannot answer that question: 64 half-transparent
|
|
@@ -533,7 +653,10 @@ An unreadable painted background layer throws an error naming its element and co
|
|
|
533
653
|
Non-finite calculations such as `color(srgb calc(infinity) 0 0)` are deliberately unreadable.
|
|
534
654
|
A layer with an explicit zero alpha paints nothing and is skipped, including an unreadable one.
|
|
535
655
|
Background images remain outside this color reader. The refusal propagates through `readBackdrop`,
|
|
536
|
-
`readContrast`, and the
|
|
656
|
+
`readContrast`, `readColorContrast`, and the reading `readRing` takes of painted focus chrome, even
|
|
657
|
+
with a supplied floor. `readRing` reads the backdrop for every control matching `:focus-visible`
|
|
658
|
+
before it looks for chrome, so a focused control whose cascade paints no chrome is refused over an
|
|
659
|
+
unreadable surface too.
|
|
537
660
|
|
|
538
661
|
`readBackdrop` composites that stack and takes its floor as an argument rather than reaching for
|
|
539
662
|
`CANVAS_COLOR` itself, so a measurement over a surface the canvas never shows through names the
|
|
@@ -566,6 +689,16 @@ class declared inside an earlier grouping rule; 0.0.8 popped a stack and inserte
|
|
|
566
689
|
first. Iterate the set where the order is the subject and read `has` where membership is. A
|
|
567
690
|
`@keyframes` rule's own children are outside the walk, so an animation's stops define no token here.
|
|
568
691
|
|
|
692
|
+
Each rule's selector text is read by `collectSelectorClasses`, and that reading differs from 0.0.26,
|
|
693
|
+
which matched a pattern over the text. An escaped name decodes, so `.sm\:flex` defines `sm:flex`
|
|
694
|
+
where 0.0.26 read `sm`. Text inside an attribute value, a string, or a comment defines nothing, so
|
|
695
|
+
`[title=".card"]` defines no `card`. A name opening with an underscore, a hyphen, or a non-ASCII
|
|
696
|
+
letter counts, where 0.0.26 skipped it. A non-ASCII letter inside a name stays in it, so `.café`
|
|
697
|
+
defines `café` where 0.0.26 ended the class at the first code point outside ASCII letters, digits,
|
|
698
|
+
`_`, and `-` and defined `caf`. A census that saw any of those misreadings reports the
|
|
699
|
+
corrected set, so `readCensus` can move a token into or out of `undeclared`. One rule's own tokens
|
|
700
|
+
enter the set in code-unit order rather than in the order the selector writes them.
|
|
701
|
+
|
|
569
702
|
`findRule` and `findKeyframes` differ in how they match, and the subject is what decides it. A
|
|
570
703
|
selector is compound, so `findRule` matches its argument as a substring of the whole selector text:
|
|
571
704
|
`findRule('.card')` finds `.card`, `.card:hover`, and `.panel > .card` alike, and more of the
|
|
@@ -626,7 +759,9 @@ the body instead, taking the largest bottom edge in document coordinates plus th
|
|
|
626
759
|
bottom margin, and adds the body's and the root's bottom padding and margin under them. An
|
|
627
760
|
ancestor that clips its overflow (the `clipsOverflow` helper: an `overflow-y` value other than the
|
|
628
761
|
`visible` keyword, or a paint containment) caps a descendant's edge at that ancestor's clip edge,
|
|
629
|
-
which the `readClipEdge` helper reads.
|
|
762
|
+
which the `readClipEdge` helper reads. The `collectClippingAncestors` helper finds those ancestors
|
|
763
|
+
through the flat tree, from an element to the slot it is assigned to, to its parent, and out of a
|
|
764
|
+
shadow root to its host, so a wrapper in a shadow tree around a slot clips what is slotted into it. An `overflow-y` value of the `hidden` keyword, the `auto`
|
|
630
765
|
keyword, or the `scroll` keyword clips at the padding box, whatever the ancestor's
|
|
631
766
|
`overflow-clip-margin` value selects. The `clip` keyword and a paint containment over a `visible`
|
|
632
767
|
overflow clip at the box that value selects, the padding box by default, expanded by the length the
|
|
@@ -657,15 +792,27 @@ written at a height that is already wrong. That bound is 4: a document holding h
|
|
|
657
792
|
fixed block settles in two restagings, one whose growth is capped part way settles in three, and
|
|
658
793
|
the fourth is headroom.
|
|
659
794
|
|
|
660
|
-
An element
|
|
661
|
-
lengths resolve against the declared viewport
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
795
|
+
An element that fits with its native scroll clearance is shot in the declared pane, so its viewport
|
|
796
|
+
lengths resolve against the declared viewport: a `50vh` element under a 900-row block reads back 422
|
|
797
|
+
rows in an 844-row pane. A short fixed panel that native alignment cannot move keeps that pane too.
|
|
798
|
+
A captured sticky element with a vertical start inset keeps the declared pane when native end
|
|
799
|
+
alignment places its box fully inside it. Its own inset determines that fitted placement; adding
|
|
800
|
+
the document's start-clearance gap can otherwise grow a viewport-bound height on every restaging.
|
|
801
|
+
This exception belongs to the captured sticky element, not to in-flow content it contains or a
|
|
802
|
+
region containing sticky children. A sticky declaration without a vertical start inset retains
|
|
803
|
+
the ordinary clearance behavior.
|
|
804
|
+
For an element whose height plus clearance exceeds the declared height, native start alignment
|
|
805
|
+
resolves the clearance, and the pane reserves the element's height plus the space above its aligned
|
|
806
|
+
top. This includes an element shorter than the declared pane. It honors authored root scroll padding
|
|
807
|
+
and target scroll margins, including computed lengths, without
|
|
808
|
+
parsing CSS or hiding a sticky header. The captured image still contains only the element's box.
|
|
809
|
+
An overlay without authored clearance remains visible in the image; the instrument detects no
|
|
810
|
+
arbitrary occlusion. Viewport-dependent clearance participates in the same bounded settling loop,
|
|
811
|
+
so a frame whose geometry has not settled within that bound is refused.
|
|
665
812
|
Where the element's box lies outside the pane, the document is scrolled by the nearest distance that
|
|
666
813
|
would bring it inside, and the box is read again. A fixed element past the pane can take a scroll
|
|
667
|
-
that does not move it, and that scroll is handed back with the rest.
|
|
668
|
-
|
|
814
|
+
that does not move it, and that scroll is handed back with the rest. Other short elements that need no
|
|
815
|
+
additional room keep their nearest native alignment.
|
|
669
816
|
|
|
670
817
|
The provider paints an element that fits the runner's window only where that window shows it. Where
|
|
671
818
|
such an element lies past the window, the `captureFrame` function offsets the calling tester frame up
|
|
@@ -694,8 +841,10 @@ pixels; a file with no PNG header is refused without a size.
|
|
|
694
841
|
|
|
695
842
|
`createPortfolio` refuses an unregistered variant name at creation, so a run cannot write a filename
|
|
696
843
|
naming a combination it did not render. A portfolio left un-`enabled` is the ordinary run: `place`
|
|
697
|
-
resizes nothing, writes nothing, and records nothing, so a journey calls it unconditionally.
|
|
698
|
-
|
|
844
|
+
resizes nothing, writes nothing, and records nothing, so a journey calls it unconditionally. It
|
|
845
|
+
still refuses an unregistered state and a second placement of one state, so a journey that names a
|
|
846
|
+
state wrongly fails the ordinary run rather than the first capture run; `placements` and `paths`
|
|
847
|
+
stay empty, because they answer for what was captured. An enabled `place` applies the variant and writes `<directory>/<state>--<variant>.png` through
|
|
699
848
|
`captureFrame`, so it stages the pane at the variant's size, covers the whole document, verifies the
|
|
700
849
|
written bytes, and records only a path that read back as this run's own frame. The tester comes back
|
|
701
850
|
at the viewport it had before the placement, so a journey that places a state carries on at its own
|
|
@@ -719,6 +868,12 @@ collision refusal before writing.
|
|
|
719
868
|
|
|
720
869
|
Imported from `@orkestrel/test/server`.
|
|
721
870
|
|
|
871
|
+
The provider command consumes the browser journey's resolved selector inside Vitest's tester frame.
|
|
872
|
+
|
|
873
|
+
| API | Kind | Signature | Summary |
|
|
874
|
+
| ------------- | -------- | --------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
|
|
875
|
+
| `chooseFiles` | function | `(context: ChooserContext, request: ChooserRequest) => Promise<void>` | Observes a native chooser before activating its input and supplies the verified chooser's fixture bytes. |
|
|
876
|
+
|
|
722
877
|
#### Types
|
|
723
878
|
|
|
724
879
|
A `Shape` cell holds an interface's data members as bare names in braces, `?` marking an optional
|
|
@@ -736,6 +891,7 @@ it adds after.
|
|
|
736
891
|
| `InventoryOptions` | interface | `{ extensions?, exclude? }` | Configures a source inventory read. |
|
|
737
892
|
| `UpgradeOptions` | interface | `WaitOptions` plus `{ path?, protocols? }` | Configures a client upgrade request. |
|
|
738
893
|
| `UpgradeResult` | type | `{ claimed, protocol } \| { claimed, status }` | Represents what one server did with a client upgrade request. |
|
|
894
|
+
| `ChooserContext` | interface | `{ page, iframe }` | Supplies the real Playwright page and tester frame to a native chooser command. |
|
|
739
895
|
|
|
740
896
|
#### Constants
|
|
741
897
|
|
|
@@ -903,6 +1059,24 @@ this package never reserves a port number.
|
|
|
903
1059
|
The call-signature members of each behavioral interface. Their `readonly` data members stay in the
|
|
904
1060
|
earlier [Surface](#surface) rows.
|
|
905
1061
|
|
|
1062
|
+
#### `SheetAdoption`
|
|
1063
|
+
|
|
1064
|
+
The adoption releases only the sheet it owns.
|
|
1065
|
+
|
|
1066
|
+
| Method | Signature | Summary |
|
|
1067
|
+
| --------- | ------------ | ----------------------------------------------------------------------- |
|
|
1068
|
+
| `release` | `() => void` | Removes this sheet from the document without removing another adoption. |
|
|
1069
|
+
|
|
1070
|
+
Release an adoption after the fixture has read its sheet.
|
|
1071
|
+
|
|
1072
|
+
```ts
|
|
1073
|
+
import type { SheetAdoption } from '@orkestrel/test/browser'
|
|
1074
|
+
import { adoptSheet } from '@orkestrel/test/browser'
|
|
1075
|
+
|
|
1076
|
+
const adopted: SheetAdoption = adoptSheet('@layer example {}')
|
|
1077
|
+
adopted.release()
|
|
1078
|
+
```
|
|
1079
|
+
|
|
906
1080
|
#### `RecorderInterface`
|
|
907
1081
|
|
|
908
1082
|
| Method | Returns | Summary |
|
|
@@ -1086,51 +1260,66 @@ what the link reaches, not on what it stores.
|
|
|
1086
1260
|
Every message `src/browser` throws. Keep them distinct: a journey asserts the one it means, and
|
|
1087
1261
|
absent, present-but-gated, and ambiguous are different findings about an interface.
|
|
1088
1262
|
|
|
1089
|
-
| Voice | Thrown by
|
|
1090
|
-
| ---------------------------------------------------------------------------------------- |
|
|
1091
|
-
| `No interactive element has the accessible name "<name>"` | `resolveRendered`
|
|
1092
|
-
| `Interactive target "<name>" is not visible and focus-reachable` | `resolveRendered`
|
|
1093
|
-
| `Interactive target "<name>" is ambiguous across <n> elements` | `resolveRendered`
|
|
1094
|
-
| `Interactive target "<name>" could not be resolved` | `resolveRendered`
|
|
1095
|
-
| `Interactive target "<name>" is unreachable after scrolling` | `resolveAccessible`
|
|
1096
|
-
| `Interactive target "<name>" is not reachable inside "<region>"` | `resolveAccessibleWithin`
|
|
1097
|
-
| `Interactive target "<name>" is ambiguous across <n> elements inside "<region>"` | `resolveAccessibleWithin`
|
|
1098
|
-
| `Interactive target "<name>" could not be resolved inside "<region>"` | `resolveAccessibleWithin`
|
|
1099
|
-
| `Native disclosure "<name>" is not visible and focus-reachable` | `clickDisclosure`
|
|
1100
|
-
| `Native disclosure "<name>" is ambiguous across <n> elements` | `clickDisclosure`
|
|
1101
|
-
| `Native disclosure "<name>" could not be resolved` | `clickDisclosure`
|
|
1102
|
-
| `
|
|
1103
|
-
| `
|
|
1104
|
-
| `Named region "<name>" is
|
|
1105
|
-
| `Named region "<name>"
|
|
1106
|
-
| `
|
|
1107
|
-
| `
|
|
1108
|
-
| `Computed
|
|
1109
|
-
| `
|
|
1110
|
-
| `
|
|
1111
|
-
| `
|
|
1112
|
-
| `
|
|
1113
|
-
| `
|
|
1114
|
-
| `
|
|
1115
|
-
| `Capture frame at <path>
|
|
1116
|
-
| `Capture frame
|
|
1117
|
-
| `Capture frame at <path>
|
|
1118
|
-
| `Capture
|
|
1119
|
-
| `Capture
|
|
1120
|
-
| `Capture
|
|
1121
|
-
| `
|
|
1122
|
-
| `
|
|
1123
|
-
| `
|
|
1124
|
-
| `
|
|
1125
|
-
| `
|
|
1126
|
-
| `
|
|
1127
|
-
| `
|
|
1128
|
-
| `
|
|
1129
|
-
| `
|
|
1130
|
-
| `
|
|
1131
|
-
| `
|
|
1132
|
-
| `
|
|
1133
|
-
| `
|
|
1263
|
+
| Voice | Thrown by |
|
|
1264
|
+
| ---------------------------------------------------------------------------------------- | ---------------------------------------------- |
|
|
1265
|
+
| `No interactive element has the accessible name "<name>"` | `resolveRendered` |
|
|
1266
|
+
| `Interactive target "<name>" is not visible and focus-reachable` | `resolveRendered` |
|
|
1267
|
+
| `Interactive target "<name>" is ambiguous across <n> elements` | `resolveRendered` |
|
|
1268
|
+
| `Interactive target "<name>" could not be resolved` | `resolveRendered` |
|
|
1269
|
+
| `Interactive target "<name>" is unreachable after scrolling` | `resolveAccessible` |
|
|
1270
|
+
| `Interactive target "<name>" is not reachable inside "<region>"` | `resolveAccessibleWithin` |
|
|
1271
|
+
| `Interactive target "<name>" is ambiguous across <n> elements inside "<region>"` | `resolveAccessibleWithin` |
|
|
1272
|
+
| `Interactive target "<name>" could not be resolved inside "<region>"` | `resolveAccessibleWithin` |
|
|
1273
|
+
| `Native disclosure "<name>" is not visible and focus-reachable` | `clickDisclosure` |
|
|
1274
|
+
| `Native disclosure "<name>" is ambiguous across <n> elements` | `clickDisclosure` |
|
|
1275
|
+
| `Native disclosure "<name>" could not be resolved` | `clickDisclosure` |
|
|
1276
|
+
| `The element is not connected to a document, so it has no point to read` | `readProtocolPoint` |
|
|
1277
|
+
| `Interactive target "<name>" is not reachable through forward Tab traversal: <trail>` | `driveTraversal` |
|
|
1278
|
+
| `Named region "<name>" is not visible` | `readPerception` |
|
|
1279
|
+
| `Named region "<name>" is ambiguous across <n> elements` | `readPerception` |
|
|
1280
|
+
| `Named region "<name>" could not be resolved` | `readPerception` |
|
|
1281
|
+
| `Interactive target "<name>" does not carry a value` | `readValue` |
|
|
1282
|
+
| `Computed foreground color is unavailable` | `readContrast` |
|
|
1283
|
+
| `Computed background color is unavailable` | `readColorContrast` |
|
|
1284
|
+
| `Color "<value>" is unreadable` | `readColorContrast` |
|
|
1285
|
+
| `Contrast opacity must be between 0 and 1` | `readColorContrast` |
|
|
1286
|
+
| `The element is not connected to a document, so it has no clipping ancestors to read` | `collectClippingAncestors`, `readClippedBlock` |
|
|
1287
|
+
| `Tester pane is unavailable for a capture` | `stagePane` |
|
|
1288
|
+
| `Tester pane rendered <w>x<h> for a <w>x<h> viewport` | `stagePane` |
|
|
1289
|
+
| `Capture frame at <path> never settled after <n> restagings: <h> over a <h> pane` | `captureFrame` |
|
|
1290
|
+
| `Capture frame was written to <path> where <path> was asked for` | `captureFrame` |
|
|
1291
|
+
| `Capture frame at <path> is not the one this run shot` | `captureFrame` |
|
|
1292
|
+
| `Capture frame at <path> could not be read` | `readFrame` |
|
|
1293
|
+
| `Capture frame at <path> is not an image this browser decodes` | `readFrame` |
|
|
1294
|
+
| `Capture frame at <path> is not an image this browser decodes: <w>x<h> device pixels` | `readFrame` |
|
|
1295
|
+
| `Capture frame at <path> cannot be measured without a 2D canvas` | `readFrame` |
|
|
1296
|
+
| `Shot is not an image this browser decodes` | `readShotPixel` |
|
|
1297
|
+
| `Shot cannot be measured without a 2D canvas` | `readShotPixel` |
|
|
1298
|
+
| `Shot pixel position must be a fraction from 0 to 1` | `readShotPixel` |
|
|
1299
|
+
| `Capture variant "<name>" is not registered` | `createPortfolio` |
|
|
1300
|
+
| `Capture state "<state>" is not registered` | `place` |
|
|
1301
|
+
| `Capture state "<state>" is already placed` | `place` |
|
|
1302
|
+
| `IndexedDB database "<name>" could not be deleted` | `removeDatabase` |
|
|
1303
|
+
| `IndexedDB database "<name>" is blocked by an open connection` | `removeDatabase` |
|
|
1304
|
+
| `Key sequence "<keys>" was sent with nothing focused` | `pressKeys` |
|
|
1305
|
+
| `Focus sits in a frame from another origin, which cannot be read` | `readActiveElement` |
|
|
1306
|
+
| `Focus traversal did not end` | `walkFocus` |
|
|
1307
|
+
| `The start element cannot take focus` | `collectTabStops` |
|
|
1308
|
+
| `Stability frames must be a positive integer` | `waitForStability` |
|
|
1309
|
+
| `Condition "<description>" did not hold within <n>ms (waited <n>ms)` | `waitForStability` |
|
|
1310
|
+
| `Condition "<subject>" did not hold within <n>ms (waited <n>ms) (last states: <states>)` | `waitForState` |
|
|
1311
|
+
| `Animation subject is not connected` | `waitForAnimations` |
|
|
1312
|
+
| `Animation "<subject>" did not settle within <n>ms (waited <n>ms): <animations>` | `waitForAnimations` |
|
|
1313
|
+
| `Class census walked no element` | `readCensus` |
|
|
1314
|
+
| `Contrast control cannot straddle the bar <bar>` | `buildContrast` |
|
|
1315
|
+
| `Access is denied for <operation> "<key>"` | `buildDenial` |
|
|
1316
|
+
| `No room is left for <key>` | `createStorage` |
|
|
1317
|
+
| `Storage quota must be a non-negative integer` | `createStorage` |
|
|
1318
|
+
| `Statechart harness mounted no transition` | `createHarness` |
|
|
1319
|
+
| `Statechart harness carries no status` | `status` |
|
|
1320
|
+
|
|
1321
|
+
`readContrast` measures through `readColorContrast`, so its background refusal is that row's voice,
|
|
1322
|
+
and `readRing` never raises it, because it names `CANVAS_COLOR` as the floor on every reading.
|
|
1134
1323
|
|
|
1135
1324
|
Some of those rows are not plain `Error` messages. `buildDenial` returns a `DOMException` named
|
|
1136
1325
|
`SecurityError`, `createStorage` raises that one from every operation the permission withholds and a
|
|
@@ -1144,7 +1333,8 @@ states it last read, so an exhausted wait says what the control was announcing i
|
|
|
1144
1333
|
`waitForAnimations` names the subject through `readRole` and `readName` and lists the animations
|
|
1145
1334
|
still running. Both validate their bounds through `checkBounds`, which raises
|
|
1146
1335
|
`Wait budget must be finite and non-negative` for the first and `Animation budget must be finite and
|
|
1147
|
-
non-negative` for the second.
|
|
1336
|
+
non-negative` for the second. `settleCapture` raises the `waitForAnimations` voices unchanged, and
|
|
1337
|
+
because it waits on the document's root element, an exhausted settle names `html` as its subject.
|
|
1148
1338
|
|
|
1149
1339
|
Some of them are narrowing rather than findings, and no input reaches them. Each `could not be
|
|
1150
1340
|
resolved` is one: a preceding length check does not narrow the later lookup under
|
|
@@ -1162,27 +1352,39 @@ disk disagrees with the bytes the provider handed back — which a provider that
|
|
|
1162
1352
|
never produces, so the suite proves that comparison discriminates with a planted file rather than by
|
|
1163
1353
|
reaching the refusal. `Capture frame at <path> cannot be measured without a 2D canvas` is narrowing
|
|
1164
1354
|
of the same kind: a canvas allocated for this reading and asked for no other context type hands one
|
|
1165
|
-
back.
|
|
1355
|
+
back. `readShotPixel` carries the same pair for a shot the provider hands back rather than a file:
|
|
1356
|
+
`Shot cannot be measured without a 2D canvas` is that narrowing, and `Shot is not an image this
|
|
1357
|
+
browser decodes` fires only where the provider returns bytes that are not the image it shot. Both
|
|
1358
|
+
readers decode and draw through `paintImage`, which hands the decode failure and a missing context
|
|
1359
|
+
on to the caller to word, so the decode is driven there with bytes that are no image. The
|
|
1360
|
+
`Shot pixel position must be a fraction from 0 to 1` refusal is driven, by a fraction below `0`,
|
|
1361
|
+
above `1`, and `NaN`. The remaining refusals of the `readFrame` function are driven, by a path holding no file, by a
|
|
1166
1362
|
file holding no image, and by a PNG header over no image data, and so is
|
|
1167
1363
|
`Capture frame at <path> never settled after <n> restagings`, by a fixture whose full-height panel
|
|
1168
1364
|
grows with every pane the capture stages.
|
|
1169
1365
|
|
|
1170
1366
|
The pointer, pseudo-element, and media helpers add the following voices.
|
|
1171
1367
|
|
|
1172
|
-
| Voice | Thrown by
|
|
1173
|
-
| ------------------------------------------------------------- |
|
|
1174
|
-
| `Browser provider exposes no DevTools session` | `sendProtocol`
|
|
1175
|
-
| `Pointer is already held at <x>x<y>` | `driveHold`
|
|
1176
|
-
| `Interactive target "<name>" did not enter the pressed state` | `driveHold`
|
|
1177
|
-
| `
|
|
1178
|
-
| `
|
|
1179
|
-
| `
|
|
1180
|
-
| `
|
|
1181
|
-
| `
|
|
1368
|
+
| Voice | Thrown by |
|
|
1369
|
+
| ------------------------------------------------------------- | ------------------ |
|
|
1370
|
+
| `Browser provider exposes no DevTools session` | `sendProtocol` |
|
|
1371
|
+
| `Pointer is already held at <x>x<y>` | `driveHold` |
|
|
1372
|
+
| `Interactive target "<name>" did not enter the pressed state` | `driveHold` |
|
|
1373
|
+
| `Protocol search returned no search id` | `readProtocolNode` |
|
|
1374
|
+
| `Protocol search found <n> elements where one is required` | `readProtocolNode` |
|
|
1375
|
+
| `Protocol search returned no node id` | `readProtocolNode` |
|
|
1376
|
+
| `Pseudo-element "<pseudo>" must start with "::"` | `readStyle` |
|
|
1377
|
+
| `Pseudo-element "<pseudo>" is not one this engine exposes` | `readStyle` |
|
|
1378
|
+
| `Media emulation was staged with nothing to emulate` | `stageMedia` |
|
|
1379
|
+
| `Media emulation did not reach the tester: <query>` | `stageMedia` |
|
|
1380
|
+
| `Media emulation did not clear from the tester` | `releaseMedia` |
|
|
1182
1381
|
|
|
1183
1382
|
The resolver's absent, gated, ambiguous, and unreachable voices stay unchanged. The DevTools-session
|
|
1184
1383
|
and media-delivery refusals guard provider failures the managed Chromium suite doesn't induce.
|
|
1185
1384
|
The suite exercises real delivery rather than substituting a provider that manufactures a failure.
|
|
1385
|
+
`readAccessibilityNode` raises the `readProtocolNode` voices unchanged. Of those, `found <n>
|
|
1386
|
+
elements` is driven, by a detached element. The other two narrow a reply that omits `searchId` or
|
|
1387
|
+
`nodeIds`, which the browser never sends, so they guard a provider that does.
|
|
1186
1388
|
|
|
1187
1389
|
### Refusals outside the journey layer
|
|
1188
1390
|
|
|
@@ -1404,8 +1606,9 @@ These hold across `src/core`, `src/browser`, `src/server`, and this guide.
|
|
|
1404
1606
|
predicates, the element readers, and the describers do take a node —
|
|
1405
1607
|
`isRendered`, `isReachable`, `readHit`, `readText`, `readRole`, `readName`, `readStates`,
|
|
1406
1608
|
`readCensus`, `describeTree`, `describeFocus`, `extractOrphans`, `readRows`, `readStyle`,
|
|
1407
|
-
`readToken`, `readPixels`, `readContrast`, `readLayers`, `readBackdrop`,
|
|
1408
|
-
each is a reader of a node the caller already has rather than a verb that
|
|
1609
|
+
`readToken`, `readPixels`, `readContrast`, `readColorContrast`, `readLayers`, `readBackdrop`,
|
|
1610
|
+
and `readRing` — and each is a reader of a node the caller already has rather than a verb that
|
|
1611
|
+
acts on a target.
|
|
1409
1612
|
`waitForAnimations` takes one as the subject of a wait, and waiting for a browser to stop
|
|
1410
1613
|
painting it changes nothing about it. `buildContrast`, `buildEscapes`, and `buildCensus` return
|
|
1411
1614
|
detached nodes for the caller to append and remove, the way `build` does. `captureFrame`
|
|
@@ -1526,7 +1729,8 @@ These hold across `src/core`, `src/browser`, `src/server`, and this guide.
|
|
|
1526
1729
|
the one before it produced so a converging document lands on its fixed point rather than
|
|
1527
1730
|
creeping toward it. The re-reading is bounded by `CAPTURE_STAGINGS`, and a document still
|
|
1528
1731
|
growing at that bound is refused rather than photographed at a stale height. An element frame
|
|
1529
|
-
keeps the declared pane unless its element
|
|
1732
|
+
keeps the declared pane unless its element needs more room with its native scroll clearance,
|
|
1733
|
+
and offsets the calling tester frame only
|
|
1530
1734
|
as far as brings the element inside the runner's window. What
|
|
1531
1735
|
the capture borrows it gives back: the `releasePane` function returns the tester to the viewport
|
|
1532
1736
|
it held before the staging, the capture then restores the tester's scroll position, even where
|
|
@@ -1553,6 +1757,13 @@ These hold across `src/core`, `src/browser`, `src/server`, and this guide.
|
|
|
1553
1757
|
still read `running` would strand the gate on a reading the harness never leaves. The gate stays
|
|
1554
1758
|
outside this package: the harness carries its own tally, so nothing here reads a harness back,
|
|
1555
1759
|
and no page is generated or published to host one.
|
|
1760
|
+
20. **Sheet adoption releases only its own stylesheet.** Repeated release leaves other adoptions
|
|
1761
|
+
intact. [`tests/src/browser/sheets/helpers.test.ts`](../tests/src/browser/sheets/helpers.test.ts)
|
|
1762
|
+
proves independent adoptions and repeated release.
|
|
1763
|
+
21. **File drags carry trusted `Files` events to rendered targets.** A destination need not be
|
|
1764
|
+
focusable. The file-drag cases in
|
|
1765
|
+
[`tests/src/browser/journeys/helpers.test.ts`](../tests/src/browser/journeys/helpers.test.ts)
|
|
1766
|
+
prove trusted entry, over, and leave events over a status outside the Tab order.
|
|
1556
1767
|
|
|
1557
1768
|
### Threat model
|
|
1558
1769
|
|
|
@@ -1706,16 +1917,56 @@ the helper rather than to the host, and each names what to reach for instead.
|
|
|
1706
1917
|
used; it is covered by review. The measured layout is a single accessible, uniformly scaled tester
|
|
1707
1918
|
iframe. A covered centre or unsupported geometry can refuse even when the resolver accepts the
|
|
1708
1919
|
target. The verb inherits the resolver's focus reachability conditions.
|
|
1920
|
+
- **`parkPointer` ends hover and never ends a press.** It moves the pointer to (-1, -1) and waits for
|
|
1921
|
+
a frame, and it sends no button-up, so a press that the `holdAccessible` verb holds stays recorded under
|
|
1922
|
+
`POINTER_HOLD` and its button-up is still owed to `releasePointer`. The control the press was on
|
|
1923
|
+
loses both its `:hover` paint and its `:active` paint when the pointer leaves it. Use it where a case clears hover with no
|
|
1924
|
+
press held, and never as a teardown for a hold.
|
|
1709
1925
|
- **`releasePointer` parks the pointer outside the page.** It releases at the recorded point first,
|
|
1710
|
-
which can produce a click. It then clears hover
|
|
1711
|
-
coordinates, one pixel above and to the left of that page's viewport. The
|
|
1712
|
-
nothing outside the viewport, so no element takes a `mouseover` event or hover
|
|
1713
|
-
parked pointer until the next pointer verb. This holds even where a staging,
|
|
1714
|
-
lays content over the park point. Register it with `afterEach` before a hover
|
|
1926
|
+
which can produce a click. It then clears hover through `parkPointer`, which moves to (-1, -1) in
|
|
1927
|
+
the runner page's coordinates, one pixel above and to the left of that page's viewport. The
|
|
1928
|
+
browser hit-tests nothing outside the viewport, so no element takes a `mouseover` event or hover
|
|
1929
|
+
paint from the parked pointer until the next pointer verb. This holds even where a staging,
|
|
1930
|
+
scroll, or offset lays content over the park point. Register it with `afterEach` before a hover
|
|
1715
1931
|
or hold. A second release sends no button-up event. Holds must not overlap. A rejected press
|
|
1716
1932
|
leaves no marker. A rejected release keeps the marker for a retry and still attempts the park. If
|
|
1717
1933
|
that park also rejects, the park's error surfaces with the release rejection attached in the
|
|
1718
1934
|
aggregate's errors; the park rejection is its cause.
|
|
1935
|
+
- **`walkFocus` reports every stop it can read and refuses none of them.** It records the focused
|
|
1936
|
+
element and then presses Tab through `stepFocus`, the one Tab loop that `driveTraversal` shares,
|
|
1937
|
+
and returns what focus reached, so a focusable scroll container that Chromium focuses without a
|
|
1938
|
+
`tabindex` is a stop, and `describeFocus` omits it. Each stop is the innermost element
|
|
1939
|
+
`readActiveElement` reads, so a control inside an open shadow root or a same-origin frame is a stop
|
|
1940
|
+
of its own and its host or frame element is not. A non-HTML control inside one, such as an SVG
|
|
1941
|
+
element, reads as `undefined` rather than as its host, and `readFocus` follows it. A closed shadow root cannot be entered, so its
|
|
1942
|
+
host stands for what it holds, and focus in a frame from another origin throws, because the page
|
|
1943
|
+
cannot name a control there. A hidden or disabled stop is returned like any other. A consumer that
|
|
1944
|
+
refuses one throws from the predicate it passes. The walk ends where focus returns to the body or
|
|
1945
|
+
revisits a stop, and throws only when it outlasts the count `countElements` reads, which includes
|
|
1946
|
+
open shadow roots and same-origin frames. A control inside a same-origin frame belongs to the
|
|
1947
|
+
frame's window, so it fails this window's `instanceof HTMLElement`. `collectTabStops` is the same
|
|
1948
|
+
walk bounded to a region by `containsNode`, which places a control inside an open shadow root or a
|
|
1949
|
+
same-origin frame in the region that holds its host or frame element. The start element is the
|
|
1950
|
+
walk's origin and never its end, so a start immediately before the region, outside it, reaches the
|
|
1951
|
+
region's first stop with the first press.
|
|
1952
|
+
- **`waitForStability` compares the last `frames + 1` reads.** The first read is immediate and each
|
|
1953
|
+
later read follows a painted frame, with the interval slept between polls, so the reads are not on
|
|
1954
|
+
consecutive frames when the interval is longer than one. A reading that settles on read `n`
|
|
1955
|
+
resolves on read `n + frames`. The default is four frames; the budget and interval are those of
|
|
1956
|
+
`waitForCondition`. A reading that changes on every read exhausts the budget, and the refusal names
|
|
1957
|
+
the description. The budget and the abort signal are checked between reads, so a frame that never
|
|
1958
|
+
paints is not bounded by either. The `releaseMedia` function with nothing staged waits through it
|
|
1959
|
+
for one frame.
|
|
1960
|
+
- **`settleCapture` holds endless animations until its resume runs.** It parks the pointer through
|
|
1961
|
+
`parkPointer`, so a held press stays held and only loses its hover and pressed paint; `pointer: false`
|
|
1962
|
+
leaves the pointer, its hover, and that paint where they are. It waits out every finite animation
|
|
1963
|
+
in the document, root element included, then pauses each endless one at its first frame and
|
|
1964
|
+
resolves to the resume. Call the resume from a `finally` block once the frame is shot. A settle
|
|
1965
|
+
whose wait exhausts throws before it holds anything, so it owes no resume.
|
|
1966
|
+
- **`readShotPixel` reads a shot at the runner's scale.** The position is a fraction of the shot,
|
|
1967
|
+
and a fraction of `1` reads its last row or column. Where the runner scales the tester, the shot's
|
|
1968
|
+
edge pixels can blend with what lies beside the element, so read a pixel inside a painted band rather
|
|
1969
|
+
than on its edge.
|
|
1719
1970
|
- **`stageMedia` overrides the provider page, and `releaseMedia` restores the first stage's
|
|
1720
1971
|
readings.** Pin a base with `{ motion: true }` rather than assuming the host prefers motion.
|
|
1721
1972
|
`motion: false` stages reduced motion; `print: true` stages print, and `print: false` stages
|
|
@@ -1724,28 +1975,70 @@ the helper rather than to the host, and each names what to reach for instead.
|
|
|
1724
1975
|
other emulated feature the provider configured is cleared. An empty `{}`
|
|
1725
1976
|
refuses. Each staged query has a 1000 ms read-back budget with a 10 ms poll interval; refusal
|
|
1726
1977
|
restores the carried pre-call readings before throwing and can take two budgets. A restoration
|
|
1727
|
-
failure is attached as the refusal's cause. The
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1978
|
+
failure is attached as the refusal's cause. The pointer refusal proof passes an unsupported runtime
|
|
1979
|
+
pointer value through the JavaScript boundary and checks restoration after read-back exhaustion.
|
|
1980
|
+
The first stage records print, reduced motion, dark colour scheme, and forced colours on the
|
|
1981
|
+
tester root under `MEDIA_STAGE`, as a bit string in that order (`1` for a match, `0` otherwise).
|
|
1982
|
+
The first pointer stage appends a fifth bit for the pre-call coarse-pointer reading; later pointer
|
|
1983
|
+
stages retain it. A stage without a pointer keeps the four-bit marker until a pointer stage occurs.
|
|
1984
|
+
Release restores those readings as explicit emulation rather than removing every override, waits
|
|
1985
|
+
per axis for its recorded value, and removes the marker. A release whose wait exhausts keeps
|
|
1986
|
+
`MEDIA_STAGE` on the tester root, so the next `releaseMedia` retries from the same recorded
|
|
1987
|
+
readings. A release with nothing staged clears media overrides and compares readings taken
|
|
1988
|
+
strictly after the reset until they are stable.
|
|
1736
1989
|
Stability doesn't prove the engine's own baseline. Each release read-back has a 1000 ms budget and
|
|
1737
1990
|
waits for a frame per poll, with 10 ms between polls. The budget is checked between polls, so a
|
|
1738
1991
|
frame that never paints is not bounded by it. Media scopes must not overlap. The browser project
|
|
1739
1992
|
runs files serially.
|
|
1993
|
+
- **Pointer emulation also changes hover.** `pointer: 'coarse'` enables touch emulation with one
|
|
1994
|
+
touch point and reads `(pointer: coarse)`, `(any-pointer: coarse)`, `(hover: none)`, and
|
|
1995
|
+
`(any-hover: none)`. `pointer: 'fine'` disables touch emulation and reads fine precision with
|
|
1996
|
+
hover support. A pointer stage and its release preserve precision, not an earlier maximum
|
|
1997
|
+
touch-point count. Staging and releasing media without a pointer axis sends no touch-emulation
|
|
1998
|
+
command, including an unstaged release.
|
|
1999
|
+
- **Touch input requires a Chromium protocol session.** `tapTouch` enables touch emulation, waits
|
|
2000
|
+
for the touch layout's box to settle, then sends a single-point start and end. It does not scroll
|
|
2001
|
+
or check focus reachability. A tap that
|
|
2002
|
+
stops a scroller's momentum can produce no click. `releaseTouch` tolerates Chromium's idle
|
|
2003
|
+
cancellation refusal, disables emulation, and parks without sending a mouse release. Parking
|
|
2004
|
+
does not prove that sticky touch hover cleared. A native drag holding the mouse needs its own
|
|
2005
|
+
`mouseReleased` protocol command before parking. Touch cleanup also disables a coarse pointer
|
|
2006
|
+
staged by `stageMedia`, leaving `(pointer: fine)` while `MEDIA_STAGE` stays unchanged. Stage
|
|
2007
|
+
`pointer: 'coarse'` again after cleanup when later steps need it. `releaseMedia` still restores
|
|
2008
|
+
the reading recorded before the first pointer stage. A first pointer stage while tap emulation
|
|
2009
|
+
is live records coarse. In teardown, call `releaseMedia` before `releaseTouch`. The reverse
|
|
2010
|
+
order restores coarse emulation with one touch point after touch cleanup.
|
|
2011
|
+
- **File cancellation must leave the target first.** Chromium raises no `dragleave` for protocol
|
|
2012
|
+
cancellation alone. `sendFileDrag` first moves outside the page. It writes named fixture files
|
|
2013
|
+
under `tmp/drag`, refuses names containing a path, and sends no drop or file-content delivery.
|
|
2014
|
+
- **Layer names follow declaration order at every depth.** `readLayerNames` descends through
|
|
2015
|
+
grouping and style rules, qualifying each statement and block by its enclosing layer. It includes
|
|
2016
|
+
anonymous layers and repeated names, and reads conditions whether or not they match the document.
|
|
2017
|
+
An anonymous nested layer contributes a trailing dot to its enclosing qualified name.
|
|
2018
|
+
An `@import ... layer()` rule contributes nothing, and neither do its imported sheet's rules.
|
|
2019
|
+
A dotted declaration such as `@layer a.b` contributes `a.b` as declared, without an implicit `a`.
|
|
2020
|
+
Distinct anonymous layers produce the same names; the result does not distinguish their identities.
|
|
1740
2021
|
- **`readStyle` refuses a pseudo argument rather than ignoring it.** The argument must start with
|
|
1741
2022
|
`::` before the engine's selector-support check runs. A supported pseudo-element with no value for
|
|
1742
2023
|
the requested property still reads as an empty string. `readPixels` uses the same guard.
|
|
1743
2024
|
- **`sendProtocol` reaches a Chromium-family provider alone.** It needs the provider's DevTools
|
|
1744
|
-
session, passes the named command and parameters through, and
|
|
1745
|
-
|
|
2025
|
+
session, passes the named command and parameters through, and resolves the reply as `unknown`.
|
|
2026
|
+
Narrow the reply with guards before reading a field, and omit the parameters for a command that
|
|
2027
|
+
takes none. Browser termination cannot promise cleanup. Edge observations belong to a separate run.
|
|
2028
|
+
It resolves the reply since 0.0.27, where 0.0.26 resolved nothing. A callback typed to return
|
|
2029
|
+
`void | Promise<void>`, such as a teardown or an `onTestFinished` hook, that returns
|
|
2030
|
+
`sendProtocol(…)` directly no longer type-checks. Write `async () => { await sendProtocol(…) }`.
|
|
2031
|
+
- **`readProtocolPoint` reads the layout now, and `readProtocolNode` hands back an id to use at
|
|
2032
|
+
once.** The point is the layout at the call, so a box that moves afterwards moves the point it
|
|
2033
|
+
named. Each frame on the way up adds its border and its padding, because its content starts inside
|
|
2034
|
+
both. An element no document holds is refused, because its window still names the tester frame and
|
|
2035
|
+
the call would otherwise answer that frame's corner. A node id comes from a document the browser is asked for afresh on every call, so use it
|
|
2036
|
+
before the next call. Both leave `readHit` its own question, which is what the element's own
|
|
2037
|
+
document hit-tests at the centre and never leaves that document.
|
|
1746
2038
|
- **`parseCSSColor` resolves an undeclared token to the inherited color.** A `var()` naming a custom
|
|
1747
2039
|
property nothing declares is not a parse failure: the cascade accepts it and computes the
|
|
1748
|
-
inherited color,
|
|
2040
|
+
inherited color, which is the body's, or the `scope` element's with one, so
|
|
2041
|
+
`parseCSSColor('var(--absent)')` hands back channels rather than `undefined`.
|
|
1749
2042
|
Read `readToken` or `readRootToken` where a missing token is the subject.
|
|
1750
2043
|
- **`createLoopback` cannot take back an upgraded socket.** A server that claims an upgrade keeps
|
|
1751
2044
|
that connection, detached from the server itself, so `destroy()`'s `closeAllConnections` never
|
|
@@ -2273,7 +2566,7 @@ browser suite runs. It is a native disclosure with two doors: the summary toggle
|
|
|
2273
2566
|
button closes it and does nothing when it is already closed. That second door is what gives the
|
|
2274
2567
|
table a row whose event leaves the state where it found it, which a lone `<details>` cannot have —
|
|
2275
2568
|
its one event always flips. Every value these fences claim is pinned in
|
|
2276
|
-
`tests/src/browser/factories.test.ts`, because the fences drive a browser and the `guides` project
|
|
2569
|
+
`tests/src/browser/journeys/factories.test.ts`, because the fences drive a browser and the `guides` project
|
|
2277
2570
|
runs with the browser disabled.
|
|
2278
2571
|
|
|
2279
2572
|
The phases are module functions the whole table shares, which is the shape a table of any size
|
|
@@ -2547,11 +2840,11 @@ Object.keys(
|
|
|
2547
2840
|
// 'src/core/types.ts', 'src/core/validators.ts']
|
|
2548
2841
|
|
|
2549
2842
|
// A directory key takes every key below it.
|
|
2550
|
-
Object.keys(
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
//
|
|
2554
|
-
// 'src/core/validators.ts']
|
|
2843
|
+
Object.keys(
|
|
2844
|
+
readInventory(root, ['src'], { extensions: ['.ts'], exclude: ['src/server', 'src/browser'] }),
|
|
2845
|
+
)
|
|
2846
|
+
// ['src/core/constants.ts', 'src/core/factories.ts', 'src/core/helpers.ts', 'src/core/index.ts',
|
|
2847
|
+
// 'src/core/types.ts', 'src/core/validators.ts']
|
|
2555
2848
|
|
|
2556
2849
|
// An exclusion also applies to a target you name, so naming one file below an excluded directory
|
|
2557
2850
|
// does not reinstate it.
|
|
@@ -2907,6 +3200,41 @@ await traverseAccessible('Evaluate')
|
|
|
2907
3200
|
readPerception('Run') // one visible named region, whitespace collapsed, hidden-but-read text kept
|
|
2908
3201
|
```
|
|
2909
3202
|
|
|
3203
|
+
#### Tap with one touch
|
|
3204
|
+
|
|
3205
|
+
Resolve the element the fixture supplies, then release touch emulation in cleanup.
|
|
3206
|
+
|
|
3207
|
+
```ts
|
|
3208
|
+
import { releaseTouch, resolveRendered, tapTouch } from '@orkestrel/test/browser'
|
|
3209
|
+
|
|
3210
|
+
try {
|
|
3211
|
+
await tapTouch(resolveRendered('Tap target'))
|
|
3212
|
+
} finally {
|
|
3213
|
+
await releaseTouch()
|
|
3214
|
+
}
|
|
3215
|
+
```
|
|
3216
|
+
|
|
3217
|
+
The browser proof records one trusted touch click and no click on the sibling control.
|
|
3218
|
+
Pass a trailing stability-options object when the fixture needs a longer settling budget.
|
|
3219
|
+
|
|
3220
|
+
#### Drag files from outside the page
|
|
3221
|
+
|
|
3222
|
+
A rendered status receives the drag even when it is absent from the Tab order.
|
|
3223
|
+
|
|
3224
|
+
```ts
|
|
3225
|
+
import { sendFileDrag } from '@orkestrel/test/browser'
|
|
3226
|
+
|
|
3227
|
+
await sendFileDrag('dragEnter', 'status', 'Drop status', ['note.txt'])
|
|
3228
|
+
try {
|
|
3229
|
+
await sendFileDrag('dragOver', 'status', 'Drop status', ['note.txt'])
|
|
3230
|
+
} finally {
|
|
3231
|
+
await sendFileDrag('dragCancel', 'status', 'Drop status', ['note.txt'])
|
|
3232
|
+
}
|
|
3233
|
+
```
|
|
3234
|
+
|
|
3235
|
+
The browser proof observes trusted entry, over, and leave events carrying the `Files` type.
|
|
3236
|
+
No drop occurs; fixture files remain under `tmp/drag` for the caller to remove.
|
|
3237
|
+
|
|
2910
3238
|
### Hold a control and read the pressed paint
|
|
2911
3239
|
|
|
2912
3240
|
Register pointer cleanup before a test can fail. This fixture declares `padding-top: 16px` on its
|
|
@@ -2982,6 +3310,21 @@ matchMedia('(prefers-reduced-motion: reduce)').matches === reduced // true
|
|
|
2982
3310
|
readPixels(button, 'padding-top') === (reduced ? 2 : 1) // true
|
|
2983
3311
|
```
|
|
2984
3312
|
|
|
3313
|
+
Pointer precision uses touch emulation. These readings are proved in the browser media cases.
|
|
3314
|
+
|
|
3315
|
+
```ts
|
|
3316
|
+
import { releaseMedia, stageMedia } from '@orkestrel/test/browser'
|
|
3317
|
+
|
|
3318
|
+
await stageMedia({ pointer: 'coarse' })
|
|
3319
|
+
matchMedia('(pointer: coarse)').matches // true
|
|
3320
|
+
matchMedia('(any-pointer: coarse)').matches // true
|
|
3321
|
+
matchMedia('(hover: none)').matches // true
|
|
3322
|
+
await stageMedia({ pointer: 'fine' })
|
|
3323
|
+
matchMedia('(pointer: fine)').matches // true
|
|
3324
|
+
matchMedia('(hover: hover)').matches // true
|
|
3325
|
+
await releaseMedia()
|
|
3326
|
+
```
|
|
3327
|
+
|
|
2985
3328
|
### Send a key to what holds focus
|
|
2986
3329
|
|
|
2987
3330
|
Bring focus about through a verb, then send the sequence. A key sent while the document body holds
|
|
@@ -3452,6 +3795,16 @@ await portfolio.place('start-empty')
|
|
|
3452
3795
|
portfolio.place('answer-partial') // rejects: Capture state "answer-partial" is not registered
|
|
3453
3796
|
```
|
|
3454
3797
|
|
|
3798
|
+
Settle the page before each frame of a capture run. `settleCapture` parks the pointer, waits out
|
|
3799
|
+
every finite animation in the document, and holds each endless one at its first frame, so a hover,
|
|
3800
|
+
a transition caught part way, and a spinner's phase stay out of the picture. It resolves to the
|
|
3801
|
+
resume; call `place` after it, and call the resume from a `finally` block, so the held animations
|
|
3802
|
+
run again whether or not the frame was written. Pass `pointer: false` where the pointer is part of
|
|
3803
|
+
the state, such as a drag in flight. Gate the settle on the flag that `enabled` takes: an ordinary run's
|
|
3804
|
+
`place` shoots nothing, and parking the pointer there changes the journey that run is proving.
|
|
3805
|
+
Where a frame holds a scroll region, record `describeScrollRegions` of what `collectScrollRegions`
|
|
3806
|
+
finds beside it, because a picture does not show how far a pane scrolls.
|
|
3807
|
+
|
|
3455
3808
|
### Measure a document's content edge
|
|
3456
3809
|
|
|
3457
3810
|
A capture stages the pane at the height the document needs, and the body's box cannot answer for
|
|
@@ -3557,7 +3910,11 @@ Each entry names the contracts its file proves. The test names carry the cases.
|
|
|
3557
3910
|
carrying both the arrival and the departure that `absent` waits past, an empty expectation and an
|
|
3558
3911
|
empty departure each refused, a reader throw propagated unchanged, the timeout naming the wait and
|
|
3559
3912
|
the budget, an abort rejecting with the signal's own reason, and a refused bound raised through the
|
|
3560
|
-
family. `
|
|
3913
|
+
family. `collectSelectorClasses` takes a selector list whose functional pseudo-classes nest class
|
|
3914
|
+
names beside an attribute block, quoted strings, and a comment that name none, every escape form
|
|
3915
|
+
decoded with the out-of-range points read as the replacement character, names opening with an
|
|
3916
|
+
underscore, a hyphen, two hyphens, and a non-ASCII letter, the empty selector, and each unreadable
|
|
3917
|
+
text refused by name. `decodeJSONLines` takes empty input, a trailing newline, CRLF,
|
|
3561
3918
|
line order, primitive lines, and a malformed physical line named with the native `SyntaxError` as
|
|
3562
3919
|
its cause. `collect` and `collectStream` drain an empty and an ordered source, and the stream's
|
|
3563
3920
|
reader lock is released afterwards. `roundTripJSON` takes a copy of a flat and a nested
|
|
@@ -3589,9 +3946,22 @@ Each entry names the contracts its file proves. The test names carry the cases.
|
|
|
3589
3946
|
that is called empty and called twice. `createHostileValues` proves a naive-reader failure for
|
|
3590
3947
|
every member, frozen and fresh membership, and one total guard's benign and hostile answers with
|
|
3591
3948
|
loop-index attribution.
|
|
3592
|
-
- [`tests/src/browser/helpers.test.ts`](../tests/src/browser/helpers.test.ts)
|
|
3593
|
-
|
|
3594
|
-
|
|
3949
|
+
- [`tests/src/browser/helpers.test.ts`](../tests/src/browser/helpers.test.ts),
|
|
3950
|
+
[`tests/src/browser/journeys/helpers.test.ts`](../tests/src/browser/journeys/helpers.test.ts),
|
|
3951
|
+
[`tests/src/browser/captures/helpers.test.ts`](../tests/src/browser/captures/helpers.test.ts),
|
|
3952
|
+
[`tests/src/browser/colors/helpers.test.ts`](../tests/src/browser/colors/helpers.test.ts), and
|
|
3953
|
+
[`tests/src/browser/sheets/helpers.test.ts`](../tests/src/browser/sheets/helpers.test.ts) — the
|
|
3954
|
+
journey-layer, role-map, and announced-half-and-clickable-half contracts across the layer, in real Chromium
|
|
3955
|
+
against constructed markup. The touch proofs cover a pointer-dependent target beside a sibling,
|
|
3956
|
+
a target moving across painted frames before settling, a supplied stability budget that refuses
|
|
3957
|
+
the tap, and both orders of media and touch teardown. The pointer proof restores the first coarse
|
|
3958
|
+
reading after fine then coarse staging. The file-drag proofs reach a target under a smooth root
|
|
3959
|
+
and refuse a file name without scrolling or writing any file in the batch. The `releaseTouch`
|
|
3960
|
+
rethrow of a non-idle protocol error is covered by review: its cancellation parameters are fixed,
|
|
3961
|
+
and no controllable non-idle refusal was found through the browser provider without replacing
|
|
3962
|
+
its transport or disrupting the tester session. A provider with a recoverable protocol-failure
|
|
3963
|
+
seam would let a proof drive that branch.
|
|
3964
|
+
The resolver takes a bare name, a
|
|
3595
3965
|
role that disambiguates a tab from its own panel, a name no element carries, a name carried only by
|
|
3596
3966
|
a role outside `ACCESSIBLE_ROLES`, and the disabled, hidden, and inert matches that are present but
|
|
3597
3967
|
gated. It takes the glyph cases against a fixture stylesheet that really paints one: an exact name
|
|
@@ -3623,7 +3993,17 @@ Each entry names the contracts its file proves. The test names carry the cases.
|
|
|
3623
3993
|
reading, and a refused bound. `waitForAnimations` takes a descendant transition awaited to its end,
|
|
3624
3994
|
the exhaustion naming the subject and the animation still running, an infinite-iteration animation
|
|
3625
3995
|
excluded while it is still turning, a detached subject refused, and a refused bound; its settled
|
|
3626
|
-
reading is compared against the interpolated one taken mid-transition. `
|
|
3996
|
+
reading is compared against the interpolated one taken mid-transition. `readAnimations` takes a
|
|
3997
|
+
running transition and a running infinite animation split apart, a paused animation and one
|
|
3998
|
+
outside the subject left out, and a detached element read as two empty lists. `settleCapture`
|
|
3999
|
+
takes a hovered control's transition waited out and a spinner held at its first frame until the
|
|
4000
|
+
resume sets it running, a held press whose hover and pressed paint `pointer: false` leaves in
|
|
4001
|
+
place beside the default park that takes both away, and an exhausted wait refused with nothing
|
|
4002
|
+
held. `collectScrollRegions` takes a vertical and a horizontal scroller beside a box whose content
|
|
4003
|
+
fits, a clipping box, and a hidden one, each axis alone, and a scrolling root counted itself;
|
|
4004
|
+
`describeScrollRegions` takes a region named by its tag, its id, and its cut accessible name with
|
|
4005
|
+
its offsets after a scroll, the window's position after a scroll, and an empty population.
|
|
4006
|
+
`readRefusal` takes the
|
|
3627
4007
|
absent, gated, and ambiguous voices beside a target that resolves under a bare name and under a
|
|
3628
4008
|
role, and — as the control for the rethrow — a fixture element whose own `tabIndex` getter refuses
|
|
3629
4009
|
with a string, handed straight back. `readCensus` takes a population carrying both undeclared
|
|
@@ -3650,8 +4030,23 @@ Each entry names the contracts its file proves. The test names carry the cases.
|
|
|
3650
4030
|
region an `aria-hidden` attribute withholds, and its not-visible and ambiguous refusals, `readPage`
|
|
3651
4031
|
the whole page as one
|
|
3652
4032
|
normalized sentence, and
|
|
3653
|
-
`readFocus` a focused control's rendered text, a focused element that renders none,
|
|
3654
|
-
|
|
4033
|
+
`readFocus` a focused control's rendered text, a focused element that renders none, an SVG element
|
|
4034
|
+
focused inside an open shadow root that reads nothing rather than its host's text, a host holding
|
|
4035
|
+
focus with nothing inside, and nothing holding focus at all; `readValue` takes a rendered value
|
|
4036
|
+
and a control carrying none. The focus
|
|
4037
|
+
walk takes its inputs across each boundary: `readActiveElement` takes the page's focused control,
|
|
4038
|
+
focus inside an open shadow root and through nested ones, an SVG element focused inside one that
|
|
4039
|
+
answers nothing rather than its host, a host holding focus with nothing inside
|
|
4040
|
+
and one with a closed root, a control inside a same-origin frame typed for the frame's window, a
|
|
4041
|
+
frame holding focus with nothing inside, and a frame from another origin refused;
|
|
4042
|
+
`countElements` takes the shadow and frame content a plain query misses; `containsNode` takes a
|
|
4043
|
+
region's own content, a shadow root's and a frame's, and a detached node left outside;
|
|
4044
|
+
`stepFocus` takes one press per landing, none past the consumer's last read, a limit of zero, and
|
|
4045
|
+
a landing on nothing. `walkFocus` and `collectTabStops` take the buttons of an open shadow root
|
|
4046
|
+
and of a same-origin frame between two light controls, a start element inside a shadow root, a
|
|
4047
|
+
start element immediately before the region that reaches the region's first stop, and
|
|
4048
|
+
focus in a foreign frame refused; `readProtocolPoint` takes a padded frame beside a bordered one,
|
|
4049
|
+
both hit-tested through the protocol, and a disconnected element refused. The element
|
|
3655
4050
|
readers follow: `readText` takes an `aria-hidden` glyph dropped with the runs around it collapsed
|
|
3656
4051
|
and an element with no text at all; `readRole` takes exactly the tags `IMPLICIT_ROLES` carries and
|
|
3657
4052
|
one it leaves out, a declared role taken over the implicit one, a section made a region only by
|
|
@@ -3676,7 +4071,12 @@ Each entry names the contracts its file proves. The test names carry the cases.
|
|
|
3676
4071
|
nothing paints and one whose every painted layer is translucent, a stack 64 translucent layers
|
|
3677
4072
|
deep whose composite has rounded to the canvas's own channels, a detached element whose computed
|
|
3678
4073
|
foreground does not exist, and the same unpainted and translucent stacks measured against a
|
|
3679
|
-
supplied floor instead of refused.
|
|
4074
|
+
supplied floor instead of refused. `readColorContrast` takes the ceiling, the floor, a clear
|
|
4075
|
+
color, and a half-opaque one over an opaque surface, a keyword and a `var()` reference resolved
|
|
4076
|
+
through the cascade, a translucent and an unpainted stack refused until a floor is named and then
|
|
4077
|
+
composited onto it, an `opacity` reading equal to the declared alpha it multiplies with the
|
|
4078
|
+
refused factors beside it, and an unreadable color and an unreadable painted layer each refused.
|
|
4079
|
+
The color leaves beneath it take their own inputs: `parseColor`
|
|
3680
4080
|
across the legacy and modern syntaxes, a refused keyword, hex triple, empty value, and unsupported
|
|
3681
4081
|
color space, and — as the control the literals cannot supply — what this browser actually computes
|
|
3682
4082
|
for a keyword and for a `color-mix()`. `blendColor`, `measureLuminance`, and `measureContrast`
|
|
@@ -3687,7 +4087,8 @@ Each entry names the contracts its file proves. The test names carry the cases.
|
|
|
3687
4087
|
composited onto it, and an opaque layer that ends the walk. `readRing` takes a painted outline and
|
|
3688
4088
|
a painted box-shadow reached through `traverseAccessible`, a control that is not focused, a
|
|
3689
4089
|
focused control left the browser's own ring, a focus style that only repaints the control's fill,
|
|
3690
|
-
|
|
4090
|
+
a `worn` element whose reading separates from the control's own, and an unpainted focused control
|
|
4091
|
+
over an unreadable surface that is refused. `measureContent` takes a
|
|
3691
4092
|
1600-row document read under an 844 pane and under a 2356 one, against the scroll height that
|
|
3692
4093
|
agrees with it under the shorter pane and stretches to the pane under the taller, and a document
|
|
3693
4094
|
whose last element carries a bottom margin under a body carrying bottom padding, where a reading
|
|
@@ -3717,7 +4118,10 @@ Each entry names the contracts its file proves. The test names carry the cases.
|
|
|
3717
4118
|
height on the panel's own color with the scroll handed back; an element below both the pane and
|
|
3718
4119
|
the window, whole on the document's floor with the scroll handed back; a `50vh` element and a
|
|
3719
4120
|
`30vh` element below the fold, at the declared pane rather than a grown one; an element taller
|
|
3720
|
-
than the pane, in a pane of its own height;
|
|
4121
|
+
than the pane, in a pane of its own height; tall and near-viewport elements below authored native
|
|
4122
|
+
clearance, with decoded heading pixels distinguishing them from an undeclared sticky obstruction;
|
|
4123
|
+
a fixed element beyond a padded viewport that keeps its declared viewport height;
|
|
4124
|
+
an element that outgrows every pane, refused with the
|
|
3721
4125
|
pane and the scroll handed back; a second tester frame the offset leaves in place; and a frame
|
|
3722
4126
|
carrying no `style` attribute, handed back without one. After the `releasePointer` function, an
|
|
3723
4127
|
element frame takes no `mouseover` event for an element inside the window, which also takes no `scroll` event;
|
|
@@ -3736,8 +4140,31 @@ Each entry names the contracts its file proves. The test names carry the cases.
|
|
|
3736
4140
|
frame's size and floor, read a second way through the cascade's own answer for the same canvas, a
|
|
3737
4141
|
bottom row split between two colors reported as no floor at all, a path holding no file,
|
|
3738
4142
|
a file holding no image and refused without a size, and a PNG header over no image data, refused
|
|
3739
|
-
with the size the header declares. The `
|
|
3740
|
-
|
|
4143
|
+
with the size the header declares. The `paintImage` function takes a PNG painted at its natural
|
|
4144
|
+
size and bytes that are no image, whose decode failure it hands on unchanged. The `readShotPixel`
|
|
4145
|
+
function takes each half of a split shot, frozen, and both corners clamped onto the shot, and
|
|
4146
|
+
refuses a fraction below `0`, above `1`, infinite, or `NaN` on either axis. The `readClippedBlock` function takes a frame
|
|
4147
|
+
clipping a taller child, a paint containment and a clip margin, elements wholly under a frame's
|
|
4148
|
+
edge, an unclipped control, a block in an open shadow tree under a clipping wrapper around its
|
|
4149
|
+
host, a slotted child under a clipping wrapper around its slot, a disconnected element refused,
|
|
4150
|
+
and the same reading on a page scrolled past its top, which a reading
|
|
4151
|
+
that skipped the coordinate conversion fails. The `collectClippingAncestors` function takes the
|
|
4152
|
+
same climb through a host and through a slot, nearest first, and a disconnected element refused.
|
|
4153
|
+
The `measureContent` function takes a slotted child ended at the shadow wrapper that clips around
|
|
4154
|
+
its slot. The `waitForStability` function takes reads spaced by the interval past the second.
|
|
4155
|
+
The `parseCSSColor` function takes an expression resolved on the scope it is handed, a registered
|
|
4156
|
+
token that does not inherit, a keyword, a hex triple, and `currentColor` at an `input` and an SVG
|
|
4157
|
+
element, a running color transition read at its sampled midpoint and left running, a scroller
|
|
4158
|
+
with a running height transition keeping its height and scroll position, a scope that records no
|
|
4159
|
+
mutation during the read, a transition on every property that starts none, a color scheme
|
|
4160
|
+
answered to a system color and to `light-dark()`, a token named only in a fallback carried, a
|
|
4161
|
+
disconnected scope answered with nothing, and an element that is no HTML, SVG, or MathML element
|
|
4162
|
+
resolved like any other. The `readColorContrast`
|
|
4163
|
+
function takes a token on an ancestor the body never declares, `currentColor`, and a token the
|
|
4164
|
+
element declares itself, each read at the element, a keyword, a hex triple, and a token at an
|
|
4165
|
+
`input`, a registered token that does not inherit, and a disconnected element refused. The `readCascade` function takes class tokens collected from
|
|
4166
|
+
plain and grouped rules and only real ones, and an escaped class decoded beside an attribute
|
|
4167
|
+
value whose class-like text defines nothing;
|
|
3741
4168
|
`readRows` takes a row joined from its own text nodes rather than from run-together content, and
|
|
3742
4169
|
an empty list; `extractOrphans` takes a child class rendered outside its container with a nested
|
|
3743
4170
|
one left alone, nothing reported when every child sits inside one, and, as the control, an element
|
|
@@ -3752,11 +4179,14 @@ Each entry names the contracts its file proves. The test names carry the cases.
|
|
|
3752
4179
|
element carrying an inline attribute reported once, a whitespace-only attribute read past, a
|
|
3753
4180
|
fragment root, and — as the control — markup whose classes and `data-*` attributes leave it with
|
|
3754
4181
|
nothing to report.
|
|
3755
|
-
- [`tests/src/browser/factories.test.ts`](../tests/src/browser/factories.test.ts)
|
|
4182
|
+
- [`tests/src/browser/journeys/factories.test.ts`](../tests/src/browser/journeys/factories.test.ts) and
|
|
4183
|
+
[`tests/src/browser/captures/factories.test.ts`](../tests/src/browser/captures/factories.test.ts) — the journal
|
|
3756
4184
|
contract, and the portfolio's refusals, its disabled gate, and its writes. Creation refuses an
|
|
3757
4185
|
unregistered variant name; the registry expands across every variant whether or not the run
|
|
3758
4186
|
writes; a run
|
|
3759
|
-
that is not enabled applies nothing, writes nothing, and records nothing
|
|
4187
|
+
that is not enabled applies nothing, writes nothing, and records nothing, yet refuses an
|
|
4188
|
+
unregistered state and a second placement of one state, and accepts two distinct registered states
|
|
4189
|
+
with its lists still empty; an enabled run applies
|
|
3760
4190
|
the variant, resizes the viewport, writes a real file through the provider, records it, and hands
|
|
3761
4191
|
out snapshots rather than its own lists; it refuses an unregistered state and a second placement of
|
|
3762
4192
|
one state; and a placement handed an element writes a frame that is not the whole page's and leaves
|
|
@@ -3769,7 +4199,11 @@ Each entry names the contracts its file proves. The test names carry the cases.
|
|
|
3769
4199
|
operation, each withheld operation refused in its own voice, both permissions granted at once with
|
|
3770
4200
|
the store answering from what it kept, a quota spent on accepted writes alone with `removeItem`
|
|
3771
4201
|
consuming none of it, a granted permission replenishing no room, every refused quota value, and —
|
|
3772
|
-
as the control for the inertness claim — a write that leaves `localStorage` exactly as it was.
|
|
4202
|
+
as the control for the inertness claim — a write that leaves `localStorage` exactly as it was. The
|
|
4203
|
+
event factories take the real event type, the bubbling, cancelable, and composed defaults and an
|
|
4204
|
+
override of each, and an event dispatched from a button inside an open shadow root that a
|
|
4205
|
+
`document` listener hears, beside a bare event of the same type that it does not, and a pointer
|
|
4206
|
+
or drag event whose `{ composed: false }` override keeps it inside the root.
|
|
3773
4207
|
- [`tests/src/server/helpers.test.ts`](../tests/src/server/helpers.test.ts) — the `readInventory` and
|
|
3774
4208
|
wait-family contracts, and each pure leaf against its own inputs. `resolveContained` takes
|
|
3775
4209
|
contained relative and absolute targets and both spellings of an escape, and `requireContained`
|