doc-detective 4.23.0 → 4.25.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/dist/common/src/schemas/schemas.json +39128 -4588
- package/dist/common/src/types/generated/record_v3.d.ts +38 -5
- package/dist/common/src/types/generated/record_v3.d.ts.map +1 -1
- package/dist/common/src/types/generated/step_v3.d.ts +529 -44
- package/dist/common/src/types/generated/step_v3.d.ts.map +1 -1
- package/dist/common/src/types/generated/swipe_v3.d.ts +288 -0
- package/dist/common/src/types/generated/swipe_v3.d.ts.map +1 -0
- package/dist/common/src/types/generated/swipe_v3.js +7 -0
- package/dist/common/src/types/generated/swipe_v3.js.map +1 -0
- package/dist/common/src/types/generated/test_v3.d.ts +2159 -1125
- package/dist/common/src/types/generated/test_v3.d.ts.map +1 -1
- package/dist/core/tests/appGestures.d.ts +27 -0
- package/dist/core/tests/appGestures.d.ts.map +1 -0
- package/dist/core/tests/appGestures.js +325 -0
- package/dist/core/tests/appGestures.js.map +1 -0
- package/dist/core/tests/appSurface.d.ts +2 -1
- package/dist/core/tests/appSurface.d.ts.map +1 -1
- package/dist/core/tests/appSurface.js +101 -29
- package/dist/core/tests/appSurface.js.map +1 -1
- package/dist/core/tests/click.d.ts.map +1 -1
- package/dist/core/tests/click.js +12 -8
- package/dist/core/tests/click.js.map +1 -1
- package/dist/core/tests/ffmpegRecorder.d.ts +29 -2
- package/dist/core/tests/ffmpegRecorder.d.ts.map +1 -1
- package/dist/core/tests/ffmpegRecorder.js +154 -8
- package/dist/core/tests/ffmpegRecorder.js.map +1 -1
- package/dist/core/tests/findElement.d.ts.map +1 -1
- package/dist/core/tests/findElement.js +82 -10
- package/dist/core/tests/findElement.js.map +1 -1
- package/dist/core/tests/mobileBrowser.d.ts.map +1 -1
- package/dist/core/tests/mobileBrowser.js +4 -3
- package/dist/core/tests/mobileBrowser.js.map +1 -1
- package/dist/core/tests/movement.d.ts +43 -0
- package/dist/core/tests/movement.d.ts.map +1 -0
- package/dist/core/tests/movement.js +92 -0
- package/dist/core/tests/movement.js.map +1 -0
- package/dist/core/tests/startRecording.d.ts +9 -1
- package/dist/core/tests/startRecording.d.ts.map +1 -1
- package/dist/core/tests/startRecording.js +187 -19
- package/dist/core/tests/startRecording.js.map +1 -1
- package/dist/core/tests/stopRecording.d.ts +8 -1
- package/dist/core/tests/stopRecording.d.ts.map +1 -1
- package/dist/core/tests/stopRecording.js +108 -3
- package/dist/core/tests/stopRecording.js.map +1 -1
- package/dist/core/tests/swipe.d.ts +8 -0
- package/dist/core/tests/swipe.d.ts.map +1 -0
- package/dist/core/tests/swipe.js +158 -0
- package/dist/core/tests/swipe.js.map +1 -0
- package/dist/core/tests/typeKeys.d.ts +8 -1
- package/dist/core/tests/typeKeys.d.ts.map +1 -1
- package/dist/core/tests/typeKeys.js +123 -23
- package/dist/core/tests/typeKeys.js.map +1 -1
- package/dist/core/tests.d.ts.map +1 -1
- package/dist/core/tests.js +55 -22
- package/dist/core/tests.js.map +1 -1
- package/dist/core/utils.d.ts +2 -1
- package/dist/core/utils.d.ts.map +1 -1
- package/dist/core/utils.js +36 -3
- package/dist/core/utils.js.map +1 -1
- package/dist/hints/context.d.ts.map +1 -1
- package/dist/hints/context.js +4 -0
- package/dist/hints/context.js.map +1 -1
- package/dist/hints/hints.d.ts.map +1 -1
- package/dist/hints/hints.js +7 -2
- package/dist/hints/hints.js.map +1 -1
- package/dist/hints/types.d.ts +3 -4
- package/dist/hints/types.d.ts.map +1 -1
- package/dist/index.cjs +39556 -3991
- package/dist/reporters/htmlReporter.js +3 -2
- package/dist/reporters/htmlReporter.js.map +1 -1
- package/dist/runtime/androidInstaller.d.ts +27 -0
- package/dist/runtime/androidInstaller.d.ts.map +1 -1
- package/dist/runtime/androidInstaller.js +138 -2
- package/dist/runtime/androidInstaller.js.map +1 -1
- package/dist/runtime/browserStepKeys.d.ts +17 -1
- package/dist/runtime/browserStepKeys.d.ts.map +1 -1
- package/dist/runtime/browserStepKeys.js +25 -0
- package/dist/runtime/browserStepKeys.js.map +1 -1
- package/dist/runtime/heavyDeps.d.ts +25 -0
- package/dist/runtime/heavyDeps.d.ts.map +1 -1
- package/dist/runtime/heavyDeps.js +34 -0
- package/dist/runtime/heavyDeps.js.map +1 -1
- package/dist/runtime/inferRuntimeNeeds.js +8 -2
- package/dist/runtime/inferRuntimeNeeds.js.map +1 -1
- package/dist/runtime/installer.d.ts +9 -0
- package/dist/runtime/installer.d.ts.map +1 -1
- package/dist/runtime/installer.js +17 -1
- package/dist/runtime/installer.js.map +1 -1
- package/dist/runtime/loader.d.ts.map +1 -1
- package/dist/runtime/loader.js +16 -8
- package/dist/runtime/loader.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { MovementPoint, SwipeDirection } from "./movement.js";
|
|
2
|
+
export type { AppGestureAdapter, SwipeGesture };
|
|
3
|
+
interface SwipeGesture {
|
|
4
|
+
direction?: SwipeDirection;
|
|
5
|
+
distance?: number;
|
|
6
|
+
from?: MovementPoint;
|
|
7
|
+
to?: MovementPoint;
|
|
8
|
+
duration: number;
|
|
9
|
+
}
|
|
10
|
+
interface AppGestureAdapter {
|
|
11
|
+
swipe(driver: any, gesture: SwipeGesture): Promise<void>;
|
|
12
|
+
longPress(driver: any, element: any, durationMs: number): Promise<void>;
|
|
13
|
+
clickButton(driver: any, element: any, button: string): Promise<{
|
|
14
|
+
error?: string;
|
|
15
|
+
}>;
|
|
16
|
+
pressKey?(driver: any, token: string): Promise<{
|
|
17
|
+
error?: string;
|
|
18
|
+
}>;
|
|
19
|
+
typeFocused?(driver: any, text: string): Promise<void>;
|
|
20
|
+
scrollStep?(driver: any): Promise<boolean>;
|
|
21
|
+
}
|
|
22
|
+
export declare const ANDROID_KEYCODES: Record<string, number>;
|
|
23
|
+
export declare const IOS_BUTTONS: Record<string, string>;
|
|
24
|
+
export declare const IOS_TEXT_KEYS: Record<string, string>;
|
|
25
|
+
export declare const DEVICE_KEYS: Set<string>;
|
|
26
|
+
export declare const APP_GESTURES: Record<string, AppGestureAdapter>;
|
|
27
|
+
//# sourceMappingURL=appGestures.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"appGestures.d.ts","sourceRoot":"","sources":["../../../src/core/tests/appGestures.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAKnE,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,CAAC;AAKhD,UAAU,YAAY;IACpB,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,EAAE,CAAC,EAAE,aAAa,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,iBAAiB;IAGzB,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzD,SAAS,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAKxE,WAAW,CACT,MAAM,EAAE,GAAG,EACX,OAAO,EAAE,GAAG,EACZ,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAI/B,QAAQ,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAInE,WAAW,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAKvD,UAAU,CAAC,CAAC,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5C;AAKD,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAqBnD,CAAC;AAGF,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAI9C,CAAC;AAGF,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAMhD,CAAC;AAIF,eAAO,MAAM,WAAW,EAAE,GAAG,CAAC,MAAM,CAMlC,CAAC;AA6EH,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAuO1D,CAAC"}
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
// Per-platform gesture adapters for app surfaces (phase A6): swipe,
|
|
2
|
+
// long-press, device keys, focused typing, and the find auto-scroll step.
|
|
3
|
+
// Keyed identically to APP_DRIVER_PLATFORMS in appSurface.ts — adding a
|
|
4
|
+
// platform means adding a row in both tables. Rows use each driver's native
|
|
5
|
+
// execute extensions where they exist and the shared W3C movement engine
|
|
6
|
+
// (movement.ts) where they don't; everything is mockable with a fake
|
|
7
|
+
// { execute, getWindowRect, action } driver.
|
|
8
|
+
import { directionToPoints, fractionsToPixels, surfaceToAbsolutePixels, performMovement, DEFAULT_SWIPE_DISTANCE, DEFAULT_SWIPE_DURATION, MOVEMENT_INSET, } from "./movement.js";
|
|
9
|
+
// Android KeyEvent codes (https://developer.android.com/reference/android/view/KeyEvent).
|
|
10
|
+
// $HOME$ on an app surface is the DEVICE home button, not cursor-to-line-start
|
|
11
|
+
// — the design-doc overload, called out in the type reference docs.
|
|
12
|
+
export const ANDROID_KEYCODES = {
|
|
13
|
+
// Device keys (the new A6 vocabulary)
|
|
14
|
+
$BACK$: 4,
|
|
15
|
+
$HOME$: 3,
|
|
16
|
+
$APP_SWITCH$: 187,
|
|
17
|
+
$VOLUME_UP$: 24,
|
|
18
|
+
$VOLUME_DOWN$: 25,
|
|
19
|
+
// Common editing keys, mapped onto keycodes for app surfaces
|
|
20
|
+
$ENTER$: 66,
|
|
21
|
+
$RETURN$: 66,
|
|
22
|
+
$TAB$: 61,
|
|
23
|
+
$SPACE$: 62,
|
|
24
|
+
$BACKSPACE$: 67,
|
|
25
|
+
$DELETE$: 112,
|
|
26
|
+
$ESCAPE$: 111,
|
|
27
|
+
$ARROW_UP$: 19,
|
|
28
|
+
$ARROW_DOWN$: 20,
|
|
29
|
+
$ARROW_LEFT$: 21,
|
|
30
|
+
$ARROW_RIGHT$: 22,
|
|
31
|
+
$PAGE_UP$: 92,
|
|
32
|
+
$PAGE_DOWN$: 93,
|
|
33
|
+
};
|
|
34
|
+
// Physical buttons XCUITest can press (mobile: pressButton).
|
|
35
|
+
export const IOS_BUTTONS = {
|
|
36
|
+
$HOME$: "home",
|
|
37
|
+
$VOLUME_UP$: "volumeup",
|
|
38
|
+
$VOLUME_DOWN$: "volumedown",
|
|
39
|
+
};
|
|
40
|
+
// Tokens that fold into typed text on iOS (sent through setValue/addValue).
|
|
41
|
+
export const IOS_TEXT_KEYS = {
|
|
42
|
+
$ENTER$: "\n",
|
|
43
|
+
$RETURN$: "\n",
|
|
44
|
+
$TAB$: "\t",
|
|
45
|
+
$BACKSPACE$: "\b",
|
|
46
|
+
$DELETE$: "\b",
|
|
47
|
+
};
|
|
48
|
+
// Device-only keys: pressing these needs no element criteria (there's no
|
|
49
|
+
// text field involved in pressing Back or Volume Up).
|
|
50
|
+
export const DEVICE_KEYS = new Set([
|
|
51
|
+
"$BACK$",
|
|
52
|
+
"$HOME$",
|
|
53
|
+
"$APP_SWITCH$",
|
|
54
|
+
"$VOLUME_UP$",
|
|
55
|
+
"$VOLUME_DOWN$",
|
|
56
|
+
]);
|
|
57
|
+
// The window area directional swipes act within, inset per MOVEMENT_INSET.
|
|
58
|
+
async function insetWindowArea(driver) {
|
|
59
|
+
const rect = await driver.getWindowRect();
|
|
60
|
+
return {
|
|
61
|
+
left: Math.round(rect.x + rect.width * MOVEMENT_INSET),
|
|
62
|
+
top: Math.round(rect.y + rect.height * MOVEMENT_INSET),
|
|
63
|
+
width: Math.round(rect.width * (1 - 2 * MOVEMENT_INSET)),
|
|
64
|
+
height: Math.round(rect.height * (1 - 2 * MOVEMENT_INSET)),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
// XCUITest's dragFromToForDuration takes absolute screen coordinates and a
|
|
68
|
+
// float-second duration in [0.5, 60]. `from`/`to` arrive as absolute pixels.
|
|
69
|
+
async function iosDrag(driver, from, to, durationMs) {
|
|
70
|
+
await driver.execute("mobile: dragFromToForDuration", {
|
|
71
|
+
duration: Math.min(60, Math.max(0.5, durationMs / 1000)),
|
|
72
|
+
fromX: Math.round(from.x),
|
|
73
|
+
fromY: Math.round(from.y),
|
|
74
|
+
toX: Math.round(to.x),
|
|
75
|
+
toY: Math.round(to.y),
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
// Desktop wheel-scroll sign conventions are only loosely documented; each is
|
|
79
|
+
// isolated here so a fixture-observed inversion is a one-line fix.
|
|
80
|
+
// NovaWindows deltas are wheel clicks ("positive deltaY = forward rotation");
|
|
81
|
+
// a swipe up (revealing content below) is a backward rotation, and a wheel
|
|
82
|
+
// click moves roughly 120px of content, so clicks ≈ distance × axis / 120.
|
|
83
|
+
function windowsWheelDeltas(direction, distance, rect) {
|
|
84
|
+
const clicks = (axis) => Math.max(1, Math.round((distance * axis) / 120));
|
|
85
|
+
switch (direction) {
|
|
86
|
+
case "up":
|
|
87
|
+
return { deltaY: -clicks(rect.height) };
|
|
88
|
+
case "down":
|
|
89
|
+
return { deltaY: clicks(rect.height) };
|
|
90
|
+
case "left":
|
|
91
|
+
return { deltaX: clicks(rect.width) };
|
|
92
|
+
case "right":
|
|
93
|
+
return { deltaX: -clicks(rect.width) };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Mac2 deltas are float pixels; XCTest's scroll convention has positive
|
|
97
|
+
// deltaY scroll toward content above, so a swipe up is negative deltaY.
|
|
98
|
+
function macScrollDeltas(direction, distance, rect) {
|
|
99
|
+
switch (direction) {
|
|
100
|
+
case "up":
|
|
101
|
+
return { deltaX: 0, deltaY: -Math.round(distance * rect.height) };
|
|
102
|
+
case "down":
|
|
103
|
+
return { deltaX: 0, deltaY: Math.round(distance * rect.height) };
|
|
104
|
+
case "left":
|
|
105
|
+
return { deltaX: -Math.round(distance * rect.width), deltaY: 0 };
|
|
106
|
+
case "right":
|
|
107
|
+
return { deltaX: Math.round(distance * rect.width), deltaY: 0 };
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
export const APP_GESTURES = {
|
|
111
|
+
android: {
|
|
112
|
+
async swipe(driver, gesture) {
|
|
113
|
+
if (gesture.from && gesture.to) {
|
|
114
|
+
const rect = await driver.getWindowRect();
|
|
115
|
+
await performMovement({
|
|
116
|
+
driver,
|
|
117
|
+
from: surfaceToAbsolutePixels(rect, gesture.from),
|
|
118
|
+
to: surfaceToAbsolutePixels(rect, gesture.to),
|
|
119
|
+
duration: gesture.duration,
|
|
120
|
+
pointerType: "touch",
|
|
121
|
+
});
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const area = await insetWindowArea(driver);
|
|
125
|
+
await driver.execute("mobile: swipeGesture", {
|
|
126
|
+
...area,
|
|
127
|
+
direction: gesture.direction,
|
|
128
|
+
percent: gesture.distance ?? DEFAULT_SWIPE_DISTANCE,
|
|
129
|
+
});
|
|
130
|
+
},
|
|
131
|
+
async longPress(driver, element, durationMs) {
|
|
132
|
+
await driver.execute("mobile: longClickGesture", {
|
|
133
|
+
elementId: element.elementId,
|
|
134
|
+
duration: durationMs,
|
|
135
|
+
});
|
|
136
|
+
},
|
|
137
|
+
async clickButton(_driver, _element, button) {
|
|
138
|
+
return {
|
|
139
|
+
error: `${button}-click isn't available on Android app surfaces — touch input has no ${button} button. Use a left tap, or \`duration\` for a long-press.`,
|
|
140
|
+
};
|
|
141
|
+
},
|
|
142
|
+
async pressKey(driver, token) {
|
|
143
|
+
const keycode = ANDROID_KEYCODES[token];
|
|
144
|
+
if (keycode === undefined) {
|
|
145
|
+
return {
|
|
146
|
+
error: `${token} has no Android key mapping on app surfaces. Supported keys: ${Object.keys(ANDROID_KEYCODES).join(", ")}.`,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
await driver.execute("mobile: pressKey", { keycode });
|
|
150
|
+
return {};
|
|
151
|
+
},
|
|
152
|
+
async typeFocused(driver, text) {
|
|
153
|
+
await driver.execute("mobile: type", { text });
|
|
154
|
+
},
|
|
155
|
+
async scrollStep(driver) {
|
|
156
|
+
const area = await insetWindowArea(driver);
|
|
157
|
+
// scrollGesture's direction is the CONTENT direction: scrolling "down"
|
|
158
|
+
// views content further down (the finger moves up). Returns true while
|
|
159
|
+
// the container can still scroll that way.
|
|
160
|
+
const canScrollMore = await driver.execute("mobile: scrollGesture", {
|
|
161
|
+
...area,
|
|
162
|
+
direction: "down",
|
|
163
|
+
percent: 0.7,
|
|
164
|
+
});
|
|
165
|
+
return canScrollMore !== false;
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
ios: {
|
|
169
|
+
async swipe(driver, gesture) {
|
|
170
|
+
const rect = await driver.getWindowRect();
|
|
171
|
+
let from;
|
|
172
|
+
let to;
|
|
173
|
+
if (gesture.from && gesture.to) {
|
|
174
|
+
from = surfaceToAbsolutePixels(rect, gesture.from);
|
|
175
|
+
to = surfaceToAbsolutePixels(rect, gesture.to);
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
const points = directionToPoints(gesture.direction, gesture.distance ?? DEFAULT_SWIPE_DISTANCE);
|
|
179
|
+
from = fractionsToPixels(rect, points.from);
|
|
180
|
+
to = fractionsToPixels(rect, points.to);
|
|
181
|
+
}
|
|
182
|
+
await iosDrag(driver, from, to, gesture.duration);
|
|
183
|
+
},
|
|
184
|
+
async longPress(driver, element, durationMs) {
|
|
185
|
+
await driver.execute("mobile: touchAndHold", {
|
|
186
|
+
elementId: element.elementId,
|
|
187
|
+
duration: durationMs / 1000,
|
|
188
|
+
});
|
|
189
|
+
},
|
|
190
|
+
async clickButton(_driver, _element, button) {
|
|
191
|
+
return {
|
|
192
|
+
error: `${button}-click isn't available on iOS app surfaces — touch input has no ${button} button. Use a left tap, or \`duration\` for a long-press.`,
|
|
193
|
+
};
|
|
194
|
+
},
|
|
195
|
+
async pressKey(driver, token) {
|
|
196
|
+
const button = IOS_BUTTONS[token];
|
|
197
|
+
if (button) {
|
|
198
|
+
await driver.execute("mobile: pressButton", { name: button });
|
|
199
|
+
return {};
|
|
200
|
+
}
|
|
201
|
+
if (token === "$BACK$") {
|
|
202
|
+
return {
|
|
203
|
+
error: `$BACK$ isn't supported on iOS: iOS devices have no system back button. Click the app's own back control instead (e.g. { "click": { "elementText": "Back", "surface": { "app": "…" } } }).`,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
if (token === "$APP_SWITCH$") {
|
|
207
|
+
return {
|
|
208
|
+
error: `$APP_SWITCH$ isn't supported on iOS app surfaces: XCUITest exposes no app-switcher button. Switch apps by targeting another app surface by name instead.`,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
return {
|
|
212
|
+
error: `${token} has no iOS key mapping on app surfaces. Physical buttons: ${Object.keys(IOS_BUTTONS).join(", ")}; text keys (${Object.keys(IOS_TEXT_KEYS).join(", ")}) type into an element.`,
|
|
213
|
+
};
|
|
214
|
+
},
|
|
215
|
+
// No typeFocused: XCUITest's `mobile: keys` is iPad-only (Xcode 15+), so
|
|
216
|
+
// iOS text typing keeps requiring element criteria.
|
|
217
|
+
async scrollStep(driver) {
|
|
218
|
+
const rect = await driver.getWindowRect();
|
|
219
|
+
const { from, to } = directionToPoints("up", 0.7);
|
|
220
|
+
await iosDrag(driver, fractionsToPixels(rect, from), fractionsToPixels(rect, to), DEFAULT_SWIPE_DURATION);
|
|
221
|
+
// XCUITest has no can-scroll-more feedback; the caller's attempt bound
|
|
222
|
+
// is the only stop.
|
|
223
|
+
return true;
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
windows: {
|
|
227
|
+
async swipe(driver, gesture) {
|
|
228
|
+
const rect = await driver.getWindowRect();
|
|
229
|
+
if (gesture.from && gesture.to) {
|
|
230
|
+
const fromPx = surfaceToAbsolutePixels(rect, gesture.from);
|
|
231
|
+
const toPx = surfaceToAbsolutePixels(rect, gesture.to);
|
|
232
|
+
await driver.execute("windows: clickAndDrag", {
|
|
233
|
+
startX: fromPx.x,
|
|
234
|
+
startY: fromPx.y,
|
|
235
|
+
endX: toPx.x,
|
|
236
|
+
endY: toPx.y,
|
|
237
|
+
durationMs: gesture.duration,
|
|
238
|
+
});
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
const center = fractionsToPixels(rect, { x: 0.5, y: 0.5 });
|
|
242
|
+
const deltas = windowsWheelDeltas(gesture.direction, gesture.distance ?? DEFAULT_SWIPE_DISTANCE, rect);
|
|
243
|
+
await driver.execute("windows: scroll", {
|
|
244
|
+
x: center.x,
|
|
245
|
+
y: center.y,
|
|
246
|
+
...deltas,
|
|
247
|
+
});
|
|
248
|
+
},
|
|
249
|
+
async longPress(driver, element, durationMs) {
|
|
250
|
+
// durationMs is NovaWindows' press-to-release hold time.
|
|
251
|
+
await driver.execute("windows: click", {
|
|
252
|
+
elementId: element.elementId,
|
|
253
|
+
durationMs,
|
|
254
|
+
});
|
|
255
|
+
},
|
|
256
|
+
async clickButton(driver, element, button) {
|
|
257
|
+
// `windows: click` accepts left/middle/right/back/forward, but the
|
|
258
|
+
// click.button schema only exposes left/right/middle — so only right and
|
|
259
|
+
// middle ever reach here. Pass the button straight through.
|
|
260
|
+
await driver.execute("windows: click", {
|
|
261
|
+
elementId: element.elementId,
|
|
262
|
+
button,
|
|
263
|
+
});
|
|
264
|
+
return {};
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
mac: {
|
|
268
|
+
async swipe(driver, gesture) {
|
|
269
|
+
const rect = await driver.getWindowRect();
|
|
270
|
+
if (gesture.from && gesture.to) {
|
|
271
|
+
const fromPx = surfaceToAbsolutePixels(rect, gesture.from);
|
|
272
|
+
const toPx = surfaceToAbsolutePixels(rect, gesture.to);
|
|
273
|
+
await driver.execute("macos: clickAndDrag", {
|
|
274
|
+
startX: fromPx.x,
|
|
275
|
+
startY: fromPx.y,
|
|
276
|
+
endX: toPx.x,
|
|
277
|
+
endY: toPx.y,
|
|
278
|
+
duration: gesture.duration / 1000,
|
|
279
|
+
});
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
const center = fractionsToPixels(rect, { x: 0.5, y: 0.5 });
|
|
283
|
+
const deltas = macScrollDeltas(gesture.direction, gesture.distance ?? DEFAULT_SWIPE_DISTANCE, rect);
|
|
284
|
+
await driver.execute("macos: scroll", {
|
|
285
|
+
x: center.x,
|
|
286
|
+
y: center.y,
|
|
287
|
+
...deltas,
|
|
288
|
+
});
|
|
289
|
+
},
|
|
290
|
+
async longPress(driver, element, durationMs) {
|
|
291
|
+
// Mac2 supports mouse-only W3C actions; prefer the standard chain and
|
|
292
|
+
// fall back to the native extension if the actions endpoint misbehaves.
|
|
293
|
+
try {
|
|
294
|
+
await driver
|
|
295
|
+
.action("pointer", { parameters: { pointerType: "mouse" } })
|
|
296
|
+
.move({ origin: element })
|
|
297
|
+
.down()
|
|
298
|
+
.pause(durationMs)
|
|
299
|
+
.up()
|
|
300
|
+
.perform();
|
|
301
|
+
}
|
|
302
|
+
catch {
|
|
303
|
+
await driver.execute("macos: clickAndDragAndHold", {
|
|
304
|
+
sourceElementId: element.elementId,
|
|
305
|
+
destinationElementId: element.elementId,
|
|
306
|
+
duration: 0.1,
|
|
307
|
+
holdDuration: durationMs / 1000,
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
async clickButton(driver, element, button) {
|
|
312
|
+
// Mac2 has a dedicated right-click but no middle-click command.
|
|
313
|
+
if (button === "right") {
|
|
314
|
+
await driver.execute("macos: rightClick", {
|
|
315
|
+
elementId: element.elementId,
|
|
316
|
+
});
|
|
317
|
+
return {};
|
|
318
|
+
}
|
|
319
|
+
return {
|
|
320
|
+
error: `${button}-click isn't supported on macOS app surfaces — the Mac2 driver has no ${button}-click. Use a left click or a right-click.`,
|
|
321
|
+
};
|
|
322
|
+
},
|
|
323
|
+
},
|
|
324
|
+
};
|
|
325
|
+
//# sourceMappingURL=appGestures.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"appGestures.js","sourceRoot":"","sources":["../../../src/core/tests/appGestures.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { resolveHeavyDepPath, resolveHeavyDepPathInCache, resolveHeavyDepSource, ensureRuntimeInstalled } from "../../runtime/loader.js";
|
|
2
|
+
import { stepTargetsAppSurface } from "../../runtime/browserStepKeys.js";
|
|
2
3
|
export { classifyAppIdentifier, defaultAppSurfaceName, classifyNativeSelector, buildUiaLocator, buildAxLocator, buildUiAutomator2Locator, buildXCUITestLocator, createAppSessionState, appSurfacePreflight, probeMacAccessibility, isAppDriverRequired, stepTargetsAppSurface, resolveAppSurfaceRef, ensureAppForeground, startAppSurface, findAppElement, buildAppLocator, closeAppSurface, teardownAppSession, snapshotAppServerDescendants, reapConsoleOrphans, listWindowsDescendantPids, invalidateStaleAppiumManifest, probeIosToolchain, };
|
|
3
4
|
export type { AppSessionState, AppSurfaceEntry };
|
|
4
5
|
type AppIdentifierKind = "path" | "aumid" | "id";
|
|
@@ -96,7 +97,6 @@ declare function createAppSessionState(): AppSessionState;
|
|
|
96
97
|
declare function isAppDriverRequired({ test }: {
|
|
97
98
|
test: any;
|
|
98
99
|
}): boolean;
|
|
99
|
-
declare function stepTargetsAppSurface(step: any): boolean;
|
|
100
100
|
declare function resolveAppSurfaceRef(surface: any, appSession?: AppSessionState): {
|
|
101
101
|
entry?: AppSurfaceEntry;
|
|
102
102
|
window?: any;
|
|
@@ -150,6 +150,7 @@ declare function buildAppLocator(criteria: {
|
|
|
150
150
|
} | {
|
|
151
151
|
error: string;
|
|
152
152
|
};
|
|
153
|
+
export declare const MAX_FIND_SCROLLS = 5;
|
|
153
154
|
declare function findAppElement({ driver, criteria, timeout, platform, }: {
|
|
154
155
|
driver: any;
|
|
155
156
|
criteria: any;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"appSurface.d.ts","sourceRoot":"","sources":["../../../src/core/tests/appSurface.ts"],"names":[],"mappings":"AAaA,OAAO,EACL,mBAAmB,EACnB,0BAA0B,EAC1B,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"appSurface.d.ts","sourceRoot":"","sources":["../../../src/core/tests/appSurface.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,9 +14,11 @@ import { resolveHeavyDepPath, resolveHeavyDepPathInCache, resolveHeavyDepSource,
|
|
|
14
14
|
import { appiumHomeForDriverPath } from "../appium.js";
|
|
15
15
|
import { getRuntimeDir } from "../../runtime/cacheDir.js";
|
|
16
16
|
import { log } from "../utils.js";
|
|
17
|
-
import {
|
|
17
|
+
import { resolveAppWindowRect } from "./ffmpegRecorder.js";
|
|
18
18
|
import { normalizeDeviceDescriptor } from "./androidEmulator.js";
|
|
19
|
+
import { APP_GESTURES } from "./appGestures.js";
|
|
19
20
|
import { isMobileTargetPlatform } from "./mobilePlatform.js";
|
|
21
|
+
import { stepTargetsAppSurface } from "../../runtime/browserStepKeys.js";
|
|
20
22
|
import { validate } from "../../common/src/validate.js";
|
|
21
23
|
export { classifyAppIdentifier, defaultAppSurfaceName, classifyNativeSelector, buildUiaLocator, buildAxLocator, buildUiAutomator2Locator, buildXCUITestLocator, createAppSessionState, appSurfacePreflight,
|
|
22
24
|
// Exported as a test seam: the JXA probe must return a definitive boolean
|
|
@@ -517,18 +519,10 @@ function isAppDriverRequired({ test }) {
|
|
|
517
519
|
return false;
|
|
518
520
|
return test.steps.some((step) => typeof step?.startSurface !== "undefined" || stepTargetsAppSurface(step));
|
|
519
521
|
}
|
|
520
|
-
//
|
|
521
|
-
//
|
|
522
|
-
//
|
|
523
|
-
|
|
524
|
-
if (!step || typeof step !== "object")
|
|
525
|
-
return false;
|
|
526
|
-
return Object.values(step).some((payload) => payload &&
|
|
527
|
-
typeof payload === "object" &&
|
|
528
|
-
payload.surface &&
|
|
529
|
-
typeof payload.surface === "object" &&
|
|
530
|
-
typeof payload.surface.app === "string");
|
|
531
|
-
}
|
|
522
|
+
// `stepTargetsAppSurface` (imported from ../../runtime/browserStepKeys.js and
|
|
523
|
+
// re-exported above) decides whether an action payload names an app surface
|
|
524
|
+
// with the object form — shared with the runtime's browser-need inference so
|
|
525
|
+
// the two never drift.
|
|
532
526
|
// Resolve a step's `surface` reference to a registered app surface, or null
|
|
533
527
|
// when the reference isn't an app reference (browser/process/engine) or names
|
|
534
528
|
// nothing in the registry. Object form is authoritative; a bare string only
|
|
@@ -818,6 +812,10 @@ function buildAppLocator(criteria, platform) {
|
|
|
818
812
|
}
|
|
819
813
|
// Locate an element on an app surface's driver session. Waits up to `timeout`
|
|
820
814
|
// for existence. Returns the wdio element or an error string.
|
|
815
|
+
// Upper bound on find auto-scroll attempts per element (phase A6). Exported
|
|
816
|
+
// (inline — the top-of-file export list predates this const) as a test seam
|
|
817
|
+
// and so fixtures can reason about worst-case scroll depth.
|
|
818
|
+
export const MAX_FIND_SCROLLS = 5;
|
|
821
819
|
async function findAppElement({ driver, criteria, timeout = 5000, platform, }) {
|
|
822
820
|
const locator = buildAppLocator(criteria, platform);
|
|
823
821
|
if ("error" in locator)
|
|
@@ -838,15 +836,50 @@ async function findAppElement({ driver, criteria, timeout = 5000, platform, }) {
|
|
|
838
836
|
error: `App driver error while locating an element (locator: ${selector}): ${error?.message ?? error}`,
|
|
839
837
|
};
|
|
840
838
|
}
|
|
839
|
+
// Auto-scroll (phase A6): on mobile app surfaces a miss scrolls toward
|
|
840
|
+
// content below and re-checks, matching web find's scroll-into-view
|
|
841
|
+
// behavior — so click and element-targeted type gain it too (they delegate
|
|
842
|
+
// here). Desktop surfaces don't scroll: UIA/AX expose off-screen elements
|
|
843
|
+
// in the accessibility tree, and blind wheel-scrolling risks disturbing
|
|
844
|
+
// state. The initial wait shortens only when scrolling is available.
|
|
845
|
+
const start = Date.now();
|
|
846
|
+
const gestures = APP_GESTURES[platform ?? "windows"];
|
|
847
|
+
const canAutoScroll = typeof gestures?.scrollStep === "function";
|
|
848
|
+
const initialTimeout = canAutoScroll ? Math.min(timeout, 1500) : timeout;
|
|
849
|
+
let scrolls = 0;
|
|
841
850
|
try {
|
|
842
|
-
await element.waitForExist({ timeout });
|
|
851
|
+
await element.waitForExist({ timeout: initialTimeout });
|
|
843
852
|
return { element };
|
|
844
853
|
}
|
|
845
854
|
catch {
|
|
846
|
-
|
|
847
|
-
error: `No element matched ${JSON.stringify(criteria)} on the app surface within ${timeout}ms (locator: ${selector}).`,
|
|
848
|
-
};
|
|
855
|
+
// fall through to the scroll loop / final error below
|
|
849
856
|
}
|
|
857
|
+
if (canAutoScroll) {
|
|
858
|
+
while (scrolls < MAX_FIND_SCROLLS && Date.now() - start < timeout) {
|
|
859
|
+
let canScrollMore;
|
|
860
|
+
try {
|
|
861
|
+
canScrollMore = await gestures.scrollStep(driver);
|
|
862
|
+
}
|
|
863
|
+
catch (error) {
|
|
864
|
+
return {
|
|
865
|
+
error: `App driver error while scrolling to find an element (locator: ${selector}): ${error?.message ?? error}`,
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
scrolls += 1;
|
|
869
|
+
try {
|
|
870
|
+
if (await element.isExisting())
|
|
871
|
+
return { element };
|
|
872
|
+
}
|
|
873
|
+
catch {
|
|
874
|
+
break;
|
|
875
|
+
}
|
|
876
|
+
if (!canScrollMore)
|
|
877
|
+
break;
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
return {
|
|
881
|
+
error: `No element matched ${JSON.stringify(criteria)} on the app surface within ${timeout}ms (locator: ${selector}${scrolls ? `; scrolled ${scrolls} time(s) looking for it` : ""}).`,
|
|
882
|
+
};
|
|
850
883
|
}
|
|
851
884
|
// The startSurface step (app branch): launch the app through the native
|
|
852
885
|
// driver, wait for readiness, and register the surface. Starts the app
|
|
@@ -1051,19 +1084,58 @@ async function startAppSurface({ config, step, appSession, platform, serverDeps,
|
|
|
1051
1084
|
deviceName,
|
|
1052
1085
|
});
|
|
1053
1086
|
appSession.activeApp = name;
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1087
|
+
if (!isMobileTargetPlatform(platform)) {
|
|
1088
|
+
// Late-bind window crops (desktop): an autoRecord capture in an app-only
|
|
1089
|
+
// context starts before any app window exists, so it records the full
|
|
1090
|
+
// display with a pending marker. The first app surface to open supplies
|
|
1091
|
+
// its window rect as the crop — scoping the recording to the app under
|
|
1092
|
+
// test. The rect is stored UNSCALED with a pending-scale marker: native
|
|
1093
|
+
// drivers can't answer a devicePixelRatio probe, so stopRecording derives
|
|
1094
|
+
// the physical-pixel scale from the capture frame size instead (phase A7).
|
|
1095
|
+
const pendingHandles = (appSession.recordingHost?.state?.recordings ?? []).filter((handle) => handle?.pendingAppWindowCrop && !handle.crop && !handle.cropRect);
|
|
1096
|
+
for (const handle of pendingHandles) {
|
|
1097
|
+
try {
|
|
1098
|
+
const rect = await resolveAppWindowRect(driver);
|
|
1099
|
+
if (rect) {
|
|
1100
|
+
handle.cropRect = rect;
|
|
1101
|
+
handle.cropPendingScale = true;
|
|
1102
|
+
}
|
|
1103
|
+
else {
|
|
1104
|
+
log(config, "warning", "Couldn't resolve the app window geometry for the active recording (malformed window rect); it stays full-display.");
|
|
1105
|
+
}
|
|
1106
|
+
handle.pendingAppWindowCrop = false;
|
|
1107
|
+
}
|
|
1108
|
+
catch (error) {
|
|
1109
|
+
log(config, "warning", `Couldn't resolve the app window geometry for the active recording; it stays full-display. ${error?.message ?? error}`);
|
|
1110
|
+
}
|
|
1064
1111
|
}
|
|
1065
|
-
|
|
1066
|
-
|
|
1112
|
+
}
|
|
1113
|
+
else {
|
|
1114
|
+
// Late-start pending device recordings (mobile): an autoRecord (or early
|
|
1115
|
+
// record) step in a mobile app-only context ran before any device session
|
|
1116
|
+
// existed. Now that one does, start the device recording on it. A handle
|
|
1117
|
+
// that never gets a session is drained as SKIPPED by stopRecording.
|
|
1118
|
+
const pendingDeviceHandles = (appSession.recordingHost?.state?.recordings ?? []).filter((handle) => handle?.type === "appium-pending");
|
|
1119
|
+
for (const handle of pendingDeviceHandles) {
|
|
1120
|
+
const options = platform === "ios"
|
|
1121
|
+
? { videoType: "h264", timeLimit: 1800 }
|
|
1122
|
+
: { timeLimit: 1800 };
|
|
1123
|
+
try {
|
|
1124
|
+
await driver.startRecordingScreen(options);
|
|
1125
|
+
handle.type = "appium";
|
|
1126
|
+
handle.driver = driver;
|
|
1127
|
+
}
|
|
1128
|
+
catch (error) {
|
|
1129
|
+
// Stash the real error on the handle so stopRecording surfaces it as
|
|
1130
|
+
// a FAIL instead of the misleading "never started" skip. A missing
|
|
1131
|
+
// host ffmpeg (the XCUITest encoder dependency) is an environment
|
|
1132
|
+
// gap, so it degrades to a SKIP instead.
|
|
1133
|
+
const message = `Couldn't start the pending device recording: ${error?.message ?? error}`;
|
|
1134
|
+
handle.startError = message;
|
|
1135
|
+
if (/ffmpeg.*not found/i.test(message))
|
|
1136
|
+
handle.startSkip = true;
|
|
1137
|
+
log(config, "warning", message);
|
|
1138
|
+
}
|
|
1067
1139
|
}
|
|
1068
1140
|
}
|
|
1069
1141
|
log(config, "debug", `Opened app surface "${name}" (${appId}).`);
|