@orkestrel/scaffold 0.0.103 → 0.0.105
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 +17 -10
- package/dist/bin/main.js.map +1 -1
- package/dist/host/agents/orchestration.md +6 -6
- 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-parallel/SKILL.md +72 -0
- package/dist/host/agents/skills/orkestrel-parallel/agents/openai.yaml +4 -0
- package/dist/host/agents/skills/orkestrel-parallel/references/harnesses.md +12 -0
- 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/agents/verifier.md +1 -1
- 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/claude/skills/orkestrel-parallel/SKILL.md +11 -0
- package/dist/host/codex/agents/analyst.toml +3 -3
- package/dist/host/codex/agents/reviewer.toml +4 -4
- package/dist/host/codex/agents/verifier.toml +3 -1
- 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 +1674 -598
- package/dist/host/guides/budget.md +89 -29
- package/dist/host/guides/form.md +485 -99
- package/dist/host/guides/mcp.md +14 -2
- package/dist/host/guides/ollama.md +367 -86
- package/dist/host/guides/probe.md +1 -1
- package/dist/host/guides/scaffold.md +158 -101
- package/dist/host/guides/study.md +3185 -0
- package/dist/host/guides/table.md +239 -29
- package/dist/host/guides/terminal.md +22 -20
- package/dist/host/guides/test.md +776 -315
- package/dist/host/manifest.json +117 -65
- package/dist/host/tests/config.test.ts +136 -82
- package/dist/host/tests/policy.test.ts +41 -3
- package/dist/host/tests/setupPolicy.ts +87 -29
- package/dist/src/core/index.cjs +1389 -612
- 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 +1387 -613
- 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 +5 -5
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.
|
|
@@ -172,41 +180,52 @@ for a missing or inherited key, and for a member carrying neither. Per-key tuple
|
|
|
172
180
|
claim the narrowing carries rather than something the reading checks, so a caller relying on it
|
|
173
181
|
establishes the pairing between an event and the recorder stored under that event first;
|
|
174
182
|
`createRecorders` establishes it by wiring each recorder to exactly the event it stores that recorder
|
|
175
|
-
under. Every
|
|
183
|
+
under. Every read of untrusted input is contained, so a value whose keys or getters throw answers `false`
|
|
176
184
|
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
|
|
@@ -231,17 +277,23 @@ markup or from a tag and its classes; `createHarness` mounts a whole statechart
|
|
|
231
277
|
back the root it mounted; `buildContrast`, `buildEscapes`, and `buildCensus` each build
|
|
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
|
-
a node the caller already has — `isRendered`, `isReachable`, `readHit`, `readText`, `readRole`,
|
|
235
|
-
`readName`, `readStates`, `
|
|
236
|
-
`
|
|
237
|
-
|
|
280
|
+
a node the caller already has — `isRendered`, `isReachable`, `supportsSegmentedFocus`, `readHit`, `readText`, `readRole`,
|
|
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. |
|
|
@@ -276,129 +335,164 @@ a union's arms escaped as `\|`.
|
|
|
276
335
|
|
|
277
336
|
A `Shape` cell holds the constant's declared type.
|
|
278
337
|
|
|
279
|
-
| API
|
|
280
|
-
|
|
|
281
|
-
| `ACCESSIBLE_ROLES`
|
|
282
|
-
| `CANVAS_COLOR`
|
|
283
|
-
| `CAPTURE_PANE`
|
|
284
|
-
| `CAPTURE_STAGINGS`
|
|
285
|
-
| `CONTENT_ROLES`
|
|
286
|
-
| `FIELD_ROLES`
|
|
287
|
-
| `FOCUSABLE_SELECTOR`
|
|
288
|
-
| `
|
|
289
|
-
| `
|
|
290
|
-
| `
|
|
291
|
-
| `
|
|
338
|
+
| API | Kind | Shape | Summary |
|
|
339
|
+
| ----------------------- | ----- | ---------------------------------- | ---------------------------------------------------------------------------------------------------------- |
|
|
340
|
+
| `ACCESSIBLE_ROLES` | const | `readonly string[]` | Names the interactive ARIA roles a bare accessible name is searched across. |
|
|
341
|
+
| `CANVAS_COLOR` | const | `Color` | Names the color a browser paints an unstyled document with: opaque white. |
|
|
342
|
+
| `CAPTURE_PANE` | const | `string` | Names the attribute marking the runner's tester pane, and the rule that sizes it, while a frame is staged. |
|
|
343
|
+
| `CAPTURE_STAGINGS` | const | `number` | Bounds the restagings one capture takes before it refuses a document whose height never settles. |
|
|
344
|
+
| `CONTENT_ROLES` | const | `readonly string[]` | Names the roles whose accessible name is the text a reader can see inside them. |
|
|
345
|
+
| `FIELD_ROLES` | const | `Readonly<Record<string, string>>` | Names the role each `input` type carries. |
|
|
346
|
+
| `FOCUSABLE_SELECTOR` | const | `string` | Names what sequential keyboard navigation can reach, before disabled and unrendered elements go. |
|
|
347
|
+
| `SEGMENTED_INPUT_TYPES` | const | `readonly string[]` | Names the native input types whose editable segments share one focused element. |
|
|
348
|
+
| `FOCUS_SEGMENT_LIMIT` | const | `number` | Bounds consecutive focus landings and the Tab presses budgeted per segmented input. |
|
|
349
|
+
| `HEADER_ROLES` | const | `Readonly<Record<string, string>>` | Names the role a `th` carries for the header axis its `scope` names. |
|
|
350
|
+
| `IMPLICIT_ROLES` | const | `Readonly<Record<string, string>>` | Names the role each listed tag carries in the accessibility tree when it declares none of its own. |
|
|
351
|
+
| `MEDIA_STAGE` | const | `string` | Names the tester root's attribute holding the media readings observed before the first stage. |
|
|
352
|
+
| `POINTER_HOLD` | const | `string` | Names the tester root's attribute holding the pressed pointer's page coordinates. |
|
|
292
353
|
|
|
293
354
|
#### Helpers
|
|
294
355
|
|
|
295
|
-
| API | Kind | Signature
|
|
296
|
-
| -------------------------- | -------- |
|
|
297
|
-
| `
|
|
298
|
-
| `
|
|
299
|
-
| `
|
|
300
|
-
| `
|
|
301
|
-
| `
|
|
302
|
-
| `
|
|
303
|
-
| `
|
|
304
|
-
| `
|
|
305
|
-
| `
|
|
306
|
-
| `
|
|
307
|
-
| `
|
|
308
|
-
| `
|
|
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
|
-
| `
|
|
356
|
+
| API | Kind | Signature | Summary |
|
|
357
|
+
| -------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
358
|
+
| `supportsSegmentedFocus` | function | `(element: Element) => boolean` | Determines whether a native input exposes separately editable segments under one focused element. |
|
|
359
|
+
| `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. |
|
|
360
|
+
| `resolveAccessibleWithin` | function | `(region: string, role: string, name: string) => HTMLElement` | Resolves one human-reachable control by role and accessible-name text inside a named region. |
|
|
361
|
+
| `resolveRendered` | function | `(first: string, second?: string) => HTMLElement` | Resolves one rendered, focus-reachable interactive element without requiring it to intersect the viewport yet. |
|
|
362
|
+
| `computeNamePattern` | function | `(name: string) => RegExp` | Computes the pattern that matches one accessible name a decorative glyph may sit beside. |
|
|
363
|
+
| `isOutsideViewport` | function | `(rectangle: DOMRectReadOnly) => boolean` | Determines whether a rectangle lies wholly outside the browser viewport. |
|
|
364
|
+
| `isRendered` | function | `(element: Element) => boolean` | Determines whether the accessibility tree presents one element at all. |
|
|
365
|
+
| `isReachable` | function | `(element: Element) => boolean` | Determines whether a person can click one element where it sits. |
|
|
366
|
+
| `readHit` | function | `(element: Element) => Element \| undefined` | Reads the topmost element at one element's bounding-box centre. |
|
|
367
|
+
| `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. |
|
|
368
|
+
| `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. |
|
|
369
|
+
| `clickDisclosure` | function | `(name: string) => Promise<void>` | Opens or closes one native details disclosure by its rendered summary. |
|
|
370
|
+
| `sendProtocol` | function | `(method: string, params?: Readonly<Record<string, unknown>>) => Promise<unknown>` | Sends one DevTools protocol command through the browser provider. |
|
|
371
|
+
| `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. |
|
|
372
|
+
| `readProtocolNode` | function | `(element: Element) => Promise<number>` | Resolves one element to the node the browser's DOM tree holds for it. |
|
|
373
|
+
| `readAccessibilityNode` | function | `(element: Element) => Promise<AccessibilityNode>` | Reads the accessibility node the browser computed for one element. |
|
|
374
|
+
| `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. |
|
|
375
|
+
| `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. |
|
|
376
|
+
| `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. |
|
|
377
|
+
| `driveHold` | function | `(resolve: () => HTMLElement, name: string) => Promise<void>` | Holds the primary pointer button on the control a resolver returns, through the browser provider. |
|
|
378
|
+
| `parkPointer` | function | `() => Promise<void>` | Parks the pointer outside the page and waits for the parked pointer's frame to paint. |
|
|
379
|
+
| `releasePointer` | function | `() => Promise<void>` | Releases a held pointer and parks it outside the page, clearing hover. |
|
|
380
|
+
| `typeAccessible` | function | `(name: string, text: string) => Promise<void>` | Replaces a named field's value through focus, select-all, deletion, and real keystrokes. |
|
|
381
|
+
| `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. |
|
|
382
|
+
| `traverseAccessible` | function | `(name: string) => Promise<HTMLElement>` | Reaches a named control only through natural forward Tab traversal from the current focus. |
|
|
383
|
+
| `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. |
|
|
384
|
+
| `readActiveElement` | function | `(root?: Document \| ShadowRoot) => HTMLElement \| undefined` | Reads the HTML element that holds focus, following it into open shadow roots and same-origin frames. |
|
|
385
|
+
| `countElements` | function | `(root?: Document \| ShadowRoot) => number` | Counts the elements a tree holds, descending into open shadow roots and same-origin frames. |
|
|
386
|
+
| `containsNode` | function | `(root: Node, node: Node) => boolean` | Determines whether a node sits inside a root, through open shadow roots and frames. |
|
|
387
|
+
| `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. |
|
|
388
|
+
| `driveTraversal` | function | `(resolve: () => HTMLElement, name: string) => Promise<HTMLElement>` | Reaches the control a resolver returns, only through natural forward Tab traversal from the current focus. |
|
|
389
|
+
| `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. |
|
|
390
|
+
| `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. |
|
|
391
|
+
| `pressKeys` | function | `(keys: string) => Promise<void>` | Sends a key sequence to whatever holds focus, and refuses to send it to nothing. |
|
|
392
|
+
| `readPerception` | function | `(name: string) => string` | Reads the normalized visible text of one named region, dialog, table, tab panel, or alert. |
|
|
393
|
+
| `readPage` | function | `() => string` | Reads the normalized visible text of the whole page. |
|
|
394
|
+
| `readFocus` | function | `() => string \| undefined` | Reads the rendered text of the element that holds focus. |
|
|
395
|
+
| `readValue` | function | `(role: string, name: string) => string` | Reads the value a resolved control renders. |
|
|
396
|
+
| `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. |
|
|
397
|
+
| `readText` | function | `(element: Element) => string` | Reads one element's rendered text the way a name computation reads it. |
|
|
398
|
+
| `readRole` | function | `(element: Element) => string \| undefined` | Reads the role one element carries in the accessibility tree. |
|
|
399
|
+
| `readName` | function | `(element: Element) => string` | Reads the accessible name one element is announced under. |
|
|
400
|
+
| `readStates` | function | `(element: Element) => readonly string[]` | Reads the states one element is announced in. |
|
|
401
|
+
| `describeTree` | function | `(element: Element) => string` | Describes the accessible tree one rendered element presents. |
|
|
402
|
+
| `describeFocus` | function | `(element: Element) => string` | Describes the order sequential keyboard navigation visits one element's controls in. |
|
|
403
|
+
| `waitForFrame` | function | `() => Promise<void>` | Waits for one animation frame to settle pending browser paint work. |
|
|
404
|
+
| `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. |
|
|
405
|
+
| `waitForAnimations` | function | `(element: Element, options?: WaitOptions) => Promise<void>` | Waits until every finite animation on one element and its subtree has stopped moving. |
|
|
406
|
+
| `readAnimations` | function | `(element: Element) => AnimationReading` | Reads the animations running on one element and its subtree, split by whether each one ends. |
|
|
407
|
+
| `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. |
|
|
408
|
+
| `collectScrollRegions` | function | `(root: Element, axis?: 'inline' \| 'block') => readonly HTMLElement[]` | Collects the rendered boxes a person can scroll. |
|
|
409
|
+
| `describeScrollRegions` | function | `(regions: readonly HTMLElement[]) => string` | Describes the window's scroll position and each scroll region's offsets and extents. |
|
|
410
|
+
| `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. |
|
|
411
|
+
| `mount` | function | `<T extends Element>(element: T) => T` | Puts one element into the document and hands it straight back. |
|
|
412
|
+
| `typeInput` | function | `(element: HTMLInputElement \| HTMLTextAreaElement, text: string) => void` | Sets one field's value and announces it the way typing into the field does. |
|
|
413
|
+
| `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. |
|
|
414
|
+
| `render` | function | `(markup: string) => HTMLDivElement` / `(tag: K, classes: string) => HTMLElementTagNameMap[K]` | Renders one fixture into the document from trusted markup. |
|
|
415
|
+
| `clearStorage` | function | `() => void` | Clears both browser storage surfaces. |
|
|
416
|
+
| `removeDatabase` | function | `(name: string) => Promise<void>` | Deletes one IndexedDB database and reports what the request actually did. |
|
|
417
|
+
| `convertSRGB` | function | `(red: number, green: number, blue: number, alpha?: number) => Color` | Converts normalized encoded sRGB channels to the clipped paint scale. |
|
|
418
|
+
| `convertLinearSRGB` | function | `(red: number, green: number, blue: number, alpha?: number) => Color` | Converts linear sRGB channels to encoded, clipped paint channels. |
|
|
419
|
+
| `convertXYZD65` | function | `(x: number, y: number, z: number, alpha?: number) => Color` | Converts D65 XYZ coordinates to clipped sRGB paint channels. |
|
|
420
|
+
| `convertXYZD50` | function | `(x: number, y: number, z: number, alpha?: number) => Color` | Converts D50 XYZ coordinates to clipped sRGB paint channels. |
|
|
421
|
+
| `convertOKLab` | function | `(lightness: number, a: number, b: number, alpha?: number) => Color` | Converts OKLab coordinates to clipped sRGB paint channels. |
|
|
422
|
+
| `convertLab` | function | `(lightness: number, a: number, b: number, alpha?: number) => Color` | Converts CIE Lab coordinates relative to D50 to clipped sRGB paint channels. |
|
|
423
|
+
| `convertDisplayP3` | function | `(red: number, green: number, blue: number, alpha?: number) => Color` | Converts encoded Display P3 channels to clipped sRGB paint channels. |
|
|
424
|
+
| `convertA98RGB` | function | `(red: number, green: number, blue: number, alpha?: number) => Color` | Converts encoded A98 RGB channels to clipped sRGB paint channels. |
|
|
425
|
+
| `convertProPhotoRGB` | function | `(red: number, green: number, blue: number, alpha?: number) => Color` | Converts encoded ProPhoto RGB channels to clipped sRGB paint channels. |
|
|
426
|
+
| `convertRec2020` | function | `(red: number, green: number, blue: number, alpha?: number) => Color` | Converts encoded Rec. 2020 channels to clipped sRGB paint channels. |
|
|
427
|
+
| `parseColor` | function | `(value: string) => Color \| undefined` | Parses computed CSS Color 4 values into clipped straight sRGB channels. |
|
|
428
|
+
| `parseCSSColor` | function | `(value: string, scope?: Element) => Color \| undefined` | Resolves any CSS color expression to straight sRGB channels, by asking the browser. |
|
|
429
|
+
| `matchesColor` | function | `(first: string \| Color, second: string \| Color) => boolean` | Determines whether two colors render the same, within the rounding a browser does. |
|
|
430
|
+
| `blendColor` | function | `(front: Color, back: Color) => Color` | Composites one color over another. |
|
|
431
|
+
| `measureLuminance` | function | `(color: Color) => number` | Measures one opaque color's WCAG relative luminance. |
|
|
432
|
+
| `measureContrast` | function | `(front: Color, back: Color) => number` | Measures the WCAG 2.x contrast ratio between two opaque colors. |
|
|
433
|
+
| `readLayers` | function | `(element: Element) => readonly Color[]` | Collects readable background color layers and refuses an unreadable painted layer. |
|
|
434
|
+
| `readBackdrop` | function | `(element: Element, floor: Color) => Color` | Resolves the opaque color standing behind one element. |
|
|
435
|
+
| `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. |
|
|
436
|
+
| `readContrast` | function | `(element: Element, floor?: Color) => number` | Measures the WCAG 2.x contrast ratio between an element's computed text and background colors. |
|
|
437
|
+
| `readRing` | function | `(control: Element, worn?: Element) => number \| undefined` | Measures the contrast the focus chrome painted on one control reaches against its own backdrop. |
|
|
438
|
+
| `readClipEdge` | function | `(element: Element) => number \| undefined` | Measures the row a clipping element cuts its content off at, in document coordinates. |
|
|
439
|
+
| `readClipMargin` | function | `(element: Element) => number` | Measures how far past its own box a clipping element lets its content show. |
|
|
440
|
+
| `readClippedBlock` | function | `(element: Element) => number` | Measures the block size an element shows after every clipping ancestor cuts it. |
|
|
441
|
+
| `collectClippingAncestors` | function | `(element: Element) => readonly Element[]` | Collects the ancestors of an element that clip their descendants' overflow. |
|
|
442
|
+
| `clipsOverflow` | function | `(element: Element) => boolean` | Reports whether an element clips its descendants' overflow. |
|
|
443
|
+
| `measureContent` | function | `() => number` | Measures the row the document's own content ends on, in document coordinates. |
|
|
444
|
+
| `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. |
|
|
445
|
+
| `releasePane` | function | `() => Promise<void>` | Hands the tester pane back to the runner's own layout, at the viewport it had before staging. |
|
|
446
|
+
| `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. |
|
|
447
|
+
| `stageMedia` | function | `(options: MediaOptions) => Promise<void>` | Stages the tester's print medium, motion preference, forced colours, and pointer precision through the browser provider. |
|
|
448
|
+
| `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. |
|
|
449
|
+
| `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. |
|
|
450
|
+
| `captureFrame` | function | `(options: FrameOptions) => Promise<string>` | Shoots one frame at one viewport size and proves the file on disk holds this run's bytes. |
|
|
451
|
+
| `paintImage` | function | `(encoded: string) => Promise<OffscreenCanvasRenderingContext2D \| undefined>` | Decodes a base64 PNG and paints it, unscaled, onto a fresh offscreen 2D canvas. |
|
|
452
|
+
| `readFrame` | function | `(path: string) => Promise<FrameReading>` | Reads one written frame back and reports its size and the color its bottom row paints. |
|
|
453
|
+
| `readShotPixel` | function | `(element: Element, x: number, y: number) => Promise<Color>` | Reads one painted pixel of an element's screenshot. |
|
|
454
|
+
| `readCascade` | function | `() => ReadonlySet<string>` | Collects every class token the stylesheets loaded into this document actually define. |
|
|
455
|
+
| `readClasses` | function | `(root: ParentNode) => ReadonlySet<string>` | Collects every class token the markup under one root carries. |
|
|
456
|
+
| `readCensus` | function | `(root: ParentNode) => CensusReading` | Takes the authored-class census of one subtree against the cascade this document loaded. |
|
|
457
|
+
| `sendTouch` | function | `(type: 'touchStart' \| 'touchMove' \| 'touchEnd' \| 'touchCancel', element?: Element, point?: ProtocolPoint) => Promise<void>` | Sends one emulated touch event through the browser protocol. |
|
|
458
|
+
| `tapTouch` | function | `(element: Element, options?: StabilityOptions) => Promise<void>` | Taps an element's centre with emulated touch after its box settles. |
|
|
459
|
+
| `releaseTouch` | function | `() => Promise<void>` | Cancels emulated touch input, disables touch emulation, and parks the pointer. |
|
|
460
|
+
| `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. |
|
|
461
|
+
| `adoptSheet` | function | `(text: string) => SheetAdoption` | Adopts CSS text into the document with an idempotent release operation. |
|
|
462
|
+
| `readLayerNames` | function | `(source: CSSStyleSheet \| CSSGroupingRule \| CSSStyleRule, layer?: string) => readonly string[]` | Reads layer statements and blocks in declaration order, including repeated names. |
|
|
463
|
+
| `readRules` | function | `() => readonly CSSRule[]` | Collects every rule the stylesheets loaded into this document hold, nested grouping rules included. |
|
|
464
|
+
| `findRule` | function | `(selector: string) => CSSStyleRule \| undefined` | Finds the first style rule in the cascade whose selector carries a fragment. |
|
|
465
|
+
| `findKeyframes` | function | `(name: string) => CSSKeyframesRule \| undefined` | Finds the animation the cascade declares under one name. |
|
|
466
|
+
| `readRows` | function | `(root: ParentNode, selector: string) => readonly string[]` | Reads the normalized visible text of every element a selector matches, in document order. |
|
|
467
|
+
| `extractOrphans` | function | `(root: ParentNode, child: string, parent: string) => readonly string[]` | Collects every element carrying a component class rendered outside the container it belongs to. |
|
|
468
|
+
| `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`. |
|
|
469
|
+
| `readStyle` | function | `(element: Element, property: string, pseudo?: string) => string` | Reads one resolved CSS property from a real browser element or a named pseudo-element. |
|
|
470
|
+
| `readToken` | function | `(element: Element, name: string) => string` | Reads one custom property from an element's resolved style. |
|
|
471
|
+
| `readRootToken` | function | `(name: string) => string` | Reads one custom property from the document element. |
|
|
472
|
+
| `readPixels` | function | `(element: Element, property: string, pseudo?: string) => number` | Reads one resolved CSS length as a number of pixels. |
|
|
473
|
+
| `expandCaptures` | function | `(states: readonly string[], variants: readonly CaptureVariant[]) => readonly string[]` | Expands a capture registry across every variant into the filenames a complete portfolio holds. |
|
|
474
|
+
| `buildDenial` | function | `(operation: string, key?: string) => DOMException` | Builds the refusal a host withholding a storage operation raises. |
|
|
475
|
+
| `buildContrast` | function | `(bar: number) => ContrastFixture` | Builds a detached translucent stack whose composited and flat contrast readings straddle one bar. |
|
|
476
|
+
| `buildEscapes` | function | `(permitted: string) => EscapeFixture` | Builds detached markup carrying one style escape of each kind, plus the sheet a project allows. |
|
|
477
|
+
| `buildCensus` | function | `() => CensusFixture` | Builds detached markup carrying one undeclared class token on HTML and another on SVG. |
|
|
390
478
|
|
|
391
479
|
#### Factories
|
|
392
480
|
|
|
393
|
-
| API
|
|
394
|
-
|
|
|
395
|
-
| `
|
|
396
|
-
| `
|
|
397
|
-
| `
|
|
398
|
-
| `
|
|
399
|
-
| `
|
|
400
|
-
| `
|
|
401
|
-
| `
|
|
481
|
+
| API | Kind | Signature | Summary |
|
|
482
|
+
| --------------------- | -------- | --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
|
|
483
|
+
| `createPortfolio` | function | `(options: PortfolioOptions) => PortfolioInterface` | Creates the capture portfolio one run places its screenshots through; a disabled run still refuses. |
|
|
484
|
+
| `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. |
|
|
485
|
+
| `createJournal` | function | `() => JournalInterface` | Creates the journal one scenario records its steps and the page's own output into. |
|
|
486
|
+
| `createStorage` | function | `(options?: StorageOptions) => WebStorageInterface` | Creates an inert `Storage` a host can withhold, grant, and run out of room in. |
|
|
487
|
+
| `createHarness` | function | `(options: HarnessOptions<TState, TEvent, TContext>) => HarnessInterface` | Creates a mounted statechart harness that renders one transition table and drives it row by row. |
|
|
488
|
+
| `createPointerEvent` | function | `(name: string, options?: PointerEventInit) => PointerEvent` | Creates one real pointer event, ready to dispatch. |
|
|
489
|
+
| `createDragEvent` | function | `(name: string, options?: DragEventInit) => DragEvent` | Creates one real drag event carrying a live data transfer, ready to dispatch. |
|
|
490
|
+
| `createKeyboardEvent` | function | `(name: string, options?: KeyboardEventInit) => KeyboardEvent` | Creates one real keyboard event, ready to dispatch. |
|
|
491
|
+
|
|
492
|
+
`createPointerEvent` and `createDragEvent` default to `composed: true` from 0.0.27, where 0.0.26
|
|
493
|
+
left it `false`. An event dispatched inside an open shadow root stayed there in 0.0.26, and a
|
|
494
|
+
listener outside that root heard nothing; a listener outside it hears the event from 0.0.27. Pass
|
|
495
|
+
`{ composed: false }` to restore the 0.0.26 boundary behavior.
|
|
402
496
|
|
|
403
497
|
`resolveAccessible` counts a match as reachable only when every condition holds: it is connected; it
|
|
404
498
|
passes a visibility check honouring opacity and CSS; its box has non-zero width and height; its
|
|
@@ -446,12 +540,21 @@ resolution on its own, and `holdAccessibleWithin` and `traverseAccessibleWithin`
|
|
|
446
540
|
resolves the way `holdAccessible` and `traverseAccessible` drive a document-wide one, so a twin of
|
|
447
541
|
the same name in another region is left alone.
|
|
448
542
|
|
|
449
|
-
`traverseAccessible` charges a step only when focus actually lands on an element
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
543
|
+
`traverseAccessible` charges a step only when focus actually lands on an element and re-resolves
|
|
544
|
+
the target by name on every step, because a framework may replace the node between resolution and
|
|
545
|
+
focus arrival. Consecutive landings on the same native `date`, `time`, `datetime-local`, `month`, or
|
|
546
|
+
`week` input pass through its editable segments and count that control once, up to
|
|
547
|
+
`FOCUS_SEGMENT_LIMIT` landings. A longer run or any other revisit ends the traversal, including a
|
|
548
|
+
consecutive repeat on a button in a focus trap. Any different landing starts a separate run.
|
|
549
|
+
The `supportsSegmentedFocus` predicate is true for an input whose `type` is in `SEGMENTED_INPUT_TYPES`,
|
|
550
|
+
checked against the element's own document's `HTMLInputElement`, so a same-origin frame's input
|
|
551
|
+
counts. It is false where the document has no window. The hard cap is `FOCUS_SEGMENT_LIMIT` times
|
|
552
|
+
the page's candidate count plus ten, including disabled controls and elements with `tabindex="-1"`.
|
|
553
|
+
The limit budgets ten presses per candidate. Chromium measured nine landings on a `datetime-local`
|
|
554
|
+
input with `step="0.001"`: year, month, day, hour, minute, second, millisecond, and meridiem segments,
|
|
555
|
+
plus the picker indicator. The budget leaves one spare press per input, so a page of segmented
|
|
556
|
+
inputs can finish while a page whose focus never settles still fails.
|
|
557
|
+
`driveTraversal` implements this forward Tab traversal for any resolver. `driveHold` is the one pointer drive every hold
|
|
455
558
|
verb shares, releasing the pointer before refusing when the frame wait or the pressed-state read
|
|
456
559
|
fails, as well as when the press misses; each verb supplies its resolver and the name its refusals
|
|
457
560
|
voice.
|
|
@@ -498,12 +601,26 @@ clipped to 0–255 after conversion; this reader does not perform perceptual gam
|
|
|
498
601
|
Alpha is clipped to 0–1.
|
|
499
602
|
|
|
500
603
|
`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
|
|
604
|
+
only the computed syntaxes a cascade hands back; `parseCSSColor` hands the expression to the real
|
|
605
|
+
cascade and reads back what the engine computed — which is the only way a keyword, a hex triple, a
|
|
606
|
+
`var()` reference, or a `color-mix()` becomes channels at all. With no scope the expression resolves
|
|
607
|
+
on a probe that is a child of the body, mounted so a `var()` reference resolves against the tokens
|
|
608
|
+
`:root` declares, and removed in a `finally`. Refusal is the CSSOM's: an expression it will not parse
|
|
609
|
+
returns `undefined`. A `var()` naming an undeclared custom property is not refused, and
|
|
610
|
+
[Limits](#limits) states what that costs. The optional `scope` argument resolves the expression on
|
|
611
|
+
that same body-mounted probe, which carries the scope's computed context onto its own inline style:
|
|
612
|
+
the computed value of every custom property the expression names, a fallback's included, the
|
|
613
|
+
scope's computed `color`, and its computed `color-scheme`. The expression is written into
|
|
614
|
+
`background-color`, so `currentColor` is the carried `color`, and a system color or `light-dark()`
|
|
615
|
+
answers as the scope's scheme. The element's own and inherited custom properties apply, a registered
|
|
616
|
+
property that does not inherit included, and an `input`, an SVG element, or any other element
|
|
617
|
+
resolves like any other. A custom property is named by letters, digits, `_`, and `-` after its `--`,
|
|
618
|
+
and a name the scope leaves undeclared is not carried, so its `var()` fallback still applies. The
|
|
619
|
+
scope element is never written: the probe is freshly created, so it has no earlier style to start a transition
|
|
620
|
+
from, a transition running on the scope keeps running and `currentColor` reads the color the scope
|
|
621
|
+
shows at that moment, and the scope's geometry and scroll position stay as they were. No attribute,
|
|
622
|
+
style, or child of the scope changes, so a `MutationObserver` on it records nothing. A disconnected
|
|
623
|
+
scope computes no style and returns `undefined`.
|
|
507
624
|
|
|
508
625
|
`matchesColor` compares two colors as a browser renders them. Each string side resolves through
|
|
509
626
|
`parseCSSColor`, so a keyword, a token reference, and the `rgb()` an engine computes for either
|
|
@@ -522,6 +639,21 @@ or the color a fragment is really mounted onto — and the same stack composites
|
|
|
522
639
|
being refused. A detached element is refused either way, because its computed foreground color does
|
|
523
640
|
not exist.
|
|
524
641
|
|
|
642
|
+
`readColorContrast` is the same measurement with the color handed in, for paint that is not the
|
|
643
|
+
element's own text: a separator grip, a placeholder, a checkbox mark. `readContrast` and `readRing`
|
|
644
|
+
both measure through it. A computed color value parses directly, and any other expression — a
|
|
645
|
+
keyword, a hex triple, a `var()` reference — resolves through `parseCSSColor` at the element's own
|
|
646
|
+
scope: a token reads as the element and its ancestors declare it, and `currentColor` is the
|
|
647
|
+
element's own text color, not the body's. The read carries the element's computed custom
|
|
648
|
+
properties, `color`, and `color-scheme` onto a probe, so an `input` and a registered token that does
|
|
649
|
+
not inherit resolve as they do on any other element, and the element itself is never written. A
|
|
650
|
+
disconnected element computes no style, so it refuses such an expression as unreadable; hand it a
|
|
651
|
+
computed color such as `rgb(255, 255, 255)`. `floor` takes the
|
|
652
|
+
part `readContrast`'s second argument takes, with the same refusal and the same voice when it is
|
|
653
|
+
omitted. `opacity` multiplies the color's own alpha before it is composited, for a mark painted
|
|
654
|
+
inside an element whose `opacity` is below `1`, and a value outside `0` to `1` is refused rather than
|
|
655
|
+
read.
|
|
656
|
+
|
|
525
657
|
`readLayers` is the reading that refusal turns on. It hands back the painted layers themselves,
|
|
526
658
|
element first and the deepest last, so a walk that ended on a real surface is the one whose last
|
|
527
659
|
layer has an alpha of `1`. A composited color cannot answer that question: 64 half-transparent
|
|
@@ -533,14 +665,17 @@ An unreadable painted background layer throws an error naming its element and co
|
|
|
533
665
|
Non-finite calculations such as `color(srgb calc(infinity) 0 0)` are deliberately unreadable.
|
|
534
666
|
A layer with an explicit zero alpha paints nothing and is skipped, including an unreadable one.
|
|
535
667
|
Background images remain outside this color reader. The refusal propagates through `readBackdrop`,
|
|
536
|
-
`readContrast`, and the
|
|
668
|
+
`readContrast`, `readColorContrast`, and the reading `readRing` takes of painted focus chrome, even
|
|
669
|
+
with a supplied floor. `readRing` reads the backdrop for every control matching `:focus-visible`
|
|
670
|
+
before it looks for chrome, so a focused control whose cascade paints no chrome is refused over an
|
|
671
|
+
unreadable surface too.
|
|
537
672
|
|
|
538
673
|
`readBackdrop` composites that stack and takes its floor as an argument rather than reaching for
|
|
539
674
|
`CANVAS_COLOR` itself, so a measurement over a surface the canvas never shows through names the
|
|
540
675
|
color it actually sits on. When no layer paints it hands that floor straight back.
|
|
541
676
|
|
|
542
677
|
`readRing` reads and never acts. Focus arrives through the published verbs, and this measures what
|
|
543
|
-
the browser painted
|
|
678
|
+
the browser painted after it landed: the `outline` the cascade declares, and the first color in a
|
|
544
679
|
`box-shadow`. A control that is not matching `:focus-visible`, a control left the browser's own
|
|
545
680
|
`outline-style: auto` ring, and a focus style that only changes the control's own fill all report
|
|
546
681
|
`undefined` — in each case no measurement taken here would be about focus. `worn` names the element
|
|
@@ -566,6 +701,16 @@ class declared inside an earlier grouping rule; 0.0.8 popped a stack and inserte
|
|
|
566
701
|
first. Iterate the set where the order is the subject and read `has` where membership is. A
|
|
567
702
|
`@keyframes` rule's own children are outside the walk, so an animation's stops define no token here.
|
|
568
703
|
|
|
704
|
+
Each rule's selector text is read by `collectSelectorClasses`, and that reading differs from 0.0.26,
|
|
705
|
+
which matched a pattern over the text. An escaped name decodes, so `.sm\:flex` defines `sm:flex`
|
|
706
|
+
where 0.0.26 read `sm`. Text inside an attribute value, a string, or a comment defines nothing, so
|
|
707
|
+
`[title=".card"]` defines no `card`. A name opening with an underscore, a hyphen, or a non-ASCII
|
|
708
|
+
letter counts, where 0.0.26 skipped it. A non-ASCII letter inside a name stays in it, so `.café`
|
|
709
|
+
defines `café` where 0.0.26 ended the class at the first code point outside ASCII letters, digits,
|
|
710
|
+
`_`, and `-` and defined `caf`. A census that saw any of those misreadings reports the
|
|
711
|
+
corrected set, so `readCensus` can move a token into or out of `undeclared`. One rule's own tokens
|
|
712
|
+
enter the set in code-unit order rather than in the order the selector writes them.
|
|
713
|
+
|
|
569
714
|
`findRule` and `findKeyframes` differ in how they match, and the subject is what decides it. A
|
|
570
715
|
selector is compound, so `findRule` matches its argument as a substring of the whole selector text:
|
|
571
716
|
`findRule('.card')` finds `.card`, `.card:hover`, and `.panel > .card` alike, and more of the
|
|
@@ -587,7 +732,7 @@ where that distinction matters.
|
|
|
587
732
|
|
|
588
733
|
`stagePane` unscales the runner's tester and lifts it to the window's origin, because a frame shot
|
|
589
734
|
through the runner's fitting scale is a thumbnail of the surface. That couples it to Vitest's own
|
|
590
|
-
tester layout, which is contract rather than accident: `vitest@4.1.
|
|
735
|
+
tester layout, which is contract rather than accident: `vitest@4.1.12` is the version behind the
|
|
591
736
|
`iframe[data-vitest]` selector and the `--tester-transform`, `--tester-margin-left`,
|
|
592
737
|
`--viewport-width`, and `--viewport-height` custom properties it writes. A release that renames any
|
|
593
738
|
of them reddens the size check rather than writing a wrong frame. Always hand the pane back with
|
|
@@ -626,7 +771,9 @@ the body instead, taking the largest bottom edge in document coordinates plus th
|
|
|
626
771
|
bottom margin, and adds the body's and the root's bottom padding and margin under them. An
|
|
627
772
|
ancestor that clips its overflow (the `clipsOverflow` helper: an `overflow-y` value other than the
|
|
628
773
|
`visible` keyword, or a paint containment) caps a descendant's edge at that ancestor's clip edge,
|
|
629
|
-
which the `readClipEdge` helper reads.
|
|
774
|
+
which the `readClipEdge` helper reads. The `collectClippingAncestors` helper finds those ancestors
|
|
775
|
+
through the flat tree, from an element to the slot it is assigned to, to its parent, and out of a
|
|
776
|
+
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
777
|
keyword, or the `scroll` keyword clips at the padding box, whatever the ancestor's
|
|
631
778
|
`overflow-clip-margin` value selects. The `clip` keyword and a paint containment over a `visible`
|
|
632
779
|
overflow clip at the box that value selects, the padding box by default, expanded by the length the
|
|
@@ -657,15 +804,27 @@ written at a height that is already wrong. That bound is 4: a document holding h
|
|
|
657
804
|
fixed block settles in two restagings, one whose growth is capped part way settles in three, and
|
|
658
805
|
the fourth is headroom.
|
|
659
806
|
|
|
660
|
-
An element
|
|
661
|
-
lengths resolve against the declared viewport
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
807
|
+
An element that fits with its native scroll clearance is shot in the declared pane, so its viewport
|
|
808
|
+
lengths resolve against the declared viewport: a `50vh` element under a 900-row block reads back 422
|
|
809
|
+
rows in an 844-row pane. A short fixed panel that native alignment cannot move keeps that pane too.
|
|
810
|
+
A captured sticky element with a vertical start inset keeps the declared pane when native end
|
|
811
|
+
alignment places its box fully inside it. Its own inset determines that fitted placement; adding
|
|
812
|
+
the document's start-clearance gap can otherwise grow a viewport-bound height on every restaging.
|
|
813
|
+
This exception belongs to the captured sticky element, not to in-flow content it contains or a
|
|
814
|
+
region containing sticky children. A sticky declaration without a vertical start inset retains
|
|
815
|
+
the ordinary clearance behavior.
|
|
816
|
+
For an element whose height plus clearance exceeds the declared height, native start alignment
|
|
817
|
+
resolves the clearance, and the pane reserves the element's height plus the space above its aligned
|
|
818
|
+
top. This includes an element shorter than the declared pane. It honors authored root scroll padding
|
|
819
|
+
and target scroll margins, including computed lengths, without
|
|
820
|
+
parsing CSS or hiding a sticky header. The captured image still contains only the element's box.
|
|
821
|
+
An overlay without authored clearance remains visible in the image; the instrument detects no
|
|
822
|
+
arbitrary occlusion. Viewport-dependent clearance participates in the same bounded settling loop,
|
|
823
|
+
so a frame whose geometry has not settled within that bound is refused.
|
|
665
824
|
Where the element's box lies outside the pane, the document is scrolled by the nearest distance that
|
|
666
825
|
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
|
-
|
|
826
|
+
that does not move it, and that scroll is handed back with the rest. Other short elements that need no
|
|
827
|
+
additional room keep their nearest native alignment.
|
|
669
828
|
|
|
670
829
|
The provider paints an element that fits the runner's window only where that window shows it. Where
|
|
671
830
|
such an element lies past the window, the `captureFrame` function offsets the calling tester frame up
|
|
@@ -694,8 +853,10 @@ pixels; a file with no PNG header is refused without a size.
|
|
|
694
853
|
|
|
695
854
|
`createPortfolio` refuses an unregistered variant name at creation, so a run cannot write a filename
|
|
696
855
|
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
|
-
|
|
856
|
+
resizes nothing, writes nothing, and records nothing, so a journey calls it unconditionally. It
|
|
857
|
+
still refuses an unregistered state and a second placement of one state, so a journey that names a
|
|
858
|
+
state wrongly fails the ordinary run rather than the first capture run; `placements` and `paths`
|
|
859
|
+
stay empty, because they answer for what was captured. An enabled `place` applies the variant and writes `<directory>/<state>--<variant>.png` through
|
|
699
860
|
`captureFrame`, so it stages the pane at the variant's size, covers the whole document, verifies the
|
|
700
861
|
written bytes, and records only a path that read back as this run's own frame. The tester comes back
|
|
701
862
|
at the viewport it had before the placement, so a journey that places a state carries on at its own
|
|
@@ -719,6 +880,12 @@ collision refusal before writing.
|
|
|
719
880
|
|
|
720
881
|
Imported from `@orkestrel/test/server`.
|
|
721
882
|
|
|
883
|
+
The provider command consumes the browser journey's resolved selector inside Vitest's tester frame.
|
|
884
|
+
|
|
885
|
+
| API | Kind | Signature | Summary |
|
|
886
|
+
| ------------- | -------- | --------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
|
|
887
|
+
| `chooseFiles` | function | `(context: ChooserContext, request: ChooserRequest) => Promise<void>` | Observes a native chooser before activating its input and supplies the verified chooser's fixture bytes. |
|
|
888
|
+
|
|
722
889
|
#### Types
|
|
723
890
|
|
|
724
891
|
A `Shape` cell holds an interface's data members as bare names in braces, `?` marking an optional
|
|
@@ -736,6 +903,7 @@ it adds after.
|
|
|
736
903
|
| `InventoryOptions` | interface | `{ extensions?, exclude? }` | Configures a source inventory read. |
|
|
737
904
|
| `UpgradeOptions` | interface | `WaitOptions` plus `{ path?, protocols? }` | Configures a client upgrade request. |
|
|
738
905
|
| `UpgradeResult` | type | `{ claimed, protocol } \| { claimed, status }` | Represents what one server did with a client upgrade request. |
|
|
906
|
+
| `ChooserContext` | interface | `{ page, iframe }` | Supplies the real Playwright page and tester frame to a native chooser command. |
|
|
739
907
|
|
|
740
908
|
#### Constants
|
|
741
909
|
|
|
@@ -753,7 +921,7 @@ A `Shape` cell holds the constant's declared type.
|
|
|
753
921
|
| ------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
|
|
754
922
|
| `readInventory` | function | `(root: URL \| string, targets: readonly string[], options?: InventoryOptions) => Readonly<Record<string, string>>` | Reads files from selected targets below a root directory. |
|
|
755
923
|
| `resolveContained` | function | `(root: string, target: string) => string \| undefined` | Resolves a target that stays below a root directory. |
|
|
756
|
-
| `requireContained` | function | `(root: string, target: string) => string` | Resolves a target that stays below a root directory, refusing
|
|
924
|
+
| `requireContained` | function | `(root: string, target: string) => string` | Resolves a target that stays below a root directory, refusing a path outside it. |
|
|
757
925
|
| `hasScratchPath` | function | `(root: string, target: string) => boolean` | Reports whether a contained entry exists under a scratch directory without following its final link. |
|
|
758
926
|
| `isExcluded` | function | `(key: string, exclusions: readonly string[]) => boolean` | Reports whether a root-relative key matches an exclusion. |
|
|
759
927
|
| `readIdentity` | function | `(status: Stats) => ScratchIdentity` | Reads the identity of one allocated directory off a host status. |
|
|
@@ -792,10 +960,10 @@ delete `resolveContained` and import `resolveContainedPath` from `@orkestrel/sca
|
|
|
792
960
|
package already carries as a `devDependency`, rather than adding a third variant.
|
|
793
961
|
|
|
794
962
|
`requireContained` is that same resolution with the refusal every contained scratch operation makes
|
|
795
|
-
of
|
|
963
|
+
of a path outside the root: it throws `Path outside scratch directory: <target>` where `resolveContained` answers
|
|
796
964
|
`undefined`. Every `ScratchInterface` member and the `files` seeding pass through it, so the check
|
|
797
|
-
and its one message are stated once rather than at each member. Read `resolveContained` where
|
|
798
|
-
|
|
965
|
+
and its one message are stated once rather than at each member. Read `resolveContained` where
|
|
966
|
+
a path outside the root is an answer the caller handles rather than a refusal it wants raised.
|
|
799
967
|
|
|
800
968
|
`isExcluded` is the exclusion rule itself, and `readInventory` applies it to a named target and a
|
|
801
969
|
walked entry alike. An exclusion matches whole segments of a root-relative key, so it drops the key
|
|
@@ -806,9 +974,9 @@ is exported because a consumer walking its own tree wants that rule rather than
|
|
|
806
974
|
what `exclude` means.
|
|
807
975
|
|
|
808
976
|
`matchesIdentity` is the comparison `destroy()` makes before it removes anything: whether the
|
|
809
|
-
identity read from the allocated path
|
|
977
|
+
identity read from the allocated path is the identity recorded when the directory was allocated.
|
|
810
978
|
All three fields are compared because none of them alone identifies an allocation. A device is
|
|
811
|
-
shared by every directory on one filesystem, an index node is reused
|
|
979
|
+
shared by every directory on one filesystem, an index node is reused after its directory is removed,
|
|
812
980
|
and a creation time repeats within the host's timestamp resolution. It is exported so a fixture that
|
|
813
981
|
manages its own directory can make the same check rather than trusting a path. `readIdentity` reads
|
|
814
982
|
that triple off a `node:fs` `Stats`, and it is the one reading `createScratch` takes at allocation,
|
|
@@ -867,7 +1035,7 @@ that names the mechanism it needs: an unprivileged Windows host answers `support
|
|
|
867
1035
|
`true` through a junction while answering `supportsFileLinks` `false`, so a fixture that reads a
|
|
868
1036
|
file through a link asks the second question rather than the first. `supportsMode` answers whether a
|
|
869
1037
|
permission bit is stored, which is narrower than whether it is enforced — a POSIX host running as
|
|
870
|
-
uid `0` stores every bit faithfully and
|
|
1038
|
+
uid `0` stores every bit faithfully and is exempt from the access check those bits describe, so a proof
|
|
871
1039
|
that needs a refusal probes that refusal itself.
|
|
872
1040
|
|
|
873
1041
|
#### Factories
|
|
@@ -889,7 +1057,7 @@ starts the generated directory name, and defaults to `orkestrel-test-`; allocati
|
|
|
889
1057
|
contains `/` or `\`, which is what stops a prefix steering the allocation out of its parent. Nothing
|
|
890
1058
|
else is refused: a fragment carrying no separator is one path segment, so `release-0..2-` allocates.
|
|
891
1059
|
`files` seeds files on allocation, keyed by path below the scratch directory; allocation removes the
|
|
892
|
-
directory it recently made and rethrows when a key
|
|
1060
|
+
directory it recently made and rethrows when a key resolves outside it or the host refuses a write.
|
|
893
1061
|
|
|
894
1062
|
`createLoopback` takes a `node:net` `Server` — `node:http`'s and `node:https`'s both extend it — and
|
|
895
1063
|
never constructs one. It listens on port `0` at `127.0.0.1`, waits for the `listening` event, and
|
|
@@ -903,6 +1071,24 @@ this package never reserves a port number.
|
|
|
903
1071
|
The call-signature members of each behavioral interface. Their `readonly` data members stay in the
|
|
904
1072
|
earlier [Surface](#surface) rows.
|
|
905
1073
|
|
|
1074
|
+
#### `SheetAdoption`
|
|
1075
|
+
|
|
1076
|
+
The adoption releases only the sheet it owns.
|
|
1077
|
+
|
|
1078
|
+
| Method | Signature | Summary |
|
|
1079
|
+
| --------- | ------------ | ----------------------------------------------------------------------- |
|
|
1080
|
+
| `release` | `() => void` | Removes this sheet from the document without removing another adoption. |
|
|
1081
|
+
|
|
1082
|
+
Release an adoption after the fixture has read its sheet.
|
|
1083
|
+
|
|
1084
|
+
```ts
|
|
1085
|
+
import type { SheetAdoption } from '@orkestrel/test/browser'
|
|
1086
|
+
import { adoptSheet } from '@orkestrel/test/browser'
|
|
1087
|
+
|
|
1088
|
+
const adopted: SheetAdoption = adoptSheet('@layer example {}')
|
|
1089
|
+
adopted.release()
|
|
1090
|
+
```
|
|
1091
|
+
|
|
906
1092
|
#### `RecorderInterface`
|
|
907
1093
|
|
|
908
1094
|
| Method | Returns | Summary |
|
|
@@ -1086,51 +1272,66 @@ what the link reaches, not on what it stores.
|
|
|
1086
1272
|
Every message `src/browser` throws. Keep them distinct: a journey asserts the one it means, and
|
|
1087
1273
|
absent, present-but-gated, and ambiguous are different findings about an interface.
|
|
1088
1274
|
|
|
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
|
-
| `
|
|
1275
|
+
| Voice | Thrown by |
|
|
1276
|
+
| ---------------------------------------------------------------------------------------- | ---------------------------------------------- |
|
|
1277
|
+
| `No interactive element has the accessible name "<name>"` | `resolveRendered` |
|
|
1278
|
+
| `Interactive target "<name>" is not visible and focus-reachable` | `resolveRendered` |
|
|
1279
|
+
| `Interactive target "<name>" is ambiguous across <n> elements` | `resolveRendered` |
|
|
1280
|
+
| `Interactive target "<name>" could not be resolved` | `resolveRendered` |
|
|
1281
|
+
| `Interactive target "<name>" is unreachable after scrolling` | `resolveAccessible` |
|
|
1282
|
+
| `Interactive target "<name>" is not reachable inside "<region>"` | `resolveAccessibleWithin` |
|
|
1283
|
+
| `Interactive target "<name>" is ambiguous across <n> elements inside "<region>"` | `resolveAccessibleWithin` |
|
|
1284
|
+
| `Interactive target "<name>" could not be resolved inside "<region>"` | `resolveAccessibleWithin` |
|
|
1285
|
+
| `Native disclosure "<name>" is not visible and focus-reachable` | `clickDisclosure` |
|
|
1286
|
+
| `Native disclosure "<name>" is ambiguous across <n> elements` | `clickDisclosure` |
|
|
1287
|
+
| `Native disclosure "<name>" could not be resolved` | `clickDisclosure` |
|
|
1288
|
+
| `The element is not connected to a document, so it has no point to read` | `readProtocolPoint` |
|
|
1289
|
+
| `Interactive target "<name>" is not reachable through forward Tab traversal: <trail>` | `driveTraversal` |
|
|
1290
|
+
| `Named region "<name>" is not visible` | `readPerception` |
|
|
1291
|
+
| `Named region "<name>" is ambiguous across <n> elements` | `readPerception` |
|
|
1292
|
+
| `Named region "<name>" could not be resolved` | `readPerception` |
|
|
1293
|
+
| `Interactive target "<name>" does not carry a value` | `readValue` |
|
|
1294
|
+
| `Computed foreground color is unavailable` | `readContrast` |
|
|
1295
|
+
| `Computed background color is unavailable` | `readColorContrast` |
|
|
1296
|
+
| `Color "<value>" is unreadable` | `readColorContrast` |
|
|
1297
|
+
| `Contrast opacity must be between 0 and 1` | `readColorContrast` |
|
|
1298
|
+
| `The element is not connected to a document, so it has no clipping ancestors to read` | `collectClippingAncestors`, `readClippedBlock` |
|
|
1299
|
+
| `Tester pane is unavailable for a capture` | `stagePane` |
|
|
1300
|
+
| `Tester pane rendered <w>x<h> for a <w>x<h> viewport` | `stagePane` |
|
|
1301
|
+
| `Capture frame at <path> never settled after <n> restagings: <h> over a <h> pane` | `captureFrame` |
|
|
1302
|
+
| `Capture frame was written to <path> where <path> was asked for` | `captureFrame` |
|
|
1303
|
+
| `Capture frame at <path> is not the one this run shot` | `captureFrame` |
|
|
1304
|
+
| `Capture frame at <path> could not be read` | `readFrame` |
|
|
1305
|
+
| `Capture frame at <path> is not an image this browser decodes` | `readFrame` |
|
|
1306
|
+
| `Capture frame at <path> is not an image this browser decodes: <w>x<h> device pixels` | `readFrame` |
|
|
1307
|
+
| `Capture frame at <path> cannot be measured without a 2D canvas` | `readFrame` |
|
|
1308
|
+
| `Shot is not an image this browser decodes` | `readShotPixel` |
|
|
1309
|
+
| `Shot cannot be measured without a 2D canvas` | `readShotPixel` |
|
|
1310
|
+
| `Shot pixel position must be a fraction from 0 to 1` | `readShotPixel` |
|
|
1311
|
+
| `Capture variant "<name>" is not registered` | `createPortfolio` |
|
|
1312
|
+
| `Capture state "<state>" is not registered` | `place` |
|
|
1313
|
+
| `Capture state "<state>" is already placed` | `place` |
|
|
1314
|
+
| `IndexedDB database "<name>" could not be deleted` | `removeDatabase` |
|
|
1315
|
+
| `IndexedDB database "<name>" is blocked by an open connection` | `removeDatabase` |
|
|
1316
|
+
| `Key sequence "<keys>" was sent with nothing focused` | `pressKeys` |
|
|
1317
|
+
| `Focus sits in a frame from another origin, which cannot be read` | `readActiveElement` |
|
|
1318
|
+
| `Focus traversal did not end` | `walkFocus` |
|
|
1319
|
+
| `The start element cannot take focus` | `collectTabStops` |
|
|
1320
|
+
| `Stability frames must be a positive integer` | `waitForStability` |
|
|
1321
|
+
| `Condition "<description>" did not hold within <n>ms (waited <n>ms)` | `waitForStability` |
|
|
1322
|
+
| `Condition "<subject>" did not hold within <n>ms (waited <n>ms) (last states: <states>)` | `waitForState` |
|
|
1323
|
+
| `Animation subject is not connected` | `waitForAnimations` |
|
|
1324
|
+
| `Animation "<subject>" did not settle within <n>ms (waited <n>ms): <animations>` | `waitForAnimations` |
|
|
1325
|
+
| `Class census walked no element` | `readCensus` |
|
|
1326
|
+
| `Contrast control cannot straddle the bar <bar>` | `buildContrast` |
|
|
1327
|
+
| `Access is denied for <operation> "<key>"` | `buildDenial` |
|
|
1328
|
+
| `No room is left for <key>` | `createStorage` |
|
|
1329
|
+
| `Storage quota must be a non-negative integer` | `createStorage` |
|
|
1330
|
+
| `Statechart harness mounted no transition` | `createHarness` |
|
|
1331
|
+
| `Statechart harness carries no status` | `status` |
|
|
1332
|
+
|
|
1333
|
+
`readContrast` measures through `readColorContrast`, so its background refusal is that row's voice,
|
|
1334
|
+
and `readRing` never raises it, because it names `CANVAS_COLOR` as the floor on every reading.
|
|
1134
1335
|
|
|
1135
1336
|
Some of those rows are not plain `Error` messages. `buildDenial` returns a `DOMException` named
|
|
1136
1337
|
`SecurityError`, `createStorage` raises that one from every operation the permission withholds and a
|
|
@@ -1144,7 +1345,8 @@ states it last read, so an exhausted wait says what the control was announcing i
|
|
|
1144
1345
|
`waitForAnimations` names the subject through `readRole` and `readName` and lists the animations
|
|
1145
1346
|
still running. Both validate their bounds through `checkBounds`, which raises
|
|
1146
1347
|
`Wait budget must be finite and non-negative` for the first and `Animation budget must be finite and
|
|
1147
|
-
non-negative` for the second.
|
|
1348
|
+
non-negative` for the second. `settleCapture` raises the `waitForAnimations` voices unchanged, and
|
|
1349
|
+
because it waits on the document's root element, an exhausted settle names `html` as its subject.
|
|
1148
1350
|
|
|
1149
1351
|
Some of them are narrowing rather than findings, and no input reaches them. Each `could not be
|
|
1150
1352
|
resolved` is one: a preceding length check does not narrow the later lookup under
|
|
@@ -1162,27 +1364,39 @@ disk disagrees with the bytes the provider handed back — which a provider that
|
|
|
1162
1364
|
never produces, so the suite proves that comparison discriminates with a planted file rather than by
|
|
1163
1365
|
reaching the refusal. `Capture frame at <path> cannot be measured without a 2D canvas` is narrowing
|
|
1164
1366
|
of the same kind: a canvas allocated for this reading and asked for no other context type hands one
|
|
1165
|
-
back.
|
|
1367
|
+
back. `readShotPixel` carries the same pair for a shot the provider hands back rather than a file:
|
|
1368
|
+
`Shot cannot be measured without a 2D canvas` is that narrowing, and `Shot is not an image this
|
|
1369
|
+
browser decodes` fires only where the provider returns bytes that are not the image it shot. Both
|
|
1370
|
+
readers decode and draw through `paintImage`, which hands the decode failure and a missing context
|
|
1371
|
+
on to the caller to word, so the decode is driven there with bytes that are no image. The
|
|
1372
|
+
`Shot pixel position must be a fraction from 0 to 1` refusal is driven, by a fraction below `0`,
|
|
1373
|
+
above `1`, and `NaN`. The remaining refusals of the `readFrame` function are driven, by a path holding no file, by a
|
|
1166
1374
|
file holding no image, and by a PNG header over no image data, and so is
|
|
1167
1375
|
`Capture frame at <path> never settled after <n> restagings`, by a fixture whose full-height panel
|
|
1168
1376
|
grows with every pane the capture stages.
|
|
1169
1377
|
|
|
1170
1378
|
The pointer, pseudo-element, and media helpers add the following voices.
|
|
1171
1379
|
|
|
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
|
-
| `
|
|
1380
|
+
| Voice | Thrown by |
|
|
1381
|
+
| ------------------------------------------------------------- | ------------------ |
|
|
1382
|
+
| `Browser provider exposes no DevTools session` | `sendProtocol` |
|
|
1383
|
+
| `Pointer is already held at <x>x<y>` | `driveHold` |
|
|
1384
|
+
| `Interactive target "<name>" did not enter the pressed state` | `driveHold` |
|
|
1385
|
+
| `Protocol search returned no search id` | `readProtocolNode` |
|
|
1386
|
+
| `Protocol search found <n> elements where one is required` | `readProtocolNode` |
|
|
1387
|
+
| `Protocol search returned no node id` | `readProtocolNode` |
|
|
1388
|
+
| `Pseudo-element "<pseudo>" must start with "::"` | `readStyle` |
|
|
1389
|
+
| `Pseudo-element "<pseudo>" is not one this engine exposes` | `readStyle` |
|
|
1390
|
+
| `Media emulation was staged with nothing to emulate` | `stageMedia` |
|
|
1391
|
+
| `Media emulation did not reach the tester: <query>` | `stageMedia` |
|
|
1392
|
+
| `Media emulation did not clear from the tester` | `releaseMedia` |
|
|
1182
1393
|
|
|
1183
1394
|
The resolver's absent, gated, ambiguous, and unreachable voices stay unchanged. The DevTools-session
|
|
1184
1395
|
and media-delivery refusals guard provider failures the managed Chromium suite doesn't induce.
|
|
1185
1396
|
The suite exercises real delivery rather than substituting a provider that manufactures a failure.
|
|
1397
|
+
`readAccessibilityNode` raises the `readProtocolNode` voices unchanged. Of those, `found <n>
|
|
1398
|
+
elements` is driven, by a detached element. The other two narrow a reply that omits `searchId` or
|
|
1399
|
+
`nodeIds`, which the browser never sends, so they guard a provider that does.
|
|
1186
1400
|
|
|
1187
1401
|
### Refusals outside the journey layer
|
|
1188
1402
|
|
|
@@ -1258,7 +1472,7 @@ These hold across `src/core`, `src/browser`, `src/server`, and this guide.
|
|
|
1258
1472
|
nor a directory, or when a target resolves outside the root. A missing target surfaces the host's
|
|
1259
1473
|
own `ENOENT` rather than a message from this package. It skips a symlink met while walking rather
|
|
1260
1474
|
than following it. A target may be written relative to the root or as an absolute path inside it,
|
|
1261
|
-
and one that
|
|
1475
|
+
and one that resolves outside the root is refused either way.
|
|
1262
1476
|
|
|
1263
1477
|
A link in the **middle** of a named target is a separate refusal, and the only one that reaches
|
|
1264
1478
|
it: the symbolic-link check reads the final segment, which such a link is not. The named target is
|
|
@@ -1289,13 +1503,13 @@ These hold across `src/core`, `src/browser`, `src/server`, and this guide.
|
|
|
1289
1503
|
case are the same file varies by filesystem, so the suite probes the running host and asserts
|
|
1290
1504
|
what the probe returned instead of assuming either answer.
|
|
1291
1505
|
|
|
1292
|
-
7. **`createScratch` refuses a
|
|
1506
|
+
7. **`createScratch` refuses a path lexically outside its directory, not a symbolic link.** It allocates with
|
|
1293
1507
|
`mkdtempSync` below `parent`, which creates the directory at mode `0700` on a host that applies
|
|
1294
1508
|
POSIX permission bits. The suite gates that assertion on `supportsMode`, so the mode is proven
|
|
1295
1509
|
where the probe answers `true` and the case is skipped where it answers `false`. A Windows host
|
|
1296
1510
|
answers `false` and reads the same allocation back as `0666`, so the bits describe nothing it
|
|
1297
1511
|
applies. Every member that takes a target — `write`, `read`, `has`, `names`, `ensure`, `link`,
|
|
1298
|
-
and `remove` — throws when that target lexically
|
|
1512
|
+
and `remove` — throws when that target lexically resolves outside the allocated directory, and a failed
|
|
1299
1513
|
seed removes the directory before rethrowing. `remove` adds a refusal the others do not need: a
|
|
1300
1514
|
target naming the allocation itself, lexically or through an intermediate symbolic link. The
|
|
1301
1515
|
lexical half compares paths. The physical half reads only the final entry with `lstat` and
|
|
@@ -1392,7 +1606,7 @@ These hold across `src/core`, `src/browser`, `src/server`, and this guide.
|
|
|
1392
1606
|
lists every member with the reading it breaks. Every member makes a naive read throw or violates
|
|
1393
1607
|
a naive structural assumption; a total guard survives every member without throwing. Each has a
|
|
1394
1608
|
direct probe for that failure. The negative control keeps an inert value from entering the corpus
|
|
1395
|
-
under a
|
|
1609
|
+
under a name suggesting untrusted input. Whether it accepts or refuses one is that guard's own contract. Membership
|
|
1396
1610
|
may grow in a release, so consumers loop over the whole array, assert their guard's expected
|
|
1397
1611
|
answer per index, and attribute each failure by that index instead of naming or counting members
|
|
1398
1612
|
locally.
|
|
@@ -1402,10 +1616,11 @@ These hold across `src/core`, `src/browser`, `src/server`, and this guide.
|
|
|
1402
1616
|
into a description of the markup. `build` creates a node, `mount` attaches one, `render` does
|
|
1403
1617
|
both, `clearStorage` takes nothing at all, and `removeDatabase` takes a database name. The
|
|
1404
1618
|
predicates, the element readers, and the describers do take a node —
|
|
1405
|
-
`isRendered`, `isReachable`, `readHit`, `readText`, `readRole`, `readName`, `readStates`,
|
|
1619
|
+
`isRendered`, `isReachable`, `supportsSegmentedFocus`, `readHit`, `readText`, `readRole`, `readName`, `readStates`,
|
|
1406
1620
|
`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
|
|
1621
|
+
`readToken`, `readPixels`, `readContrast`, `readColorContrast`, `readLayers`, `readBackdrop`,
|
|
1622
|
+
and `readRing` — and each is a reader of a node the caller already has rather than a verb that
|
|
1623
|
+
acts on a target.
|
|
1409
1624
|
`waitForAnimations` takes one as the subject of a wait, and waiting for a browser to stop
|
|
1410
1625
|
painting it changes nothing about it. `buildContrast`, `buildEscapes`, and `buildCensus` return
|
|
1411
1626
|
detached nodes for the caller to append and remove, the way `build` does. `captureFrame`
|
|
@@ -1504,7 +1719,7 @@ These hold across `src/core`, `src/browser`, `src/server`, and this guide.
|
|
|
1504
1719
|
stopped, and `steps` and `output` hand out snapshots. There is no shared instance: a file that
|
|
1505
1720
|
needs one journal per scenario creates one per scenario.
|
|
1506
1721
|
18. **The capture layer depends on the Vitest runner's own tester layout, deliberately.** A
|
|
1507
|
-
screenshot is taken off the page the runner painted, and `vitest@4.1.
|
|
1722
|
+
screenshot is taken off the page the runner painted, and `vitest@4.1.12` lays its tester out
|
|
1508
1723
|
inside a smaller page and fits it by scaling the pane the tester sits in, so a frame shot through
|
|
1509
1724
|
that scale is a thumbnail of the surface. `stagePane` therefore reaches into that layout: the
|
|
1510
1725
|
`iframe[data-vitest]` selector and the `--tester-transform`, `--tester-margin-left`,
|
|
@@ -1526,7 +1741,8 @@ These hold across `src/core`, `src/browser`, `src/server`, and this guide.
|
|
|
1526
1741
|
the one before it produced so a converging document lands on its fixed point rather than
|
|
1527
1742
|
creeping toward it. The re-reading is bounded by `CAPTURE_STAGINGS`, and a document still
|
|
1528
1743
|
growing at that bound is refused rather than photographed at a stale height. An element frame
|
|
1529
|
-
keeps the declared pane unless its element
|
|
1744
|
+
keeps the declared pane unless its element needs more room with its native scroll clearance,
|
|
1745
|
+
and offsets the calling tester frame only
|
|
1530
1746
|
as far as brings the element inside the runner's window. What
|
|
1531
1747
|
the capture borrows it gives back: the `releasePane` function returns the tester to the viewport
|
|
1532
1748
|
it held before the staging, the capture then restores the tester's scroll position, even where
|
|
@@ -1553,6 +1769,13 @@ These hold across `src/core`, `src/browser`, `src/server`, and this guide.
|
|
|
1553
1769
|
still read `running` would strand the gate on a reading the harness never leaves. The gate stays
|
|
1554
1770
|
outside this package: the harness carries its own tally, so nothing here reads a harness back,
|
|
1555
1771
|
and no page is generated or published to host one.
|
|
1772
|
+
20. **Sheet adoption releases only its own stylesheet.** Repeated release leaves other adoptions
|
|
1773
|
+
intact. [`tests/src/browser/sheets/helpers.test.ts`](../tests/src/browser/sheets/helpers.test.ts)
|
|
1774
|
+
proves independent adoptions and repeated release.
|
|
1775
|
+
21. **File drags carry trusted `Files` events to rendered targets.** A destination need not be
|
|
1776
|
+
focusable. The file-drag cases in
|
|
1777
|
+
[`tests/src/browser/journeys/helpers.test.ts`](../tests/src/browser/journeys/helpers.test.ts)
|
|
1778
|
+
prove trusted entry, over, and leave events over a status outside the Tab order.
|
|
1556
1779
|
|
|
1557
1780
|
### Threat model
|
|
1558
1781
|
|
|
@@ -1566,15 +1789,15 @@ that applies POSIX permission bits, and the suite asserts that mode where `suppo
|
|
|
1566
1789
|
answers `false` the mode protects nothing, and the allocation carries only the access its parent
|
|
1567
1790
|
directory already gives. The mode does not keep out a sibling test worker or the code under test on
|
|
1568
1791
|
any host, because both run as the same uid, and they are the population that would create a link
|
|
1569
|
-
here. Its containment check is lexical: it refuses a relative path that
|
|
1792
|
+
here. Its containment check is lexical: it refuses a relative path that resolves outside the allocated
|
|
1570
1793
|
directory, which is the accident that actually happens — a test writing `../foo`. It does not walk
|
|
1571
1794
|
the path's segments for symbolic links, because per-segment walking is sandbox behavior and this is
|
|
1572
1795
|
not a sandbox.
|
|
1573
1796
|
|
|
1574
1797
|
So a link inside the allocation was created by the test process or by the code the test drives, and
|
|
1575
1798
|
handing `scratch.path` to the code under test is the ordinary use of this helper. `link` is this
|
|
1576
|
-
package's own entry in that population: it creates a symbolic link on request, it refuses only
|
|
1577
|
-
|
|
1799
|
+
package's own entry in that population: it creates a symbolic link on request, it refuses only a
|
|
1800
|
+
target outside its directory, and its source may name anything. The source stays unchecked except on the fallback
|
|
1578
1801
|
path, which stats it to decide whether a junction can point there. [Traversal](#traversal) states
|
|
1579
1802
|
what each member does with a link it meets, and a contained path reaching outside the allocation
|
|
1580
1803
|
through one is the result. This helper does not defend against that.
|
|
@@ -1618,7 +1841,7 @@ a time in the following table, and some of them ship while others do not.
|
|
|
1618
1841
|
|
|
1619
1842
|
A member is one implementation group carried by one package, under whatever name that package
|
|
1620
1843
|
spells it and whether it exports the helper or declares it inside a test file. Repeated calls routed
|
|
1621
|
-
through one shared implementation stay one member, and a set of
|
|
1844
|
+
through one shared implementation stay one member, and a set of unexpected values fed through one
|
|
1622
1845
|
totality loop is one member rather than one per value. Read the first column as the group rather
|
|
1623
1846
|
than as an export: **nothing in this section is importable**, and the only names you can install are
|
|
1624
1847
|
in [Surface](#surface).
|
|
@@ -1630,12 +1853,12 @@ or when a consumer appears the ruling did not consider.
|
|
|
1630
1853
|
| Candidate | Ruling | Why |
|
|
1631
1854
|
| ------------------------------------------------------------------------------------------------ | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1632
1855
|
| A recorder map over an emitter's events, with its map, event-map, subscriber, and totality types | Ships | It ships as `createRecorders`, with `RecorderMap` and `EventSourceInterface` beside it. Inference is what the earlier refusal turned on, and the shape improves it without settling it: a source parameter typed `EventSourceInterface<TMap>` is an inference site, so a call against one names no type argument, while a concrete class supplies none and the call names both. A keying limit survives that: `TName` derives from the events array's element type, so an array declared with a wider union than its contents keys the map past the events actually listed, and [Bounds a shipped helper carries](#bounds-a-shipped-helper-carries) states what to pass instead. A published signature still cannot import a consumer's event map, so the interface asks for the subscribe half alone and the consumer's own map is what it is instantiated with. |
|
|
1633
|
-
|
|
|
1856
|
+
| Unexpected guard-input sets | Ships | `form`, `table`, and `supervisor` each feed one unexpected-value set through total readers, and the set is a mechanism rather than a policy: a guard's own contract decides the answers, not the corpus. It ships as `createHostileValues`; its members do not each become a factory, and every member carries a naive-reader negative control. |
|
|
1634
1857
|
| Raw invocation — `invokeRaw` | Ships | It ships as `invokeUnchecked`, with `readProperty` beside it for the read. Native `Reflect.apply` still makes the call; what these add is the boundary — a callability refusal before the call, a target refusal before the read, and one named place where an unchecked runtime result meets the type its caller claims. The claim stays the caller's, and so does the guard that narrows what came back. Without them a consumer that bans `as` cannot drive a foreign object at all. |
|
|
1635
1858
|
| Condition polling — wall-clock predicate loops | Ships | The wait-family contract states the distinction: the no-polling architecture law governs a product's idle wakeup, and a test instrument waiting on a fact another process produces has no event to park on. It ships as `waitForCondition`. `retryUntil` ships on the same reading, because retrying a real operation is not re-reading a predicate; and where an event does exist, `waitForEvent` is the door. |
|
|
1636
1859
|
| Deep nesting beyond a guard's cap | Refused | `table` builds a record chain and `supervisor` builds nested arrays. The two nest different containers, so one shared factory needs a selector argument that changes the construction algorithm — a mode switch rather than a mechanism. |
|
|
1637
1860
|
| Canonical wire fixpoint assertions | Refused | `form` and `table` each serialize, parse untrusted JSON, serialize again, and compare exact bytes. The comparison is an assertion over the consumer's own codecs rather than a reusable mechanism, so the shape stays consumer-local and [Prove a wire fixpoint](#prove-a-wire-fixpoint) publishes the pattern instead. |
|
|
1638
|
-
| Numeric corpora,
|
|
1861
|
+
| Numeric corpora, unexpected-key tables, and deep-freeze | Refused | A numeric corpus or an unexpected-object table is test policy — what a given suite decided to check — rather than a mechanism, and one factory covering the variants would need a mode argument. `createHostileValues` ships because a guard's totality is a property of the guard; these encode a decision about coverage. |
|
|
1639
1862
|
| Clearing web storage between tests | Ships | Emptying local and session storage together is one mechanism, and the `afterEach` hook that must run after a failed test too is where every browser suite needs it. It ships as `clearStorage`. |
|
|
1640
1863
|
| Class-ancestry orphan detection | Ships | A rendered element carrying a child class with no container class above it is a real invariant a stylesheet cannot state, and the check is mechanism when the class names are parameters rather than one framework's. It ships as `extractOrphans(root, child, parent)`. |
|
|
1641
1864
|
| A DOM element builder | Ships | It ships as `build` for the element and `mount` for the attachment, and `render` widened to take a tag and its class list as well as markup. A class list, a text, and an attribute map are what a fixture actually varies, and expressing that variation through markup means assembling a string. Nothing here assembles a tree one call at a time: a fixture with children is still written as markup. |
|
|
@@ -1706,16 +1929,59 @@ the helper rather than to the host, and each names what to reach for instead.
|
|
|
1706
1929
|
used; it is covered by review. The measured layout is a single accessible, uniformly scaled tester
|
|
1707
1930
|
iframe. A covered centre or unsupported geometry can refuse even when the resolver accepts the
|
|
1708
1931
|
target. The verb inherits the resolver's focus reachability conditions.
|
|
1932
|
+
- **`parkPointer` ends hover and never ends a press.** It moves the pointer to (-1, -1) and waits for
|
|
1933
|
+
a frame, and it sends no button-up, so a press that the `holdAccessible` verb holds stays recorded under
|
|
1934
|
+
`POINTER_HOLD` and its button-up is still owed to `releasePointer`. The control the press was on
|
|
1935
|
+
loses both its `:hover` paint and its `:active` paint when the pointer leaves it. Use it where a case clears hover with no
|
|
1936
|
+
press held, and never as a teardown for a hold.
|
|
1709
1937
|
- **`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
|
|
1938
|
+
which can produce a click. It then clears hover through `parkPointer`, which moves to (-1, -1) in
|
|
1939
|
+
the runner page's coordinates, one pixel above and to the left of that page's viewport. The
|
|
1940
|
+
browser hit-tests nothing outside the viewport, so no element takes a `mouseover` event or hover
|
|
1941
|
+
paint from the parked pointer until the next pointer verb. This holds even where a staging,
|
|
1942
|
+
scroll, or offset lays content over the park point. Register it with `afterEach` before a hover
|
|
1715
1943
|
or hold. A second release sends no button-up event. Holds must not overlap. A rejected press
|
|
1716
1944
|
leaves no marker. A rejected release keeps the marker for a retry and still attempts the park. If
|
|
1717
1945
|
that park also rejects, the park's error surfaces with the release rejection attached in the
|
|
1718
1946
|
aggregate's errors; the park rejection is its cause.
|
|
1947
|
+
- **`walkFocus` reports every stop it can read and refuses none of them.** It records the focused
|
|
1948
|
+
element and then presses Tab through `stepFocus`, the one Tab loop that `driveTraversal` shares,
|
|
1949
|
+
and returns what focus reached, so a focusable scroll container that Chromium focuses without a
|
|
1950
|
+
`tabindex` is a stop, and `describeFocus` omits it. Each stop is the innermost element
|
|
1951
|
+
`readActiveElement` reads, so a control inside an open shadow root or a same-origin frame is a stop
|
|
1952
|
+
of its own and its host or frame element is not. A non-HTML control inside one, such as an SVG
|
|
1953
|
+
element, reads as `undefined` rather than as its host, and `readFocus` follows it. A closed shadow root cannot be entered, so its
|
|
1954
|
+
host stands for what it holds, and focus in a frame from another origin throws, because the page
|
|
1955
|
+
cannot name a control there. A hidden or disabled stop is returned like any other. A consumer that
|
|
1956
|
+
refuses one throws from the predicate it passes. The walk ends where focus returns to the body or
|
|
1957
|
+
revisits a stop, except that consecutive landings on the same native segmented input pass through
|
|
1958
|
+
its segments and contribute one stop, up to `FOCUS_SEGMENT_LIMIT` landings including the initial
|
|
1959
|
+
focused element. A longer run or a consecutive repeat on any other element ends the walk.
|
|
1960
|
+
Any different landing starts a separate run. The press cap is `FOCUS_SEGMENT_LIMIT` times the count `countElements` reads, which includes
|
|
1961
|
+
open shadow roots and same-origin frames; exceeding it throws. A control inside a same-origin frame belongs to the
|
|
1962
|
+
frame's window, so it fails this window's `instanceof HTMLElement`. `collectTabStops` is the same
|
|
1963
|
+
walk bounded to a region by `containsNode`, which places a control inside an open shadow root or a
|
|
1964
|
+
same-origin frame in the region that holds its host or frame element. The start element is the
|
|
1965
|
+
walk's origin and never its end, so a start immediately before the region, outside it, reaches the
|
|
1966
|
+
region's first stop with the first press.
|
|
1967
|
+
- **`waitForStability` compares the last `frames + 1` reads.** The first read is immediate and each
|
|
1968
|
+
later read follows a painted frame, with the interval slept between polls, so the reads are not on
|
|
1969
|
+
consecutive frames when the interval is longer than one. A reading that settles on read `n`
|
|
1970
|
+
resolves on read `n + frames`. The default is four frames; the budget and interval are those of
|
|
1971
|
+
`waitForCondition`. A reading that changes on every read exhausts the budget, and the refusal names
|
|
1972
|
+
the description. The budget and the abort signal are checked between reads, so a frame that never
|
|
1973
|
+
paints is not bounded by either. The `releaseMedia` function with nothing staged waits through it
|
|
1974
|
+
for one frame.
|
|
1975
|
+
- **`settleCapture` holds endless animations until its resume runs.** It parks the pointer through
|
|
1976
|
+
`parkPointer`, so a held press stays held and only loses its hover and pressed paint; `pointer: false`
|
|
1977
|
+
leaves the pointer, its hover, and that paint where they are. It waits out every finite animation
|
|
1978
|
+
in the document, root element included, then pauses each endless one at its first frame and
|
|
1979
|
+
resolves to the resume. Call the resume from a `finally` block after the frame is shot. A settle
|
|
1980
|
+
whose wait exhausts throws before it holds anything, so it owes no resume.
|
|
1981
|
+
- **`readShotPixel` reads a shot at the runner's scale.** The position is a fraction of the shot,
|
|
1982
|
+
and a fraction of `1` reads its last row or column. Where the runner scales the tester, the shot's
|
|
1983
|
+
edge pixels can blend with what lies beside the element, so read a pixel inside a painted band rather
|
|
1984
|
+
than on its edge.
|
|
1719
1985
|
- **`stageMedia` overrides the provider page, and `releaseMedia` restores the first stage's
|
|
1720
1986
|
readings.** Pin a base with `{ motion: true }` rather than assuming the host prefers motion.
|
|
1721
1987
|
`motion: false` stages reduced motion; `print: true` stages print, and `print: false` stages
|
|
@@ -1724,28 +1990,70 @@ the helper rather than to the host, and each names what to reach for instead.
|
|
|
1724
1990
|
other emulated feature the provider configured is cleared. An empty `{}`
|
|
1725
1991
|
refuses. Each staged query has a 1000 ms read-back budget with a 10 ms poll interval; refusal
|
|
1726
1992
|
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
|
-
|
|
1993
|
+
failure is attached as the refusal's cause. The pointer refusal proof passes an unsupported runtime
|
|
1994
|
+
pointer value through the JavaScript boundary and checks restoration after read-back exhaustion.
|
|
1995
|
+
The first stage records print, reduced motion, dark colour scheme, and forced colours on the
|
|
1996
|
+
tester root under `MEDIA_STAGE`, as a bit string in that order (`1` for a match, `0` otherwise).
|
|
1997
|
+
The first pointer stage appends a fifth bit for the pre-call coarse-pointer reading; later pointer
|
|
1998
|
+
stages retain it. A stage without a pointer keeps the four-bit marker until a pointer stage occurs.
|
|
1999
|
+
Release restores those readings as explicit emulation rather than removing every override, waits
|
|
2000
|
+
per axis for its recorded value, and removes the marker. A release whose wait exhausts keeps
|
|
2001
|
+
`MEDIA_STAGE` on the tester root, so the next `releaseMedia` retries from the same recorded
|
|
2002
|
+
readings. A release with nothing staged clears media overrides and compares readings taken
|
|
2003
|
+
strictly after the reset until they are stable.
|
|
1736
2004
|
Stability doesn't prove the engine's own baseline. Each release read-back has a 1000 ms budget and
|
|
1737
2005
|
waits for a frame per poll, with 10 ms between polls. The budget is checked between polls, so a
|
|
1738
2006
|
frame that never paints is not bounded by it. Media scopes must not overlap. The browser project
|
|
1739
2007
|
runs files serially.
|
|
2008
|
+
- **Pointer emulation also changes hover.** `pointer: 'coarse'` enables touch emulation with one
|
|
2009
|
+
touch point and reads `(pointer: coarse)`, `(any-pointer: coarse)`, `(hover: none)`, and
|
|
2010
|
+
`(any-hover: none)`. `pointer: 'fine'` disables touch emulation and reads fine precision with
|
|
2011
|
+
hover support. A pointer stage and its release preserve precision, not an earlier maximum
|
|
2012
|
+
touch-point count. Staging and releasing media without a pointer axis sends no touch-emulation
|
|
2013
|
+
command, including an unstaged release.
|
|
2014
|
+
- **Touch input requires a Chromium protocol session.** `tapTouch` enables touch emulation, waits
|
|
2015
|
+
for the touch layout's box to settle, then sends a single-point start and end. It does not scroll
|
|
2016
|
+
or check focus reachability. A tap that
|
|
2017
|
+
stops a scroller's momentum can produce no click. `releaseTouch` tolerates Chromium's idle
|
|
2018
|
+
cancellation refusal, disables emulation, and parks without sending a mouse release. Parking
|
|
2019
|
+
does not prove that sticky touch hover cleared. A native drag holding the mouse needs its own
|
|
2020
|
+
`mouseReleased` protocol command before parking. Touch cleanup also disables a coarse pointer
|
|
2021
|
+
staged by `stageMedia`, leaving `(pointer: fine)` while `MEDIA_STAGE` stays unchanged. Stage
|
|
2022
|
+
`pointer: 'coarse'` again after cleanup when later steps need it. `releaseMedia` still restores
|
|
2023
|
+
the reading recorded before the first pointer stage. A first pointer stage while tap emulation
|
|
2024
|
+
is live records coarse. In teardown, call `releaseMedia` before `releaseTouch`. The reverse
|
|
2025
|
+
order restores coarse emulation with one touch point after touch cleanup.
|
|
2026
|
+
- **File cancellation must leave the target first.** Chromium raises no `dragleave` for protocol
|
|
2027
|
+
cancellation alone. `sendFileDrag` first moves outside the page. It writes named fixture files
|
|
2028
|
+
under `tmp/drag`, refuses names containing a path, and sends no drop or file-content delivery.
|
|
2029
|
+
- **Layer names follow declaration order at every depth.** `readLayerNames` descends through
|
|
2030
|
+
grouping and style rules, qualifying each statement and block by its enclosing layer. It includes
|
|
2031
|
+
anonymous layers and repeated names, and reads conditions whether or not they match the document.
|
|
2032
|
+
An anonymous nested layer contributes a trailing dot to its enclosing qualified name.
|
|
2033
|
+
An `@import ... layer()` rule contributes nothing, and neither do its imported sheet's rules.
|
|
2034
|
+
A dotted declaration such as `@layer a.b` contributes `a.b` as declared, without an implicit `a`.
|
|
2035
|
+
Distinct anonymous layers produce the same names; the result does not distinguish their identities.
|
|
1740
2036
|
- **`readStyle` refuses a pseudo argument rather than ignoring it.** The argument must start with
|
|
1741
2037
|
`::` before the engine's selector-support check runs. A supported pseudo-element with no value for
|
|
1742
2038
|
the requested property still reads as an empty string. `readPixels` uses the same guard.
|
|
1743
2039
|
- **`sendProtocol` reaches a Chromium-family provider alone.** It needs the provider's DevTools
|
|
1744
|
-
session, passes the named command and parameters through, and
|
|
1745
|
-
|
|
2040
|
+
session, passes the named command and parameters through, and resolves the reply as `unknown`.
|
|
2041
|
+
Narrow the reply with guards before reading a field, and omit the parameters for a command that
|
|
2042
|
+
takes none. Browser termination cannot promise cleanup. Edge observations belong to a separate run.
|
|
2043
|
+
It resolves the reply since 0.0.27, where 0.0.26 resolved nothing. A callback typed to return
|
|
2044
|
+
`void | Promise<void>`, such as a teardown or an `onTestFinished` hook, that returns
|
|
2045
|
+
`sendProtocol(…)` directly no longer type-checks. Write `async () => { await sendProtocol(…) }`.
|
|
2046
|
+
- **`readProtocolPoint` reads the layout at the call, and `readProtocolNode` hands back an id to use at
|
|
2047
|
+
once.** The point is the layout at the call, so a box that moves afterwards moves the point it
|
|
2048
|
+
named. Each frame on the way up adds its border and its padding, because its content starts inside
|
|
2049
|
+
both. An element no document holds is refused, because its window still names the tester frame and
|
|
2050
|
+
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
|
|
2051
|
+
before the next call. Both leave `readHit` its own question, which is what the element's own
|
|
2052
|
+
document hit-tests at the centre and never leaves that document.
|
|
1746
2053
|
- **`parseCSSColor` resolves an undeclared token to the inherited color.** A `var()` naming a custom
|
|
1747
2054
|
property nothing declares is not a parse failure: the cascade accepts it and computes the
|
|
1748
|
-
inherited color,
|
|
2055
|
+
inherited color, which is the body's, or the `scope` element's with one, so
|
|
2056
|
+
`parseCSSColor('var(--absent)')` hands back channels rather than `undefined`.
|
|
1749
2057
|
Read `readToken` or `readRootToken` where a missing token is the subject.
|
|
1750
2058
|
- **`createLoopback` cannot take back an upgraded socket.** A server that claims an upgrade keeps
|
|
1751
2059
|
that connection, detached from the server itself, so `destroy()`'s `closeAllConnections` never
|
|
@@ -1753,7 +2061,7 @@ the helper rather than to the host, and each names what to reach for instead.
|
|
|
1753
2061
|
handler took and destroys it before destroying the loopback.
|
|
1754
2062
|
- **`destroyScratch`'s behavior under a permission hold is unproven where the hold cannot bind.** The
|
|
1755
2063
|
retry path is proven against a real host refusal, and a host that produces no such refusal cannot
|
|
1756
|
-
exercise it: a container running as uid `0`
|
|
2064
|
+
exercise it: a container running as uid `0` is exempt from the access check the mode bits describe, so
|
|
1757
2065
|
the suite reads a runtime probe and skips that case rather than asserting either answer. Read
|
|
1758
2066
|
`supportsMode` for the narrower question of whether the bits are stored at all.
|
|
1759
2067
|
- **`createRecorders` keys its map from the events array's declared element type.** An array declared
|
|
@@ -1769,7 +2077,7 @@ the helper rather than to the host, and each names what to reach for instead.
|
|
|
1769
2077
|
the quota, and the grant are.
|
|
1770
2078
|
- **`readProperty`'s `TypeError` names the target, never the read.** It refuses a target that is
|
|
1771
2079
|
neither an object nor a function before it reads anything, and a getter that throws on an accepted
|
|
1772
|
-
target hands that throw straight to the caller. Wrap the call in `captureError` where
|
|
2080
|
+
target hands that throw straight to the caller. Wrap the call in `captureError` where an untrusted
|
|
1773
2081
|
getter is the subject.
|
|
1774
2082
|
- **`readPixels` reports a measured contribution rather than a parsed length.** A resolved value
|
|
1775
2083
|
carrying no leading number — `'auto'`, `'none'`, `''` — reads as `0`, because none of them
|
|
@@ -2220,9 +2528,9 @@ for (const [index, value] of values.entries()) {
|
|
|
2220
2528
|
```
|
|
2221
2529
|
|
|
2222
2530
|
The corpus is the positive proof input. Keep a negative control for every member too: perform the
|
|
2223
|
-
naive read or the naive structural reading that member is meant to break, and prove it
|
|
2224
|
-
way the member's
|
|
2225
|
-
look stronger without exercising another
|
|
2531
|
+
naive read or the naive structural reading that member is meant to break, and prove it fails the
|
|
2532
|
+
way the member's structure dictates. Without that control, an inert value can make the totality loop
|
|
2533
|
+
look stronger without exercising another untrusted-input boundary.
|
|
2226
2534
|
|
|
2227
2535
|
This package's own suite carries one control per member, in corpus order, and each names the reading
|
|
2228
2536
|
that member breaks:
|
|
@@ -2273,7 +2581,7 @@ browser suite runs. It is a native disclosure with two doors: the summary toggle
|
|
|
2273
2581
|
button closes it and does nothing when it is already closed. That second door is what gives the
|
|
2274
2582
|
table a row whose event leaves the state where it found it, which a lone `<details>` cannot have —
|
|
2275
2583
|
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
|
|
2584
|
+
`tests/src/browser/journeys/factories.test.ts`, because the fences drive a browser and the `guides` project
|
|
2277
2585
|
runs with the browser disabled.
|
|
2278
2586
|
|
|
2279
2587
|
The phases are module functions the whole table shares, which is the shape a table of any size
|
|
@@ -2547,11 +2855,11 @@ Object.keys(
|
|
|
2547
2855
|
// 'src/core/types.ts', 'src/core/validators.ts']
|
|
2548
2856
|
|
|
2549
2857
|
// A directory key takes every key below it.
|
|
2550
|
-
Object.keys(
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
//
|
|
2554
|
-
// 'src/core/validators.ts']
|
|
2858
|
+
Object.keys(
|
|
2859
|
+
readInventory(root, ['src'], { extensions: ['.ts'], exclude: ['src/server', 'src/browser'] }),
|
|
2860
|
+
)
|
|
2861
|
+
// ['src/core/constants.ts', 'src/core/factories.ts', 'src/core/helpers.ts', 'src/core/index.ts',
|
|
2862
|
+
// 'src/core/types.ts', 'src/core/validators.ts']
|
|
2555
2863
|
|
|
2556
2864
|
// An exclusion also applies to a target you name, so naming one file below an excluded directory
|
|
2557
2865
|
// does not reinstate it.
|
|
@@ -2562,7 +2870,7 @@ readInventory(root, ['src/core/index.ts'], { extensions: ['.ts'], exclude: ['src
|
|
|
2562
2870
|
### Own a temporary directory
|
|
2563
2871
|
|
|
2564
2872
|
This demonstration builds a scratch directory seeded with a file, writes and reads inside it,
|
|
2565
|
-
refuses
|
|
2873
|
+
refuses a write outside its directory, and nests one allocation inside another.
|
|
2566
2874
|
|
|
2567
2875
|
```ts
|
|
2568
2876
|
import { createScratch } from '@orkestrel/test/server'
|
|
@@ -2821,9 +3129,9 @@ jar.read('session') // undefined
|
|
|
2821
3129
|
jar.header // 'theme=dark'
|
|
2822
3130
|
```
|
|
2823
3131
|
|
|
2824
|
-
### Refuse
|
|
3132
|
+
### Refuse a path outside the root in your own fixture
|
|
2825
3133
|
|
|
2826
|
-
`readInventory` and `createScratch` refuse
|
|
3134
|
+
`readInventory` and `createScratch` refuse a path outside the root with this predicate. Reach for it when a
|
|
2827
3135
|
fixture of your own resolves a caller-supplied path below a root.
|
|
2828
3136
|
|
|
2829
3137
|
```ts
|
|
@@ -2907,6 +3215,41 @@ await traverseAccessible('Evaluate')
|
|
|
2907
3215
|
readPerception('Run') // one visible named region, whitespace collapsed, hidden-but-read text kept
|
|
2908
3216
|
```
|
|
2909
3217
|
|
|
3218
|
+
#### Tap with one touch
|
|
3219
|
+
|
|
3220
|
+
Resolve the element the fixture supplies, then release touch emulation in cleanup.
|
|
3221
|
+
|
|
3222
|
+
```ts
|
|
3223
|
+
import { releaseTouch, resolveRendered, tapTouch } from '@orkestrel/test/browser'
|
|
3224
|
+
|
|
3225
|
+
try {
|
|
3226
|
+
await tapTouch(resolveRendered('Tap target'))
|
|
3227
|
+
} finally {
|
|
3228
|
+
await releaseTouch()
|
|
3229
|
+
}
|
|
3230
|
+
```
|
|
3231
|
+
|
|
3232
|
+
The browser proof records one trusted touch click and no click on the sibling control.
|
|
3233
|
+
Pass a trailing stability-options object when the fixture needs a longer settling budget.
|
|
3234
|
+
|
|
3235
|
+
#### Drag files from outside the page
|
|
3236
|
+
|
|
3237
|
+
A rendered status receives the drag even when it is absent from the Tab order.
|
|
3238
|
+
|
|
3239
|
+
```ts
|
|
3240
|
+
import { sendFileDrag } from '@orkestrel/test/browser'
|
|
3241
|
+
|
|
3242
|
+
await sendFileDrag('dragEnter', 'status', 'Drop status', ['note.txt'])
|
|
3243
|
+
try {
|
|
3244
|
+
await sendFileDrag('dragOver', 'status', 'Drop status', ['note.txt'])
|
|
3245
|
+
} finally {
|
|
3246
|
+
await sendFileDrag('dragCancel', 'status', 'Drop status', ['note.txt'])
|
|
3247
|
+
}
|
|
3248
|
+
```
|
|
3249
|
+
|
|
3250
|
+
The browser proof observes trusted entry, over, and leave events carrying the `Files` type.
|
|
3251
|
+
No drop occurs; fixture files remain under `tmp/drag` for the caller to remove.
|
|
3252
|
+
|
|
2910
3253
|
### Hold a control and read the pressed paint
|
|
2911
3254
|
|
|
2912
3255
|
Register pointer cleanup before a test can fail. This fixture declares `padding-top: 16px` on its
|
|
@@ -2982,6 +3325,21 @@ matchMedia('(prefers-reduced-motion: reduce)').matches === reduced // true
|
|
|
2982
3325
|
readPixels(button, 'padding-top') === (reduced ? 2 : 1) // true
|
|
2983
3326
|
```
|
|
2984
3327
|
|
|
3328
|
+
Pointer precision uses touch emulation. These readings are proved in the browser media cases.
|
|
3329
|
+
|
|
3330
|
+
```ts
|
|
3331
|
+
import { releaseMedia, stageMedia } from '@orkestrel/test/browser'
|
|
3332
|
+
|
|
3333
|
+
await stageMedia({ pointer: 'coarse' })
|
|
3334
|
+
matchMedia('(pointer: coarse)').matches // true
|
|
3335
|
+
matchMedia('(any-pointer: coarse)').matches // true
|
|
3336
|
+
matchMedia('(hover: none)').matches // true
|
|
3337
|
+
await stageMedia({ pointer: 'fine' })
|
|
3338
|
+
matchMedia('(pointer: fine)').matches // true
|
|
3339
|
+
matchMedia('(hover: hover)').matches // true
|
|
3340
|
+
await releaseMedia()
|
|
3341
|
+
```
|
|
3342
|
+
|
|
2985
3343
|
### Send a key to what holds focus
|
|
2986
3344
|
|
|
2987
3345
|
Bring focus about through a verb, then send the sequence. A key sent while the document body holds
|
|
@@ -3452,10 +3810,20 @@ await portfolio.place('start-empty')
|
|
|
3452
3810
|
portfolio.place('answer-partial') // rejects: Capture state "answer-partial" is not registered
|
|
3453
3811
|
```
|
|
3454
3812
|
|
|
3813
|
+
Settle the page before each frame of a capture run. `settleCapture` parks the pointer, waits out
|
|
3814
|
+
every finite animation in the document, and holds each endless one at its first frame, so a hover,
|
|
3815
|
+
a transition caught part way, and a spinner's phase stay out of the picture. It resolves to the
|
|
3816
|
+
resume; call `place` after it, and call the resume from a `finally` block, so the held animations
|
|
3817
|
+
run again whether or not the frame was written. Pass `pointer: false` where the pointer is part of
|
|
3818
|
+
the state, such as a drag in flight. Gate the settle on the flag that `enabled` takes: an ordinary run's
|
|
3819
|
+
`place` shoots nothing, and parking the pointer there changes the journey that run is proving.
|
|
3820
|
+
Where a frame holds a scroll region, record `describeScrollRegions` of what `collectScrollRegions`
|
|
3821
|
+
finds beside it, because a picture does not show how far a pane scrolls.
|
|
3822
|
+
|
|
3455
3823
|
### Measure a document's content edge
|
|
3456
3824
|
|
|
3457
3825
|
A capture stages the pane at the height the document needs, and the body's box cannot answer for
|
|
3458
|
-
that height
|
|
3826
|
+
that height after the pane grows taller than the document. In the following fence the document holds
|
|
3459
3827
|
1600 rows of fixed content and nothing is bound to the viewport.
|
|
3460
3828
|
|
|
3461
3829
|
```ts
|
|
@@ -3532,7 +3900,7 @@ picking one of them.
|
|
|
3532
3900
|
is either slower than it needs to be or shorter than the slowest host, and it reports nothing when
|
|
3533
3901
|
it fails. Name the fact instead, and let `waitForCondition`, `retryUntil`, or `waitForEvent` decide
|
|
3534
3902
|
when it holds.
|
|
3535
|
-
- **Let `readInventory` refuse.** A symlinked root or
|
|
3903
|
+
- **Let `readInventory` refuse.** A symlinked root or a target outside the root is an error, not a
|
|
3536
3904
|
filtered result, so a misconfigured walk fails loudly instead of returning a short map.
|
|
3537
3905
|
- **Reach for `parent` only when the allocation must be somewhere named.** The default keeps it out
|
|
3538
3906
|
of the repository, and a path inside a package tree is walked by every tool that reads that tree.
|
|
@@ -3557,7 +3925,11 @@ Each entry names the contracts its file proves. The test names carry the cases.
|
|
|
3557
3925
|
carrying both the arrival and the departure that `absent` waits past, an empty expectation and an
|
|
3558
3926
|
empty departure each refused, a reader throw propagated unchanged, the timeout naming the wait and
|
|
3559
3927
|
the budget, an abort rejecting with the signal's own reason, and a refused bound raised through the
|
|
3560
|
-
family. `
|
|
3928
|
+
family. `collectSelectorClasses` takes a selector list whose functional pseudo-classes nest class
|
|
3929
|
+
names beside an attribute block, quoted strings, and a comment that name none, every escape form
|
|
3930
|
+
decoded with the out-of-range points read as the replacement character, names opening with an
|
|
3931
|
+
underscore, a hyphen, two hyphens, and a non-ASCII letter, the empty selector, and each unreadable
|
|
3932
|
+
text refused by name. `decodeJSONLines` takes empty input, a trailing newline, CRLF,
|
|
3561
3933
|
line order, primitive lines, and a malformed physical line named with the native `SyntaxError` as
|
|
3562
3934
|
its cause. `collect` and `collectStream` drain an empty and an ordered source, and the stream's
|
|
3563
3935
|
reader lock is released afterwards. `roundTripJSON` takes a copy of a flat and a nested
|
|
@@ -3587,11 +3959,24 @@ Each entry names the contracts its file proves. The test names carry the cases.
|
|
|
3587
3959
|
with every remaining handler still run, both together aggregated in run order, a handler added
|
|
3588
3960
|
during a run kept for the next call, the count reset before the handlers run, and a `destroy()`
|
|
3589
3961
|
that is called empty and called twice. `createHostileValues` proves a naive-reader failure for
|
|
3590
|
-
every member, frozen and fresh membership, and one total guard's
|
|
3962
|
+
every member, frozen and fresh membership, and one total guard's answers for ordinary and unexpected inputs with
|
|
3591
3963
|
loop-index attribution.
|
|
3592
|
-
- [`tests/src/browser/helpers.test.ts`](../tests/src/browser/helpers.test.ts)
|
|
3593
|
-
|
|
3594
|
-
|
|
3964
|
+
- [`tests/src/browser/helpers.test.ts`](../tests/src/browser/helpers.test.ts),
|
|
3965
|
+
[`tests/src/browser/journeys/helpers.test.ts`](../tests/src/browser/journeys/helpers.test.ts),
|
|
3966
|
+
[`tests/src/browser/captures/helpers.test.ts`](../tests/src/browser/captures/helpers.test.ts),
|
|
3967
|
+
[`tests/src/browser/colors/helpers.test.ts`](../tests/src/browser/colors/helpers.test.ts), and
|
|
3968
|
+
[`tests/src/browser/sheets/helpers.test.ts`](../tests/src/browser/sheets/helpers.test.ts) — the
|
|
3969
|
+
journey-layer, role-map, and announced-half-and-clickable-half contracts across the layer, in real Chromium
|
|
3970
|
+
against constructed markup. The touch proofs cover a pointer-dependent target beside a sibling,
|
|
3971
|
+
a target moving across painted frames before settling, a supplied stability budget that refuses
|
|
3972
|
+
the tap, and both orders of media and touch teardown. The pointer proof restores the first coarse
|
|
3973
|
+
reading after fine then coarse staging. The file-drag proofs reach a target under a smooth root
|
|
3974
|
+
and refuse a file name without scrolling or writing any file in the batch. The `releaseTouch`
|
|
3975
|
+
rethrow of a non-idle protocol error is covered by review: its cancellation parameters are fixed,
|
|
3976
|
+
and no controllable non-idle refusal was found through the browser provider without replacing
|
|
3977
|
+
its transport or disrupting the tester session. A provider with a recoverable protocol-failure
|
|
3978
|
+
seam would let a proof drive that branch.
|
|
3979
|
+
The resolver takes a bare name, a
|
|
3595
3980
|
role that disambiguates a tab from its own panel, a name no element carries, a name carried only by
|
|
3596
3981
|
a role outside `ACCESSIBLE_ROLES`, and the disabled, hidden, and inert matches that are present but
|
|
3597
3982
|
gated. It takes the glyph cases against a fixture stylesheet that really paints one: an exact name
|
|
@@ -3623,7 +4008,17 @@ Each entry names the contracts its file proves. The test names carry the cases.
|
|
|
3623
4008
|
reading, and a refused bound. `waitForAnimations` takes a descendant transition awaited to its end,
|
|
3624
4009
|
the exhaustion naming the subject and the animation still running, an infinite-iteration animation
|
|
3625
4010
|
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. `
|
|
4011
|
+
reading is compared against the interpolated one taken mid-transition. `readAnimations` takes a
|
|
4012
|
+
running transition and a running infinite animation split apart, a paused animation and one
|
|
4013
|
+
outside the subject left out, and a detached element read as two empty lists. `settleCapture`
|
|
4014
|
+
takes a hovered control's transition waited out and a spinner held at its first frame until the
|
|
4015
|
+
resume sets it running, a held press whose hover and pressed paint `pointer: false` leaves in
|
|
4016
|
+
place beside the default park that takes both away, and an exhausted wait refused with nothing
|
|
4017
|
+
held. `collectScrollRegions` takes a vertical and a horizontal scroller beside a box whose content
|
|
4018
|
+
fits, a clipping box, and a hidden one, each axis alone, and a scrolling root counted itself;
|
|
4019
|
+
`describeScrollRegions` takes a region named by its tag, its id, and its cut accessible name with
|
|
4020
|
+
its offsets after a scroll, the window's position after a scroll, and an empty population.
|
|
4021
|
+
`readRefusal` takes the
|
|
3627
4022
|
absent, gated, and ambiguous voices beside a target that resolves under a bare name and under a
|
|
3628
4023
|
role, and — as the control for the rethrow — a fixture element whose own `tabIndex` getter refuses
|
|
3629
4024
|
with a string, handed straight back. `readCensus` takes a population carrying both undeclared
|
|
@@ -3641,17 +4036,44 @@ Each entry names the contracts its file proves. The test names carry the cases.
|
|
|
3641
4036
|
Each acting verb takes its happy path and every voice it owns, including both
|
|
3642
4037
|
region-scoped refusals and both native-disclosure ones; `clickAccessibleWithin` also takes a
|
|
3643
4038
|
glyph-captioned control inside a region a glyph-carrying heading labels, which is the loose match
|
|
3644
|
-
proving unchanged. `traverseAccessible` takes a Tab-reachable
|
|
3645
|
-
|
|
4039
|
+
proving unchanged. `traverseAccessible` takes a Tab-reachable target, a crossing for each type in
|
|
4040
|
+
`SEGMENTED_INPUT_TYPES`, and a page of fractional-second `datetime-local` inputs that traversal
|
|
4041
|
+
and census both cross with spare presses for another landing per input. As the cap control, it
|
|
4042
|
+
takes a lone target whose own focus handler blurs it, so focus never lands
|
|
3646
4043
|
and the cap fails with an empty trail; and, as the cycle control, the same self-blurring target
|
|
3647
4044
|
behind a reachable decoy, so the traversal completes one cycle and reports the decoy in its trail.
|
|
4045
|
+
`driveTraversal` takes a non-modal button trap with a resolvable target and refuses after the
|
|
4046
|
+
repeated landing, plus a segmented input trap that refuses within its consecutive landing budget.
|
|
3648
4047
|
The page readers take their own inputs: `readPerception` takes one named region including its
|
|
3649
4048
|
visually hidden text, a region a glyph-carrying heading labels through `aria-labelledby`, a painted
|
|
3650
4049
|
region an `aria-hidden` attribute withholds, and its not-visible and ambiguous refusals, `readPage`
|
|
3651
4050
|
the whole page as one
|
|
3652
4051
|
normalized sentence, and
|
|
3653
|
-
`readFocus` a focused control's rendered text, a focused element that renders none,
|
|
3654
|
-
|
|
4052
|
+
`readFocus` a focused control's rendered text, a focused element that renders none, an SVG element
|
|
4053
|
+
focused inside an open shadow root that reads nothing rather than its host's text, a host holding
|
|
4054
|
+
focus with nothing inside, and nothing holding focus at all; `readValue` takes a rendered value
|
|
4055
|
+
and a control carrying none. The focus
|
|
4056
|
+
walk takes its inputs across each boundary: `readActiveElement` takes the page's focused control,
|
|
4057
|
+
focus inside an open shadow root and through nested ones, an SVG element focused inside one that
|
|
4058
|
+
answers nothing rather than its host, a host holding focus with nothing inside
|
|
4059
|
+
and one with a closed root, a control inside a same-origin frame typed for the frame's window, a
|
|
4060
|
+
frame holding focus with nothing inside, and a frame from another origin refused;
|
|
4061
|
+
`countElements` takes the shadow and frame content a plain query misses; `containsNode` takes a
|
|
4062
|
+
region's own content, a shadow root's and a frame's, and a detached node left outside;
|
|
4063
|
+
`stepFocus` takes one press per landing, none past the consumer's last read, a limit of zero,
|
|
4064
|
+
a landing on nothing, repeated segment landings for each type in `SEGMENTED_INPUT_TYPES`, and
|
|
4065
|
+
the measured nine landings of a fractional-second `datetime-local` input with a spare press in
|
|
4066
|
+
its budget. `supportsSegmentedFocus` takes the frozen type list, every listed type beside text
|
|
4067
|
+
and number inputs, a button and a non-input carrying `type="date"`, an input from a same-origin
|
|
4068
|
+
frame, and a document with no window. `walkFocus` takes a date input counted once before the
|
|
4069
|
+
following control, a single-button modal trap that returns after one press, and a lone segmented
|
|
4070
|
+
input trap that returns within its consecutive landing budget. `collectTabStops` takes a region
|
|
4071
|
+
holding a date input with every stop listed and a trapped date input returned within that budget.
|
|
4072
|
+
`walkFocus` and `collectTabStops` take the buttons of an open shadow root
|
|
4073
|
+
and of a same-origin frame between two light controls, a start element inside a shadow root, a
|
|
4074
|
+
start element immediately before the region that reaches the region's first stop, and
|
|
4075
|
+
focus in a foreign frame refused; `readProtocolPoint` takes a padded frame beside a bordered one,
|
|
4076
|
+
both hit-tested through the protocol, and a disconnected element refused. The element
|
|
3655
4077
|
readers follow: `readText` takes an `aria-hidden` glyph dropped with the runs around it collapsed
|
|
3656
4078
|
and an element with no text at all; `readRole` takes exactly the tags `IMPLICIT_ROLES` carries and
|
|
3657
4079
|
one it leaves out, a declared role taken over the implicit one, a section made a region only by
|
|
@@ -3676,7 +4098,12 @@ Each entry names the contracts its file proves. The test names carry the cases.
|
|
|
3676
4098
|
nothing paints and one whose every painted layer is translucent, a stack 64 translucent layers
|
|
3677
4099
|
deep whose composite has rounded to the canvas's own channels, a detached element whose computed
|
|
3678
4100
|
foreground does not exist, and the same unpainted and translucent stacks measured against a
|
|
3679
|
-
supplied floor instead of refused.
|
|
4101
|
+
supplied floor instead of refused. `readColorContrast` takes the ceiling, the floor, a clear
|
|
4102
|
+
color, and a half-opaque one over an opaque surface, a keyword and a `var()` reference resolved
|
|
4103
|
+
through the cascade, a translucent and an unpainted stack refused until a floor is named and then
|
|
4104
|
+
composited onto it, an `opacity` reading equal to the declared alpha it multiplies with the
|
|
4105
|
+
refused factors beside it, and an unreadable color and an unreadable painted layer each refused.
|
|
4106
|
+
The color leaves beneath it take their own inputs: `parseColor`
|
|
3680
4107
|
across the legacy and modern syntaxes, a refused keyword, hex triple, empty value, and unsupported
|
|
3681
4108
|
color space, and — as the control the literals cannot supply — what this browser actually computes
|
|
3682
4109
|
for a keyword and for a `color-mix()`. `blendColor`, `measureLuminance`, and `measureContrast`
|
|
@@ -3687,7 +4114,8 @@ Each entry names the contracts its file proves. The test names carry the cases.
|
|
|
3687
4114
|
composited onto it, and an opaque layer that ends the walk. `readRing` takes a painted outline and
|
|
3688
4115
|
a painted box-shadow reached through `traverseAccessible`, a control that is not focused, a
|
|
3689
4116
|
focused control left the browser's own ring, a focus style that only repaints the control's fill,
|
|
3690
|
-
|
|
4117
|
+
a `worn` element whose reading separates from the control's own, and an unpainted focused control
|
|
4118
|
+
over an unreadable surface that is refused. `measureContent` takes a
|
|
3691
4119
|
1600-row document read under an 844 pane and under a 2356 one, against the scroll height that
|
|
3692
4120
|
agrees with it under the shorter pane and stretches to the pane under the taller, and a document
|
|
3693
4121
|
whose last element carries a bottom margin under a body carrying bottom padding, where a reading
|
|
@@ -3717,7 +4145,10 @@ Each entry names the contracts its file proves. The test names carry the cases.
|
|
|
3717
4145
|
height on the panel's own color with the scroll handed back; an element below both the pane and
|
|
3718
4146
|
the window, whole on the document's floor with the scroll handed back; a `50vh` element and a
|
|
3719
4147
|
`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;
|
|
4148
|
+
than the pane, in a pane of its own height; tall and near-viewport elements below authored native
|
|
4149
|
+
clearance, with decoded heading pixels distinguishing them from an undeclared sticky obstruction;
|
|
4150
|
+
a fixed element beyond a padded viewport that keeps its declared viewport height;
|
|
4151
|
+
an element that outgrows every pane, refused with the
|
|
3721
4152
|
pane and the scroll handed back; a second tester frame the offset leaves in place; and a frame
|
|
3722
4153
|
carrying no `style` attribute, handed back without one. After the `releasePointer` function, an
|
|
3723
4154
|
element frame takes no `mouseover` event for an element inside the window, which also takes no `scroll` event;
|
|
@@ -3736,8 +4167,31 @@ Each entry names the contracts its file proves. The test names carry the cases.
|
|
|
3736
4167
|
frame's size and floor, read a second way through the cascade's own answer for the same canvas, a
|
|
3737
4168
|
bottom row split between two colors reported as no floor at all, a path holding no file,
|
|
3738
4169
|
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
|
-
|
|
4170
|
+
with the size the header declares. The `paintImage` function takes a PNG painted at its natural
|
|
4171
|
+
size and bytes that are no image, whose decode failure it hands on unchanged. The `readShotPixel`
|
|
4172
|
+
function takes each half of a split shot, frozen, and both corners clamped onto the shot, and
|
|
4173
|
+
refuses a fraction below `0`, above `1`, infinite, or `NaN` on either axis. The `readClippedBlock` function takes a frame
|
|
4174
|
+
clipping a taller child, a paint containment and a clip margin, elements wholly under a frame's
|
|
4175
|
+
edge, an unclipped control, a block in an open shadow tree under a clipping wrapper around its
|
|
4176
|
+
host, a slotted child under a clipping wrapper around its slot, a disconnected element refused,
|
|
4177
|
+
and the same reading on a page scrolled past its top, which a reading
|
|
4178
|
+
that skipped the coordinate conversion fails. The `collectClippingAncestors` function takes the
|
|
4179
|
+
same climb through a host and through a slot, nearest first, and a disconnected element refused.
|
|
4180
|
+
The `measureContent` function takes a slotted child ended at the shadow wrapper that clips around
|
|
4181
|
+
its slot. The `waitForStability` function takes reads spaced by the interval past the second.
|
|
4182
|
+
The `parseCSSColor` function takes an expression resolved on the scope it is handed, a registered
|
|
4183
|
+
token that does not inherit, a keyword, a hex triple, and `currentColor` at an `input` and an SVG
|
|
4184
|
+
element, a running color transition read at its sampled midpoint and left running, a scroller
|
|
4185
|
+
with a running height transition keeping its height and scroll position, a scope that records no
|
|
4186
|
+
mutation during the read, a transition on every property that starts none, a color scheme
|
|
4187
|
+
answered to a system color and to `light-dark()`, a token named only in a fallback carried, a
|
|
4188
|
+
disconnected scope answered with nothing, and an element that is no HTML, SVG, or MathML element
|
|
4189
|
+
resolved like any other. The `readColorContrast`
|
|
4190
|
+
function takes a token on an ancestor the body never declares, `currentColor`, and a token the
|
|
4191
|
+
element declares itself, each read at the element, a keyword, a hex triple, and a token at an
|
|
4192
|
+
`input`, a registered token that does not inherit, and a disconnected element refused. The `readCascade` function takes class tokens collected from
|
|
4193
|
+
plain and grouped rules and only real ones, and an escaped class decoded beside an attribute
|
|
4194
|
+
value whose class-like text defines nothing;
|
|
3741
4195
|
`readRows` takes a row joined from its own text nodes rather than from run-together content, and
|
|
3742
4196
|
an empty list; `extractOrphans` takes a child class rendered outside its container with a nested
|
|
3743
4197
|
one left alone, nothing reported when every child sits inside one, and, as the control, an element
|
|
@@ -3752,11 +4206,14 @@ Each entry names the contracts its file proves. The test names carry the cases.
|
|
|
3752
4206
|
element carrying an inline attribute reported once, a whitespace-only attribute read past, a
|
|
3753
4207
|
fragment root, and — as the control — markup whose classes and `data-*` attributes leave it with
|
|
3754
4208
|
nothing to report.
|
|
3755
|
-
- [`tests/src/browser/factories.test.ts`](../tests/src/browser/factories.test.ts)
|
|
4209
|
+
- [`tests/src/browser/journeys/factories.test.ts`](../tests/src/browser/journeys/factories.test.ts) and
|
|
4210
|
+
[`tests/src/browser/captures/factories.test.ts`](../tests/src/browser/captures/factories.test.ts) — the journal
|
|
3756
4211
|
contract, and the portfolio's refusals, its disabled gate, and its writes. Creation refuses an
|
|
3757
4212
|
unregistered variant name; the registry expands across every variant whether or not the run
|
|
3758
4213
|
writes; a run
|
|
3759
|
-
that is not enabled applies nothing, writes nothing, and records nothing
|
|
4214
|
+
that is not enabled applies nothing, writes nothing, and records nothing, yet refuses an
|
|
4215
|
+
unregistered state and a second placement of one state, and accepts two distinct registered states
|
|
4216
|
+
with its lists still empty; an enabled run applies
|
|
3760
4217
|
the variant, resizes the viewport, writes a real file through the provider, records it, and hands
|
|
3761
4218
|
out snapshots rather than its own lists; it refuses an unregistered state and a second placement of
|
|
3762
4219
|
one state; and a placement handed an element writes a frame that is not the whole page's and leaves
|
|
@@ -3769,11 +4226,15 @@ Each entry names the contracts its file proves. The test names carry the cases.
|
|
|
3769
4226
|
operation, each withheld operation refused in its own voice, both permissions granted at once with
|
|
3770
4227
|
the store answering from what it kept, a quota spent on accepted writes alone with `removeItem`
|
|
3771
4228
|
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.
|
|
4229
|
+
as the control for the inertness claim — a write that leaves `localStorage` exactly as it was. The
|
|
4230
|
+
event factories take the real event type, the bubbling, cancelable, and composed defaults and an
|
|
4231
|
+
override of each, and an event dispatched from a button inside an open shadow root that a
|
|
4232
|
+
`document` listener hears, beside a bare event of the same type that it does not, and a pointer
|
|
4233
|
+
or drag event whose `{ composed: false }` override keeps it inside the root.
|
|
3773
4234
|
- [`tests/src/server/helpers.test.ts`](../tests/src/server/helpers.test.ts) — the `readInventory` and
|
|
3774
4235
|
wait-family contracts, and each pure leaf against its own inputs. `resolveContained` takes
|
|
3775
|
-
contained relative and absolute targets and both spellings of
|
|
3776
|
-
takes the same contained pair and each
|
|
4236
|
+
contained relative and absolute targets and both spellings of a path outside the root, and `requireContained`
|
|
4237
|
+
takes the same contained pair and each path outside the root refused with the message naming the target it was
|
|
3777
4238
|
given. `readIdentity` takes a real
|
|
3778
4239
|
allocation's three fields, that allocation matching itself across a `stat` and an `lstat`, and a
|
|
3779
4240
|
second allocation reading as a different identity. `readErrorCode` takes a real `ENOENT` off the
|
|
@@ -3814,14 +4275,14 @@ Each entry names the contracts its file proves. The test names carry the cases.
|
|
|
3814
4275
|
leaves a moved allocation alone. Then one group per subject.
|
|
3815
4276
|
`destruction` takes `write`, `read`, `has`, `names`, `ensure`, `link`, and `remove` after
|
|
3816
4277
|
`destroy()`, with `write`, `ensure`, and `link` also proven not to rebuild the allocation root, and
|
|
3817
|
-
`remove` proving its root and
|
|
4278
|
+
`remove` proving its root and path-containment refusals answer before the destroyed-allocation one.
|
|
3818
4279
|
`names` takes its sorted output, including the population that discriminates a dropped `.sort()`.
|
|
3819
4280
|
`ensure` takes an empty directory, every missing parent, and a repeated call. `link` takes
|
|
3820
4281
|
traversal through a planted link, the final segment `has` reports rather than follows, and the
|
|
3821
4282
|
`EEXIST` an occupied final segment throws. `remove` takes a file beside a kept
|
|
3822
4283
|
sibling, an empty directory, a populated subtree, a missing target, an ancestor link back to the
|
|
3823
4284
|
allocation with every seeded file read back afterwards, a final link whose destination is read back
|
|
3824
|
-
afterwards, a sibling directory reached through that same ancestor link,
|
|
4285
|
+
afterwards, a sibling directory reached through that same ancestor link, a target outside the root with
|
|
3825
4286
|
the file outside left intact, the root refused as `''`, as `'.'`, and as its absolute path, a
|
|
3826
4287
|
foreign directory swapped onto the allocated path that `remove('')` refuses, and that same swap
|
|
3827
4288
|
under `destroy()`, which removes nothing either. `parent` and `prefix` take their own refusals.
|