react-native-ai-devtools 1.4.3 → 1.4.5
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__/helpers/tap-test-helpers.d.ts +36 -0
- package/build/__tests__/helpers/tap-test-helpers.d.ts.map +1 -0
- package/build/__tests__/helpers/tap-test-helpers.js +125 -0
- package/build/__tests__/helpers/tap-test-helpers.js.map +1 -0
- package/build/__tests__/integration/tap-strategies.test.d.ts +2 -0
- package/build/__tests__/integration/tap-strategies.test.d.ts.map +1 -0
- package/build/__tests__/integration/tap-strategies.test.js +265 -0
- package/build/__tests__/integration/tap-strategies.test.js.map +1 -0
- package/build/__tests__/unit/burst.test.d.ts +2 -0
- package/build/__tests__/unit/burst.test.d.ts.map +1 -0
- package/build/__tests__/unit/burst.test.js +50 -0
- package/build/__tests__/unit/burst.test.js.map +1 -0
- package/build/__tests__/unit/imageBuffer.test.d.ts +2 -0
- package/build/__tests__/unit/imageBuffer.test.d.ts.map +1 -0
- package/build/__tests__/unit/imageBuffer.test.js +128 -0
- package/build/__tests__/unit/imageBuffer.test.js.map +1 -0
- package/build/__tests__/unit/tap.test.js +67 -1
- package/build/__tests__/unit/tap.test.js.map +1 -1
- package/build/core/executor.d.ts.map +1 -1
- package/build/core/executor.js +108 -126
- package/build/core/executor.js.map +1 -1
- package/build/core/imageBuffer.d.ts +37 -0
- package/build/core/imageBuffer.d.ts.map +1 -0
- package/build/core/imageBuffer.js +58 -0
- package/build/core/imageBuffer.js.map +1 -0
- package/build/core/index.d.ts +3 -1
- package/build/core/index.d.ts.map +1 -1
- package/build/core/index.js +3 -1
- package/build/core/index.js.map +1 -1
- package/build/core/state.d.ts +2 -0
- package/build/core/state.d.ts.map +1 -1
- package/build/core/state.js +3 -0
- package/build/core/state.js.map +1 -1
- package/build/index.js +123 -2
- package/build/index.js.map +1 -1
- package/build/pro/tap.d.ts +24 -0
- package/build/pro/tap.d.ts.map +1 -1
- package/build/pro/tap.js +259 -47
- package/build/pro/tap.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { TapResult } from "../../pro/tap.js";
|
|
2
|
+
export type Platform = "ios" | "android";
|
|
3
|
+
/**
|
|
4
|
+
* Detect which platform is available by checking for booted simulators/emulators.
|
|
5
|
+
* Returns the first available platform.
|
|
6
|
+
*/
|
|
7
|
+
export declare function detectPlatform(): Promise<Platform>;
|
|
8
|
+
/**
|
|
9
|
+
* Connect to Metro and return the platform of the connected device.
|
|
10
|
+
*/
|
|
11
|
+
export declare function connectToMetro(): Promise<Platform>;
|
|
12
|
+
/**
|
|
13
|
+
* Disconnect all apps and clean up state.
|
|
14
|
+
*/
|
|
15
|
+
export declare function disconnectAll(): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* Read the test app's global state to verify a tap was registered.
|
|
18
|
+
* Returns { tapCount, lastTapped } or null if not available.
|
|
19
|
+
*/
|
|
20
|
+
export declare function readTestState(): Promise<{
|
|
21
|
+
tapCount: number;
|
|
22
|
+
lastTapped: string;
|
|
23
|
+
} | null>;
|
|
24
|
+
/**
|
|
25
|
+
* Reset the test app's tap counter and last-tapped state.
|
|
26
|
+
*/
|
|
27
|
+
export declare function resetTestState(): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Assert that a tap result succeeded and the test app registered the tap on the expected element.
|
|
30
|
+
*/
|
|
31
|
+
export declare function assertTapWorked(result: TapResult, expectedElement: string): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Wait for a short duration (ms) to let UI settle.
|
|
34
|
+
*/
|
|
35
|
+
export declare function sleep(ms: number): Promise<void>;
|
|
36
|
+
//# sourceMappingURL=tap-test-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tap-test-helpers.d.ts","sourceRoot":"","sources":["../../../src/__tests__/helpers/tap-test-helpers.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,SAAS,CAAC;AAEzC;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,QAAQ,CAAC,CAYxD;AAED;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,QAAQ,CAAC,CAwBxD;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAmBnD;AAED;;;GAGG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAU9F;AAED;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAEpD;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAW/F;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// src/__tests__/helpers/tap-test-helpers.ts
|
|
2
|
+
import { scanMetroPorts, fetchDevices, selectMainDevice } from "../../core/metro.js";
|
|
3
|
+
import { connectToDevice } from "../../core/connection.js";
|
|
4
|
+
import { executeInApp } from "../../core/executor.js";
|
|
5
|
+
import { connectedApps, pendingExecutions } from "../../core/state.js";
|
|
6
|
+
import { cancelAllReconnectionTimers, clearAllConnectionState } from "../../core/connectionState.js";
|
|
7
|
+
/**
|
|
8
|
+
* Detect which platform is available by checking for booted simulators/emulators.
|
|
9
|
+
* Returns the first available platform.
|
|
10
|
+
*/
|
|
11
|
+
export async function detectPlatform() {
|
|
12
|
+
const { execSync } = await import("child_process");
|
|
13
|
+
try {
|
|
14
|
+
const result = execSync("xcrun simctl list devices booted 2>/dev/null", { encoding: "utf-8" });
|
|
15
|
+
if (result.includes("Booted"))
|
|
16
|
+
return "ios";
|
|
17
|
+
}
|
|
18
|
+
catch { /* no iOS */ }
|
|
19
|
+
try {
|
|
20
|
+
const result = execSync("adb devices 2>/dev/null", { encoding: "utf-8" });
|
|
21
|
+
const lines = result.trim().split("\n").filter(l => l.includes("device") && !l.includes("List"));
|
|
22
|
+
if (lines.length > 0)
|
|
23
|
+
return "android";
|
|
24
|
+
}
|
|
25
|
+
catch { /* no Android */ }
|
|
26
|
+
throw new Error("No booted iOS simulator or Android emulator found");
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Connect to Metro and return the platform of the connected device.
|
|
30
|
+
*/
|
|
31
|
+
export async function connectToMetro() {
|
|
32
|
+
const ports = await scanMetroPorts();
|
|
33
|
+
if (ports.length === 0) {
|
|
34
|
+
throw new Error("No Metro bundler found. Start Metro with the test app first.");
|
|
35
|
+
}
|
|
36
|
+
for (const port of ports) {
|
|
37
|
+
const devices = await fetchDevices(port);
|
|
38
|
+
const main = selectMainDevice(devices);
|
|
39
|
+
if (main) {
|
|
40
|
+
const key = await connectToDevice(main, port, {
|
|
41
|
+
reconnectionConfig: {
|
|
42
|
+
enabled: false,
|
|
43
|
+
maxAttempts: 0,
|
|
44
|
+
initialDelayMs: 0,
|
|
45
|
+
maxDelayMs: 0,
|
|
46
|
+
backoffMultiplier: 1,
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
const app = connectedApps.get(key);
|
|
50
|
+
if (app?.platform)
|
|
51
|
+
return app.platform;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
throw new Error("Connected to Metro but could not determine platform");
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Disconnect all apps and clean up state.
|
|
58
|
+
*/
|
|
59
|
+
export async function disconnectAll() {
|
|
60
|
+
const closePromises = [];
|
|
61
|
+
for (const [key, app] of connectedApps.entries()) {
|
|
62
|
+
closePromises.push(new Promise((resolve) => {
|
|
63
|
+
if (app.ws.readyState === app.ws.CLOSED) {
|
|
64
|
+
resolve();
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
app.ws.on("close", () => resolve());
|
|
68
|
+
try {
|
|
69
|
+
app.ws.close();
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
resolve();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}));
|
|
76
|
+
connectedApps.delete(key);
|
|
77
|
+
}
|
|
78
|
+
await Promise.all(closePromises);
|
|
79
|
+
pendingExecutions.clear();
|
|
80
|
+
cancelAllReconnectionTimers();
|
|
81
|
+
clearAllConnectionState();
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Read the test app's global state to verify a tap was registered.
|
|
85
|
+
* Returns { tapCount, lastTapped } or null if not available.
|
|
86
|
+
*/
|
|
87
|
+
export async function readTestState() {
|
|
88
|
+
const result = await executeInApp("JSON.stringify({ tapCount: global.__TEST_STATE__?.tapCount ?? -1, lastTapped: global.__TEST_STATE__?.lastTapped ?? 'unknown' })");
|
|
89
|
+
if (!result.success || !result.result)
|
|
90
|
+
return null;
|
|
91
|
+
try {
|
|
92
|
+
return JSON.parse(result.result);
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Reset the test app's tap counter and last-tapped state.
|
|
100
|
+
*/
|
|
101
|
+
export async function resetTestState() {
|
|
102
|
+
await executeInApp("global.__TEST_STATE__?.reset?.()");
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Assert that a tap result succeeded and the test app registered the tap on the expected element.
|
|
106
|
+
*/
|
|
107
|
+
export async function assertTapWorked(result, expectedElement) {
|
|
108
|
+
if (!result.success) {
|
|
109
|
+
throw new Error(`Tap failed: ${result.error ?? result.suggestion ?? "unknown reason"}`);
|
|
110
|
+
}
|
|
111
|
+
const state = await readTestState();
|
|
112
|
+
if (!state) {
|
|
113
|
+
throw new Error("Could not read test app state via execute_in_app");
|
|
114
|
+
}
|
|
115
|
+
if (state.lastTapped !== expectedElement) {
|
|
116
|
+
throw new Error(`Expected lastTapped="${expectedElement}" but got "${state.lastTapped}"`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Wait for a short duration (ms) to let UI settle.
|
|
121
|
+
*/
|
|
122
|
+
export function sleep(ms) {
|
|
123
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=tap-test-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tap-test-helpers.js","sourceRoot":"","sources":["../../../src/__tests__/helpers/tap-test-helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tap-strategies.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/integration/tap-strategies.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
// src/__tests__/integration/tap-strategies.test.ts
|
|
2
|
+
import { describe, it, expect, beforeAll, afterAll, afterEach } from "@jest/globals";
|
|
3
|
+
import { tap } from "../../pro/tap.js";
|
|
4
|
+
import { connectToMetro, disconnectAll, resetTestState, readTestState, assertTapWorked, sleep, } from "../helpers/tap-test-helpers.js";
|
|
5
|
+
let platform;
|
|
6
|
+
beforeAll(async () => {
|
|
7
|
+
platform = await connectToMetro();
|
|
8
|
+
}, 30000);
|
|
9
|
+
afterAll(async () => {
|
|
10
|
+
await disconnectAll();
|
|
11
|
+
}, 10000);
|
|
12
|
+
afterEach(async () => {
|
|
13
|
+
await resetTestState();
|
|
14
|
+
await sleep(500);
|
|
15
|
+
}, 10000);
|
|
16
|
+
describe("Category 1: RN Fiber & JS Strategies", () => {
|
|
17
|
+
it("tap button by testID (auto strategy)", async () => {
|
|
18
|
+
const result = await tap({ testID: "submit-btn" });
|
|
19
|
+
await assertTapWorked(result, "submit-btn");
|
|
20
|
+
}, 30000);
|
|
21
|
+
it("tap button by visible text (auto strategy)", async () => {
|
|
22
|
+
const result = await tap({ text: "Cancel" });
|
|
23
|
+
await assertTapWorked(result, "cancel-btn");
|
|
24
|
+
}, 30000);
|
|
25
|
+
it("tap icon-only button by component name", async () => {
|
|
26
|
+
const result = await tap({ component: "HeartIcon" });
|
|
27
|
+
await assertTapWorked(result, "heart-btn");
|
|
28
|
+
}, 30000);
|
|
29
|
+
it("tap by text with explicit fiber strategy", async () => {
|
|
30
|
+
const result = await tap({ text: "Submit", strategy: "fiber" });
|
|
31
|
+
await assertTapWorked(result, "submit-btn");
|
|
32
|
+
}, 30000);
|
|
33
|
+
it("tap by testID with explicit accessibility strategy", async () => {
|
|
34
|
+
const result = await tap({ testID: "submit-btn", strategy: "accessibility" });
|
|
35
|
+
await assertTapWorked(result, "submit-btn");
|
|
36
|
+
}, 30000);
|
|
37
|
+
it("tap by text with explicit OCR strategy", async () => {
|
|
38
|
+
const result = await tap({ text: "Submit", strategy: "ocr" });
|
|
39
|
+
await assertTapWorked(result, "submit-btn");
|
|
40
|
+
}, 30000);
|
|
41
|
+
it("focus TextInput by testID", async () => {
|
|
42
|
+
const result = await tap({ testID: "name-input" });
|
|
43
|
+
expect(result.success).toBe(true);
|
|
44
|
+
// TextInput has onChangeText, not onPress — fiber detects this and falls
|
|
45
|
+
// through to native tap for focus. No tap counter increment expected since
|
|
46
|
+
// the test app only counts onPress handlers, not input focus events.
|
|
47
|
+
expect(result.method).toBeDefined();
|
|
48
|
+
}, 30000);
|
|
49
|
+
it("tap Cyrillic text button", async () => {
|
|
50
|
+
const result = await tap({ text: "Отправить" });
|
|
51
|
+
await assertTapWorked(result, "cyrillic-btn");
|
|
52
|
+
}, 30000);
|
|
53
|
+
it("tap CJK text button", async () => {
|
|
54
|
+
const result = await tap({ text: "送信" });
|
|
55
|
+
await assertTapWorked(result, "cjk-btn");
|
|
56
|
+
}, 30000);
|
|
57
|
+
});
|
|
58
|
+
describe("Category 2: RN Coordinates & Verification", () => {
|
|
59
|
+
it("tap by pixel coordinates", async () => {
|
|
60
|
+
// First, tap by testID to find the element's coordinates.
|
|
61
|
+
// tappedAt returns coordinates in the native unit used by the platform
|
|
62
|
+
// (points on iOS, pixels on Android). tap({ x, y }) treats these as
|
|
63
|
+
// screenshot pixel coordinates and applies conversion internally.
|
|
64
|
+
const findResult = await tap({ testID: "submit-btn", screenshot: true });
|
|
65
|
+
expect(findResult.success).toBe(true);
|
|
66
|
+
expect(findResult.tappedAt).toBeDefined();
|
|
67
|
+
await resetTestState();
|
|
68
|
+
await sleep(500);
|
|
69
|
+
const { x, y } = findResult.tappedAt;
|
|
70
|
+
const result = await tap({ x, y });
|
|
71
|
+
await assertTapWorked(result, "submit-btn");
|
|
72
|
+
expect(result.method).toBe("coordinate");
|
|
73
|
+
}, 30000);
|
|
74
|
+
it("tap with native=true at coordinates", async () => {
|
|
75
|
+
// Get coordinates from a known element
|
|
76
|
+
const findResult = await tap({ testID: "cancel-btn", screenshot: true });
|
|
77
|
+
expect(findResult.success).toBe(true);
|
|
78
|
+
expect(findResult.tappedAt).toBeDefined();
|
|
79
|
+
await resetTestState();
|
|
80
|
+
await sleep(500);
|
|
81
|
+
const { x, y } = findResult.tappedAt;
|
|
82
|
+
const result = await tap({ x, y, native: true });
|
|
83
|
+
expect(result.success).toBe(true);
|
|
84
|
+
// Native tap bypasses RN, verify via test state
|
|
85
|
+
const state = await readTestState();
|
|
86
|
+
expect(state?.lastTapped).toBe("cancel-btn");
|
|
87
|
+
}, 30000);
|
|
88
|
+
it("tap with screenshot verification", async () => {
|
|
89
|
+
const result = await tap({ testID: "submit-btn", verify: true, screenshot: true });
|
|
90
|
+
expect(result.success).toBe(true);
|
|
91
|
+
expect(result.screenshot).toBeDefined();
|
|
92
|
+
expect(result.screenshot?.image).toBeTruthy();
|
|
93
|
+
expect(result.verification).toBeDefined();
|
|
94
|
+
expect(result.verification?.meaningful).toBe(true);
|
|
95
|
+
}, 30000);
|
|
96
|
+
it("tap with screenshot=false", async () => {
|
|
97
|
+
const result = await tap({ testID: "submit-btn", screenshot: false });
|
|
98
|
+
expect(result.success).toBe(true);
|
|
99
|
+
expect(result.screenshot).toBeUndefined();
|
|
100
|
+
}, 30000);
|
|
101
|
+
it("tap non-existent element returns failure with suggestion", async () => {
|
|
102
|
+
const result = await tap({ text: "DoesNotExist" });
|
|
103
|
+
expect(result.success).toBe(false);
|
|
104
|
+
expect(result.suggestion).toBeTruthy();
|
|
105
|
+
expect(result.attempted).toBeDefined();
|
|
106
|
+
expect(result.attempted.length).toBeGreaterThan(0);
|
|
107
|
+
}, 30000);
|
|
108
|
+
it("tap completes within timeout budget", async () => {
|
|
109
|
+
const start = Date.now();
|
|
110
|
+
const result = await tap({ testID: "submit-btn" });
|
|
111
|
+
const elapsed = Date.now() - start;
|
|
112
|
+
expect(result.success).toBe(true);
|
|
113
|
+
// Successful tap should complete well under the 10s timeout
|
|
114
|
+
expect(elapsed).toBeLessThan(10000);
|
|
115
|
+
}, 30000);
|
|
116
|
+
it("failed tap respects timeout and does not hang", async () => {
|
|
117
|
+
const start = Date.now();
|
|
118
|
+
const result = await tap({ text: "DoesNotExist_Timeout_Test" });
|
|
119
|
+
const elapsed = Date.now() - start;
|
|
120
|
+
expect(result.success).toBe(false);
|
|
121
|
+
// Failed tap should not exceed ~10s budget (with some margin for cleanup)
|
|
122
|
+
expect(elapsed).toBeLessThan(15000);
|
|
123
|
+
// Check that attempted strategies report timeout/skip info
|
|
124
|
+
expect(result.attempted).toBeDefined();
|
|
125
|
+
expect(result.attempted.length).toBeGreaterThan(0);
|
|
126
|
+
}, 30000);
|
|
127
|
+
it("tap navigation button and verify screen change", async () => {
|
|
128
|
+
const result = await tap({ testID: "nav-scroll-btn" });
|
|
129
|
+
expect(result.success).toBe(true);
|
|
130
|
+
await sleep(1000); // wait for navigation animation
|
|
131
|
+
// Verify we're on Screen 2 by checking for its elements
|
|
132
|
+
const backBtnResult = await tap({ testID: "nav-back-btn", screenshot: false });
|
|
133
|
+
expect(backBtnResult.success).toBe(true);
|
|
134
|
+
await sleep(500); // wait for navigation back
|
|
135
|
+
}, 30000);
|
|
136
|
+
it("scroll then tap bottom button", async () => {
|
|
137
|
+
// Navigate to scroll screen
|
|
138
|
+
await tap({ testID: "nav-scroll-btn" });
|
|
139
|
+
await sleep(1000);
|
|
140
|
+
// Swipe up to scroll down and reveal the bottom button
|
|
141
|
+
const { iosSwipe } = await import("../../core/ios.js");
|
|
142
|
+
const { androidSwipe } = await import("../../core/android.js");
|
|
143
|
+
// Perform multiple swipes to reach the bottom
|
|
144
|
+
for (let i = 0; i < 5; i++) {
|
|
145
|
+
if (platform === "ios") {
|
|
146
|
+
await iosSwipe(200, 600, 200, 200);
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
await androidSwipe(540, 1500, 540, 500);
|
|
150
|
+
}
|
|
151
|
+
await sleep(500);
|
|
152
|
+
}
|
|
153
|
+
// Try to tap the bottom button
|
|
154
|
+
const result = await tap({ testID: "bottom-btn" });
|
|
155
|
+
await assertTapWorked(result, "bottom-btn");
|
|
156
|
+
// Navigate back
|
|
157
|
+
await tap({ testID: "nav-back-btn" });
|
|
158
|
+
await sleep(500);
|
|
159
|
+
}, 60000);
|
|
160
|
+
});
|
|
161
|
+
describe("Category 3: Non-RN Native App (System Apps)", () => {
|
|
162
|
+
const IOS_SETTINGS_BUNDLE = "com.apple.Preferences";
|
|
163
|
+
const ANDROID_SETTINGS_PACKAGE = "com.android.settings";
|
|
164
|
+
// Platform checks are inside it() bodies because platform is set in beforeAll,
|
|
165
|
+
// which runs after Jest collects describe blocks synchronously.
|
|
166
|
+
it("tap Settings item by text (iOS)", async () => {
|
|
167
|
+
if (platform !== "ios")
|
|
168
|
+
return;
|
|
169
|
+
const { iosLaunchApp } = await import("../../core/ios.js");
|
|
170
|
+
await iosLaunchApp(IOS_SETTINGS_BUNDLE);
|
|
171
|
+
await sleep(2000);
|
|
172
|
+
const result = await tap({ text: "General", native: true });
|
|
173
|
+
expect(result.success).toBe(true);
|
|
174
|
+
}, 30000);
|
|
175
|
+
it("tap by OCR on native app (iOS)", async () => {
|
|
176
|
+
if (platform !== "ios")
|
|
177
|
+
return;
|
|
178
|
+
const { iosLaunchApp } = await import("../../core/ios.js");
|
|
179
|
+
await iosLaunchApp(IOS_SETTINGS_BUNDLE);
|
|
180
|
+
await sleep(2000);
|
|
181
|
+
const result = await tap({ text: "General", strategy: "ocr", native: true });
|
|
182
|
+
expect(result.success).toBe(true);
|
|
183
|
+
expect(result.method).toBe("ocr");
|
|
184
|
+
}, 30000);
|
|
185
|
+
it("find and tap via iOS accessibility tree", async () => {
|
|
186
|
+
if (platform !== "ios")
|
|
187
|
+
return;
|
|
188
|
+
const { iosLaunchApp, iosFindElement } = await import("../../core/ios.js");
|
|
189
|
+
await iosLaunchApp(IOS_SETTINGS_BUNDLE);
|
|
190
|
+
await sleep(2000);
|
|
191
|
+
const findResult = await iosFindElement({ labelContains: "General" });
|
|
192
|
+
expect(findResult.success).toBe(true);
|
|
193
|
+
expect(findResult.found).toBe(true);
|
|
194
|
+
expect(findResult.element).toBeDefined();
|
|
195
|
+
const { x, y } = findResult.element.center;
|
|
196
|
+
const tapResult = await tap({ x, y, native: true });
|
|
197
|
+
expect(tapResult.success).toBe(true);
|
|
198
|
+
}, 30000);
|
|
199
|
+
it("tap Settings item by text (Android)", async () => {
|
|
200
|
+
if (platform !== "android")
|
|
201
|
+
return;
|
|
202
|
+
const { androidLaunchApp } = await import("../../core/android.js");
|
|
203
|
+
await androidLaunchApp(ANDROID_SETTINGS_PACKAGE);
|
|
204
|
+
await sleep(2000);
|
|
205
|
+
const result = await tap({ text: "Network", native: true });
|
|
206
|
+
expect(result.success).toBe(true);
|
|
207
|
+
}, 30000);
|
|
208
|
+
it("tap by OCR on native app (Android)", async () => {
|
|
209
|
+
if (platform !== "android")
|
|
210
|
+
return;
|
|
211
|
+
const { androidLaunchApp } = await import("../../core/android.js");
|
|
212
|
+
await androidLaunchApp(ANDROID_SETTINGS_PACKAGE);
|
|
213
|
+
await sleep(2000);
|
|
214
|
+
const result = await tap({ text: "Network", strategy: "ocr", native: true });
|
|
215
|
+
expect(result.success).toBe(true);
|
|
216
|
+
expect(result.method).toBe("ocr");
|
|
217
|
+
}, 30000);
|
|
218
|
+
it("find and tap via Android accessibility tree", async () => {
|
|
219
|
+
if (platform !== "android")
|
|
220
|
+
return;
|
|
221
|
+
const { androidLaunchApp, androidFindElement } = await import("../../core/android.js");
|
|
222
|
+
await androidLaunchApp(ANDROID_SETTINGS_PACKAGE);
|
|
223
|
+
await sleep(2000);
|
|
224
|
+
const findResult = await androidFindElement({ textContains: "Network" });
|
|
225
|
+
expect(findResult.success).toBe(true);
|
|
226
|
+
expect(findResult.found).toBe(true);
|
|
227
|
+
expect(findResult.element).toBeDefined();
|
|
228
|
+
const { x, y } = findResult.element.center;
|
|
229
|
+
const tapResult = await tap({ x, y, native: true });
|
|
230
|
+
expect(tapResult.success).toBe(true);
|
|
231
|
+
}, 30000);
|
|
232
|
+
it("tap by coordinates on native app", async () => {
|
|
233
|
+
if (platform === "ios") {
|
|
234
|
+
const { iosLaunchApp } = await import("../../core/ios.js");
|
|
235
|
+
await iosLaunchApp(IOS_SETTINGS_BUNDLE);
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
const { androidLaunchApp } = await import("../../core/android.js");
|
|
239
|
+
await androidLaunchApp(ANDROID_SETTINGS_PACKAGE);
|
|
240
|
+
}
|
|
241
|
+
await sleep(2000);
|
|
242
|
+
const targetText = platform === "ios" ? "General" : "Network";
|
|
243
|
+
const ocrResult = await tap({ text: targetText, strategy: "ocr", native: true });
|
|
244
|
+
expect(ocrResult.success).toBe(true);
|
|
245
|
+
expect(ocrResult.tappedAt).toBeDefined();
|
|
246
|
+
}, 30000);
|
|
247
|
+
it("tap without Metro connection (native only)", async () => {
|
|
248
|
+
await disconnectAll();
|
|
249
|
+
await sleep(1000);
|
|
250
|
+
if (platform === "ios") {
|
|
251
|
+
const { iosLaunchApp } = await import("../../core/ios.js");
|
|
252
|
+
await iosLaunchApp(IOS_SETTINGS_BUNDLE);
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
const { androidLaunchApp } = await import("../../core/android.js");
|
|
256
|
+
await androidLaunchApp(ANDROID_SETTINGS_PACKAGE);
|
|
257
|
+
}
|
|
258
|
+
await sleep(2000);
|
|
259
|
+
const result = await tap({ x: 200, y: 400, native: true, platform });
|
|
260
|
+
expect(result.success).toBe(true);
|
|
261
|
+
// Reconnect for any subsequent test runs
|
|
262
|
+
await connectToMetro();
|
|
263
|
+
}, 30000);
|
|
264
|
+
});
|
|
265
|
+
//# sourceMappingURL=tap-strategies.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tap-strategies.test.js","sourceRoot":"","sources":["../../../src/__tests__/integration/tap-strategies.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"burst.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/burst.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { describe, it, expect } from "@jest/globals";
|
|
2
|
+
import sharp from "sharp";
|
|
3
|
+
import { analyzeBurstFrames } from "../../pro/tap.js";
|
|
4
|
+
async function solidImage(r, g, b, size = 100) {
|
|
5
|
+
return sharp({
|
|
6
|
+
create: { width: size, height: size, channels: 3, background: { r, g, b } },
|
|
7
|
+
}).png().toBuffer();
|
|
8
|
+
}
|
|
9
|
+
describe("analyzeBurstFrames", () => {
|
|
10
|
+
it("detects no change when all frames are identical", async () => {
|
|
11
|
+
const frame = await solidImage(200, 200, 200);
|
|
12
|
+
const result = await analyzeBurstFrames([frame, frame, frame, frame, frame]);
|
|
13
|
+
expect(result.transientChangeDetected).toBe(false);
|
|
14
|
+
expect(result.peakChangeRate).toBeLessThan(0.005);
|
|
15
|
+
expect(result.persistentChangeRate).toBeLessThan(0.005);
|
|
16
|
+
expect(result.meaningful).toBe(false);
|
|
17
|
+
});
|
|
18
|
+
it("detects persistent change (last frame differs from first)", async () => {
|
|
19
|
+
const before = await solidImage(200, 200, 200);
|
|
20
|
+
const after = await solidImage(255, 0, 0);
|
|
21
|
+
const result = await analyzeBurstFrames([before, before, before, after, after]);
|
|
22
|
+
expect(result.meaningful).toBe(true);
|
|
23
|
+
expect(result.persistentChangeRate).toBeGreaterThan(0.005);
|
|
24
|
+
});
|
|
25
|
+
it("detects transient change (middle frame differs, last matches first)", async () => {
|
|
26
|
+
const normal = await solidImage(200, 200, 200);
|
|
27
|
+
const highlight = await solidImage(255, 0, 0);
|
|
28
|
+
const result = await analyzeBurstFrames([normal, highlight, normal, normal, normal]);
|
|
29
|
+
expect(result.transientChangeDetected).toBe(true);
|
|
30
|
+
expect(result.meaningful).toBe(true);
|
|
31
|
+
expect(result.peakFrame).toBe(1);
|
|
32
|
+
expect(result.peakChangeRate).toBeGreaterThan(0.5);
|
|
33
|
+
expect(result.persistentChangeRate).toBeLessThan(0.005);
|
|
34
|
+
});
|
|
35
|
+
it("handles 2 frames (minimum)", async () => {
|
|
36
|
+
const a = await solidImage(200, 200, 200);
|
|
37
|
+
const b = await solidImage(255, 0, 0);
|
|
38
|
+
const result = await analyzeBurstFrames([a, b]);
|
|
39
|
+
expect(result.meaningful).toBe(true);
|
|
40
|
+
expect(result.persistentChangeRate).toBeGreaterThan(0.5);
|
|
41
|
+
});
|
|
42
|
+
it("returns correct framesWithChange indices", async () => {
|
|
43
|
+
const normal = await solidImage(200, 200, 200);
|
|
44
|
+
const highlight = await solidImage(255, 0, 0);
|
|
45
|
+
const result = await analyzeBurstFrames([normal, highlight, highlight, normal, normal]);
|
|
46
|
+
expect(result.framesWithChange).toContain(1);
|
|
47
|
+
expect(result.framesWithChange).toContain(3);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
//# sourceMappingURL=burst.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"burst.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/burst.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"imageBuffer.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/imageBuffer.test.ts"],"names":[],"mappings":""}
|