execbro 2.0.0 → 2.1.1
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/build/__tests__/unit/coordinateMiss.test.d.ts +2 -0
- package/build/__tests__/unit/coordinateMiss.test.d.ts.map +1 -0
- package/build/__tests__/unit/coordinateMiss.test.js +111 -0
- package/build/__tests__/unit/coordinateMiss.test.js.map +1 -0
- package/build/__tests__/unit/deviceResolverStaleRetry.test.d.ts +2 -0
- package/build/__tests__/unit/deviceResolverStaleRetry.test.d.ts.map +1 -0
- package/build/__tests__/unit/deviceResolverStaleRetry.test.js +69 -0
- package/build/__tests__/unit/deviceResolverStaleRetry.test.js.map +1 -0
- package/build/__tests__/unit/errorCategorization.test.d.ts +2 -0
- package/build/__tests__/unit/errorCategorization.test.d.ts.map +1 -0
- package/build/__tests__/unit/errorCategorization.test.js +106 -0
- package/build/__tests__/unit/errorCategorization.test.js.map +1 -0
- package/build/__tests__/unit/findElementTreeReuse.test.d.ts +2 -0
- package/build/__tests__/unit/findElementTreeReuse.test.d.ts.map +1 -0
- package/build/__tests__/unit/findElementTreeReuse.test.js +77 -0
- package/build/__tests__/unit/findElementTreeReuse.test.js.map +1 -0
- package/build/__tests__/unit/settleAndDiff.test.d.ts +2 -0
- package/build/__tests__/unit/settleAndDiff.test.d.ts.map +1 -0
- package/build/__tests__/unit/settleAndDiff.test.js +110 -0
- package/build/__tests__/unit/settleAndDiff.test.js.map +1 -0
- package/build/__tests__/unit/verifyAction.test.js +2 -1
- package/build/__tests__/unit/verifyAction.test.js.map +1 -1
- package/build/__tests__/unit/waitForMeasurements.test.d.ts +2 -0
- package/build/__tests__/unit/waitForMeasurements.test.d.ts.map +1 -0
- package/build/__tests__/unit/waitForMeasurements.test.js +69 -0
- package/build/__tests__/unit/waitForMeasurements.test.js.map +1 -0
- package/build/bin.d.ts +3 -0
- package/build/bin.d.ts.map +1 -0
- package/build/bin.js +23 -0
- package/build/bin.js.map +1 -0
- package/build/core/android.d.ts +3 -1
- package/build/core/android.d.ts.map +1 -1
- package/build/core/android.js +5 -5
- package/build/core/android.js.map +1 -1
- package/build/core/deviceDiscovery.d.ts +5 -1
- package/build/core/deviceDiscovery.d.ts.map +1 -1
- package/build/core/deviceDiscovery.js +13 -2
- package/build/core/deviceDiscovery.js.map +1 -1
- package/build/core/deviceResolver.d.ts.map +1 -1
- package/build/core/deviceResolver.js +17 -2
- package/build/core/deviceResolver.js.map +1 -1
- package/build/core/ios.d.ts +14 -3
- package/build/core/ios.d.ts.map +1 -1
- package/build/core/ios.js +39 -15
- package/build/core/ios.js.map +1 -1
- package/build/core/pressables.d.ts +33 -0
- package/build/core/pressables.d.ts.map +1 -1
- package/build/core/pressables.js +73 -4
- package/build/core/pressables.js.map +1 -1
- package/build/core/register.d.ts.map +1 -1
- package/build/core/register.js +10 -2
- package/build/core/register.js.map +1 -1
- package/build/core/telemetry.d.ts +16 -1
- package/build/core/telemetry.d.ts.map +1 -1
- package/build/core/telemetry.js +50 -1
- package/build/core/telemetry.js.map +1 -1
- package/build/pro/coordinateMiss.d.ts +55 -0
- package/build/pro/coordinateMiss.d.ts.map +1 -0
- package/build/pro/coordinateMiss.js +122 -0
- package/build/pro/coordinateMiss.js.map +1 -0
- package/build/pro/tap.d.ts +8 -0
- package/build/pro/tap.d.ts.map +1 -1
- package/build/pro/tap.js +99 -11
- package/build/pro/tap.js.map +1 -1
- package/build/pro/verifyAction.d.ts +43 -2
- package/build/pro/verifyAction.d.ts.map +1 -1
- package/build/pro/verifyAction.js +95 -36
- package/build/pro/verifyAction.js.map +1 -1
- package/build/tools/interactionTools.d.ts +6 -0
- package/build/tools/interactionTools.d.ts.map +1 -1
- package/build/tools/interactionTools.js +28 -11
- package/build/tools/interactionTools.js.map +1 -1
- package/build/tools/screenshotTools.d.ts.map +1 -1
- package/build/tools/screenshotTools.js +33 -12
- package/build/tools/screenshotTools.js.map +1 -1
- package/package.json +6 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordinateMiss.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/coordinateMiss.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { describe, it, expect } from "@jest/globals";
|
|
2
|
+
import { explainCoordinateMiss } from "../../pro/coordinateMiss.js";
|
|
3
|
+
const pressable = (over = {}) => ({
|
|
4
|
+
label: null,
|
|
5
|
+
component: null,
|
|
6
|
+
testID: null,
|
|
7
|
+
center: { x: 0, y: 0 },
|
|
8
|
+
bounds: { x: 0, y: 0, width: 0, height: 0 },
|
|
9
|
+
...over,
|
|
10
|
+
});
|
|
11
|
+
/**
|
|
12
|
+
* Modelled on the real repro: an "Insufficient Balance" bottom sheet with an OK
|
|
13
|
+
* button, over a screen whose own buttons are covered by the sheet.
|
|
14
|
+
*/
|
|
15
|
+
const sheetState = {
|
|
16
|
+
route: { name: "OneGiftAtATime", params: null, stack: [] },
|
|
17
|
+
overlays: [
|
|
18
|
+
{
|
|
19
|
+
type: "BottomSheet",
|
|
20
|
+
title: null,
|
|
21
|
+
pressables: [
|
|
22
|
+
pressable({
|
|
23
|
+
label: "OK",
|
|
24
|
+
component: "Button",
|
|
25
|
+
center: { x: 210, y: 834 },
|
|
26
|
+
bounds: { x: 20, y: 806, width: 380, height: 56 },
|
|
27
|
+
}),
|
|
28
|
+
],
|
|
29
|
+
texts: [
|
|
30
|
+
{
|
|
31
|
+
text: "It looks like there aren't enough funds to add this gift.",
|
|
32
|
+
center: { x: 210, y: 734 },
|
|
33
|
+
bounds: { x: 41, y: 700, width: 338, height: 70 },
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
pressables: [
|
|
39
|
+
// Sits directly under the sheet's OK button (same band) — a tap there
|
|
40
|
+
// reaches OK, not this.
|
|
41
|
+
pressable({
|
|
42
|
+
label: "Proceed to Checkout",
|
|
43
|
+
component: "Button",
|
|
44
|
+
center: { x: 210, y: 838 },
|
|
45
|
+
bounds: { x: 20, y: 810, width: 380, height: 56 },
|
|
46
|
+
blockedByOverlay: true,
|
|
47
|
+
}),
|
|
48
|
+
// Higher up the screen, covered by the sheet but overlapping nothing
|
|
49
|
+
// reachable — the pure "you targeted something behind an overlay" case.
|
|
50
|
+
pressable({
|
|
51
|
+
label: "Clear Cart and Add New Item",
|
|
52
|
+
component: "Button",
|
|
53
|
+
center: { x: 210, y: 774 },
|
|
54
|
+
bounds: { x: 20, y: 746, width: 380, height: 56 },
|
|
55
|
+
blockedByOverlay: true,
|
|
56
|
+
}),
|
|
57
|
+
],
|
|
58
|
+
texts: [],
|
|
59
|
+
images: [],
|
|
60
|
+
};
|
|
61
|
+
describe("explainCoordinateMiss", () => {
|
|
62
|
+
it("names the text it hit and points at the nearest reachable pressable", () => {
|
|
63
|
+
// The exact miss from the live session: 100pt above the OK button.
|
|
64
|
+
const d = explainCoordinateMiss({ x: 210, y: 734 }, sheetState);
|
|
65
|
+
expect(d).not.toBeNull();
|
|
66
|
+
expect(d.hit).toContain("It looks like there aren't enough funds");
|
|
67
|
+
expect(d.nearest?.label).toBe("OK");
|
|
68
|
+
expect(d.nearest?.center).toEqual({ x: 210, y: 834 });
|
|
69
|
+
expect(d.nearest?.direction).toBe("below");
|
|
70
|
+
expect(d.suggestion).toContain("(210, 834)");
|
|
71
|
+
});
|
|
72
|
+
it("says so when the point landed on something an overlay covers", () => {
|
|
73
|
+
// "Clear Cart and Add New Item" is visible in the screenshot but unreachable.
|
|
74
|
+
const d = explainCoordinateMiss({ x: 210, y: 774 }, sheetState);
|
|
75
|
+
expect(d.blockedByOverlay).toBe(true);
|
|
76
|
+
expect(d.hit).toContain("Clear Cart and Add New Item");
|
|
77
|
+
expect(d.hit).toContain("BottomSheet");
|
|
78
|
+
expect(d.suggestion).toMatch(/Dismiss the BottomSheet/);
|
|
79
|
+
// It must still offer the reachable alternative.
|
|
80
|
+
expect(d.suggestion).toContain("(210, 834)");
|
|
81
|
+
});
|
|
82
|
+
it("prefers the reachable overlay button when it overlaps a covered element", () => {
|
|
83
|
+
// (210,834) is inside BOTH the sheet's OK button and the covered
|
|
84
|
+
// "Proceed to Checkout" beneath it. The touch reaches OK, so the
|
|
85
|
+
// diagnosis must describe OK — not the element behind it.
|
|
86
|
+
const d = explainCoordinateMiss({ x: 210, y: 834 }, sheetState);
|
|
87
|
+
expect(d.hit).toContain("OK");
|
|
88
|
+
expect(d.hit).not.toContain("Proceed to Checkout");
|
|
89
|
+
expect(d.blockedByOverlay).toBe(false);
|
|
90
|
+
expect(d.suggestion).toContain("coordinates were correct");
|
|
91
|
+
expect(d.suggestion).toMatch(/onPress handler/);
|
|
92
|
+
// No "nearest" steer — the aim was fine.
|
|
93
|
+
expect(d.nearest).toBeUndefined();
|
|
94
|
+
});
|
|
95
|
+
it("reports empty space when the point hit nothing at all", () => {
|
|
96
|
+
const d = explainCoordinateMiss({ x: 5, y: 20 }, sheetState);
|
|
97
|
+
expect(d.hit).toBe("no element (empty space)");
|
|
98
|
+
expect(d.nearest?.label).toBe("OK");
|
|
99
|
+
});
|
|
100
|
+
it("converts suggested coordinates into the caller's space", () => {
|
|
101
|
+
// Caller works in screenshot pixels at ~2.19 px per point.
|
|
102
|
+
const d = explainCoordinateMiss({ x: 210, y: 734 }, sheetState, (v) => Math.round(v * 2.19));
|
|
103
|
+
expect(d.nearest?.center).toEqual({ x: 460, y: 1826 });
|
|
104
|
+
expect(d.suggestion).toContain("(460, 1826)");
|
|
105
|
+
});
|
|
106
|
+
it("returns null when the screen state carries nothing to reason about", () => {
|
|
107
|
+
const empty = { route: null, overlays: [], pressables: [], texts: [], images: [] };
|
|
108
|
+
expect(explainCoordinateMiss({ x: 1, y: 1 }, empty)).toBeNull();
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
//# sourceMappingURL=coordinateMiss.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordinateMiss.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/coordinateMiss.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deviceResolverStaleRetry.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/deviceResolverStaleRetry.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { describe, it, expect, jest, beforeEach } from "@jest/globals";
|
|
2
|
+
/**
|
|
3
|
+
* The device inventory cache was raised from 5s to 30s so back-to-back taps stop
|
|
4
|
+
* re-shelling `simctl list` / `adb devices`. That is only safe because a failed
|
|
5
|
+
* resolution retries once against a freshly queried inventory — these tests pin
|
|
6
|
+
* that contract.
|
|
7
|
+
*/
|
|
8
|
+
const listAllDevices = jest.fn();
|
|
9
|
+
const resetDeviceDiscoveryCache = jest.fn();
|
|
10
|
+
jest.unstable_mockModule("../../core/deviceDiscovery.js", () => ({
|
|
11
|
+
listAllDevices,
|
|
12
|
+
resetDeviceDiscoveryCache,
|
|
13
|
+
}));
|
|
14
|
+
jest.unstable_mockModule("../../core/connection.js", () => ({
|
|
15
|
+
getConnectedApps: () => [],
|
|
16
|
+
}));
|
|
17
|
+
jest.unstable_mockModule("../../core/projectMemory.js", () => ({
|
|
18
|
+
listDevices: () => [],
|
|
19
|
+
recordDevice: () => undefined,
|
|
20
|
+
}));
|
|
21
|
+
const empty = {
|
|
22
|
+
ios: { available: true, simulators: [] },
|
|
23
|
+
android: { available: true, emulators: [], physical: [] },
|
|
24
|
+
summary: { booted: 0, total: 0 },
|
|
25
|
+
};
|
|
26
|
+
const withBootedSim = {
|
|
27
|
+
ios: {
|
|
28
|
+
available: true,
|
|
29
|
+
simulators: [
|
|
30
|
+
{ name: "iPhone Air", udid: "F93612A3-0042-4BDC-855F-8CAB1BDD76C6", state: "booted", runtime: "iOS 26.0" },
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
android: { available: true, emulators: [], physical: [] },
|
|
34
|
+
summary: { booted: 1, total: 1 },
|
|
35
|
+
};
|
|
36
|
+
const { resolveDeviceTarget } = await import("../../core/deviceResolver.js");
|
|
37
|
+
describe("resolveDeviceTarget stale-inventory retry", () => {
|
|
38
|
+
beforeEach(() => {
|
|
39
|
+
listAllDevices.mockReset();
|
|
40
|
+
resetDeviceDiscoveryCache.mockReset();
|
|
41
|
+
});
|
|
42
|
+
it("re-queries a fresh inventory when the device wasn't found", async () => {
|
|
43
|
+
// First pass: cached inventory is stale and has nothing. Second pass:
|
|
44
|
+
// the simulator that was booted moments ago shows up.
|
|
45
|
+
listAllDevices
|
|
46
|
+
.mockResolvedValueOnce(empty)
|
|
47
|
+
.mockResolvedValue(withBootedSim);
|
|
48
|
+
const result = await resolveDeviceTarget("F93612A3-0042-4BDC-855F-8CAB1BDD76C6");
|
|
49
|
+
expect(resetDeviceDiscoveryCache).toHaveBeenCalledTimes(1);
|
|
50
|
+
expect(result.ok).toBe(true);
|
|
51
|
+
if (result.ok)
|
|
52
|
+
expect(result.target.deviceName).toBe("iPhone Air");
|
|
53
|
+
});
|
|
54
|
+
it("does not pay for a refresh when resolution succeeds first time", async () => {
|
|
55
|
+
listAllDevices.mockResolvedValue(withBootedSim);
|
|
56
|
+
const result = await resolveDeviceTarget("F93612A3-0042-4BDC-855F-8CAB1BDD76C6");
|
|
57
|
+
expect(result.ok).toBe(true);
|
|
58
|
+
expect(resetDeviceDiscoveryCache).not.toHaveBeenCalled();
|
|
59
|
+
});
|
|
60
|
+
it("still reports the failure when a fresh inventory also has no match", async () => {
|
|
61
|
+
listAllDevices.mockResolvedValue(empty);
|
|
62
|
+
const result = await resolveDeviceTarget("F93612A3-0042-4BDC-855F-8CAB1BDD76C6");
|
|
63
|
+
expect(result.ok).toBe(false);
|
|
64
|
+
expect(resetDeviceDiscoveryCache).toHaveBeenCalledTimes(1);
|
|
65
|
+
if (!result.ok)
|
|
66
|
+
expect(result.error.code).toBe("DEVICE_NOT_FOUND");
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
//# sourceMappingURL=deviceResolverStaleRetry.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deviceResolverStaleRetry.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/deviceResolverStaleRetry.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errorCategorization.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/errorCategorization.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { describe, it, expect } from "@jest/globals";
|
|
2
|
+
import { categorizeError } from "../../core/telemetry.js";
|
|
3
|
+
/**
|
|
4
|
+
* Cases are the real top failure shapes from the 30d telemetry window ending
|
|
5
|
+
* 2026-08-01 (docs/telemetry/error-tracking-value-analysis.md). Counts in the
|
|
6
|
+
* comments are that window's event volume, so a regression here has a known
|
|
7
|
+
* production cost.
|
|
8
|
+
*
|
|
9
|
+
* The window exposed an inverted categorizer: `execution` held exactly 203
|
|
10
|
+
* events (121+62+20) and every one was a Hermes eval *guard*, while the only
|
|
11
|
+
* genuine runtime fault in the top 25 ("TypeError: undefined is not a
|
|
12
|
+
* function") fell through to `unknown`. `unknown` was 2,313 events — 37% of all
|
|
13
|
+
* failures and the single largest category, which made the category dimension
|
|
14
|
+
* unreadable.
|
|
15
|
+
*/
|
|
16
|
+
describe("categorizeError", () => {
|
|
17
|
+
describe("Hermes eval guards are validation, not execution", () => {
|
|
18
|
+
// These are documented product limitations the tool description already
|
|
19
|
+
// warns about. They mean the agent wrote an unsupported expression, not
|
|
20
|
+
// that anything faulted at runtime.
|
|
21
|
+
it.each([
|
|
22
|
+
["Error: Multi-statement expressions are not supported by Hermes Runtime.evaluate", 121],
|
|
23
|
+
["Error: require() is not available in Hermes Runtime.evaluate", 62],
|
|
24
|
+
["Error: top-level await is not supported in Hermes Runtime.evaluate", 20],
|
|
25
|
+
])("%s", (message) => {
|
|
26
|
+
expect(categorizeError(message)).toBe("validation");
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
describe("genuine JS runtime faults are execution", () => {
|
|
30
|
+
it.each([
|
|
31
|
+
"Error: TypeError: undefined is not a function",
|
|
32
|
+
"TypeError: Cannot read property 'map' of undefined",
|
|
33
|
+
"ReferenceError: foo is not defined",
|
|
34
|
+
"RangeError: Maximum call stack size exceeded",
|
|
35
|
+
"null is not an object (evaluating 'a.b')",
|
|
36
|
+
])("%s", (message) => {
|
|
37
|
+
expect(categorizeError(message)).toBe("execution");
|
|
38
|
+
});
|
|
39
|
+
it("beats the broad 'fetch' network match when a real fault mentions fetch", () => {
|
|
40
|
+
expect(categorizeError("TypeError: fetch is not a function")).toBe("execution");
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
describe("native command failures are execution", () => {
|
|
44
|
+
it.each([
|
|
45
|
+
"Error: Failed to launch app: Command failed: xcrun simctl launch UDID com.example.dev",
|
|
46
|
+
"Error: Failed to capture screenshot: Command failed: adb -s SERIAL shell screencap",
|
|
47
|
+
])("%s", (message) => {
|
|
48
|
+
expect(categorizeError(message)).toBe("execution");
|
|
49
|
+
});
|
|
50
|
+
it("still prefers driver_missing when the driver is absent entirely", () => {
|
|
51
|
+
expect(categorizeError("adb is not installed or not in PATH")).toBe("driver_missing");
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
describe("agent-input and UI-state guards are validation", () => {
|
|
55
|
+
it.each([
|
|
56
|
+
["Error: no focused TextInput. Tap an input first", 243],
|
|
57
|
+
["Must provide at least one of: text, testID, component, or x/y coordinates", 15],
|
|
58
|
+
["Element matches the query but is not visible on screen", 31],
|
|
59
|
+
["Inspect at (100,200): No component found at this point", 18],
|
|
60
|
+
["Error: No <Provider store> with a redux-shaped store found in the fiber tree.", 14],
|
|
61
|
+
])("%s", (message) => {
|
|
62
|
+
expect(categorizeError(message)).toBe("validation");
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
describe("device-name mismatch splits on whether anything is connected", () => {
|
|
66
|
+
it("is validation when devices exist but the name does not match", () => {
|
|
67
|
+
expect(categorizeError('No connected device matches "iPhone". Connected devices: Pixel_7')).toBe("validation");
|
|
68
|
+
});
|
|
69
|
+
it("is connection when nothing is connected at all", () => {
|
|
70
|
+
// Message continues into the scan_metro hint, which is a genuine
|
|
71
|
+
// connection problem rather than a bad argument.
|
|
72
|
+
expect(categorizeError('No connected device matches "iPhone". No devices are currently connected — run scan_metro to discover and connect to Metro servers.')).toBe("connection");
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
describe("app-state and environment problems are connection", () => {
|
|
76
|
+
it.each([
|
|
77
|
+
["Error: React DevTools hook not found.", 23],
|
|
78
|
+
["Error: React DevTools hook not registered (likely a production / non-__DEV__ build)", 14],
|
|
79
|
+
["Error: No Android device connected. Connect a device or start an emulator.", 27],
|
|
80
|
+
["Connection succeeded but app is not available", 38],
|
|
81
|
+
])("%s", (message) => {
|
|
82
|
+
expect(categorizeError(message)).toBe("connection");
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
describe("pre-existing behaviour is preserved", () => {
|
|
86
|
+
it.each([
|
|
87
|
+
["iOS UI driver (idb) is not installed", "driver_missing"],
|
|
88
|
+
["WebSocket connection ECONNREFUSED", "network"],
|
|
89
|
+
["Request timed out after 5000ms", "timeout"],
|
|
90
|
+
["No apps connected — run scan_metro", "connection"],
|
|
91
|
+
["Compiling JS failed: SyntaxError", "validation"],
|
|
92
|
+
["No element found matching the query", "validation"],
|
|
93
|
+
])("%s -> %s", (message, expected) => {
|
|
94
|
+
expect(categorizeError(message)).toBe(expected);
|
|
95
|
+
});
|
|
96
|
+
it("still falls through to unknown for genuinely unrecognised text", () => {
|
|
97
|
+
expect(categorizeError("something nobody has seen before")).toBe("unknown");
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
describe("driver_missing still wins via errorContext", () => {
|
|
101
|
+
it("uses the strategy chain when the primary message is generic", () => {
|
|
102
|
+
expect(categorizeError("No element found", "fiber:skipped|idb is not installed")).toBe("driver_missing");
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
//# sourceMappingURL=errorCategorization.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errorCategorization.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/errorCategorization.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"findElementTreeReuse.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/findElementTreeReuse.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { describe, it, expect } from "@jest/globals";
|
|
2
|
+
import { iosFindElement } from "../../core/ios.js";
|
|
3
|
+
import { androidFindElement } from "../../core/android.js";
|
|
4
|
+
/**
|
|
5
|
+
* The accessibility tap strategy runs two or three predicates over the SAME
|
|
6
|
+
* screen. Each find used to re-dump the accessibility tree (`axe describe-ui`
|
|
7
|
+
* ~210ms on iOS, a uiautomator dump on Android), so a single tap paid for the
|
|
8
|
+
* dump 2-3x. These tests pin the contract that makes the reuse possible: when a
|
|
9
|
+
* tree is supplied, no device call happens and matching runs against it.
|
|
10
|
+
*
|
|
11
|
+
* They also guard the failure mode of the optimisation — a caller passing a
|
|
12
|
+
* failed/empty tree must get an honest miss, never a silent device re-fetch.
|
|
13
|
+
*/
|
|
14
|
+
const iosTree = {
|
|
15
|
+
success: true,
|
|
16
|
+
rawOutput: JSON.stringify([{ frame: { x: 0, y: 0, width: 402, height: 874 } }]),
|
|
17
|
+
elements: [
|
|
18
|
+
{
|
|
19
|
+
label: "Proceed to Checkout",
|
|
20
|
+
value: "",
|
|
21
|
+
type: "Button",
|
|
22
|
+
identifier: "checkout-btn",
|
|
23
|
+
frame: { x: 20, y: 810, width: 380, height: 56 },
|
|
24
|
+
center: { x: 210, y: 838 },
|
|
25
|
+
enabled: true,
|
|
26
|
+
traits: [],
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
};
|
|
30
|
+
describe("iosFindElement with a pre-fetched tree", () => {
|
|
31
|
+
it("matches against the supplied tree without touching the device", async () => {
|
|
32
|
+
// No simulator is involved: a udid that cannot exist would make a real
|
|
33
|
+
// describe-ui fail, so a match here proves the tree was used.
|
|
34
|
+
const result = await iosFindElement({ labelContains: "Checkout" }, "00000000-0000-0000-0000-000000000000", iosTree);
|
|
35
|
+
expect(result.success).toBe(true);
|
|
36
|
+
expect(result.allMatches?.length).toBe(1);
|
|
37
|
+
expect(result.allMatches?.[0].label).toBe("Proceed to Checkout");
|
|
38
|
+
});
|
|
39
|
+
it("reports a clean miss for a predicate the tree doesn't satisfy", async () => {
|
|
40
|
+
const result = await iosFindElement({ labelContains: "Nonexistent" }, "00000000-0000-0000-0000-000000000000", iosTree);
|
|
41
|
+
expect(result.found).toBeFalsy();
|
|
42
|
+
expect(result.allMatches ?? []).toHaveLength(0);
|
|
43
|
+
});
|
|
44
|
+
it("surfaces a failed tree instead of silently re-fetching", async () => {
|
|
45
|
+
const failed = { success: false, error: "axe not installed" };
|
|
46
|
+
const result = await iosFindElement({ labelContains: "Checkout" }, "00000000-0000-0000-0000-000000000000", failed);
|
|
47
|
+
expect(result.success).toBe(false);
|
|
48
|
+
expect(result.error).toBe("axe not installed");
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
describe("androidFindElement with a pre-fetched tree", () => {
|
|
52
|
+
const androidTree = {
|
|
53
|
+
success: true,
|
|
54
|
+
elements: [
|
|
55
|
+
{
|
|
56
|
+
text: "Proceed to Checkout",
|
|
57
|
+
resourceId: "com.app:id/checkout",
|
|
58
|
+
contentDesc: "",
|
|
59
|
+
bounds: { x: 20, y: 810, width: 380, height: 56 },
|
|
60
|
+
center: { x: 210, y: 838 },
|
|
61
|
+
clickable: true,
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
};
|
|
65
|
+
it("matches against the supplied tree without running uiautomator", async () => {
|
|
66
|
+
const result = await androidFindElement({ textContains: "Checkout" }, "no-such-device", undefined, androidTree);
|
|
67
|
+
expect(result.success).toBe(true);
|
|
68
|
+
expect(result.allMatches?.length).toBe(1);
|
|
69
|
+
});
|
|
70
|
+
it("surfaces a failed tree instead of silently re-dumping", async () => {
|
|
71
|
+
const failed = { success: false, error: "adb offline" };
|
|
72
|
+
const result = await androidFindElement({ textContains: "Checkout" }, "no-such-device", undefined, failed);
|
|
73
|
+
expect(result.success).toBe(false);
|
|
74
|
+
expect(result.error).toBe("adb offline");
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
//# sourceMappingURL=findElementTreeReuse.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"findElementTreeReuse.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/findElementTreeReuse.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settleAndDiff.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/settleAndDiff.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { describe, it, expect } from "@jest/globals";
|
|
2
|
+
import { settleAndDiff, SETTLE_POLL_START_MS, SETTLE_STABLE_TIMEOUT_MS, NO_CHANGE_CONFIRM_MS, } from "../../pro/verifyAction.js";
|
|
3
|
+
const frame = (tag) => ({
|
|
4
|
+
buffer: Buffer.from(tag),
|
|
5
|
+
width: 100,
|
|
6
|
+
height: 200,
|
|
7
|
+
scaleFactor: 1,
|
|
8
|
+
});
|
|
9
|
+
/**
|
|
10
|
+
* Fake clock + fake capture/compare so the settle loop is exercised without a
|
|
11
|
+
* device. `compare` treats two buffers as "unchanged" when their bytes match,
|
|
12
|
+
* which mirrors what compareScreenshots reports for identical frames.
|
|
13
|
+
*/
|
|
14
|
+
function harness(script, opts = {}) {
|
|
15
|
+
const captureCostMs = opts.captureCostMs ?? 200;
|
|
16
|
+
let clock = 0;
|
|
17
|
+
let captures = 0;
|
|
18
|
+
const sleeps = [];
|
|
19
|
+
return {
|
|
20
|
+
get elapsed() { return clock; },
|
|
21
|
+
get captures() { return captures; },
|
|
22
|
+
sleeps,
|
|
23
|
+
args: {
|
|
24
|
+
beforeBuffer: Buffer.from("before"),
|
|
25
|
+
statusBarHeight: 59,
|
|
26
|
+
capture: async () => {
|
|
27
|
+
// Frames are consumed in order; the last one repeats forever.
|
|
28
|
+
const tag = script[Math.min(captures, script.length - 1)];
|
|
29
|
+
captures++;
|
|
30
|
+
clock += captureCostMs;
|
|
31
|
+
return tag === "__fail__" ? null : frame(tag);
|
|
32
|
+
},
|
|
33
|
+
compare: async (a, b) => {
|
|
34
|
+
const same = a.equals(b);
|
|
35
|
+
clock += 10;
|
|
36
|
+
return {
|
|
37
|
+
changed: !same,
|
|
38
|
+
changeRate: same ? 0 : 0.5,
|
|
39
|
+
changedPixels: same ? 0 : 5000,
|
|
40
|
+
totalPixels: 10000,
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
now: () => clock,
|
|
44
|
+
sleep: async (ms) => { sleeps.push(ms); clock += ms; },
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
describe("settleAndDiff", () => {
|
|
49
|
+
it("returns as soon as the screen changed and two consecutive frames match", async () => {
|
|
50
|
+
// "a" differs from before and repeats -> stable on the second capture.
|
|
51
|
+
const h = harness(["a", "a", "a", "a"]);
|
|
52
|
+
const result = await settleAndDiff(h.args);
|
|
53
|
+
expect(result).not.toBeNull();
|
|
54
|
+
expect(result.settled).toBe(true);
|
|
55
|
+
expect(result.diff.changedPixels).toBeGreaterThan(0);
|
|
56
|
+
expect(h.captures).toBe(2);
|
|
57
|
+
// 150ms lead-in + 2 captures — well under the old fixed 800ms wait.
|
|
58
|
+
expect(h.elapsed).toBeLessThan(700);
|
|
59
|
+
expect(h.sleeps[0]).toBe(SETTLE_POLL_START_MS);
|
|
60
|
+
});
|
|
61
|
+
it("keeps polling while the screen is still animating", async () => {
|
|
62
|
+
// Every frame differs from the previous one until the last pair.
|
|
63
|
+
const h = harness(["a", "b", "c", "c"]);
|
|
64
|
+
const result = await settleAndDiff(h.args);
|
|
65
|
+
expect(result.settled).toBe(true);
|
|
66
|
+
expect(result.frame.buffer.toString()).toBe("c");
|
|
67
|
+
expect(h.captures).toBe(4);
|
|
68
|
+
});
|
|
69
|
+
it("catches a late change that starts after the screen first looked idle", async () => {
|
|
70
|
+
// Identical to `before` twice (idle), then a modal slides in and settles.
|
|
71
|
+
const h = harness(["before", "before", "late", "late"]);
|
|
72
|
+
const result = await settleAndDiff(h.args);
|
|
73
|
+
expect(result.settled).toBe(true);
|
|
74
|
+
expect(result.diff.changedPixels).toBeGreaterThan(0);
|
|
75
|
+
expect(result.frame.buffer.toString()).toBe("late");
|
|
76
|
+
});
|
|
77
|
+
it("honours a caller-supplied no-change window (Android emulators animate slower)", async () => {
|
|
78
|
+
const h = harness(["before", "before", "before", "before", "before", "before", "before"]);
|
|
79
|
+
const result = await settleAndDiff({ ...h.args, noChangeConfirmMs: 1500 });
|
|
80
|
+
expect(result.diff.changedPixels).toBe(0);
|
|
81
|
+
expect(h.elapsed).toBeGreaterThanOrEqual(1500);
|
|
82
|
+
});
|
|
83
|
+
it("confirms 'no change' only after the confirmation window", async () => {
|
|
84
|
+
const h = harness(["before", "before", "before", "before", "before", "before"]);
|
|
85
|
+
const result = await settleAndDiff(h.args);
|
|
86
|
+
expect(result.settled).toBe(true);
|
|
87
|
+
expect(result.diff.changedPixels).toBe(0);
|
|
88
|
+
expect(h.elapsed).toBeGreaterThanOrEqual(NO_CHANGE_CONFIRM_MS);
|
|
89
|
+
// ...but it must not burn the full stable timeout on a quiet screen.
|
|
90
|
+
expect(h.elapsed).toBeLessThan(SETTLE_STABLE_TIMEOUT_MS + 500);
|
|
91
|
+
});
|
|
92
|
+
it("gives up at the cap when the screen never stabilises", async () => {
|
|
93
|
+
const h = harness(["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"]);
|
|
94
|
+
const result = await settleAndDiff(h.args);
|
|
95
|
+
expect(result.settled).toBe(false);
|
|
96
|
+
expect(result.diff).toBeDefined();
|
|
97
|
+
expect(h.elapsed).toBeLessThan(SETTLE_STABLE_TIMEOUT_MS + 600);
|
|
98
|
+
});
|
|
99
|
+
it("returns null when the first capture fails", async () => {
|
|
100
|
+
const h = harness(["__fail__"]);
|
|
101
|
+
expect(await settleAndDiff(h.args)).toBeNull();
|
|
102
|
+
});
|
|
103
|
+
it("falls back to the last good frame when a later capture fails", async () => {
|
|
104
|
+
const h = harness(["a", "__fail__"]);
|
|
105
|
+
const result = await settleAndDiff(h.args);
|
|
106
|
+
expect(result).not.toBeNull();
|
|
107
|
+
expect(result.frame.buffer.toString()).toBe("a");
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
//# sourceMappingURL=settleAndDiff.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settleAndDiff.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/settleAndDiff.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,7 +6,8 @@ describe("verifyAction module", () => {
|
|
|
6
6
|
expect(typeof mod.verifyAndCapture).toBe("function");
|
|
7
7
|
expect(typeof mod.burstCaptureAndVerify).toBe("function");
|
|
8
8
|
expect(typeof mod.drawTapMarker).toBe("function");
|
|
9
|
-
expect(typeof mod.
|
|
9
|
+
expect(typeof mod.settleAndDiff).toBe("function");
|
|
10
|
+
expect(typeof mod.SETTLE_POLL_START_MS).toBe("number");
|
|
10
11
|
expect(typeof mod.BURST_FRAME_COUNT).toBe("number");
|
|
11
12
|
expect(typeof mod.BURST_FRAME_INTERVAL_MS).toBe("number");
|
|
12
13
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verifyAction.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/verifyAction.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAErD,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;QAC3C,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,2BAA2B,CAAC,CAAC;QACtD,MAAM,CAAC,OAAO,GAAG,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACtD,MAAM,CAAC,OAAO,GAAG,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACrD,MAAM,CAAC,OAAO,GAAG,CAAC,qBAAqB,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1D,MAAM,CAAC,OAAO,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAClD,MAAM,CAAC,OAAO,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"verifyAction.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/verifyAction.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAErD,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;QAC3C,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,2BAA2B,CAAC,CAAC;QACtD,MAAM,CAAC,OAAO,GAAG,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACtD,MAAM,CAAC,OAAO,GAAG,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACrD,MAAM,CAAC,OAAO,GAAG,CAAC,qBAAqB,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1D,MAAM,CAAC,OAAO,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAClD,MAAM,CAAC,OAAO,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAClD,MAAM,CAAC,OAAO,GAAG,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvD,MAAM,CAAC,OAAO,GAAG,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpD,MAAM,CAAC,OAAO,GAAG,CAAC,uBAAuB,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mGAAmG,EAAE,KAAK,IAAI,EAAE;QAC/G,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,2BAA2B,CAAC,CAAC;QACvE,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC;YAClC,QAAQ,EAAE,KAAK;YACf,YAAY,EAAE,KAAK;YACnB,gBAAgB,EAAE,KAAK;YACvB,YAAY,EAAE,IAAI;YAClB,MAAM,EAAE,cAAc;SACzB,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChD,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"waitForMeasurements.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/waitForMeasurements.test.ts"],"names":[],"mappings":""}
|