react-native-ai-debugger 1.0.40 → 1.0.42
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/README.md +3 -9
- package/build/__tests__/helpers/fake-cdp-server.d.ts +56 -0
- package/build/__tests__/helpers/fake-cdp-server.d.ts.map +1 -0
- package/build/__tests__/helpers/fake-cdp-server.js +108 -0
- package/build/__tests__/helpers/fake-cdp-server.js.map +1 -0
- package/build/__tests__/integration/connection-health.test.d.ts +2 -0
- package/build/__tests__/integration/connection-health.test.d.ts.map +1 -0
- package/build/__tests__/integration/connection-health.test.js +151 -0
- package/build/__tests__/integration/connection-health.test.js.map +1 -0
- package/build/__tests__/integration/execute-in-app.test.d.ts +2 -0
- package/build/__tests__/integration/execute-in-app.test.d.ts.map +1 -0
- package/build/__tests__/integration/execute-in-app.test.js +115 -0
- package/build/__tests__/integration/execute-in-app.test.js.map +1 -0
- package/build/__tests__/integration/tools.test.d.ts +2 -0
- package/build/__tests__/integration/tools.test.d.ts.map +1 -0
- package/build/__tests__/integration/tools.test.js +228 -0
- package/build/__tests__/integration/tools.test.js.map +1 -0
- package/build/__tests__/unit/bundle.test.d.ts +2 -0
- package/build/__tests__/unit/bundle.test.d.ts.map +1 -0
- package/build/__tests__/unit/bundle.test.js +53 -0
- package/build/__tests__/unit/bundle.test.js.map +1 -0
- package/build/__tests__/unit/connection-health.test.d.ts +2 -0
- package/build/__tests__/unit/connection-health.test.d.ts.map +1 -0
- package/build/__tests__/unit/connection-health.test.js +28 -0
- package/build/__tests__/unit/connection-health.test.js.map +1 -0
- package/build/__tests__/unit/executor.test.d.ts +2 -0
- package/build/__tests__/unit/executor.test.d.ts.map +1 -0
- package/build/__tests__/unit/executor.test.js +79 -0
- package/build/__tests__/unit/executor.test.js.map +1 -0
- package/build/__tests__/unit/logs.test.d.ts +2 -0
- package/build/__tests__/unit/logs.test.d.ts.map +1 -0
- package/build/__tests__/unit/logs.test.js +81 -0
- package/build/__tests__/unit/logs.test.js.map +1 -0
- package/build/__tests__/unit/metro.test.d.ts +2 -0
- package/build/__tests__/unit/metro.test.d.ts.map +1 -0
- package/build/__tests__/unit/metro.test.js +61 -0
- package/build/__tests__/unit/metro.test.js.map +1 -0
- package/build/__tests__/unit/network.test.d.ts +2 -0
- package/build/__tests__/unit/network.test.d.ts.map +1 -0
- package/build/__tests__/unit/network.test.js +102 -0
- package/build/__tests__/unit/network.test.js.map +1 -0
- package/build/core/connection.d.ts +8 -1
- package/build/core/connection.d.ts.map +1 -1
- package/build/core/connection.js +56 -1
- package/build/core/connection.js.map +1 -1
- package/build/core/executor.d.ts +20 -0
- package/build/core/executor.d.ts.map +1 -1
- package/build/core/executor.js +3 -3
- package/build/core/executor.js.map +1 -1
- package/build/core/index.d.ts +3 -2
- package/build/core/index.d.ts.map +1 -1
- package/build/core/index.js +2 -2
- package/build/core/index.js.map +1 -1
- package/build/core/ocr.d.ts +1 -1
- package/build/core/ocr.d.ts.map +1 -1
- package/build/core/ocr.js +52 -10
- package/build/core/ocr.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 +8 -0
- package/build/core/state.js.map +1 -1
- package/build/core/types.d.ts +5 -0
- package/build/core/types.d.ts.map +1 -1
- package/build/index.js +91 -19
- package/build/index.js.map +1 -1
- package/package.json +8 -2
package/README.md
CHANGED
|
@@ -1093,17 +1093,11 @@ ios_tap with x=187 y=420
|
|
|
1093
1093
|
|
|
1094
1094
|
The tool uses EasyOCR (Python-based) for text recognition. It provides excellent accuracy on colored backgrounds and stylized text common in mobile UIs.
|
|
1095
1095
|
|
|
1096
|
-
###
|
|
1096
|
+
### EasyOCR Setup
|
|
1097
1097
|
|
|
1098
|
-
|
|
1099
|
-
# Install Python 3.10+ if not already installed
|
|
1100
|
-
brew install python@3.11
|
|
1101
|
-
|
|
1102
|
-
# Install EasyOCR
|
|
1103
|
-
pip3 install easyocr
|
|
1104
|
-
```
|
|
1098
|
+
EasyOCR and its Python dependencies are installed automatically by the `node-easyocr` package. You just need Python 3.6+ available on your system (e.g. `brew install python@3.11`).
|
|
1105
1099
|
|
|
1106
|
-
|
|
1100
|
+
The first OCR call will download language models (~100MB for English). Additional language models are downloaded automatically when configured.
|
|
1107
1101
|
|
|
1108
1102
|
### OCR Language Configuration
|
|
1109
1103
|
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
interface CDPResponse {
|
|
2
|
+
result?: {
|
|
3
|
+
result?: {
|
|
4
|
+
type: string;
|
|
5
|
+
value?: unknown;
|
|
6
|
+
subtype?: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
};
|
|
9
|
+
exceptionDetails?: {
|
|
10
|
+
exceptionId: number;
|
|
11
|
+
text: string;
|
|
12
|
+
lineNumber: number;
|
|
13
|
+
columnNumber: number;
|
|
14
|
+
exception?: {
|
|
15
|
+
type: string;
|
|
16
|
+
subtype?: string;
|
|
17
|
+
className?: string;
|
|
18
|
+
description?: string;
|
|
19
|
+
value?: unknown;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
error?: {
|
|
24
|
+
message: string;
|
|
25
|
+
code?: number;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
type ResponseHandler = (params: Record<string, unknown>) => CDPResponse | null;
|
|
29
|
+
export declare class FakeCDPServer {
|
|
30
|
+
private server;
|
|
31
|
+
private connections;
|
|
32
|
+
private evaluateHandler;
|
|
33
|
+
private _receivedMessages;
|
|
34
|
+
port: number;
|
|
35
|
+
start(): Promise<number>;
|
|
36
|
+
private handleMessage;
|
|
37
|
+
/** Set a handler for Runtime.evaluate — receives params, returns CDP response shape */
|
|
38
|
+
onEvaluate(handler: ResponseHandler): void;
|
|
39
|
+
/** Convenience: respond with a successful value */
|
|
40
|
+
respondWithValue(value: unknown, type?: string): void;
|
|
41
|
+
/** Convenience: respond with a JS exception */
|
|
42
|
+
respondWithError(errorType: string, message: string): void;
|
|
43
|
+
/** Convenience: don't respond (causes timeout) */
|
|
44
|
+
respondWithTimeout(): void;
|
|
45
|
+
/** Get all received messages */
|
|
46
|
+
get receivedMessages(): {
|
|
47
|
+
id: number;
|
|
48
|
+
method: string;
|
|
49
|
+
params: Record<string, unknown>;
|
|
50
|
+
}[];
|
|
51
|
+
/** Get the WebSocket URL for connecting as a device */
|
|
52
|
+
get wsUrl(): string;
|
|
53
|
+
stop(): Promise<void>;
|
|
54
|
+
}
|
|
55
|
+
export {};
|
|
56
|
+
//# sourceMappingURL=fake-cdp-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fake-cdp-server.d.ts","sourceRoot":"","sources":["../../../src/__tests__/helpers/fake-cdp-server.ts"],"names":[],"mappings":"AAEA,UAAU,WAAW;IACjB,MAAM,CAAC,EAAE;QACL,MAAM,CAAC,EAAE;YACL,IAAI,EAAE,MAAM,CAAC;YACb,KAAK,CAAC,EAAE,OAAO,CAAC;YAChB,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,WAAW,CAAC,EAAE,MAAM,CAAC;SACxB,CAAC;QACF,gBAAgB,CAAC,EAAE;YACf,WAAW,EAAE,MAAM,CAAC;YACpB,IAAI,EAAE,MAAM,CAAC;YACb,UAAU,EAAE,MAAM,CAAC;YACnB,YAAY,EAAE,MAAM,CAAC;YACrB,SAAS,CAAC,EAAE;gBACR,IAAI,EAAE,MAAM,CAAC;gBACb,OAAO,CAAC,EAAE,MAAM,CAAC;gBACjB,SAAS,CAAC,EAAE,MAAM,CAAC;gBACnB,WAAW,CAAC,EAAE,MAAM,CAAC;gBACrB,KAAK,CAAC,EAAE,OAAO,CAAC;aACnB,CAAC;SACL,CAAC;KACL,CAAC;IACF,KAAK,CAAC,EAAE;QACJ,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACL;AAED,KAAK,eAAe,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,WAAW,GAAG,IAAI,CAAC;AAE/E,qBAAa,aAAa;IACtB,OAAO,CAAC,MAAM,CAAgC;IAC9C,OAAO,CAAC,WAAW,CAAmB;IACtC,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,iBAAiB,CAA8E;IACvG,IAAI,SAAK;IAEH,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAqB9B,OAAO,CAAC,aAAa;IA0BrB,uFAAuF;IACvF,UAAU,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI;IAI1C,mDAAmD;IACnD,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,SAAW,GAAG,IAAI;IAMvD,+CAA+C;IAC/C,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAmB1D,kDAAkD;IAClD,kBAAkB,IAAI,IAAI;IAK1B,gCAAgC;IAChC,IAAI,gBAAgB;YAzFmB,MAAM;gBAAU,MAAM;gBAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;QA2F7F;IAED,uDAAuD;IACvD,IAAI,KAAK,IAAI,MAAM,CAElB;IAEK,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAY9B"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { WebSocketServer } from "ws";
|
|
2
|
+
export class FakeCDPServer {
|
|
3
|
+
server = null;
|
|
4
|
+
connections = [];
|
|
5
|
+
evaluateHandler = null;
|
|
6
|
+
_receivedMessages = [];
|
|
7
|
+
port = 0;
|
|
8
|
+
async start() {
|
|
9
|
+
return new Promise((resolve) => {
|
|
10
|
+
this.server = new WebSocketServer({ port: 0 }, () => {
|
|
11
|
+
this.port = this.server.address().port;
|
|
12
|
+
resolve(this.port);
|
|
13
|
+
});
|
|
14
|
+
this.server.on("connection", (ws) => {
|
|
15
|
+
this.connections.push(ws);
|
|
16
|
+
ws.on("message", (data) => {
|
|
17
|
+
const msg = JSON.parse(data.toString());
|
|
18
|
+
this._receivedMessages.push(msg);
|
|
19
|
+
this.handleMessage(ws, msg);
|
|
20
|
+
});
|
|
21
|
+
ws.on("close", () => {
|
|
22
|
+
this.connections = this.connections.filter((c) => c !== ws);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
handleMessage(ws, msg) {
|
|
28
|
+
// Auto-respond to domain enable messages
|
|
29
|
+
if (msg.method === "Runtime.enable" || msg.method === "Log.enable" || msg.method === "Network.enable") {
|
|
30
|
+
ws.send(JSON.stringify({ id: msg.id, result: {} }));
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
// Handle Runtime.evaluate with custom handler
|
|
34
|
+
if (msg.method === "Runtime.evaluate") {
|
|
35
|
+
if (this.evaluateHandler) {
|
|
36
|
+
const response = this.evaluateHandler(msg.params || {});
|
|
37
|
+
// If handler returns null, don't send a response (simulates timeout)
|
|
38
|
+
if (response !== null) {
|
|
39
|
+
ws.send(JSON.stringify({ id: msg.id, ...response }));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
// Default: return undefined
|
|
44
|
+
ws.send(JSON.stringify({
|
|
45
|
+
id: msg.id,
|
|
46
|
+
result: { result: { type: "undefined" } },
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/** Set a handler for Runtime.evaluate — receives params, returns CDP response shape */
|
|
53
|
+
onEvaluate(handler) {
|
|
54
|
+
this.evaluateHandler = handler;
|
|
55
|
+
}
|
|
56
|
+
/** Convenience: respond with a successful value */
|
|
57
|
+
respondWithValue(value, type = "object") {
|
|
58
|
+
this.onEvaluate(() => ({
|
|
59
|
+
result: { result: { type, value } },
|
|
60
|
+
}));
|
|
61
|
+
}
|
|
62
|
+
/** Convenience: respond with a JS exception */
|
|
63
|
+
respondWithError(errorType, message) {
|
|
64
|
+
this.onEvaluate(() => ({
|
|
65
|
+
result: {
|
|
66
|
+
exceptionDetails: {
|
|
67
|
+
exceptionId: 1,
|
|
68
|
+
text: "Uncaught",
|
|
69
|
+
lineNumber: 0,
|
|
70
|
+
columnNumber: 0,
|
|
71
|
+
exception: {
|
|
72
|
+
type: "object",
|
|
73
|
+
subtype: "error",
|
|
74
|
+
className: errorType,
|
|
75
|
+
description: `${errorType}: ${message}`,
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
/** Convenience: don't respond (causes timeout) */
|
|
82
|
+
respondWithTimeout() {
|
|
83
|
+
// Set a handler that returns null — handleMessage skips sending
|
|
84
|
+
this.onEvaluate(() => null);
|
|
85
|
+
}
|
|
86
|
+
/** Get all received messages */
|
|
87
|
+
get receivedMessages() {
|
|
88
|
+
return this._receivedMessages;
|
|
89
|
+
}
|
|
90
|
+
/** Get the WebSocket URL for connecting as a device */
|
|
91
|
+
get wsUrl() {
|
|
92
|
+
return `ws://localhost:${this.port}`;
|
|
93
|
+
}
|
|
94
|
+
async stop() {
|
|
95
|
+
for (const ws of this.connections) {
|
|
96
|
+
ws.close();
|
|
97
|
+
}
|
|
98
|
+
return new Promise((resolve) => {
|
|
99
|
+
if (this.server) {
|
|
100
|
+
this.server.close(() => resolve());
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
resolve();
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=fake-cdp-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fake-cdp-server.js","sourceRoot":"","sources":["../../../src/__tests__/helpers/fake-cdp-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection-health.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/integration/connection-health.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { jest, describe, it, expect, beforeAll, afterAll, beforeEach, afterEach } from "@jest/globals";
|
|
2
|
+
import { connectToDevice } from "../../core/connection.js";
|
|
3
|
+
import { checkAndEnsureConnection, getPassiveConnectionStatus } from "../../core/connection.js";
|
|
4
|
+
import { connectedApps, pendingExecutions, updateLastCDPMessageTime } from "../../core/state.js";
|
|
5
|
+
import { FakeCDPServer } from "../helpers/fake-cdp-server.js";
|
|
6
|
+
describe("Connection health (integration)", () => {
|
|
7
|
+
let server;
|
|
8
|
+
beforeAll(() => {
|
|
9
|
+
jest.spyOn(console, "error").mockImplementation(() => { });
|
|
10
|
+
});
|
|
11
|
+
afterAll(() => {
|
|
12
|
+
jest.restoreAllMocks();
|
|
13
|
+
});
|
|
14
|
+
beforeEach(async () => {
|
|
15
|
+
for (const [key, app] of connectedApps.entries()) {
|
|
16
|
+
try {
|
|
17
|
+
app.ws.close();
|
|
18
|
+
}
|
|
19
|
+
catch { /* ignore */ }
|
|
20
|
+
connectedApps.delete(key);
|
|
21
|
+
}
|
|
22
|
+
pendingExecutions.clear();
|
|
23
|
+
updateLastCDPMessageTime(null);
|
|
24
|
+
});
|
|
25
|
+
afterEach(async () => {
|
|
26
|
+
const closePromises = [];
|
|
27
|
+
for (const [key, app] of connectedApps.entries()) {
|
|
28
|
+
closePromises.push(new Promise((resolve) => {
|
|
29
|
+
if (app.ws.readyState === app.ws.CLOSED) {
|
|
30
|
+
resolve();
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
app.ws.on("close", () => resolve());
|
|
34
|
+
try {
|
|
35
|
+
app.ws.close();
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
resolve();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}));
|
|
42
|
+
connectedApps.delete(key);
|
|
43
|
+
}
|
|
44
|
+
await Promise.all(closePromises);
|
|
45
|
+
pendingExecutions.clear();
|
|
46
|
+
if (server)
|
|
47
|
+
await server.stop();
|
|
48
|
+
});
|
|
49
|
+
describe("getPassiveConnectionStatus", () => {
|
|
50
|
+
it("returns no_connection when disconnected", () => {
|
|
51
|
+
const status = getPassiveConnectionStatus();
|
|
52
|
+
expect(status.connected).toBe(false);
|
|
53
|
+
expect(status.reason).toBe("no_connection");
|
|
54
|
+
});
|
|
55
|
+
it("returns ok when connected with recent activity", async () => {
|
|
56
|
+
server = new FakeCDPServer();
|
|
57
|
+
const port = await server.start();
|
|
58
|
+
const device = {
|
|
59
|
+
id: "test-device",
|
|
60
|
+
title: "Hermes React Native",
|
|
61
|
+
description: "Test",
|
|
62
|
+
appId: "com.test",
|
|
63
|
+
type: "node",
|
|
64
|
+
webSocketDebuggerUrl: `${server.wsUrl}/inspector/device?page=1`,
|
|
65
|
+
deviceName: "Test",
|
|
66
|
+
};
|
|
67
|
+
await connectToDevice(device, port, {
|
|
68
|
+
reconnectionConfig: { enabled: false, maxAttempts: 0, initialDelayMs: 0, maxDelayMs: 0, backoffMultiplier: 1 },
|
|
69
|
+
});
|
|
70
|
+
// Simulate recent CDP activity
|
|
71
|
+
updateLastCDPMessageTime(new Date());
|
|
72
|
+
const status = getPassiveConnectionStatus();
|
|
73
|
+
expect(status.connected).toBe(true);
|
|
74
|
+
expect(status.reason).toBe("ok");
|
|
75
|
+
});
|
|
76
|
+
it("returns activity_stale when no recent messages", async () => {
|
|
77
|
+
server = new FakeCDPServer();
|
|
78
|
+
const port = await server.start();
|
|
79
|
+
const device = {
|
|
80
|
+
id: "test-device",
|
|
81
|
+
title: "Hermes React Native",
|
|
82
|
+
description: "Test",
|
|
83
|
+
appId: "com.test",
|
|
84
|
+
type: "node",
|
|
85
|
+
webSocketDebuggerUrl: `${server.wsUrl}/inspector/device?page=1`,
|
|
86
|
+
deviceName: "Test",
|
|
87
|
+
};
|
|
88
|
+
await connectToDevice(device, port, {
|
|
89
|
+
reconnectionConfig: { enabled: false, maxAttempts: 0, initialDelayMs: 0, maxDelayMs: 0, backoffMultiplier: 1 },
|
|
90
|
+
});
|
|
91
|
+
// Set last activity to 60 seconds ago
|
|
92
|
+
updateLastCDPMessageTime(new Date(Date.now() - 60_000));
|
|
93
|
+
const status = getPassiveConnectionStatus();
|
|
94
|
+
expect(status.connected).toBe(true);
|
|
95
|
+
expect(status.needsPing).toBe(true);
|
|
96
|
+
expect(status.reason).toBe("activity_stale");
|
|
97
|
+
});
|
|
98
|
+
it("returns no_activity when connected but no CDP messages ever received", async () => {
|
|
99
|
+
server = new FakeCDPServer();
|
|
100
|
+
const port = await server.start();
|
|
101
|
+
const device = {
|
|
102
|
+
id: "test-device",
|
|
103
|
+
title: "Hermes React Native",
|
|
104
|
+
description: "Test",
|
|
105
|
+
appId: "com.test",
|
|
106
|
+
type: "node",
|
|
107
|
+
webSocketDebuggerUrl: `${server.wsUrl}/inspector/device?page=1`,
|
|
108
|
+
deviceName: "Test",
|
|
109
|
+
};
|
|
110
|
+
await connectToDevice(device, port, {
|
|
111
|
+
reconnectionConfig: { enabled: false, maxAttempts: 0, initialDelayMs: 0, maxDelayMs: 0, backoffMultiplier: 1 },
|
|
112
|
+
});
|
|
113
|
+
// Note: handleCDPMessage will fire for enable responses, which updates timestamp
|
|
114
|
+
// Reset it to null to simulate the "never received" case
|
|
115
|
+
updateLastCDPMessageTime(null);
|
|
116
|
+
const status = getPassiveConnectionStatus();
|
|
117
|
+
expect(status.connected).toBe(false);
|
|
118
|
+
expect(status.reason).toBe("no_activity");
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
describe("checkAndEnsureConnection", () => {
|
|
122
|
+
it("returns failure when no Metro server is available", async () => {
|
|
123
|
+
const result = await checkAndEnsureConnection();
|
|
124
|
+
expect(result.connected).toBe(false);
|
|
125
|
+
expect(result.wasReconnected).toBe(false);
|
|
126
|
+
expect(result.message).toContain("No active connection");
|
|
127
|
+
});
|
|
128
|
+
it("returns success with no message when connection is healthy", async () => {
|
|
129
|
+
server = new FakeCDPServer();
|
|
130
|
+
const port = await server.start();
|
|
131
|
+
const device = {
|
|
132
|
+
id: "test-device",
|
|
133
|
+
title: "Hermes React Native",
|
|
134
|
+
description: "Test",
|
|
135
|
+
appId: "com.test",
|
|
136
|
+
type: "node",
|
|
137
|
+
webSocketDebuggerUrl: `${server.wsUrl}/inspector/device?page=1`,
|
|
138
|
+
deviceName: "Test",
|
|
139
|
+
};
|
|
140
|
+
await connectToDevice(device, port, {
|
|
141
|
+
reconnectionConfig: { enabled: false, maxAttempts: 0, initialDelayMs: 0, maxDelayMs: 0, backoffMultiplier: 1 },
|
|
142
|
+
});
|
|
143
|
+
updateLastCDPMessageTime(new Date());
|
|
144
|
+
const result = await checkAndEnsureConnection();
|
|
145
|
+
expect(result.connected).toBe(true);
|
|
146
|
+
expect(result.wasReconnected).toBe(false);
|
|
147
|
+
expect(result.message).toBeNull();
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
//# sourceMappingURL=connection-health.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection-health.test.js","sourceRoot":"","sources":["../../../src/__tests__/integration/connection-health.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execute-in-app.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/integration/execute-in-app.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { jest, describe, it, expect, beforeAll, afterAll, beforeEach, afterEach } from "@jest/globals";
|
|
2
|
+
import { connectToDevice } from "../../core/connection.js";
|
|
3
|
+
import { executeInApp } from "../../core/executor.js";
|
|
4
|
+
import { connectedApps, pendingExecutions } from "../../core/state.js";
|
|
5
|
+
import { FakeCDPServer } from "../helpers/fake-cdp-server.js";
|
|
6
|
+
describe("executeInApp (integration)", () => {
|
|
7
|
+
let server;
|
|
8
|
+
let device;
|
|
9
|
+
beforeAll(() => {
|
|
10
|
+
jest.spyOn(console, "error").mockImplementation(() => { });
|
|
11
|
+
});
|
|
12
|
+
afterAll(() => {
|
|
13
|
+
jest.restoreAllMocks();
|
|
14
|
+
});
|
|
15
|
+
beforeEach(async () => {
|
|
16
|
+
// Clean up any existing state
|
|
17
|
+
for (const [key, app] of connectedApps.entries()) {
|
|
18
|
+
try {
|
|
19
|
+
app.ws.close();
|
|
20
|
+
}
|
|
21
|
+
catch { /* ignore */ }
|
|
22
|
+
connectedApps.delete(key);
|
|
23
|
+
}
|
|
24
|
+
pendingExecutions.clear();
|
|
25
|
+
// Start fake CDP server
|
|
26
|
+
server = new FakeCDPServer();
|
|
27
|
+
const port = await server.start();
|
|
28
|
+
// Create device info pointing to fake server
|
|
29
|
+
device = {
|
|
30
|
+
id: "test-device",
|
|
31
|
+
title: "Hermes React Native",
|
|
32
|
+
description: "Test Device",
|
|
33
|
+
appId: "com.test.app",
|
|
34
|
+
type: "node",
|
|
35
|
+
webSocketDebuggerUrl: `${server.wsUrl}/inspector/device?page=1`,
|
|
36
|
+
deviceName: "Test",
|
|
37
|
+
};
|
|
38
|
+
// Connect to the fake server with reconnection disabled
|
|
39
|
+
// to avoid background reconnection attempts during cleanup
|
|
40
|
+
await connectToDevice(device, port, {
|
|
41
|
+
reconnectionConfig: { enabled: false, maxAttempts: 0, initialDelayMs: 0, maxDelayMs: 0, backoffMultiplier: 1 },
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
afterEach(async () => {
|
|
45
|
+
// Close all connected WebSockets and wait for them to fully close
|
|
46
|
+
const closePromises = [];
|
|
47
|
+
for (const [key, app] of connectedApps.entries()) {
|
|
48
|
+
closePromises.push(new Promise((resolve) => {
|
|
49
|
+
if (app.ws.readyState === app.ws.CLOSED) {
|
|
50
|
+
resolve();
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
app.ws.on("close", () => resolve());
|
|
54
|
+
try {
|
|
55
|
+
app.ws.close();
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
resolve();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}));
|
|
62
|
+
connectedApps.delete(key);
|
|
63
|
+
}
|
|
64
|
+
await Promise.all(closePromises);
|
|
65
|
+
pendingExecutions.clear();
|
|
66
|
+
await server.stop();
|
|
67
|
+
});
|
|
68
|
+
it("returns value for simple expression", async () => {
|
|
69
|
+
server.respondWithValue(42, "number");
|
|
70
|
+
const result = await executeInApp("21 + 21", false, { timeoutMs: 5000 });
|
|
71
|
+
expect(result.success).toBe(true);
|
|
72
|
+
expect(result.result).toBe("42");
|
|
73
|
+
});
|
|
74
|
+
it("returns string value", async () => {
|
|
75
|
+
server.respondWithValue("hello", "string");
|
|
76
|
+
const result = await executeInApp("'hello'", false, { timeoutMs: 5000 });
|
|
77
|
+
expect(result.success).toBe(true);
|
|
78
|
+
expect(result.result).toBe("hello");
|
|
79
|
+
});
|
|
80
|
+
it("returns object value as JSON", async () => {
|
|
81
|
+
server.respondWithValue({ key: "value" }, "object");
|
|
82
|
+
const result = await executeInApp("({key: 'value'})", false, { timeoutMs: 5000 });
|
|
83
|
+
expect(result.success).toBe(true);
|
|
84
|
+
const parsed = JSON.parse(result.result);
|
|
85
|
+
expect(parsed.key).toBe("value");
|
|
86
|
+
});
|
|
87
|
+
it("returns error for JS exception", async () => {
|
|
88
|
+
server.respondWithError("ReferenceError", "x is not defined");
|
|
89
|
+
const result = await executeInApp("x", false, { timeoutMs: 5000 });
|
|
90
|
+
expect(result.success).toBe(false);
|
|
91
|
+
expect(result.error).toContain("ReferenceError");
|
|
92
|
+
});
|
|
93
|
+
it("sends expression with global polyfill prepended", async () => {
|
|
94
|
+
server.respondWithValue(true, "boolean");
|
|
95
|
+
await executeInApp("__DEV__", false, { timeoutMs: 5000 });
|
|
96
|
+
const evalMsg = server.receivedMessages.find((m) => m.method === "Runtime.evaluate");
|
|
97
|
+
expect(evalMsg).toBeDefined();
|
|
98
|
+
const expr = evalMsg.params.expression;
|
|
99
|
+
expect(expr).toContain("var global");
|
|
100
|
+
expect(expr).toContain("__DEV__");
|
|
101
|
+
});
|
|
102
|
+
it("rejects emoji in expression", async () => {
|
|
103
|
+
const result = await executeInApp("'\ud83d\ude00'", false, { timeoutMs: 5000 });
|
|
104
|
+
expect(result.success).toBe(false);
|
|
105
|
+
expect(result.error).toContain("emoji");
|
|
106
|
+
});
|
|
107
|
+
it("handles timeout gracefully", async () => {
|
|
108
|
+
// Don't respond — causes timeout
|
|
109
|
+
server.respondWithTimeout();
|
|
110
|
+
const result = await executeInApp("slow()", false, { timeoutMs: 500, maxRetries: 0 });
|
|
111
|
+
expect(result.success).toBe(false);
|
|
112
|
+
expect(result.error).toContain("Timeout");
|
|
113
|
+
}, 10000);
|
|
114
|
+
});
|
|
115
|
+
//# sourceMappingURL=execute-in-app.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execute-in-app.test.js","sourceRoot":"","sources":["../../../src/__tests__/integration/execute-in-app.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/integration/tools.test.ts"],"names":[],"mappings":""}
|