@orkestrel/test 0.0.10 → 0.0.12
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/README.md +20 -8
- package/dist/src/browser/index.d.ts +483 -237
- package/dist/src/browser/index.js +357 -69
- package/dist/src/browser/index.js.map +1 -1
- package/dist/src/core/index.cjs +189 -21
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +270 -21
- package/dist/src/core/index.d.ts +270 -21
- package/dist/src/core/index.js +183 -22
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +67 -48
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +70 -32
- package/dist/src/server/index.d.ts +70 -32
- package/dist/src/server/index.js +66 -50
- package/dist/src/server/index.js.map +1 -1
- package/package.json +13 -10
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Names the interactive ARIA roles a bare accessible name is searched across.
|
|
3
3
|
*
|
|
4
4
|
* @remarks
|
|
5
5
|
* A person names a control, not a role, so the one-argument resolver searches every role a control
|
|
@@ -45,7 +45,7 @@ export declare function blendColor(front: Color, back: Color): Color;
|
|
|
45
45
|
export declare function build<K extends keyof HTMLElementTagNameMap>(tag: K, options?: ElementOptions): HTMLElementTagNameMap[K];
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
|
-
*
|
|
48
|
+
* Names the color a browser paints an unstyled document with.
|
|
49
49
|
*
|
|
50
50
|
* @remarks
|
|
51
51
|
* This is the floor a backdrop walk ends on wherever the caller wants the browser's own canvas
|
|
@@ -55,23 +55,43 @@ export declare function build<K extends keyof HTMLElementTagNameMap>(tag: K, opt
|
|
|
55
55
|
export declare const CANVAS_COLOR: Color;
|
|
56
56
|
|
|
57
57
|
/**
|
|
58
|
-
*
|
|
59
|
-
* staged.
|
|
58
|
+
* Names the attribute marking the runner's tester pane, and the rule that sizes it, while a frame
|
|
59
|
+
* is staged.
|
|
60
60
|
*
|
|
61
61
|
* @remarks
|
|
62
62
|
* `stagePane` writes it onto the pane and onto the stylesheet it appends, and `releasePane` finds
|
|
63
|
-
* both by it.
|
|
64
|
-
*
|
|
63
|
+
* both by it. The stylesheet's value is the viewport the tester had before the first staging, in
|
|
64
|
+
* `<width>x<height>` form, which is what `releasePane` hands back. Nothing else reads it, so a
|
|
65
|
+
* document carrying it after a capture returned is a pane that was never released.
|
|
65
66
|
*/
|
|
66
67
|
export declare const CAPTURE_PANE = "data-capture-pane";
|
|
67
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Bounds the restagings one capture takes before it refuses a document whose height never settles.
|
|
71
|
+
*
|
|
72
|
+
* @remarks
|
|
73
|
+
* `captureFrame` stages the pane at the content edge `measureContent` reads, and a rule bound to
|
|
74
|
+
* the viewport height lays that document out taller against the taller pane, so the edge has to be
|
|
75
|
+
* read again after every staging. The re-reading stops when the pane and the edge agree, and a rule
|
|
76
|
+
* that adds height with every pane never reaches that point, so the re-reading is bounded here and
|
|
77
|
+
* the shot is refused rather than taken at a height that is already stale.
|
|
78
|
+
*
|
|
79
|
+
* The bound is the measured need plus one. A document holding half the pane plus a fixed block
|
|
80
|
+
* settles in two restagings, because the second carries the growth the first produced and lands on
|
|
81
|
+
* the fixed point; a document whose growth is capped part way settles in three, because it takes
|
|
82
|
+
* one restaging past the cap before it comes back down to the edge. Nothing measured needs a
|
|
83
|
+
* fourth, so a fourth is the headroom that keeps a settling document off the refusal.
|
|
84
|
+
*/
|
|
85
|
+
export declare const CAPTURE_STAGINGS = 4;
|
|
86
|
+
|
|
68
87
|
/**
|
|
69
88
|
* Shoots one frame at one viewport size and proves the file on disk holds this run's bytes.
|
|
70
89
|
*
|
|
71
90
|
* @param options - The path to write, the viewport to shoot at, and the element to shoot.
|
|
72
91
|
* @returns The absolute path of the written frame, after it has been read back and matched.
|
|
73
|
-
* @throws Thrown when the pane cannot be staged, when the
|
|
74
|
-
*
|
|
92
|
+
* @throws Thrown when the pane cannot be staged, when the document's height never settles under
|
|
93
|
+
* {@link CAPTURE_STAGINGS} restagings, when the provider wrote the frame somewhere else, and when
|
|
94
|
+
* the bytes on disk are not the ones this shot produced.
|
|
75
95
|
*
|
|
76
96
|
* @remarks
|
|
77
97
|
* The path a screenshot call returns is the path it meant to write, so it is not evidence a file
|
|
@@ -81,8 +101,41 @@ export declare const CAPTURE_PANE = "data-capture-pane";
|
|
|
81
101
|
* path, so the two are compared by the segments that survive resolving `.` and `..` lexically — the
|
|
82
102
|
* refusal is what a provider resolving that path against a different base would trip.
|
|
83
103
|
*
|
|
104
|
+
* The frame covers the whole document at `options.width`, whatever `options.height` is. The
|
|
105
|
+
* provider shoots the tester's body in the top-level page's own coordinates, so a document taller
|
|
106
|
+
* than the pane is painted for the pane's height and the rows below it are the runner's page rather
|
|
107
|
+
* than the document — a frame that reads as the surface down to the fold and as bare canvas after
|
|
108
|
+
* it. The document is therefore laid out at the declared viewport first and, where it is taller
|
|
109
|
+
* than that, the pane is staged again at the height the document needs, for the shot alone.
|
|
110
|
+
*
|
|
111
|
+
* That height is {@link measureContent}, never less than `options.height`, because the declared
|
|
112
|
+
* viewport is the smallest frame a variant asks for. The reading is the content's own edge rather
|
|
113
|
+
* than the body's box: the box is the larger of the content and the pane, so it stretches with
|
|
114
|
+
* every pane staged over it and a capture that staged too tall a pane could not read its way back
|
|
115
|
+
* down. Rounding up is what covers a body ending part way through a row, which the box does and an
|
|
116
|
+
* integer scroll height does not.
|
|
117
|
+
*
|
|
118
|
+
* The edge is read again after every staging, because a rule bound to the viewport height — a `vh`
|
|
119
|
+
* length, a fixed footer, a full-height panel — lays the document out taller against the taller
|
|
120
|
+
* pane, so a surface built out of those photographs as its scrolled-open self rather than as one
|
|
121
|
+
* screen, and the reading taken before that staging is stale by exactly what the reflow added.
|
|
122
|
+
* Restaging at the edge alone converges on such a document without arriving: each staging closes
|
|
123
|
+
* the same fraction of what is left, so a rule keeping half the pane reads 1322, 1561, 1681, and
|
|
124
|
+
* 1741 against a fixed point of 1800. Each staging therefore carries the growth the one before it
|
|
125
|
+
* produced — the pane is the edge plus that growth — which lands on the fixed point rather than
|
|
126
|
+
* creeping up to it. The first staging carries no growth, because nothing has grown yet, so a
|
|
127
|
+
* document of fixed content is staged at its own edge and shot there rather than at a pane the
|
|
128
|
+
* overshoot stretched.
|
|
129
|
+
*
|
|
130
|
+
* The re-reading stops when the pane and the edge agree, which is the pane the shot is taken at. A
|
|
131
|
+
* rule that adds height with every pane never reaches that point, so the re-reading is bounded by
|
|
132
|
+
* {@link CAPTURE_STAGINGS} and the shot is refused with
|
|
133
|
+
* `Capture frame at <path> never settled after <n> restagings: <h> over a <h> pane` rather than
|
|
134
|
+
* written at a height that is already wrong.
|
|
135
|
+
*
|
|
84
136
|
* Omit `options.element` to shoot the whole page. The pane is staged for the frame and released
|
|
85
|
-
* before this returns, on the failing path as well as the passing one
|
|
137
|
+
* before this returns, on the failing path as well as the passing one, which hands the tester back
|
|
138
|
+
* the viewport it had before the first staging.
|
|
86
139
|
*
|
|
87
140
|
* @example
|
|
88
141
|
* ```ts
|
|
@@ -91,17 +144,17 @@ export declare const CAPTURE_PANE = "data-capture-pane";
|
|
|
91
144
|
*/
|
|
92
145
|
export declare function captureFrame(options: FrameOptions): Promise<string>;
|
|
93
146
|
|
|
94
|
-
/**
|
|
147
|
+
/** Represents one theme-and-viewport pair a capture run renders. */
|
|
95
148
|
export declare interface CaptureVariant {
|
|
96
|
-
/**
|
|
149
|
+
/** Holds the variant's name, which is the second half of every filename the run writes. */
|
|
97
150
|
readonly name: string;
|
|
98
|
-
/**
|
|
151
|
+
/** Holds the viewport width in pixels. */
|
|
99
152
|
readonly width: number;
|
|
100
|
-
/**
|
|
153
|
+
/** Holds the viewport height in pixels. */
|
|
101
154
|
readonly height: number;
|
|
102
155
|
/**
|
|
103
|
-
*
|
|
104
|
-
* density class, a language direction. Omit it when the variant is a viewport alone.
|
|
156
|
+
* Holds the document change this variant needs before the viewport is resized — a theme
|
|
157
|
+
* attribute, a density class, a language direction. Omit it when the variant is a viewport alone.
|
|
105
158
|
*/
|
|
106
159
|
readonly apply?: () => void;
|
|
107
160
|
}
|
|
@@ -191,7 +244,7 @@ export declare function clickAccessibleWithin(region: string, role: string, name
|
|
|
191
244
|
export declare function clickDisclosure(name: string): Promise<void>;
|
|
192
245
|
|
|
193
246
|
/**
|
|
194
|
-
*
|
|
247
|
+
* Represents one rendered color as straight sRGB channels and its alpha.
|
|
195
248
|
*
|
|
196
249
|
* @remarks
|
|
197
250
|
* The channels run 0–255 and the alpha runs 0–1, which is the shape a computed `rgb()` value already
|
|
@@ -200,33 +253,6 @@ export declare function clickDisclosure(name: string): Promise<void>;
|
|
|
200
253
|
*/
|
|
201
254
|
export declare type Color = readonly [red: number, green: number, blue: number, alpha: number];
|
|
202
255
|
|
|
203
|
-
/**
|
|
204
|
-
* Determines whether two colors render the same, within the rounding a browser does.
|
|
205
|
-
*
|
|
206
|
-
* @param first - A CSS color expression or an already-parsed color.
|
|
207
|
-
* @param second - A CSS color expression or an already-parsed color.
|
|
208
|
-
* @returns `true` when every channel and the alpha agree within the tolerance; `false` otherwise,
|
|
209
|
-
* including when either side names no readable color.
|
|
210
|
-
*
|
|
211
|
-
* @remarks
|
|
212
|
-
* Each string side is resolved through {@link rgba}, so a keyword, a token reference, and the
|
|
213
|
-
* `rgb()` the engine computes for either of them compare equal without a test converting anything
|
|
214
|
-
* first. A side that resolves to nothing makes the answer `false` rather than a throw, because this
|
|
215
|
-
* is a predicate.
|
|
216
|
-
*
|
|
217
|
-
* The tolerance is half a channel step on the 0–255 scale, and the alpha is scaled onto that same
|
|
218
|
-
* range before it is compared, so one number covers both. Half a step is what a composite of
|
|
219
|
-
* translucent layers and a `color-mix()` round trip actually drift by; anything a reader could see
|
|
220
|
-
* is further than that and reports unequal.
|
|
221
|
-
*
|
|
222
|
-
* @example
|
|
223
|
-
* ```ts
|
|
224
|
-
* colorEqual('rebeccapurple', 'rgb(102, 51, 153)') // true
|
|
225
|
-
* colorEqual('red', [0, 0, 255, 1]) // false
|
|
226
|
-
* ```
|
|
227
|
-
*/
|
|
228
|
-
export declare function colorEqual(first: string | Color, second: string | Color): boolean;
|
|
229
|
-
|
|
230
256
|
/**
|
|
231
257
|
* Sets one field's value and commits it, the way typing and then leaving the field does.
|
|
232
258
|
*
|
|
@@ -246,52 +272,43 @@ export declare function colorEqual(first: string | Color, second: string | Color
|
|
|
246
272
|
export declare function commitInput(element: HTMLInputElement | HTMLTextAreaElement, text: string): void;
|
|
247
273
|
|
|
248
274
|
/**
|
|
249
|
-
*
|
|
275
|
+
* Computes the pattern that matches one accessible name a decorative glyph may sit beside.
|
|
250
276
|
*
|
|
251
|
-
* @
|
|
252
|
-
*
|
|
253
|
-
*
|
|
254
|
-
*/
|
|
255
|
-
export declare const CONTENT_ROLES: readonly string[];
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* Measures the WCAG 2.x contrast ratio between an element's computed text and background colors.
|
|
259
|
-
*
|
|
260
|
-
* @param element - The element whose rendered text contrast to measure.
|
|
261
|
-
* @param floor - The opaque color the backdrop walk ends on. Omit it to refuse a stack the floor
|
|
262
|
-
* would show through instead of assuming one.
|
|
263
|
-
* @returns The relative-luminance contrast ratio.
|
|
264
|
-
* @throws Thrown when the element exposes no computed foreground color, and — with `floor` omitted
|
|
265
|
-
* — when the walk from the element upwards reaches no opaque layer.
|
|
277
|
+
* @param name - The exact accessible name a person reads, whitespace runs collapsed on the way in.
|
|
278
|
+
* @returns A pattern anchored at both ends, admitting a run of characters that are neither letters
|
|
279
|
+
* nor digits before the name and after it.
|
|
266
280
|
*
|
|
267
281
|
* @remarks
|
|
268
|
-
* A
|
|
269
|
-
*
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
*
|
|
282
|
+
* A role query that includes hidden elements computes a name from the `aria-hidden` subtrees too,
|
|
283
|
+
* so an icon font's `::before` glyph joins the name a person never hears and an exact string never
|
|
284
|
+
* matches again. This pattern is what {@link resolveRendered} asks the hidden pass with, and its
|
|
285
|
+
* tolerance is bounded to what a glyph can be: a leading or trailing run carrying no letter and no
|
|
286
|
+
* digit. A hidden icon whose own content is a word still defeats it, and a name differing from the
|
|
287
|
+
* requested one by punctuation alone still satisfies it.
|
|
273
288
|
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
* a chain that declares no background color at all, a chain painting only translucent layers, and a
|
|
278
|
-
* chain deep enough for its composite to round to the canvas's own channels are refused alike,
|
|
279
|
-
* because the number any of them produces is as much a report of the assumption as of the page.
|
|
280
|
-
* Supply a floor wherever the caller knows what the stack sits on — a fragment mounted into a
|
|
281
|
-
* painted host, or a document whose canvas is {@link CANVAS_COLOR} — and the composite is taken
|
|
282
|
-
* over it rather than refused.
|
|
289
|
+
* That bound is affordable because the hidden pass chooses between two refusal voices and returns
|
|
290
|
+
* nothing. The visible pass decides which element a resolver returns, and it matches the exact
|
|
291
|
+
* string against the name the accessibility tree actually publishes.
|
|
283
292
|
*
|
|
284
|
-
*
|
|
285
|
-
*
|
|
293
|
+
* Pass this to a role query with `exact: true`. That flag is the engine's case-sensitivity switch
|
|
294
|
+
* as well as its exactness one, so a query carrying `exact: false` uppercases the computed name
|
|
295
|
+
* before testing a pattern against it and a lowercase letter in the requested name never matches.
|
|
286
296
|
*
|
|
287
297
|
* @example
|
|
288
298
|
* ```ts
|
|
289
|
-
*
|
|
290
|
-
* contrast(requireValue(container.firstElementChild)) // 21
|
|
291
|
-
* contrast(requireValue(container.firstElementChild), CANVAS_COLOR) // 21, and never refuses
|
|
299
|
+
* computeNamePattern('Add building').test('\uF4FE Add building') // true
|
|
292
300
|
* ```
|
|
293
301
|
*/
|
|
294
|
-
export declare function
|
|
302
|
+
export declare function computeNamePattern(name: string): RegExp;
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Names the roles whose accessible name is the text a reader can see inside them.
|
|
306
|
+
*
|
|
307
|
+
* @remarks
|
|
308
|
+
* `readName` reads an element in this list from its own rendered text, after every `aria-hidden`
|
|
309
|
+
* descendant is dropped, and falls through to `title` for every other role.
|
|
310
|
+
*/
|
|
311
|
+
export declare const CONTENT_ROLES: readonly string[];
|
|
295
312
|
|
|
296
313
|
/**
|
|
297
314
|
* Creates one console channel that records every call it receives and hands that call on unchanged.
|
|
@@ -479,7 +496,7 @@ export declare function describeFocus(element: Element): string;
|
|
|
479
496
|
export declare function describeTree(element: Element): string;
|
|
480
497
|
|
|
481
498
|
/**
|
|
482
|
-
*
|
|
499
|
+
* Configures one built element.
|
|
483
500
|
*
|
|
484
501
|
* @remarks
|
|
485
502
|
* `classes` is written the way a `class` attribute is written — one space-separated string — so a
|
|
@@ -488,11 +505,11 @@ export declare function describeTree(element: Element): string;
|
|
|
488
505
|
* with it.
|
|
489
506
|
*/
|
|
490
507
|
export declare interface ElementOptions {
|
|
491
|
-
/**
|
|
508
|
+
/** Holds the class list, space-separated, exactly as a `class` attribute writes it. */
|
|
492
509
|
readonly classes?: string;
|
|
493
|
-
/**
|
|
510
|
+
/** Holds the text the element carries, set as text rather than parsed as markup. */
|
|
494
511
|
readonly text?: string;
|
|
495
|
-
/**
|
|
512
|
+
/** Holds every attribute to set, keyed by attribute name. */
|
|
496
513
|
readonly attributes?: Readonly<Record<string, string>>;
|
|
497
514
|
}
|
|
498
515
|
|
|
@@ -542,7 +559,34 @@ export declare function expandCaptures(states: readonly string[], variants: read
|
|
|
542
559
|
export declare function extractOrphans(root: ParentNode, child: string, parent: string): readonly string[];
|
|
543
560
|
|
|
544
561
|
/**
|
|
545
|
-
*
|
|
562
|
+
* Collects the markup of every element carrying a non-empty `style` attribute and of every `<style>`
|
|
563
|
+
* element, in document order, `root` included in both populations when it is an `Element`.
|
|
564
|
+
*
|
|
565
|
+
* @param root - The subtree to sweep. A detached element and a `DocumentFragment` both work.
|
|
566
|
+
* @returns The `outerHTML` of each such element, in document order; an empty list when the markup
|
|
567
|
+
* declares no style of its own.
|
|
568
|
+
*
|
|
569
|
+
* @remarks
|
|
570
|
+
* These are the declarations the stylesheet never sees: an inline `style` attribute, wherever it
|
|
571
|
+
* sits, and a `<style>` element, whatever it holds. Nothing else counts. A class and a `data-*`
|
|
572
|
+
* attribute name something the cascade resolves, so neither is reported however unusual it looks;
|
|
573
|
+
* an inline `style` on a `<path>` inside an SVG is reported, because a namespace changes nothing
|
|
574
|
+
* about what an inline declaration is.
|
|
575
|
+
*
|
|
576
|
+
* A `style` attribute holding nothing but whitespace declares nothing, so it is not reported. A
|
|
577
|
+
* `DocumentFragment` root contributes its descendants alone, because it is not an `Element`; a
|
|
578
|
+
* `<style>` root and a root carrying an inline attribute are each reported, and an element that is a
|
|
579
|
+
* `<style>` element and carries an inline attribute too is reported once.
|
|
580
|
+
*
|
|
581
|
+
* @example
|
|
582
|
+
* ```ts
|
|
583
|
+
* extractStyles(container) // []
|
|
584
|
+
* ```
|
|
585
|
+
*/
|
|
586
|
+
export declare function extractStyles(root: ParentNode): readonly string[];
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* Names the role each `input` type carries.
|
|
546
590
|
*
|
|
547
591
|
* @remarks
|
|
548
592
|
* Membership is the contract. The map answers for `button`, `checkbox`, `email`, `number`,
|
|
@@ -599,8 +643,8 @@ export declare function findKeyframes(name: string): CSSKeyframesRule | undefine
|
|
|
599
643
|
*
|
|
600
644
|
* @remarks
|
|
601
645
|
* This proves a declaration exists in the cascade at all, which is a different question from what an
|
|
602
|
-
* element resolves to: {@link
|
|
603
|
-
* another. Assert on this where the subject is the stylesheet, and on `
|
|
646
|
+
* element resolves to: {@link readStyle} reads the winner, and a rule this finds may be overridden by
|
|
647
|
+
* another. Assert on this where the subject is the stylesheet, and on `readStyle` where the subject is
|
|
604
648
|
* the rendered result.
|
|
605
649
|
*
|
|
606
650
|
* The match is a substring, so `findRule('.card')` finds `.card`, `.card:hover`, and
|
|
@@ -614,7 +658,7 @@ export declare function findKeyframes(name: string): CSSKeyframesRule | undefine
|
|
|
614
658
|
export declare function findRule(selector: string): CSSStyleRule | undefined;
|
|
615
659
|
|
|
616
660
|
/**
|
|
617
|
-
*
|
|
661
|
+
* Names what sequential keyboard navigation can reach, before disabled and unrendered elements go.
|
|
618
662
|
*
|
|
619
663
|
* @remarks
|
|
620
664
|
* `describeFocus` queries this selector and then drops what a browser drops: an element the
|
|
@@ -624,20 +668,40 @@ export declare function findRule(selector: string): CSSStyleRule | undefined;
|
|
|
624
668
|
*/
|
|
625
669
|
export declare const FOCUSABLE_SELECTOR = "a[href], area[href], button, input, select, summary, textarea, [tabindex]";
|
|
626
670
|
|
|
627
|
-
/**
|
|
671
|
+
/** Configures one captured frame. */
|
|
628
672
|
export declare interface FrameOptions {
|
|
629
|
-
/**
|
|
673
|
+
/** Holds the frame's path, relative to the calling test file. */
|
|
630
674
|
readonly path: string;
|
|
631
|
-
/**
|
|
675
|
+
/** Holds the viewport width in CSS pixels the frame is shot at. */
|
|
632
676
|
readonly width: number;
|
|
633
|
-
/**
|
|
677
|
+
/** Holds the viewport height in CSS pixels the frame is shot at. */
|
|
634
678
|
readonly height: number;
|
|
635
|
-
/**
|
|
679
|
+
/** Holds the element to shoot. Omit it to shoot the whole page. */
|
|
636
680
|
readonly element?: Element | undefined;
|
|
637
681
|
}
|
|
638
682
|
|
|
639
683
|
/**
|
|
640
|
-
*
|
|
684
|
+
* Represents one written frame, read back from the file a capture produced.
|
|
685
|
+
*
|
|
686
|
+
* @remarks
|
|
687
|
+
* The floor is the frame's bottom row, because that row is where coverage shows: a frame shot at a
|
|
688
|
+
* pane shorter than the document ends on the runner's own canvas rather than on the document's
|
|
689
|
+
* background, and the two read as different colors. A row counts as one color only when every
|
|
690
|
+
* channel matches across it, alpha included, and `floor` names the three color channels of that one
|
|
691
|
+
* color in the `rgb(r, g, b)` form a computed style is written in, so a literal comparison,
|
|
692
|
+
* `parseColor`, and `matchesColor` all take it.
|
|
693
|
+
*/
|
|
694
|
+
export declare interface FrameReading {
|
|
695
|
+
/** Holds the frame's width in device pixels. */
|
|
696
|
+
readonly width: number;
|
|
697
|
+
/** Holds the frame's height in device pixels. */
|
|
698
|
+
readonly height: number;
|
|
699
|
+
/** Holds the single color the frame's bottom row paints; `undefined` where that row paints several. */
|
|
700
|
+
readonly floor: string | undefined;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
/**
|
|
704
|
+
* Names the role a `th` carries for the header axis its `scope` names.
|
|
641
705
|
*
|
|
642
706
|
* @remarks
|
|
643
707
|
* A header cell heads a column or a row, and this map answers for the `col` and `row` scopes that
|
|
@@ -647,7 +711,8 @@ export declare interface FrameOptions {
|
|
|
647
711
|
export declare const HEADER_ROLES: Readonly<Record<string, string>>;
|
|
648
712
|
|
|
649
713
|
/**
|
|
650
|
-
*
|
|
714
|
+
* Names the role each listed tag carries in the accessibility tree when it declares none of its
|
|
715
|
+
* own.
|
|
651
716
|
*
|
|
652
717
|
* @remarks
|
|
653
718
|
* Membership is the contract. The map answers for the sectioning elements `ARTICLE`, `ASIDE`,
|
|
@@ -672,7 +737,7 @@ export declare const IMPLICIT_ROLES: Readonly<Record<string, string>>;
|
|
|
672
737
|
* Determines whether a rectangle lies wholly outside the browser viewport.
|
|
673
738
|
*
|
|
674
739
|
* @param rectangle - The measured client rectangle to inspect.
|
|
675
|
-
* @returns
|
|
740
|
+
* @returns True if no part of the rectangle intersects the viewport; false otherwise.
|
|
676
741
|
*
|
|
677
742
|
* @example
|
|
678
743
|
* ```ts
|
|
@@ -685,9 +750,9 @@ export declare function isOutsideViewport(rectangle: DOMRectReadOnly): boolean;
|
|
|
685
750
|
* Determines whether a person can click one element where it currently sits.
|
|
686
751
|
*
|
|
687
752
|
* @param element - The element to judge.
|
|
688
|
-
* @returns
|
|
753
|
+
* @returns True if the element is connected, visible, laid out with a non-zero box, in the
|
|
689
754
|
* sequential focus order, neither disabled nor marked `aria-disabled="true"`, and outside every
|
|
690
|
-
* `[inert]` subtree;
|
|
755
|
+
* `[inert]` subtree; false otherwise.
|
|
691
756
|
*
|
|
692
757
|
* @remarks
|
|
693
758
|
* This is the one reachability filter the layer applies. `resolveRendered`, `clickAccessibleWithin`,
|
|
@@ -710,8 +775,7 @@ export declare function isReachable(element: Element): boolean;
|
|
|
710
775
|
* Determines whether the accessibility tree presents one element at all.
|
|
711
776
|
*
|
|
712
777
|
* @param element - The element to judge.
|
|
713
|
-
* @returns
|
|
714
|
-
* `true` otherwise.
|
|
778
|
+
* @returns True if the element is presented to assistive technology and to sight; false otherwise.
|
|
715
779
|
*
|
|
716
780
|
* @remarks
|
|
717
781
|
* A control clipped to a zero-size rectangle is still announced, which is the whole point of that
|
|
@@ -734,7 +798,7 @@ export declare function isReachable(element: Element): boolean;
|
|
|
734
798
|
export declare function isRendered(element: Element): boolean;
|
|
735
799
|
|
|
736
800
|
/**
|
|
737
|
-
*
|
|
801
|
+
* Records one scenario: every step it took and everything the page said while it ran.
|
|
738
802
|
*
|
|
739
803
|
* @remarks
|
|
740
804
|
* Recording is off until {@link JournalInterface.start} arms it, so a suite that never starts a
|
|
@@ -743,9 +807,9 @@ export declare function isRendered(element: Element): boolean;
|
|
|
743
807
|
* journal that swallowed what it read would hide exactly the diagnostics it exists to keep.
|
|
744
808
|
*/
|
|
745
809
|
export declare interface JournalInterface {
|
|
746
|
-
/**
|
|
810
|
+
/** Lists every step recorded since the journal started, in the order it was taken; a snapshot. */
|
|
747
811
|
readonly steps: readonly JournalStep[];
|
|
748
|
-
/**
|
|
812
|
+
/** Lists every console line and uncaught failure the page emitted since it started; a snapshot. */
|
|
749
813
|
readonly output: readonly string[];
|
|
750
814
|
/**
|
|
751
815
|
* Starts a fresh recording, dropping whatever the previous scenario left.
|
|
@@ -773,16 +837,75 @@ export declare interface JournalInterface {
|
|
|
773
837
|
record(action: string, trigger: string, result: string): void;
|
|
774
838
|
}
|
|
775
839
|
|
|
776
|
-
/**
|
|
840
|
+
/** Represents one scripted step a journal recorded, and what the surface did about it. */
|
|
777
841
|
export declare interface JournalStep {
|
|
778
|
-
/**
|
|
842
|
+
/** Names what the run did, as one verb. */
|
|
779
843
|
readonly action: string;
|
|
780
|
-
/**
|
|
844
|
+
/** Names the exact thing it did it to. */
|
|
781
845
|
readonly trigger: string;
|
|
782
|
-
/**
|
|
846
|
+
/** Holds what was observed on the surface after the step landed. */
|
|
783
847
|
readonly result: string;
|
|
784
848
|
}
|
|
785
849
|
|
|
850
|
+
/**
|
|
851
|
+
* Determines whether two colors render the same, within the rounding a browser does.
|
|
852
|
+
*
|
|
853
|
+
* @param first - A CSS color expression or an already-parsed color.
|
|
854
|
+
* @param second - A CSS color expression or an already-parsed color.
|
|
855
|
+
* @returns True if every channel and the alpha agree within the tolerance; false otherwise,
|
|
856
|
+
* including when either side names no readable color.
|
|
857
|
+
*
|
|
858
|
+
* @remarks
|
|
859
|
+
* Each string side is resolved through {@link parseCSSColor}, so a keyword, a token reference, and the
|
|
860
|
+
* `rgb()` the engine computes for either of them compare equal without a test converting anything
|
|
861
|
+
* first. A side that resolves to nothing makes the answer `false` rather than a throw, because this
|
|
862
|
+
* is a predicate.
|
|
863
|
+
*
|
|
864
|
+
* The tolerance is half a channel step on the 0–255 scale, and the alpha is scaled onto that same
|
|
865
|
+
* range before it is compared, so one number covers both. Half a step is what a composite of
|
|
866
|
+
* translucent layers and a `color-mix()` round trip actually drift by; anything a reader could see
|
|
867
|
+
* is further than that and reports unequal.
|
|
868
|
+
*
|
|
869
|
+
* @example
|
|
870
|
+
* ```ts
|
|
871
|
+
* matchesColor('rebeccapurple', 'rgb(102, 51, 153)') // true
|
|
872
|
+
* matchesColor('red', [0, 0, 255, 1]) // false
|
|
873
|
+
* ```
|
|
874
|
+
*/
|
|
875
|
+
export declare function matchesColor(first: string | Color, second: string | Color): boolean;
|
|
876
|
+
|
|
877
|
+
/**
|
|
878
|
+
* Measures the row the document's own content ends on, in document coordinates.
|
|
879
|
+
*
|
|
880
|
+
* @returns The content edge, rounded up to a whole row.
|
|
881
|
+
*
|
|
882
|
+
* @remarks
|
|
883
|
+
* The body's box is not the document's height: it is the larger of the content and the pane. A pane
|
|
884
|
+
* taller than the document stretches it, and `document.body.getBoundingClientRect()`,
|
|
885
|
+
* `body.scrollHeight`, `body.offsetHeight`, and `documentElement.scrollHeight` all read that pane
|
|
886
|
+
* back rather than the content under it. So a caller that has staged a pane taller than the
|
|
887
|
+
* document cannot find its way down again from any of them. This reading can, because it is taken
|
|
888
|
+
* over the elements inside the body rather than over the box around them: a document of fixed
|
|
889
|
+
* content answers the same number under a short pane and a tall one, and a document laid out
|
|
890
|
+
* against the viewport answers what that viewport actually laid out.
|
|
891
|
+
*
|
|
892
|
+
* Each element contributes its client rectangle's bottom edge in document coordinates plus its own
|
|
893
|
+
* bottom margin, which sits outside that rectangle, and the largest contribution wins. Taking the
|
|
894
|
+
* largest is what handles a collapsed margin without asking whether it collapsed: a child margin
|
|
895
|
+
* that collapses out through its parent is counted once, at the child, and one the parent's padding
|
|
896
|
+
* holds in is counted once, at the parent. The body's and the root's own bottom padding and margin
|
|
897
|
+
* sit under every child rather than beside them, so they are added after the walk.
|
|
898
|
+
*
|
|
899
|
+
* The sum is rounded up because a box can end part way through a row and a frame cannot hold part
|
|
900
|
+
* of one.
|
|
901
|
+
*
|
|
902
|
+
* @example
|
|
903
|
+
* ```ts
|
|
904
|
+
* const covered = measureContent()
|
|
905
|
+
* ```
|
|
906
|
+
*/
|
|
907
|
+
export declare function measureContent(): number;
|
|
908
|
+
|
|
786
909
|
/**
|
|
787
910
|
* Measures the WCAG 2.x contrast ratio between two opaque colors.
|
|
788
911
|
*
|
|
@@ -823,8 +946,8 @@ export declare function measureLuminance(color: Color): number;
|
|
|
823
946
|
* @remarks
|
|
824
947
|
* What this buys is the composition, not the attachment: the `append` method returns `void`, and
|
|
825
948
|
* this hands the element back, so it fits where an expression is expected. The {@link render} helper
|
|
826
|
-
* returns its fixture through it, and the {@link
|
|
827
|
-
* A bare `append` call breaks each of those call sites.
|
|
949
|
+
* returns its fixture through it, and the {@link parseCSSColor} helper probes through
|
|
950
|
+
* `mount(build('span'))`. A bare `append` call breaks each of those call sites.
|
|
828
951
|
*
|
|
829
952
|
* Being connected is what the attachment then buys: `getComputedStyle` resolves against the shipped
|
|
830
953
|
* cascade, custom properties inherit from `:root`, and the element lays out a real box. A detached
|
|
@@ -866,39 +989,46 @@ export declare function mount<T extends Element>(element: T): T;
|
|
|
866
989
|
export declare function parseColor(value: string): Color | undefined;
|
|
867
990
|
|
|
868
991
|
/**
|
|
869
|
-
*
|
|
992
|
+
* Resolves any CSS color expression to straight sRGB channels, by asking the browser.
|
|
870
993
|
*
|
|
871
|
-
* @param
|
|
872
|
-
*
|
|
873
|
-
* @returns The
|
|
994
|
+
* @param value - Any value the `color` property accepts: a keyword, a hex triple, a `var()`
|
|
995
|
+
* reference, a `color-mix()`, or an already-computed `rgb()`.
|
|
996
|
+
* @returns The resolved color's channels, or `undefined` when the CSSOM refuses the value or the
|
|
997
|
+
* computed result names no color {@link parseColor} speaks.
|
|
874
998
|
*
|
|
875
999
|
* @remarks
|
|
876
|
-
*
|
|
877
|
-
*
|
|
878
|
-
*
|
|
879
|
-
*
|
|
1000
|
+
* This is the live half of the pair {@link parseColor} opens. `parseColor` reads text and speaks
|
|
1001
|
+
* only the computed syntaxes a cascade hands back; this stages a probe element, hands it to the real
|
|
1002
|
+
* cascade, and reads back what the engine computed — which is the only way a keyword, a hex triple,
|
|
1003
|
+
* or a `var()` reference becomes channels at all. The read itself goes through `parseColor`, so both
|
|
1004
|
+
* halves agree on what a computed value means.
|
|
880
1005
|
*
|
|
881
|
-
*
|
|
882
|
-
*
|
|
883
|
-
*
|
|
1006
|
+
* The probe is mounted, because an unmounted element inherits nothing and a `var()` reference to a
|
|
1007
|
+
* token declared on `:root` would resolve to the initial value instead. It is removed in a `finally`,
|
|
1008
|
+
* so a value that throws on the way through leaves no node behind.
|
|
1009
|
+
*
|
|
1010
|
+
* Refusal is the CSSOM's: an expression it will not parse leaves the probe's inline `color` empty
|
|
1011
|
+
* and this returns `undefined`. A `var()` naming an undeclared custom property is not refused,
|
|
1012
|
+
* because the cascade accepts it and computes the inherited color, so a test that means to catch a
|
|
1013
|
+
* missing token asserts on {@link readToken} rather than on this.
|
|
884
1014
|
*
|
|
885
1015
|
* @example
|
|
886
1016
|
* ```ts
|
|
887
|
-
*
|
|
888
|
-
*
|
|
1017
|
+
* parseCSSColor('rebeccapurple') // [102, 51, 153, 1]
|
|
1018
|
+
* parseCSSColor('not-a-color') // undefined
|
|
889
1019
|
* ```
|
|
890
1020
|
*/
|
|
891
|
-
export declare function
|
|
1021
|
+
export declare function parseCSSColor(value: string): Color | undefined;
|
|
892
1022
|
|
|
893
|
-
/**
|
|
1023
|
+
/** Holds the registry of capture states one run places, and the files it wrote placing them. */
|
|
894
1024
|
export declare interface PortfolioInterface {
|
|
895
|
-
/**
|
|
1025
|
+
/** Holds the name of the variant this run renders. */
|
|
896
1026
|
readonly variant: string;
|
|
897
|
-
/**
|
|
898
|
-
readonly
|
|
899
|
-
/**
|
|
1027
|
+
/** Lists every state placed so far, in placement order. */
|
|
1028
|
+
readonly placements: readonly string[];
|
|
1029
|
+
/** Lists every path written so far, in write order. */
|
|
900
1030
|
readonly paths: readonly string[];
|
|
901
|
-
/**
|
|
1031
|
+
/** Lists the filenames a complete portfolio holds: the registry expanded across every variant. */
|
|
902
1032
|
readonly files: readonly string[];
|
|
903
1033
|
/**
|
|
904
1034
|
* Places one registered state: applies the variant, stages the pane, and writes the verified
|
|
@@ -913,22 +1043,22 @@ export declare interface PortfolioInterface {
|
|
|
913
1043
|
place(state: string, element?: Element): Promise<string | undefined>;
|
|
914
1044
|
}
|
|
915
1045
|
|
|
916
|
-
/**
|
|
1046
|
+
/** Configures a capture portfolio. */
|
|
917
1047
|
export declare interface PortfolioOptions {
|
|
918
1048
|
/**
|
|
919
|
-
*
|
|
920
|
-
* list, so the registry and the disk cannot drift apart.
|
|
1049
|
+
* Lists every state name the journeys place, declared once. `place` refuses a name absent from
|
|
1050
|
+
* this list, so the registry and the disk cannot drift apart.
|
|
921
1051
|
*/
|
|
922
1052
|
readonly states: readonly string[];
|
|
923
|
-
/**
|
|
1053
|
+
/** Lists every variant the portfolio can be rendered in. One run renders exactly one of them. */
|
|
924
1054
|
readonly variants: readonly CaptureVariant[];
|
|
925
|
-
/**
|
|
1055
|
+
/** Holds the name of the variant this run renders. Creation throws when no variant carries it. */
|
|
926
1056
|
readonly variant: string;
|
|
927
|
-
/**
|
|
1057
|
+
/** Holds the directory each written file is placed in, relative to the calling test file. */
|
|
928
1058
|
readonly directory: string;
|
|
929
1059
|
/**
|
|
930
|
-
*
|
|
931
|
-
* writes nothing, and records nothing.
|
|
1060
|
+
* Determines whether this run writes files. An ordinary run leaves it unset, so `place` resizes
|
|
1061
|
+
* nothing, writes nothing, and records nothing.
|
|
932
1062
|
*/
|
|
933
1063
|
readonly enabled?: boolean;
|
|
934
1064
|
}
|
|
@@ -1000,6 +1130,69 @@ export declare function readBackdrop(element: Element, floor: Color): Color;
|
|
|
1000
1130
|
*/
|
|
1001
1131
|
export declare function readCascade(): ReadonlySet<string>;
|
|
1002
1132
|
|
|
1133
|
+
/**
|
|
1134
|
+
* Collects every class token the markup under one root carries.
|
|
1135
|
+
*
|
|
1136
|
+
* @param root - The subtree to sweep. A detached element and a `DocumentFragment` both work.
|
|
1137
|
+
* @returns The class tokens in document order of first sighting; an empty set for markup carrying no
|
|
1138
|
+
* class at all.
|
|
1139
|
+
*
|
|
1140
|
+
* @remarks
|
|
1141
|
+
* The root's own classes count when the root is an `Element`, so a `DocumentFragment` contributes
|
|
1142
|
+
* its descendants alone. Every element is read through `classList`, which is what makes an SVG
|
|
1143
|
+
* element count the same as an HTML one: `className` on an SVG element is an `SVGAnimatedString`
|
|
1144
|
+
* rather than a string, and a reader splitting that value finds nothing.
|
|
1145
|
+
*
|
|
1146
|
+
* This is the authored half of a class conformance check and {@link readCascade} is the defined
|
|
1147
|
+
* half, so the difference between them is the set of classes the markup uses and no loaded
|
|
1148
|
+
* stylesheet declares.
|
|
1149
|
+
*
|
|
1150
|
+
* @example
|
|
1151
|
+
* ```ts
|
|
1152
|
+
* [...readClasses(container)].filter((name) => !readCascade().has(name))
|
|
1153
|
+
* ```
|
|
1154
|
+
*/
|
|
1155
|
+
export declare function readClasses(root: ParentNode): ReadonlySet<string>;
|
|
1156
|
+
|
|
1157
|
+
/**
|
|
1158
|
+
* Measures the WCAG 2.x contrast ratio between an element's computed text and background colors.
|
|
1159
|
+
*
|
|
1160
|
+
* @param element - The element whose rendered text contrast to measure.
|
|
1161
|
+
* @param floor - The opaque color the backdrop walk ends on. Omit it to refuse a stack the floor
|
|
1162
|
+
* would show through instead of assuming one.
|
|
1163
|
+
* @returns The relative-luminance contrast ratio.
|
|
1164
|
+
* @throws Thrown when the element exposes no computed foreground color, and — with `floor` omitted
|
|
1165
|
+
* — when the walk from the element upwards reaches no opaque layer.
|
|
1166
|
+
*
|
|
1167
|
+
* @remarks
|
|
1168
|
+
* A transparent or translucent background resolves through the element's ancestors: every painted
|
|
1169
|
+
* layer from the element up to the first opaque one composites top-over-bottom onto that opaque
|
|
1170
|
+
* base, so a 3% surface tint reads as a tint over what shows through it rather than as a
|
|
1171
|
+
* full-strength paint. A translucent foreground then resolves against that effective background
|
|
1172
|
+
* before luminance is measured.
|
|
1173
|
+
*
|
|
1174
|
+
* With `floor` omitted, the walk from the target upwards must reach a fully opaque layer: the
|
|
1175
|
+
* measurement throws rather than assuming a white canvas wherever that canvas would still be part
|
|
1176
|
+
* of the answer. The refusal reads the alpha of the deepest layer {@link readLayers} collected, so
|
|
1177
|
+
* a chain that declares no background color at all, a chain painting only translucent layers, and a
|
|
1178
|
+
* chain deep enough for its composite to round to the canvas's own channels are refused alike,
|
|
1179
|
+
* because the number any of them produces is as much a report of the assumption as of the page.
|
|
1180
|
+
* Supply a floor wherever the caller knows what the stack sits on — a fragment mounted into a
|
|
1181
|
+
* painted host, or a document whose canvas is {@link CANVAS_COLOR} — and the composite is taken
|
|
1182
|
+
* over it rather than refused.
|
|
1183
|
+
*
|
|
1184
|
+
* The element itself must expose a computed foreground color either way. A detached element exposes
|
|
1185
|
+
* none, and the measurement throws rather than guessing one.
|
|
1186
|
+
*
|
|
1187
|
+
* @example
|
|
1188
|
+
* ```ts
|
|
1189
|
+
* const container = render('<p style="background: #000; color: #fff">Ready</p>')
|
|
1190
|
+
* readContrast(requireValue(container.firstElementChild)) // 21
|
|
1191
|
+
* readContrast(requireValue(container.firstElementChild), CANVAS_COLOR) // 21, and never refuses
|
|
1192
|
+
* ```
|
|
1193
|
+
*/
|
|
1194
|
+
export declare function readContrast(element: Element, floor?: Color): number;
|
|
1195
|
+
|
|
1003
1196
|
/**
|
|
1004
1197
|
* Reads the rendered text of the element that currently holds focus.
|
|
1005
1198
|
*
|
|
@@ -1015,6 +1208,30 @@ export declare function readCascade(): ReadonlySet<string>;
|
|
|
1015
1208
|
*/
|
|
1016
1209
|
export declare function readFocus(): string | undefined;
|
|
1017
1210
|
|
|
1211
|
+
/**
|
|
1212
|
+
* Reads one written frame back and reports its size and the color its bottom row paints.
|
|
1213
|
+
*
|
|
1214
|
+
* @param path - The frame's absolute path, as `captureFrame` returns it.
|
|
1215
|
+
* @returns The frame's size in device pixels and its floor.
|
|
1216
|
+
* @throws Thrown when the runner cannot read the path, when the bytes there are not an image this
|
|
1217
|
+
* browser decodes, and when the browser hands out no 2D canvas to measure them on.
|
|
1218
|
+
*
|
|
1219
|
+
* @remarks
|
|
1220
|
+
* The reading comes off the written file rather than off the document that produced it, which is
|
|
1221
|
+
* what makes it evidence about a capture: the browser's own image decoding and an
|
|
1222
|
+
* `OffscreenCanvas` answer for the pixels a viewer would see, so a frame that ends on the runner's
|
|
1223
|
+
* canvas reports that canvas whatever the document's style resolves to. Pass the path the provider
|
|
1224
|
+
* resolved and `captureFrame` returned; the runner's `readFile` command resolves a relative path
|
|
1225
|
+
* against its own root rather than against the calling test file, so a relative path names a file
|
|
1226
|
+
* somewhere else.
|
|
1227
|
+
*
|
|
1228
|
+
* @example
|
|
1229
|
+
* ```ts
|
|
1230
|
+
* const reading = await readFrame(written)
|
|
1231
|
+
* ```
|
|
1232
|
+
*/
|
|
1233
|
+
export declare function readFrame(path: string): Promise<FrameReading>;
|
|
1234
|
+
|
|
1018
1235
|
/**
|
|
1019
1236
|
* Collects the painted layers standing between one element and the surface it sits on.
|
|
1020
1237
|
*
|
|
@@ -1028,7 +1245,7 @@ export declare function readFocus(): string | undefined;
|
|
|
1028
1245
|
* the walk stops at the first fully opaque layer, because nothing above that layer is visible.
|
|
1029
1246
|
*
|
|
1030
1247
|
* The stack is what tells a resolved backdrop from an assumed one: the walk reached an opaque
|
|
1031
|
-
* surface exactly when its last layer's alpha is `1`. {@link
|
|
1248
|
+
* surface exactly when its last layer's alpha is `1`. {@link readContrast} refuses on that reading,
|
|
1032
1249
|
* which no comparison of composited colors can replace — 64 half-transparent layers composite to
|
|
1033
1250
|
* the same channels over opposite floors, because the floor's remaining share falls below the last
|
|
1034
1251
|
* bit a channel carries.
|
|
@@ -1091,6 +1308,13 @@ export declare function readPage(): string;
|
|
|
1091
1308
|
* visually-hidden content.
|
|
1092
1309
|
* @throws When the named region is absent, hidden, or ambiguous.
|
|
1093
1310
|
*
|
|
1311
|
+
* @remarks
|
|
1312
|
+
* One pass answers this, because absence and concealment share the refusal. The pass asks the role
|
|
1313
|
+
* engine over the elements the accessibility tree presents, so the name matched is the one a screen
|
|
1314
|
+
* reader announces and an `aria-hidden` glyph in a heading a region points at contributes nothing
|
|
1315
|
+
* to it. A region the tree does not present is refused as not visible, which is what a reader
|
|
1316
|
+
* perceiving nothing there means.
|
|
1317
|
+
*
|
|
1094
1318
|
* @example
|
|
1095
1319
|
* ```ts
|
|
1096
1320
|
* readPerception('Run')
|
|
@@ -1098,6 +1322,31 @@ export declare function readPage(): string;
|
|
|
1098
1322
|
*/
|
|
1099
1323
|
export declare function readPerception(name: string): string;
|
|
1100
1324
|
|
|
1325
|
+
/**
|
|
1326
|
+
* Reads one resolved CSS length as a number of pixels.
|
|
1327
|
+
*
|
|
1328
|
+
* @param element - The element whose resolved style to inspect.
|
|
1329
|
+
* @param property - The CSS property name, registered or custom.
|
|
1330
|
+
* @returns The leading numeric part of the resolved value, and `0` when it carries none.
|
|
1331
|
+
*
|
|
1332
|
+
* @remarks
|
|
1333
|
+
* A resolved length is text with a unit — `'12px'` — so this reads the number in front of the unit
|
|
1334
|
+
* and discards the rest. The unit is not checked: the resolved value of a length is in pixels in
|
|
1335
|
+
* every case a browser hands back, and a property that resolves to something else is the caller's
|
|
1336
|
+
* mistake rather than this reader's.
|
|
1337
|
+
*
|
|
1338
|
+
* An unparsable value reads as `0` rather than as absence, because every caller of this is measuring
|
|
1339
|
+
* and `'auto'`, `'none'`, and `''` each contribute no pixels to what a reader sees. Where the
|
|
1340
|
+
* distinction matters, read the text with {@link readStyle} instead.
|
|
1341
|
+
*
|
|
1342
|
+
* @example
|
|
1343
|
+
* ```ts
|
|
1344
|
+
* readPixels(button, 'padding-left') // 12
|
|
1345
|
+
* readPixels(button, 'width') // 0 when the width resolves to `auto`
|
|
1346
|
+
* ```
|
|
1347
|
+
*/
|
|
1348
|
+
export declare function readPixels(element: Element, property: string): number;
|
|
1349
|
+
|
|
1101
1350
|
/**
|
|
1102
1351
|
* Measures the contrast the focus chrome painted on one control reaches against its own backdrop.
|
|
1103
1352
|
*
|
|
@@ -1158,6 +1407,25 @@ export declare function readRing(control: Element, worn?: Element): number | und
|
|
|
1158
1407
|
*/
|
|
1159
1408
|
export declare function readRole(element: Element): string | undefined;
|
|
1160
1409
|
|
|
1410
|
+
/**
|
|
1411
|
+
* Reads one custom property from the document element.
|
|
1412
|
+
*
|
|
1413
|
+
* @param name - The custom property name, with or without its leading dashes.
|
|
1414
|
+
* @returns The resolved value, trimmed; an empty string when the document declares no such property.
|
|
1415
|
+
*
|
|
1416
|
+
* @remarks
|
|
1417
|
+
* This is {@link readToken} against `document.documentElement`, which is where a theme declares its
|
|
1418
|
+
* tokens and where a `[data-theme]` switch retunes them. It exists as its own name because that
|
|
1419
|
+
* element is the one a token question is nearly always about, and naming it at every call site
|
|
1420
|
+
* buries the question.
|
|
1421
|
+
*
|
|
1422
|
+
* @example
|
|
1423
|
+
* ```ts
|
|
1424
|
+
* readRootToken('surface')
|
|
1425
|
+
* ```
|
|
1426
|
+
*/
|
|
1427
|
+
export declare function readRootToken(name: string): string;
|
|
1428
|
+
|
|
1161
1429
|
/**
|
|
1162
1430
|
* Reads the normalized visible text of every element a selector matches, in document order.
|
|
1163
1431
|
*
|
|
@@ -1228,6 +1496,25 @@ export declare function readRules(): readonly CSSRule[];
|
|
|
1228
1496
|
*/
|
|
1229
1497
|
export declare function readStates(element: Element): readonly string[];
|
|
1230
1498
|
|
|
1499
|
+
/**
|
|
1500
|
+
* Reads one resolved CSS property from a real browser element.
|
|
1501
|
+
*
|
|
1502
|
+
* @param element - The element whose resolved style to inspect.
|
|
1503
|
+
* @param property - The CSS property name, registered or custom.
|
|
1504
|
+
* @returns The browser's resolved property value, trimmed; an empty string when the element resolves
|
|
1505
|
+
* none.
|
|
1506
|
+
*
|
|
1507
|
+
* @remarks
|
|
1508
|
+
* The value is trimmed, so what comes back is the value and never the whitespace around it. Internal
|
|
1509
|
+
* whitespace is kept: `--shadow: 0 0 2px` reads back with its spaces.
|
|
1510
|
+
*
|
|
1511
|
+
* @example
|
|
1512
|
+
* ```ts
|
|
1513
|
+
* readStyle(button, 'padding-left')
|
|
1514
|
+
* ```
|
|
1515
|
+
*/
|
|
1516
|
+
export declare function readStyle(element: Element, property: string): string;
|
|
1517
|
+
|
|
1231
1518
|
/**
|
|
1232
1519
|
* Reads one element's rendered text the way a name computation reads it.
|
|
1233
1520
|
*
|
|
@@ -1247,6 +1534,32 @@ export declare function readStates(element: Element): readonly string[];
|
|
|
1247
1534
|
*/
|
|
1248
1535
|
export declare function readText(element: Element): string;
|
|
1249
1536
|
|
|
1537
|
+
/**
|
|
1538
|
+
* Reads one custom property from an element's resolved style.
|
|
1539
|
+
*
|
|
1540
|
+
* @param element - The element whose resolved style to inspect.
|
|
1541
|
+
* @param name - The custom property name, with or without its leading dashes.
|
|
1542
|
+
* @returns The resolved value, trimmed; an empty string when the element inherits no such property.
|
|
1543
|
+
*
|
|
1544
|
+
* @remarks
|
|
1545
|
+
* The dashes are optional because a token is spoken about both ways — `--surface` in a stylesheet
|
|
1546
|
+
* and `surface` in prose — and a reader that accepted only one spelling would turn that into a silent
|
|
1547
|
+
* empty string. An absent token reads as `''`, which is what the CSSOM returns and is
|
|
1548
|
+
* indistinguishable from a token declared empty; assert on the value you expect rather than on
|
|
1549
|
+
* presence.
|
|
1550
|
+
*
|
|
1551
|
+
* Resolution is inheritance, so a token declared on `:root` reads from any mounted descendant and
|
|
1552
|
+
* from an unmounted element reads as `''`. Use {@link readRootToken} where the declaration is the
|
|
1553
|
+
* document's.
|
|
1554
|
+
*
|
|
1555
|
+
* @example
|
|
1556
|
+
* ```ts
|
|
1557
|
+
* readToken(panel, 'surface') // '#ffffff'
|
|
1558
|
+
* readToken(panel, '--surface') // '#ffffff'
|
|
1559
|
+
* ```
|
|
1560
|
+
*/
|
|
1561
|
+
export declare function readToken(element: Element, name: string): string;
|
|
1562
|
+
|
|
1250
1563
|
/**
|
|
1251
1564
|
* Reads the value a resolved control renders.
|
|
1252
1565
|
*
|
|
@@ -1267,22 +1580,33 @@ export declare function readText(element: Element): string;
|
|
|
1267
1580
|
export declare function readValue(role: string, name: string): string;
|
|
1268
1581
|
|
|
1269
1582
|
/**
|
|
1270
|
-
* Hands the tester pane back to the runner's own layout.
|
|
1583
|
+
* Hands the tester pane back to the runner's own layout, at the viewport it had before staging.
|
|
1271
1584
|
*
|
|
1272
1585
|
* @remarks
|
|
1273
1586
|
* A staged pane is the runner's fitting scale suppressed, so a pane left staged outlives the capture
|
|
1274
1587
|
* that needed it and every later act in the file happens on a surface the runner is no longer
|
|
1275
1588
|
* fitting to its window. What that costs is not a wrong picture: it is a control whose page
|
|
1276
1589
|
* coordinates fall outside the pane, which the runner's own layout then intercepts, so an ordinary
|
|
1277
|
-
* press fails with the voice of a control that is covered.
|
|
1590
|
+
* press fails with the voice of a control that is covered.
|
|
1591
|
+
*
|
|
1592
|
+
* The viewport goes back too, because a capture resizes the tester and the size it chose belongs to
|
|
1593
|
+
* the frame rather than to the file: a test that runs after one and reads a breakpoint would
|
|
1594
|
+
* otherwise read the last capture's variant. The size comes off the {@link CAPTURE_PANE} value
|
|
1595
|
+
* {@link stagePane} wrote onto the rule element, which is the reading taken before the first
|
|
1596
|
+
* staging. Calling this on an unstaged pane finds no such value, so it changes nothing and resizes
|
|
1278
1597
|
* nothing.
|
|
1279
1598
|
*
|
|
1599
|
+
* That hand-back is what makes {@link stagePane} and this pair a capture's staging rather than a
|
|
1600
|
+
* resize: the pair puts the tester back where it found it, so a suite that used it to reach a
|
|
1601
|
+
* breakpoint runs its next step at the old size. Call `page.viewport` from `vitest/browser` for a
|
|
1602
|
+
* journey's own size, and leave this pair to the capture.
|
|
1603
|
+
*
|
|
1280
1604
|
* @example
|
|
1281
1605
|
* ```ts
|
|
1282
|
-
* releasePane()
|
|
1606
|
+
* await releasePane()
|
|
1283
1607
|
* ```
|
|
1284
1608
|
*/
|
|
1285
|
-
export declare function releasePane(): void
|
|
1609
|
+
export declare function releasePane(): Promise<void>;
|
|
1286
1610
|
|
|
1287
1611
|
/**
|
|
1288
1612
|
* Deletes one IndexedDB database and reports what the request actually did.
|
|
@@ -1386,6 +1710,14 @@ export declare function resolveAccessible(role: string, name: string): HTMLEleme
|
|
|
1386
1710
|
* This is the resolver the acting verbs use, so a click does not fail on a target the act itself
|
|
1387
1711
|
* scrolls into view. Use {@link resolveAccessible} wherever the target must already be on screen.
|
|
1388
1712
|
*
|
|
1713
|
+
* It runs two passes, and only the first one can return an element. The visible pass asks the role
|
|
1714
|
+
* engine for the exact name over the elements the accessibility tree presents, which is the name a
|
|
1715
|
+
* screen reader announces: an `aria-hidden` icon beside the text contributes nothing to it. The
|
|
1716
|
+
* hidden pass runs only when the visible pass found nothing at all, and it decides which refusal
|
|
1717
|
+
* the caller hears — a name the page carries nowhere, or a target that is there and out of reach.
|
|
1718
|
+
* That pass must include hidden elements to see a folded control, which is what puts a glyph back
|
|
1719
|
+
* into the computed name, so it asks with {@link computeNamePattern} rather than the exact string.
|
|
1720
|
+
*
|
|
1389
1721
|
* @example
|
|
1390
1722
|
* ```ts
|
|
1391
1723
|
* resolveRendered('tab', 'Drafts')
|
|
@@ -1393,57 +1725,6 @@ export declare function resolveAccessible(role: string, name: string): HTMLEleme
|
|
|
1393
1725
|
*/
|
|
1394
1726
|
export declare function resolveRendered(first: string, second?: string): HTMLElement;
|
|
1395
1727
|
|
|
1396
|
-
/**
|
|
1397
|
-
* Resolves any CSS color expression to straight sRGB channels, by asking the browser.
|
|
1398
|
-
*
|
|
1399
|
-
* @param value - Any value the `color` property accepts: a keyword, a hex triple, a `var()`
|
|
1400
|
-
* reference, a `color-mix()`, or an already-computed `rgb()`.
|
|
1401
|
-
* @returns The resolved color's channels, or `undefined` when the CSSOM refuses the value or the
|
|
1402
|
-
* computed result names no color {@link parseColor} speaks.
|
|
1403
|
-
*
|
|
1404
|
-
* @remarks
|
|
1405
|
-
* This is the live half of the pair {@link parseColor} opens. `parseColor` reads text and speaks
|
|
1406
|
-
* only the computed syntaxes a cascade hands back; this stages a probe element, hands it to the real
|
|
1407
|
-
* cascade, and reads back what the engine computed — which is the only way a keyword, a hex triple,
|
|
1408
|
-
* or a `var()` reference becomes channels at all. The read itself goes through `parseColor`, so both
|
|
1409
|
-
* halves agree on what a computed value means.
|
|
1410
|
-
*
|
|
1411
|
-
* The probe is mounted, because an unmounted element inherits nothing and a `var()` reference to a
|
|
1412
|
-
* token declared on `:root` would resolve to the initial value instead. It is removed in a `finally`,
|
|
1413
|
-
* so a value that throws on the way through leaves no node behind.
|
|
1414
|
-
*
|
|
1415
|
-
* Refusal is the CSSOM's: an expression it will not parse leaves the probe's inline `color` empty
|
|
1416
|
-
* and this returns `undefined`. A `var()` naming an undeclared custom property is not refused,
|
|
1417
|
-
* because the cascade accepts it and computes the inherited color, so a test that means to catch a
|
|
1418
|
-
* missing token asserts on {@link token} rather than on this.
|
|
1419
|
-
*
|
|
1420
|
-
* @example
|
|
1421
|
-
* ```ts
|
|
1422
|
-
* rgba('rebeccapurple') // [102, 51, 153, 1]
|
|
1423
|
-
* rgba('not-a-color') // undefined
|
|
1424
|
-
* ```
|
|
1425
|
-
*/
|
|
1426
|
-
export declare function rgba(value: string): Color | undefined;
|
|
1427
|
-
|
|
1428
|
-
/**
|
|
1429
|
-
* Reads one custom property from the document element.
|
|
1430
|
-
*
|
|
1431
|
-
* @param name - The custom property name, with or without its leading dashes.
|
|
1432
|
-
* @returns The resolved value, trimmed; an empty string when the document declares no such property.
|
|
1433
|
-
*
|
|
1434
|
-
* @remarks
|
|
1435
|
-
* This is {@link token} against `document.documentElement`, which is where a theme declares its
|
|
1436
|
-
* tokens and where a `[data-theme]` switch retunes them. It exists as its own name because that
|
|
1437
|
-
* element is the one a token question is nearly always about, and naming it at every call site
|
|
1438
|
-
* buries the question.
|
|
1439
|
-
*
|
|
1440
|
-
* @example
|
|
1441
|
-
* ```ts
|
|
1442
|
-
* rootToken('surface')
|
|
1443
|
-
* ```
|
|
1444
|
-
*/
|
|
1445
|
-
export declare function rootToken(name: string): string;
|
|
1446
|
-
|
|
1447
1728
|
/**
|
|
1448
1729
|
* Sets the tester's viewport and renders the runner's pane at the size that viewport claims.
|
|
1449
1730
|
*
|
|
@@ -1469,6 +1750,11 @@ export declare function rootToken(name: string): string;
|
|
|
1469
1750
|
* the window puts its lower half beyond what a pointer can reach, so an ordinary press then fails
|
|
1470
1751
|
* as a control outside the viewport, in a test that took no picture at all.
|
|
1471
1752
|
*
|
|
1753
|
+
* This is a capture's staging alone. A suite that resizes the tester for a journey — a breakpoint
|
|
1754
|
+
* to drive, a variant to act at — calls `page.viewport` from `vitest/browser` and leaves the tester
|
|
1755
|
+
* there. Staging and releasing as a pair resizes and then undoes the resize, so the journey step
|
|
1756
|
+
* after it runs at the size the file started at.
|
|
1757
|
+
*
|
|
1472
1758
|
* The rule is declared rather than written inline, because the runner writes its own scale onto the
|
|
1473
1759
|
* pane as inline custom properties and rewrites them whenever the tester resizes. A declared rule
|
|
1474
1760
|
* marked important outranks an inline value and survives every rewrite. It finds the pane by the
|
|
@@ -1478,6 +1764,11 @@ export declare function rootToken(name: string): string;
|
|
|
1478
1764
|
* The wait is two frames rather than a delay: the first carries the resize into layout and the
|
|
1479
1765
|
* second is the paint a screenshot reads.
|
|
1480
1766
|
*
|
|
1767
|
+
* The viewport the tester had before this staging is written onto that rule element as the
|
|
1768
|
+
* {@link CAPTURE_PANE} value, in `<width>x<height>` form, and {@link releasePane} hands it back.
|
|
1769
|
+
* Staging an already-staged pane leaves that value alone, so a capture that stages a second time to
|
|
1770
|
+
* cover a taller document still releases to the viewport the tester started with.
|
|
1771
|
+
*
|
|
1481
1772
|
* @example
|
|
1482
1773
|
* ```ts
|
|
1483
1774
|
* await stagePane(390, 844)
|
|
@@ -1485,51 +1776,6 @@ export declare function rootToken(name: string): string;
|
|
|
1485
1776
|
*/
|
|
1486
1777
|
export declare function stagePane(width: number, height: number): Promise<void>;
|
|
1487
1778
|
|
|
1488
|
-
/**
|
|
1489
|
-
* Reads one resolved CSS property from a real browser element.
|
|
1490
|
-
*
|
|
1491
|
-
* @param element - The element whose resolved style to inspect.
|
|
1492
|
-
* @param property - The CSS property name, registered or custom.
|
|
1493
|
-
* @returns The browser's resolved property value, trimmed; an empty string when the element resolves
|
|
1494
|
-
* none.
|
|
1495
|
-
*
|
|
1496
|
-
* @remarks
|
|
1497
|
-
* The value is trimmed, so what comes back is the value and never the whitespace around it. Internal
|
|
1498
|
-
* whitespace is kept: `--shadow: 0 0 2px` reads back with its spaces.
|
|
1499
|
-
*
|
|
1500
|
-
* @example
|
|
1501
|
-
* ```ts
|
|
1502
|
-
* style(button, 'padding-left')
|
|
1503
|
-
* ```
|
|
1504
|
-
*/
|
|
1505
|
-
export declare function style(element: Element, property: string): string;
|
|
1506
|
-
|
|
1507
|
-
/**
|
|
1508
|
-
* Reads one custom property from an element's resolved style.
|
|
1509
|
-
*
|
|
1510
|
-
* @param element - The element whose resolved style to inspect.
|
|
1511
|
-
* @param name - The custom property name, with or without its leading dashes.
|
|
1512
|
-
* @returns The resolved value, trimmed; an empty string when the element inherits no such property.
|
|
1513
|
-
*
|
|
1514
|
-
* @remarks
|
|
1515
|
-
* The dashes are optional because a token is spoken about both ways — `--surface` in a stylesheet
|
|
1516
|
-
* and `surface` in prose — and a reader that accepted only one spelling would turn that into a silent
|
|
1517
|
-
* empty string. An absent token reads as `''`, which is what the CSSOM returns and is
|
|
1518
|
-
* indistinguishable from a token declared empty; assert on the value you expect rather than on
|
|
1519
|
-
* presence.
|
|
1520
|
-
*
|
|
1521
|
-
* Resolution is inheritance, so a token declared on `:root` reads from any mounted descendant and
|
|
1522
|
-
* from an unmounted element reads as `''`. Use {@link rootToken} where the declaration is the
|
|
1523
|
-
* document's.
|
|
1524
|
-
*
|
|
1525
|
-
* @example
|
|
1526
|
-
* ```ts
|
|
1527
|
-
* token(panel, 'surface') // '#ffffff'
|
|
1528
|
-
* token(panel, '--surface') // '#ffffff'
|
|
1529
|
-
* ```
|
|
1530
|
-
*/
|
|
1531
|
-
export declare function token(element: Element, name: string): string;
|
|
1532
|
-
|
|
1533
1779
|
/**
|
|
1534
1780
|
* Reaches a named control only through natural forward Tab traversal from the current focus.
|
|
1535
1781
|
*
|