execbro 2.0.0 → 2.1.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.
Files changed (61) hide show
  1. package/build/__tests__/unit/coordinateMiss.test.d.ts +2 -0
  2. package/build/__tests__/unit/coordinateMiss.test.d.ts.map +1 -0
  3. package/build/__tests__/unit/coordinateMiss.test.js +111 -0
  4. package/build/__tests__/unit/coordinateMiss.test.js.map +1 -0
  5. package/build/__tests__/unit/deviceResolverStaleRetry.test.d.ts +2 -0
  6. package/build/__tests__/unit/deviceResolverStaleRetry.test.d.ts.map +1 -0
  7. package/build/__tests__/unit/deviceResolverStaleRetry.test.js +69 -0
  8. package/build/__tests__/unit/deviceResolverStaleRetry.test.js.map +1 -0
  9. package/build/__tests__/unit/findElementTreeReuse.test.d.ts +2 -0
  10. package/build/__tests__/unit/findElementTreeReuse.test.d.ts.map +1 -0
  11. package/build/__tests__/unit/findElementTreeReuse.test.js +77 -0
  12. package/build/__tests__/unit/findElementTreeReuse.test.js.map +1 -0
  13. package/build/__tests__/unit/settleAndDiff.test.d.ts +2 -0
  14. package/build/__tests__/unit/settleAndDiff.test.d.ts.map +1 -0
  15. package/build/__tests__/unit/settleAndDiff.test.js +110 -0
  16. package/build/__tests__/unit/settleAndDiff.test.js.map +1 -0
  17. package/build/__tests__/unit/verifyAction.test.js +2 -1
  18. package/build/__tests__/unit/verifyAction.test.js.map +1 -1
  19. package/build/__tests__/unit/waitForMeasurements.test.d.ts +2 -0
  20. package/build/__tests__/unit/waitForMeasurements.test.d.ts.map +1 -0
  21. package/build/__tests__/unit/waitForMeasurements.test.js +69 -0
  22. package/build/__tests__/unit/waitForMeasurements.test.js.map +1 -0
  23. package/build/core/android.d.ts +3 -1
  24. package/build/core/android.d.ts.map +1 -1
  25. package/build/core/android.js +5 -5
  26. package/build/core/android.js.map +1 -1
  27. package/build/core/deviceDiscovery.d.ts +5 -1
  28. package/build/core/deviceDiscovery.d.ts.map +1 -1
  29. package/build/core/deviceDiscovery.js +13 -2
  30. package/build/core/deviceDiscovery.js.map +1 -1
  31. package/build/core/deviceResolver.d.ts.map +1 -1
  32. package/build/core/deviceResolver.js +17 -2
  33. package/build/core/deviceResolver.js.map +1 -1
  34. package/build/core/ios.d.ts +14 -3
  35. package/build/core/ios.d.ts.map +1 -1
  36. package/build/core/ios.js +39 -15
  37. package/build/core/ios.js.map +1 -1
  38. package/build/core/pressables.d.ts +33 -0
  39. package/build/core/pressables.d.ts.map +1 -1
  40. package/build/core/pressables.js +73 -4
  41. package/build/core/pressables.js.map +1 -1
  42. package/build/pro/coordinateMiss.d.ts +55 -0
  43. package/build/pro/coordinateMiss.d.ts.map +1 -0
  44. package/build/pro/coordinateMiss.js +122 -0
  45. package/build/pro/coordinateMiss.js.map +1 -0
  46. package/build/pro/tap.d.ts +8 -0
  47. package/build/pro/tap.d.ts.map +1 -1
  48. package/build/pro/tap.js +99 -11
  49. package/build/pro/tap.js.map +1 -1
  50. package/build/pro/verifyAction.d.ts +43 -2
  51. package/build/pro/verifyAction.d.ts.map +1 -1
  52. package/build/pro/verifyAction.js +95 -36
  53. package/build/pro/verifyAction.js.map +1 -1
  54. package/build/tools/interactionTools.d.ts +6 -0
  55. package/build/tools/interactionTools.d.ts.map +1 -1
  56. package/build/tools/interactionTools.js +28 -11
  57. package/build/tools/interactionTools.js.map +1 -1
  58. package/build/tools/screenshotTools.d.ts.map +1 -1
  59. package/build/tools/screenshotTools.js +33 -12
  60. package/build/tools/screenshotTools.js.map +1 -1
  61. package/package.json +1 -1
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=coordinateMiss.test.d.ts.map
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=deviceResolverStaleRetry.test.d.ts.map
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=findElementTreeReuse.test.d.ts.map
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=settleAndDiff.test.d.ts.map
@@ -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.SETTLE_DELAY_MS).toBe("number");
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,eAAe,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAClD,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"}
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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=waitForMeasurements.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"waitForMeasurements.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/waitForMeasurements.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,69 @@
1
+ import { describe, it, expect } from "@jest/globals";
2
+ import { waitForMeasurements, buildPendingMeasurementExpression, MEASURE_POLL_SCHEDULE_MS, MEASURE_POLL_DEADLINE_MS, } from "../../core/pressables.js";
3
+ function harness(pendingSequence) {
4
+ let clock = 0;
5
+ let calls = 0;
6
+ return {
7
+ get elapsed() { return clock; },
8
+ get calls() { return calls; },
9
+ args: {
10
+ evaluatePending: async () => {
11
+ const v = pendingSequence[Math.min(calls, pendingSequence.length - 1)];
12
+ calls++;
13
+ clock += 15; // measured cost of the probe eval on device
14
+ return v;
15
+ },
16
+ now: () => clock,
17
+ sleep: async (ms) => { clock += ms; },
18
+ },
19
+ };
20
+ }
21
+ describe("waitForMeasurements", () => {
22
+ it("returns after the first poll when every callback already landed", async () => {
23
+ const h = harness([0]);
24
+ const result = await waitForMeasurements(h.args);
25
+ expect(result.pending).toBe(0);
26
+ expect(h.calls).toBe(1);
27
+ // The whole wait costs one short sleep + one probe — far below the old
28
+ // flat 300ms delay this replaced.
29
+ expect(h.elapsed).toBe(MEASURE_POLL_SCHEDULE_MS[0] + 15);
30
+ });
31
+ it("keeps polling while measurements are still outstanding", async () => {
32
+ const h = harness([4, 2, 0]);
33
+ const result = await waitForMeasurements(h.args);
34
+ expect(result.pending).toBe(0);
35
+ expect(h.calls).toBe(3);
36
+ expect(result.polls).toBe(3);
37
+ });
38
+ it("stops at the deadline when a callback never fires", async () => {
39
+ const h = harness([1]); // permanently pending
40
+ const result = await waitForMeasurements(h.args);
41
+ expect(result.pending).toBe(1);
42
+ // Never waits materially longer than the flat delay it replaced.
43
+ expect(h.elapsed).toBeLessThanOrEqual(MEASURE_POLL_DEADLINE_MS + 200);
44
+ expect(h.calls).toBeLessThanOrEqual(MEASURE_POLL_SCHEDULE_MS.length);
45
+ });
46
+ it("gives up immediately when the probe itself fails", async () => {
47
+ const h = harness([null]);
48
+ const result = await waitForMeasurements(h.args);
49
+ expect(result.pending).toBeNull();
50
+ expect(h.calls).toBe(1);
51
+ });
52
+ });
53
+ describe("buildPendingMeasurementExpression", () => {
54
+ it("counts unfilled slots across every named global", () => {
55
+ const expr = buildPendingMeasurementExpression(["__a", "__b"]);
56
+ expect(expr).toContain("globalThis.__a");
57
+ expect(expr).toContain("globalThis.__b");
58
+ // The expression must be valid, self-contained JS that reports the
59
+ // number of null slots — evaluate it against a stub global.
60
+ const globalThisStub = { __a: [{ x: 1 }, null], __b: [null] };
61
+ const value = new Function("globalThis", `return ${expr};`)(globalThisStub);
62
+ expect(value).toBe(2);
63
+ });
64
+ it("treats a missing global as nothing to wait for", () => {
65
+ const expr = buildPendingMeasurementExpression(["__missing"]);
66
+ expect(new Function("globalThis", `return ${expr};`)({})).toBe(0);
67
+ });
68
+ });
69
+ //# sourceMappingURL=waitForMeasurements.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"waitForMeasurements.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/waitForMeasurements.test.ts"],"names":[],"mappings":"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"}
@@ -198,7 +198,9 @@ export declare function androidGetUITree(deviceId?: string, signal?: AbortSignal
198
198
  /**
199
199
  * Find element(s) in the UI tree matching the given criteria
200
200
  */
201
- export declare function androidFindElement(options: FindElementOptions, deviceId?: string, signal?: AbortSignal): Promise<FindElementResult>;
201
+ /** A pre-fetched view hierarchy, as returned by androidGetUITree. */
202
+ export type AndroidUITree = Awaited<ReturnType<typeof androidGetUITree>>;
203
+ export declare function androidFindElement(options: FindElementOptions, deviceId?: string, signal?: AbortSignal, tree?: AndroidUITree): Promise<FindElementResult>;
202
204
  /**
203
205
  * Wait for element to appear on screen with polling
204
206
  */
@@ -1 +1 @@
1
- {"version":3,"file":"android.d.ts","sourceRoot":"","sources":["../../src/core/android.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"android.d.ts","sourceRoot":"","sources":["../../src/core/android.ts"],"names":[],"mappings":"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"}
@@ -949,10 +949,7 @@ export async function androidGetUITree(deviceId, signal) {
949
949
  };
950
950
  }
951
951
  }
952
- /**
953
- * Find element(s) in the UI tree matching the given criteria
954
- */
955
- export async function androidFindElement(options, deviceId, signal) {
952
+ export async function androidFindElement(options, deviceId, signal, tree) {
956
953
  try {
957
954
  // Validate that at least one search criteria is provided
958
955
  if (!options.text && !options.textContains && !options.contentDesc &&
@@ -963,7 +960,10 @@ export async function androidFindElement(options, deviceId, signal) {
963
960
  error: "At least one search criteria (text, textContains, contentDesc, contentDescContains, or resourceId) must be provided"
964
961
  };
965
962
  }
966
- const treeResult = await androidGetUITree(deviceId, signal);
963
+ // A caller that already dumped the hierarchy can pass it in — uiautomator
964
+ // dumps are the single most expensive step of an Android accessibility
965
+ // tap, and the tap strategy runs two passes over the same screen.
966
+ const treeResult = tree ?? (await androidGetUITree(deviceId, signal));
967
967
  if (!treeResult.success || !treeResult.elements) {
968
968
  return {
969
969
  success: false,