@delacour/warden-e2e 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{chunk-zk3wxa70.mjs → chunk-e3cry5br.mjs} +287 -37
- package/index.mjs +32 -3
- package/package.json +2 -2
- package/preload.mjs +304 -30
- package/types/core/src/affected/affected.schema.d.ts +5 -0
- package/types/core/src/builds/builds.defaults.d.ts +8 -0
- package/types/core/src/builds/config.schema.d.ts +9 -0
- package/types/core/src/builds/define-config.d.ts +9 -1
- package/types/core/src/conditions/conditions.config.d.ts +6 -1
- package/types/core/src/conditions/conditions.types.d.ts +21 -0
- package/types/core/src/conditions/inject-state.d.ts +3 -2
- package/types/e2e/src/a11y/a11y-target.d.ts +2 -0
- package/types/e2e/src/conditions/condition-events.d.ts +6 -1
- package/types/e2e/src/conditions/device-conditions.d.ts +8 -2
- package/types/e2e/src/device.d.ts +10 -2
- package/types/e2e/src/driver/android/android-settings.d.ts +9 -2
- package/types/e2e/src/driver/ax-wedge.d.ts +38 -0
- package/types/e2e/src/driver/bridge-stall.d.ts +4 -0
- package/types/e2e/src/driver/driver.types.d.ts +30 -1
- package/types/e2e/src/driver/ios/inject.d.ts +17 -2
- package/types/e2e/src/driver/ios/ios-driver.d.ts +7 -2
- package/types/e2e/src/driver/ios/ios-keyboard.d.ts +39 -0
- package/types/e2e/src/driver/ios/simd-protocol.d.ts +99 -0
- package/types/e2e/src/driver/keyboard-state.d.ts +9 -0
- package/types/e2e/src/driver/physical-conditions.d.ts +1 -1
- package/types/e2e/src/driver/read-deadline.d.ts +4 -0
- package/types/e2e/src/driver/settle.d.ts +3 -1
- package/types/e2e/src/expect/a11y-matchers.d.ts +7 -0
- package/types/e2e/src/index.d.ts +2 -1
- package/types/e2e/src/screen/actions.d.ts +7 -0
- package/types/e2e/src/screen/context.d.ts +3 -1
- package/types/e2e/src/screen/keyboard-cover.d.ts +26 -0
- package/types/e2e/src/screen/locator.d.ts +16 -7
- package/types/e2e/src/session.d.ts +6 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Snapshot } from "./driver.types";
|
|
1
|
+
import type { Element, Snapshot } from "./driver.types";
|
|
2
2
|
export type SettleDeps = {
|
|
3
3
|
quietMs: number;
|
|
4
4
|
timeoutMs: number;
|
|
@@ -47,5 +47,7 @@ export declare function hashFallbackQuietMs(quietMs: number): number;
|
|
|
47
47
|
* Side effects are injected so tests drive a fake clock.
|
|
48
48
|
*/
|
|
49
49
|
export declare function settleByHash(poll: () => Promise<string>, deps: SettleDeps): Promise<SettleOutcome>;
|
|
50
|
+
/** One element as `(role, identifier, label, value, frame to 1 pt)`: what `snapshotHash` hashes, per node. */
|
|
51
|
+
export declare function elementKey(element: Element): string;
|
|
50
52
|
/** Stable fingerprint over `(role, identifier, label, value, frame)` of every node in preorder. */
|
|
51
53
|
export declare function snapshotHash(snapshot: Pick<Snapshot, "flat">): string;
|
|
@@ -28,6 +28,13 @@ export declare class DeviceAssertions {
|
|
|
28
28
|
toPassA11yAudit(options?: PassA11yAuditOptions): Promise<void>;
|
|
29
29
|
/** An announcement or live-region change whose text contains the string or matches the RegExp arrived (`.not`: none did within the timeout). */
|
|
30
30
|
toHaveAnnounced(expected: TextMatch, options?: AnnouncedOptions): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* The on-screen keyboard is up (`.not`: it is gone), read from the accessibility tree. Polls until it holds or
|
|
33
|
+
* `timeout` (default: the assertion timeout) passes. Under `hardware` mode the keyboard never shows.
|
|
34
|
+
*/
|
|
35
|
+
toHaveKeyboard(options?: {
|
|
36
|
+
timeout?: number;
|
|
37
|
+
}): Promise<void>;
|
|
31
38
|
private failure;
|
|
32
39
|
private run;
|
|
33
40
|
}
|
package/types/e2e/src/index.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
export type { KeyboardMode } from "../../core/src/conditions/conditions.types";
|
|
1
2
|
export type { A11yAuditOptions, A11yAuditResult, A11yEvent, A11yEventKind, A11yEventSource, A11yIgnore, A11yIssue, A11yRuleId, A11ySeverity, A11ySource, Announcement, ScreenReaderState, SpokenLine, } from "./a11y/a11y.types";
|
|
2
3
|
export type { OpenOptions, OpenWaitUntil } from "./app";
|
|
3
4
|
export type { CameraFacingChoice, CameraSetOptions, ClockInput, ConditionRun, DeviceCamera, DeviceClock, DeviceLocation, DeviceNetwork, DevicePermissions, Duration, FlapOptions, LocationPoint, NetworkSetOptions, NetworkStatus, RouteOptions, TimelineStepInput, } from "./conditions/device-conditions";
|
|
4
5
|
export type { BiometricState, DeviceBiometrics } from "./device";
|
|
5
6
|
export type { A11yAnnouncement, A11yAnnouncements, A11yAnnouncementsOptions, DeviceA11y, DeviceA11yAuditOptions, DeviceScreenReader, ScreenReaderSpokenOptions, } from "./device-a11y";
|
|
6
|
-
export type { A11yOp, A11yState, CameraState } from "./driver/driver.types";
|
|
7
|
+
export type { A11yOp, A11yState, CameraState, KeyboardResult, KeyboardState } from "./driver/driver.types";
|
|
7
8
|
export { E2eError } from "./errors";
|
|
8
9
|
export type { AnnouncedOptions, PassA11yAuditOptions } from "./expect/a11y-matchers";
|
|
9
10
|
export { expect } from "./expect/expect";
|
|
@@ -39,6 +39,8 @@ export declare function isOnScreen(point: Point, screen: ScreenInfo): boolean;
|
|
|
39
39
|
* field; Android keeps an input's text in `text`.
|
|
40
40
|
*/
|
|
41
41
|
export declare function fieldValue(entry: NodeEntry): string;
|
|
42
|
+
/** User-perceived characters in `text` (what a secure field shows one bullet for). */
|
|
43
|
+
export declare function graphemes(text: string): number;
|
|
42
44
|
/** What one read says a field holds: nothing, text, or (secure fields) a number of hidden characters. */
|
|
43
45
|
export type FieldContent = {
|
|
44
46
|
kind: "empty";
|
|
@@ -55,6 +57,11 @@ export type FieldContent = {
|
|
|
55
57
|
* plain field showing its placeholder cannot be told from one holding that text and reads as `text`.
|
|
56
58
|
*/
|
|
57
59
|
export declare function fieldContent(entry: NodeEntry): FieldContent;
|
|
60
|
+
/**
|
|
61
|
+
* What a fill read-back of a secure field says it holds, given the typed `text`: `text` when it shows one bullet per
|
|
62
|
+
* character of it (the only check a masked field allows), else its bullets (never the typed text, in a message).
|
|
63
|
+
*/
|
|
64
|
+
export declare function maskedReading(entry: NodeEntry, text: string): string;
|
|
58
65
|
/**
|
|
59
66
|
* Backspaces that empty a field once the caret is at its end: one per character plus a spare. Secure fields are
|
|
60
67
|
* counted by their dots. The fallback for a driver without select-all, and the retry when select-all did not empty
|
|
@@ -128,7 +128,9 @@ export declare class Runtime {
|
|
|
128
128
|
excerpt(snapshot: Snapshot): string;
|
|
129
129
|
/**
|
|
130
130
|
* `poll` on this runtime's clock and abort signal; an abort throws instead of returning. `intervalMs` is a fixed gap
|
|
131
|
-
* between attempts instead of the back-off schedule.
|
|
131
|
+
* between attempts instead of the back-off schedule. The poll's deadline is the read deadline of every driver read
|
|
132
|
+
* made inside it (`withReadDeadline`), so a read that waits for the device (the cold iOS bridge) stops with it; a
|
|
133
|
+
* poll inside another keeps the nearer deadline.
|
|
132
134
|
*/
|
|
133
135
|
poll<T, S>(step: (attempt: number) => Promise<PollStep<T, S>> | PollStep<T, S>, timeoutMs: number, options?: {
|
|
134
136
|
intervalMs?: number;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Driver, DriverResult, Point, Rect, Snapshot } from "../driver/driver.types";
|
|
2
|
+
import type { NodeEntry } from "./nodes";
|
|
3
|
+
export type Cover = {
|
|
4
|
+
/** the keyboard's top edge */
|
|
5
|
+
top: number;
|
|
6
|
+
/** the free part of the nearest scroll container (its frame down to the keyboard), when the target sits in one */
|
|
7
|
+
scroller?: Rect;
|
|
8
|
+
/** points the content has to move up to clear the keyboard with a margin */
|
|
9
|
+
shift: number;
|
|
10
|
+
};
|
|
11
|
+
/** Whether `point` is under the keyboard of `snapshot`, and how to get clear of it; undefined when it is not. */
|
|
12
|
+
export declare function coverOf(entry: NodeEntry, point: Point, snapshot: Snapshot): Cover | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* The finger path that moves the content of `scroller` up by about `shift` points (a shorter one when the free part
|
|
15
|
+
* is not that tall: the caller looks again and swipes again).
|
|
16
|
+
*/
|
|
17
|
+
export declare function scrollPath(scroller: Rect, shift: number): {
|
|
18
|
+
from: Point;
|
|
19
|
+
to: Point;
|
|
20
|
+
};
|
|
21
|
+
export declare const COVER_SCROLL_SWIPE: {
|
|
22
|
+
durationMs: number;
|
|
23
|
+
momentum: boolean;
|
|
24
|
+
};
|
|
25
|
+
/** Dismisses the keyboard the way `device.hideKeyboard()` does: iOS resigns the first responder (no Return), Android presses back. */
|
|
26
|
+
export declare function dismissKeyboard(driver: Driver): DriverResult<void>;
|
|
@@ -134,7 +134,8 @@ export declare class Locator {
|
|
|
134
134
|
degradedFailure(read: DegradedRead, waitedMs: number, snapshot: Observed["snapshot"] | undefined): E2eError;
|
|
135
135
|
/**
|
|
136
136
|
* One look that settles this locator. A whole read answers at once (never waits); a degraded one that cannot say
|
|
137
|
-
* whether the locator is there is looked at again until one can, within the action timeout
|
|
137
|
+
* whether the locator is there is looked at again until one can, within the action timeout (`quick`: within
|
|
138
|
+
* `QUICK_CHECK_WINDOW_MS`, for checks a spec branches on), then `READ_DEGRADED`.
|
|
138
139
|
*/
|
|
139
140
|
private conclusive;
|
|
140
141
|
/** The conclusive answer of `observed`, or undefined while it is `unknown`. */
|
|
@@ -219,6 +220,13 @@ export declare class Locator {
|
|
|
219
220
|
* the kept snapshot sits outside the app, where the app-scoped hit-test may not see it, and the fresh look answers it.
|
|
220
221
|
*/
|
|
221
222
|
private aimFromKept;
|
|
223
|
+
/**
|
|
224
|
+
* A target under the on-screen keyboard (the default `software` mode keeps it up) would get the touch on a key. In a
|
|
225
|
+
* scroll container it is scrolled into the free part of the screen (at most `MAX_COVER_SCROLLS` swipes, each looked at
|
|
226
|
+
* fresh); otherwise, or when scrolling does not clear it, the keyboard is dismissed once (`dismissKeyboard`). Either way
|
|
227
|
+
* the match is looked at again, and whatever that look shows is what the action uses: no retry.
|
|
228
|
+
*/
|
|
229
|
+
private clearOfKeyboard;
|
|
222
230
|
/**
|
|
223
231
|
* Taps the one visible, enabled match. With `until` it is also the retrying tap: the press on a tab bar or a list row
|
|
224
232
|
* right after a navigation is sometimes dropped with nothing on screen to tell, so it checks that `until` shows
|
|
@@ -226,9 +234,10 @@ export declare class Locator {
|
|
|
226
234
|
*/
|
|
227
235
|
tap(options?: TapOptions): Promise<void>;
|
|
228
236
|
/**
|
|
229
|
-
* One press; resolves to the snapshot it aimed from (the screen just before the press)
|
|
230
|
-
*
|
|
231
|
-
*
|
|
237
|
+
* One press; resolves to the snapshot it aimed from (the screen just before the press) and the element pressed (none
|
|
238
|
+
* for a match only the React tree knows). A plain tap may aim from the kept snapshot (`aimFromKept`); a tap with
|
|
239
|
+
* `until` takes a fresh look, since the screen it aimed from is what the checks compare against to tell the press
|
|
240
|
+
* landed, and an older one could differ only because it was older.
|
|
232
241
|
*/
|
|
233
242
|
private tapOnce;
|
|
234
243
|
/**
|
|
@@ -236,9 +245,9 @@ export declare class Locator {
|
|
|
236
245
|
* (`driver.tap` returns once the HID press is over, ~85 ms, and an AX read queues behind the app's main thread, so
|
|
237
246
|
* that look usually already shows the screen the press made; measured: holding it back to `pollMs` saved no read
|
|
238
247
|
* and cost 250 ms a press). A locator is checked on the snapshot of
|
|
239
|
-
* the poll itself, which is also compared with
|
|
240
|
-
*
|
|
241
|
-
*
|
|
248
|
+
* the poll itself, which is also compared with the screen the press aimed from (`reacted`): once the screen reacted
|
|
249
|
+
* the press landed, so it is never sent again (`landed`, even when `until` is late); a screen that has not reacted
|
|
250
|
+
* on `UNCHANGED_CHECKS` checks in a row from `UNCHANGED_AFTER_MS` on is pressed again at once. A function
|
|
242
251
|
* is called with the kept snapshot forgotten (after the first check), so its own reads take one new snapshot
|
|
243
252
|
* between them rather than the previous check's; it gets the whole window.
|
|
244
253
|
*/
|
|
@@ -37,6 +37,12 @@ export type Session = {
|
|
|
37
37
|
* reopens the driver and devtools, once per session. Resolves `true` when the test is worth running again.
|
|
38
38
|
*/
|
|
39
39
|
recoverHid: (() => Promise<boolean>) | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Present for iOS simulator runs: after a test failed, asks the open driver whether `warden-simd` restarted the
|
|
42
|
+
* sim's wedged accessibility service (backboardd, which quits the app) within the last `attemptMs` (waiting for a
|
|
43
|
+
* restart still in flight). Resolves `true` once per restart: the test is worth running again.
|
|
44
|
+
*/
|
|
45
|
+
recoverAxWedge: ((attemptMs: number) => Promise<boolean>) | undefined;
|
|
40
46
|
/** closes the open driver and devtools so the next call opens them afresh (the device was rebooted under them) */
|
|
41
47
|
resetDevice(): Promise<void>;
|
|
42
48
|
/** where the console reporter prints one line; default fd 1 */
|