react-native-ai-devtools 1.1.4 → 1.1.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/package.json +1 -1
- package/build/core/networkInterceptor.d.ts +0 -3
- package/build/core/networkInterceptor.d.ts.map +0 -1
- package/build/core/networkInterceptor.js +0 -203
- package/build/core/networkInterceptor.js.map +0 -1
- package/build/core/tap.d.ts +0 -91
- package/build/core/tap.d.ts.map +0 -1
- package/build/core/tap.js +0 -542
- package/build/core/tap.js.map +0 -1
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"networkInterceptor.d.ts","sourceRoot":"","sources":["../../src/core/networkInterceptor.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,wBAAwB,eAAe,CAAC;AAErD,wBAAgB,2BAA2B,IAAI,MAAM,CAoMpD"}
|
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
// JS-level network interception snippet injected into the React Native app.
|
|
2
|
-
// Hermes doesn't support CDP Network domain, so we monkey-patch fetch and XMLHttpRequest
|
|
3
|
-
// and report events via console.debug with a special prefix that gets intercepted
|
|
4
|
-
// by handleCDPMessage before reaching the log buffer.
|
|
5
|
-
export const NETWORK_INTERCEPT_PREFIX = "__RN_NET__";
|
|
6
|
-
export function getNetworkInterceptorScript() {
|
|
7
|
-
return `(function() {
|
|
8
|
-
if (globalThis.__RN_NET_INSTALLED__) return 'already_installed';
|
|
9
|
-
globalThis.__RN_NET_INSTALLED__ = true;
|
|
10
|
-
|
|
11
|
-
var counter = 0;
|
|
12
|
-
function nextId() { return 'net_' + (++counter) + '_' + Date.now(); }
|
|
13
|
-
|
|
14
|
-
function report(data) {
|
|
15
|
-
try {
|
|
16
|
-
console.debug('${NETWORK_INTERCEPT_PREFIX}', JSON.stringify(data));
|
|
17
|
-
} catch(e) {}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// --- Patch fetch ---
|
|
21
|
-
var originalFetch = globalThis.fetch;
|
|
22
|
-
if (originalFetch) {
|
|
23
|
-
globalThis.fetch = function(input, init) {
|
|
24
|
-
var reqId = nextId();
|
|
25
|
-
var url = typeof input === 'string' ? input : (input && input.url ? input.url : String(input));
|
|
26
|
-
var method = (init && init.method) ? init.method.toUpperCase() : 'GET';
|
|
27
|
-
var headers = {};
|
|
28
|
-
var postData;
|
|
29
|
-
|
|
30
|
-
try {
|
|
31
|
-
if (init && init.headers) {
|
|
32
|
-
if (typeof init.headers.forEach === 'function') {
|
|
33
|
-
init.headers.forEach(function(v, k) { headers[k] = v; });
|
|
34
|
-
} else if (typeof init.headers === 'object') {
|
|
35
|
-
var h = init.headers;
|
|
36
|
-
for (var k in h) {
|
|
37
|
-
if (Object.prototype.hasOwnProperty.call(h, k)) {
|
|
38
|
-
headers[k] = h[k];
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
if (init && init.body) {
|
|
44
|
-
postData = typeof init.body === 'string' ? init.body : undefined;
|
|
45
|
-
if (!postData) {
|
|
46
|
-
try { postData = JSON.stringify(init.body); } catch(e) {}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
} catch(e) {}
|
|
50
|
-
|
|
51
|
-
var startTime = Date.now();
|
|
52
|
-
report({
|
|
53
|
-
type: 'request',
|
|
54
|
-
requestId: reqId,
|
|
55
|
-
method: method,
|
|
56
|
-
url: url,
|
|
57
|
-
headers: headers,
|
|
58
|
-
postData: postData,
|
|
59
|
-
timestamp: startTime
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
return originalFetch.apply(globalThis, arguments).then(function(response) {
|
|
63
|
-
var respHeaders = {};
|
|
64
|
-
try {
|
|
65
|
-
if (response.headers && typeof response.headers.forEach === 'function') {
|
|
66
|
-
response.headers.forEach(function(v, k) { respHeaders[k] = v; });
|
|
67
|
-
}
|
|
68
|
-
} catch(e) {}
|
|
69
|
-
|
|
70
|
-
report({
|
|
71
|
-
type: 'response',
|
|
72
|
-
requestId: reqId,
|
|
73
|
-
status: response.status,
|
|
74
|
-
statusText: response.statusText,
|
|
75
|
-
headers: respHeaders,
|
|
76
|
-
mimeType: respHeaders['content-type'] || '',
|
|
77
|
-
duration: Date.now() - startTime
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
return response;
|
|
81
|
-
}, function(error) {
|
|
82
|
-
report({
|
|
83
|
-
type: 'error',
|
|
84
|
-
requestId: reqId,
|
|
85
|
-
error: error ? error.message || String(error) : 'Network error',
|
|
86
|
-
duration: Date.now() - startTime
|
|
87
|
-
});
|
|
88
|
-
throw error;
|
|
89
|
-
});
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// --- Patch XMLHttpRequest ---
|
|
94
|
-
var XHR = globalThis.XMLHttpRequest;
|
|
95
|
-
if (XHR) {
|
|
96
|
-
var origOpen = XHR.prototype.open;
|
|
97
|
-
var origSend = XHR.prototype.send;
|
|
98
|
-
var origSetHeader = XHR.prototype.setRequestHeader;
|
|
99
|
-
|
|
100
|
-
XHR.prototype.open = function(method, url) {
|
|
101
|
-
this.__rn_net__ = {
|
|
102
|
-
reqId: nextId(),
|
|
103
|
-
method: (method || 'GET').toUpperCase(),
|
|
104
|
-
url: String(url),
|
|
105
|
-
headers: {},
|
|
106
|
-
startTime: null
|
|
107
|
-
};
|
|
108
|
-
return origOpen.apply(this, arguments);
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
XHR.prototype.setRequestHeader = function(key, value) {
|
|
112
|
-
if (this.__rn_net__) {
|
|
113
|
-
this.__rn_net__.headers[key] = value;
|
|
114
|
-
}
|
|
115
|
-
return origSetHeader.apply(this, arguments);
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
XHR.prototype.send = function(body) {
|
|
119
|
-
var info = this.__rn_net__;
|
|
120
|
-
if (info) {
|
|
121
|
-
info.startTime = Date.now();
|
|
122
|
-
var postData;
|
|
123
|
-
if (body) {
|
|
124
|
-
postData = typeof body === 'string' ? body : undefined;
|
|
125
|
-
if (!postData) {
|
|
126
|
-
try { postData = JSON.stringify(body); } catch(e) {}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
report({
|
|
130
|
-
type: 'request',
|
|
131
|
-
requestId: info.reqId,
|
|
132
|
-
method: info.method,
|
|
133
|
-
url: info.url,
|
|
134
|
-
headers: info.headers,
|
|
135
|
-
postData: postData,
|
|
136
|
-
timestamp: info.startTime
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
var xhr = this;
|
|
140
|
-
var onDone = function() {
|
|
141
|
-
var respHeaders = {};
|
|
142
|
-
try {
|
|
143
|
-
var raw = xhr.getAllResponseHeaders() || '';
|
|
144
|
-
raw.split('\\r\\n').forEach(function(line) {
|
|
145
|
-
var idx = line.indexOf(':');
|
|
146
|
-
if (idx > 0) {
|
|
147
|
-
respHeaders[line.slice(0, idx).trim().toLowerCase()] = line.slice(idx + 1).trim();
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
} catch(e) {}
|
|
151
|
-
|
|
152
|
-
if (xhr.status > 0) {
|
|
153
|
-
report({
|
|
154
|
-
type: 'response',
|
|
155
|
-
requestId: info.reqId,
|
|
156
|
-
status: xhr.status,
|
|
157
|
-
statusText: xhr.statusText,
|
|
158
|
-
headers: respHeaders,
|
|
159
|
-
mimeType: respHeaders['content-type'] || '',
|
|
160
|
-
contentLength: xhr.response ? xhr.response.length : undefined,
|
|
161
|
-
duration: Date.now() - info.startTime
|
|
162
|
-
});
|
|
163
|
-
} else {
|
|
164
|
-
report({
|
|
165
|
-
type: 'error',
|
|
166
|
-
requestId: info.reqId,
|
|
167
|
-
error: 'Request failed (status 0)',
|
|
168
|
-
duration: Date.now() - info.startTime
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
var onError = function() {
|
|
174
|
-
report({
|
|
175
|
-
type: 'error',
|
|
176
|
-
requestId: info.reqId,
|
|
177
|
-
error: 'XHR error',
|
|
178
|
-
duration: Date.now() - info.startTime
|
|
179
|
-
});
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
var onAbort = function() {
|
|
183
|
-
report({
|
|
184
|
-
type: 'error',
|
|
185
|
-
requestId: info.reqId,
|
|
186
|
-
error: 'Canceled',
|
|
187
|
-
canceled: true,
|
|
188
|
-
duration: Date.now() - info.startTime
|
|
189
|
-
});
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
xhr.addEventListener('load', onDone);
|
|
193
|
-
xhr.addEventListener('error', onError);
|
|
194
|
-
xhr.addEventListener('abort', onAbort);
|
|
195
|
-
}
|
|
196
|
-
return origSend.apply(this, arguments);
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
return 'installed';
|
|
201
|
-
})()`;
|
|
202
|
-
}
|
|
203
|
-
//# sourceMappingURL=networkInterceptor.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"networkInterceptor.js","sourceRoot":"","sources":["../../src/core/networkInterceptor.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,yFAAyF;AACzF,kFAAkF;AAClF,sDAAsD;AAEtD,MAAM,CAAC,MAAM,wBAAwB,GAAG,YAAY,CAAC;AAErD,MAAM,UAAU,2BAA2B;IACvC,OAAO;;;;;;;;;6BASkB,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAyLhD,CAAC;AACN,CAAC"}
|
package/build/core/tap.d.ts
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
export type TapStrategy = "auto" | "fiber" | "accessibility" | "ocr" | "coordinate";
|
|
2
|
-
export interface TapQuery {
|
|
3
|
-
text?: string;
|
|
4
|
-
testID?: string;
|
|
5
|
-
component?: string;
|
|
6
|
-
x?: number;
|
|
7
|
-
y?: number;
|
|
8
|
-
}
|
|
9
|
-
export interface TapOptions {
|
|
10
|
-
text?: string;
|
|
11
|
-
testID?: string;
|
|
12
|
-
component?: string;
|
|
13
|
-
index?: number;
|
|
14
|
-
x?: number;
|
|
15
|
-
y?: number;
|
|
16
|
-
strategy?: TapStrategy;
|
|
17
|
-
maxTraversalDepth?: number;
|
|
18
|
-
}
|
|
19
|
-
export interface TapAttempt {
|
|
20
|
-
strategy: string;
|
|
21
|
-
reason: string;
|
|
22
|
-
}
|
|
23
|
-
export interface TapResult {
|
|
24
|
-
success: boolean;
|
|
25
|
-
method?: string;
|
|
26
|
-
query: TapQuery;
|
|
27
|
-
pressed?: string;
|
|
28
|
-
text?: string;
|
|
29
|
-
screen?: string | null;
|
|
30
|
-
path?: string | null;
|
|
31
|
-
component?: string | null;
|
|
32
|
-
tappedAt?: {
|
|
33
|
-
x: number;
|
|
34
|
-
y: number;
|
|
35
|
-
};
|
|
36
|
-
convertedTo?: {
|
|
37
|
-
x: number;
|
|
38
|
-
y: number;
|
|
39
|
-
unit: string;
|
|
40
|
-
};
|
|
41
|
-
platform?: string;
|
|
42
|
-
error?: string;
|
|
43
|
-
attempted?: TapAttempt[];
|
|
44
|
-
matches?: Array<{
|
|
45
|
-
index: number;
|
|
46
|
-
component: string;
|
|
47
|
-
text: string;
|
|
48
|
-
}>;
|
|
49
|
-
suggestion?: string;
|
|
50
|
-
}
|
|
51
|
-
export declare function buildQuery(options: TapOptions): TapQuery;
|
|
52
|
-
export declare function isNonAscii(text: string): boolean;
|
|
53
|
-
export declare function getAvailableStrategies(query: TapQuery, strategy: TapStrategy): string[];
|
|
54
|
-
export declare function convertPixelsToPoints(pixelX: number, pixelY: number, platform: "ios" | "android", devicePixelRatio: number, scaleFactor?: number): {
|
|
55
|
-
x: number;
|
|
56
|
-
y: number;
|
|
57
|
-
};
|
|
58
|
-
export declare function getCurrentScreen(): Promise<string | null>;
|
|
59
|
-
export declare function formatTapSuccess(data: {
|
|
60
|
-
method: string;
|
|
61
|
-
query: TapQuery;
|
|
62
|
-
pressed?: string;
|
|
63
|
-
text?: string;
|
|
64
|
-
screen?: string | null;
|
|
65
|
-
path?: string | null;
|
|
66
|
-
component?: string | null;
|
|
67
|
-
tappedAt?: {
|
|
68
|
-
x: number;
|
|
69
|
-
y: number;
|
|
70
|
-
};
|
|
71
|
-
convertedTo?: {
|
|
72
|
-
x: number;
|
|
73
|
-
y: number;
|
|
74
|
-
unit: string;
|
|
75
|
-
};
|
|
76
|
-
platform?: string;
|
|
77
|
-
}): TapResult;
|
|
78
|
-
export declare function formatTapFailure(data: {
|
|
79
|
-
query: TapQuery;
|
|
80
|
-
screen?: string | null;
|
|
81
|
-
error?: string;
|
|
82
|
-
attempted: TapAttempt[];
|
|
83
|
-
suggestion: string;
|
|
84
|
-
matches?: Array<{
|
|
85
|
-
index: number;
|
|
86
|
-
component: string;
|
|
87
|
-
text: string;
|
|
88
|
-
}>;
|
|
89
|
-
}): TapResult;
|
|
90
|
-
export declare function tap(options: TapOptions): Promise<TapResult>;
|
|
91
|
-
//# sourceMappingURL=tap.d.ts.map
|
package/build/core/tap.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tap.d.ts","sourceRoot":"","sources":["../../src/core/tap.ts"],"names":[],"mappings":"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"}
|
package/build/core/tap.js
DELETED
|
@@ -1,542 +0,0 @@
|
|
|
1
|
-
import { connectedApps } from "./state.js";
|
|
2
|
-
import { inferIOSDevicePixelRatio } from "./ocr.js";
|
|
3
|
-
import { executeInApp } from "./executor.js";
|
|
4
|
-
import { pressElement } from "./executor.js";
|
|
5
|
-
import { iosTap, iosFindElement, iosScreenshot } from "./ios.js";
|
|
6
|
-
import { androidTap, androidFindElement } from "./android.js";
|
|
7
|
-
import { scanMetroPorts, fetchDevices, selectMainDevice } from "./metro.js";
|
|
8
|
-
import { connectToDevice, clearReconnectionSuppression } from "./connection.js";
|
|
9
|
-
// --- Helpers ---
|
|
10
|
-
export function buildQuery(options) {
|
|
11
|
-
const query = {};
|
|
12
|
-
if (options.text !== undefined)
|
|
13
|
-
query.text = options.text;
|
|
14
|
-
if (options.testID !== undefined)
|
|
15
|
-
query.testID = options.testID;
|
|
16
|
-
if (options.component !== undefined)
|
|
17
|
-
query.component = options.component;
|
|
18
|
-
if (options.x !== undefined)
|
|
19
|
-
query.x = options.x;
|
|
20
|
-
if (options.y !== undefined)
|
|
21
|
-
query.y = options.y;
|
|
22
|
-
return query;
|
|
23
|
-
}
|
|
24
|
-
export function isNonAscii(text) {
|
|
25
|
-
return /[^\x00-\x7F]/.test(text);
|
|
26
|
-
}
|
|
27
|
-
export function getAvailableStrategies(query, strategy) {
|
|
28
|
-
if (query.x !== undefined && query.y !== undefined) {
|
|
29
|
-
return ["coordinate"];
|
|
30
|
-
}
|
|
31
|
-
if (strategy !== "auto") {
|
|
32
|
-
return [strategy];
|
|
33
|
-
}
|
|
34
|
-
if (query.component && !query.text && !query.testID) {
|
|
35
|
-
return ["fiber"];
|
|
36
|
-
}
|
|
37
|
-
if (query.testID && !query.text) {
|
|
38
|
-
return ["fiber", "accessibility"];
|
|
39
|
-
}
|
|
40
|
-
if (query.text) {
|
|
41
|
-
const strategies = [];
|
|
42
|
-
if (!isNonAscii(query.text)) {
|
|
43
|
-
strategies.push("fiber");
|
|
44
|
-
}
|
|
45
|
-
strategies.push("accessibility", "ocr");
|
|
46
|
-
return strategies;
|
|
47
|
-
}
|
|
48
|
-
return ["fiber", "accessibility", "ocr"];
|
|
49
|
-
}
|
|
50
|
-
export function convertPixelsToPoints(pixelX, pixelY, platform, devicePixelRatio, scaleFactor = 1) {
|
|
51
|
-
const originalX = pixelX * scaleFactor;
|
|
52
|
-
const originalY = pixelY * scaleFactor;
|
|
53
|
-
if (platform === "android") {
|
|
54
|
-
return { x: Math.round(originalX), y: Math.round(originalY) };
|
|
55
|
-
}
|
|
56
|
-
return {
|
|
57
|
-
x: Math.round(originalX / devicePixelRatio),
|
|
58
|
-
y: Math.round(originalY / devicePixelRatio),
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
export async function getCurrentScreen() {
|
|
62
|
-
try {
|
|
63
|
-
// Note: Uses var instead of let/const because Hermes Runtime.evaluate
|
|
64
|
-
// sometimes has issues with block-scoped declarations
|
|
65
|
-
const expression = `(function() {
|
|
66
|
-
var hook = globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
|
67
|
-
if (!hook) return null;
|
|
68
|
-
var roots = [];
|
|
69
|
-
if (hook.getFiberRoots) {
|
|
70
|
-
hook.renderers.forEach(function(r, id) {
|
|
71
|
-
var fiberRoots = hook.getFiberRoots(id);
|
|
72
|
-
if (fiberRoots) fiberRoots.forEach(function(root) { roots.push(root); });
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
if (roots.length === 0) return null;
|
|
76
|
-
|
|
77
|
-
function findScreen(fiber, depth) {
|
|
78
|
-
if (!fiber || depth > 30) return null;
|
|
79
|
-
var name = fiber.type && (fiber.type.displayName || fiber.type.name || (typeof fiber.type === 'string' ? fiber.type : null));
|
|
80
|
-
|
|
81
|
-
if (name === 'RNSScreen') {
|
|
82
|
-
var props = fiber.memoizedProps || {};
|
|
83
|
-
if (props['aria-hidden'] === true) return null;
|
|
84
|
-
var child = fiber.child;
|
|
85
|
-
while (child) {
|
|
86
|
-
var childName = child.type && (child.type.displayName || child.type.name);
|
|
87
|
-
if (childName && typeof child.type !== 'string' && childName !== 'RNSScreenContentWrapper') {
|
|
88
|
-
return childName;
|
|
89
|
-
}
|
|
90
|
-
child = child.child;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
var child = fiber.child;
|
|
95
|
-
while (child) {
|
|
96
|
-
var found = findScreen(child, depth + 1);
|
|
97
|
-
if (found) return found;
|
|
98
|
-
child = child.sibling;
|
|
99
|
-
}
|
|
100
|
-
return null;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
for (var i = 0; i < roots.length; i++) {
|
|
104
|
-
var root = roots[i].current;
|
|
105
|
-
var screen = findScreen(root, 0);
|
|
106
|
-
if (screen) return screen;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function findFirstUserComponent(fiber, depth) {
|
|
110
|
-
if (!fiber || depth > 10) return null;
|
|
111
|
-
var name = fiber.type && (fiber.type.displayName || fiber.type.name);
|
|
112
|
-
if (name && typeof fiber.type !== 'string') return name;
|
|
113
|
-
var child = fiber.child;
|
|
114
|
-
while (child) {
|
|
115
|
-
var found = findFirstUserComponent(child, depth + 1);
|
|
116
|
-
if (found) return found;
|
|
117
|
-
child = child.sibling;
|
|
118
|
-
}
|
|
119
|
-
return null;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
for (var i = 0; i < roots.length; i++) {
|
|
123
|
-
var fallback = findFirstUserComponent(roots[i].current, 0);
|
|
124
|
-
if (fallback) return fallback;
|
|
125
|
-
}
|
|
126
|
-
return null;
|
|
127
|
-
})()`;
|
|
128
|
-
const result = await executeInApp(expression, false);
|
|
129
|
-
if (result.success && result.result && result.result !== "null" && result.result !== "undefined") {
|
|
130
|
-
return result.result.replace(/^"|"$/g, "");
|
|
131
|
-
}
|
|
132
|
-
return null;
|
|
133
|
-
}
|
|
134
|
-
catch {
|
|
135
|
-
return null;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
export function formatTapSuccess(data) {
|
|
139
|
-
return {
|
|
140
|
-
success: true,
|
|
141
|
-
...data,
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
export function formatTapFailure(data) {
|
|
145
|
-
const errorMsg = data.error || buildErrorMessage(data.query);
|
|
146
|
-
return {
|
|
147
|
-
success: false,
|
|
148
|
-
query: data.query,
|
|
149
|
-
screen: data.screen,
|
|
150
|
-
error: errorMsg,
|
|
151
|
-
attempted: data.attempted,
|
|
152
|
-
suggestion: data.suggestion,
|
|
153
|
-
matches: data.matches,
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
function buildErrorMessage(query) {
|
|
157
|
-
const parts = [];
|
|
158
|
-
if (query.text)
|
|
159
|
-
parts.push(`text="${query.text}"`);
|
|
160
|
-
if (query.testID)
|
|
161
|
-
parts.push(`testID="${query.testID}"`);
|
|
162
|
-
if (query.component)
|
|
163
|
-
parts.push(`component="${query.component}"`);
|
|
164
|
-
return `No element found matching ${parts.join(", ")}`;
|
|
165
|
-
}
|
|
166
|
-
// --- Strategy Functions ---
|
|
167
|
-
async function tryFiberStrategy(query, index, maxTraversalDepth) {
|
|
168
|
-
try {
|
|
169
|
-
const result = await pressElement({
|
|
170
|
-
text: query.text,
|
|
171
|
-
testID: query.testID,
|
|
172
|
-
component: query.component,
|
|
173
|
-
index,
|
|
174
|
-
maxTraversalDepth,
|
|
175
|
-
});
|
|
176
|
-
if (!result.success) {
|
|
177
|
-
return { success: false, reason: result.error || "pressElement failed" };
|
|
178
|
-
}
|
|
179
|
-
if (!result.result) {
|
|
180
|
-
return { success: false, reason: "No result from pressElement" };
|
|
181
|
-
}
|
|
182
|
-
const parsed = JSON.parse(result.result);
|
|
183
|
-
if (parsed.error) {
|
|
184
|
-
const strategyResult = {
|
|
185
|
-
success: false,
|
|
186
|
-
reason: parsed.error,
|
|
187
|
-
};
|
|
188
|
-
if (parsed.matches) {
|
|
189
|
-
strategyResult.matches = parsed.matches;
|
|
190
|
-
}
|
|
191
|
-
return strategyResult;
|
|
192
|
-
}
|
|
193
|
-
// Input elements found via fiber can't be pressed — need native tap
|
|
194
|
-
// Return as failure so orchestrator falls through to accessibility/coordinate
|
|
195
|
-
if (parsed.needsNativeTap) {
|
|
196
|
-
return {
|
|
197
|
-
success: false,
|
|
198
|
-
reason: `Found ${parsed.pressed} (input element) but it requires native tap — falling through to next strategy`,
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
return {
|
|
202
|
-
success: true,
|
|
203
|
-
reason: "Pressed via React fiber tree",
|
|
204
|
-
pressed: parsed.pressed,
|
|
205
|
-
text: parsed.text,
|
|
206
|
-
path: parsed.path || null,
|
|
207
|
-
component: parsed.pressed || null,
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
catch (err) {
|
|
211
|
-
return {
|
|
212
|
-
success: false,
|
|
213
|
-
reason: `Fiber strategy error: ${err instanceof Error ? err.message : String(err)}`,
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
async function tryAccessibilityStrategy(query, index, platform) {
|
|
218
|
-
try {
|
|
219
|
-
const hasTestID = !!query.testID;
|
|
220
|
-
const hasText = !!query.text;
|
|
221
|
-
if (!hasTestID && !hasText) {
|
|
222
|
-
return { success: false, reason: "No text or testID for accessibility search" };
|
|
223
|
-
}
|
|
224
|
-
if (platform === "ios") {
|
|
225
|
-
// iOS: IDB does not expose accessibilityIdentifier (testID),
|
|
226
|
-
// so search by labelContains as best-effort fallback
|
|
227
|
-
const searchText = query.text || query.testID;
|
|
228
|
-
const result = await iosFindElement({
|
|
229
|
-
labelContains: searchText,
|
|
230
|
-
index,
|
|
231
|
-
});
|
|
232
|
-
if (!result.success || !result.allMatches || result.allMatches.length === 0) {
|
|
233
|
-
return { success: false, reason: result.error ?? "No iOS accessibility match" };
|
|
234
|
-
}
|
|
235
|
-
const match = result.allMatches[index ?? 0];
|
|
236
|
-
if (!match) {
|
|
237
|
-
return { success: false, reason: `Index ${index} out of bounds (${result.allMatches.length} matches)` };
|
|
238
|
-
}
|
|
239
|
-
await iosTap(match.center.x, match.center.y);
|
|
240
|
-
return {
|
|
241
|
-
success: true,
|
|
242
|
-
reason: "Tapped via iOS accessibility",
|
|
243
|
-
pressed: match.label || match.type,
|
|
244
|
-
text: match.label || undefined,
|
|
245
|
-
component: match.type || null,
|
|
246
|
-
convertedTo: { x: match.center.x, y: match.center.y, unit: "points" },
|
|
247
|
-
};
|
|
248
|
-
}
|
|
249
|
-
else {
|
|
250
|
-
// Android: testID maps to resource-id, text maps to text content
|
|
251
|
-
const searchOptions = { index };
|
|
252
|
-
if (hasTestID && !hasText) {
|
|
253
|
-
searchOptions.resourceId = query.testID;
|
|
254
|
-
}
|
|
255
|
-
else if (hasText) {
|
|
256
|
-
searchOptions.textContains = query.text;
|
|
257
|
-
}
|
|
258
|
-
let result = await androidFindElement(searchOptions);
|
|
259
|
-
// If testID search via resourceId failed, try contentDescContains
|
|
260
|
-
// (older RN versions map testID to content-description)
|
|
261
|
-
if (hasTestID && !hasText &&
|
|
262
|
-
(!result.success || !result.allMatches || result.allMatches.length === 0)) {
|
|
263
|
-
result = await androidFindElement({
|
|
264
|
-
contentDescContains: query.testID,
|
|
265
|
-
index,
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
if (!result.success || !result.allMatches || result.allMatches.length === 0) {
|
|
269
|
-
return { success: false, reason: result.error ?? "No Android accessibility match" };
|
|
270
|
-
}
|
|
271
|
-
const match = result.allMatches[index ?? 0];
|
|
272
|
-
if (!match) {
|
|
273
|
-
return { success: false, reason: `Index ${index} out of bounds (${result.allMatches.length} matches)` };
|
|
274
|
-
}
|
|
275
|
-
await androidTap(match.center.x, match.center.y);
|
|
276
|
-
return {
|
|
277
|
-
success: true,
|
|
278
|
-
reason: "Tapped via Android accessibility",
|
|
279
|
-
pressed: match.text || match.className || undefined,
|
|
280
|
-
text: match.text || undefined,
|
|
281
|
-
component: match.className || undefined,
|
|
282
|
-
convertedTo: { x: match.center.x, y: match.center.y, unit: "pixels" },
|
|
283
|
-
};
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
catch (err) {
|
|
287
|
-
return {
|
|
288
|
-
success: false,
|
|
289
|
-
reason: `Accessibility strategy error: ${err instanceof Error ? err.message : String(err)}`,
|
|
290
|
-
};
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
async function tryOcrStrategy(query, platform) {
|
|
294
|
-
try {
|
|
295
|
-
const searchText = query.text;
|
|
296
|
-
if (!searchText) {
|
|
297
|
-
return { success: false, reason: "OCR strategy requires text query" };
|
|
298
|
-
}
|
|
299
|
-
let imageBuffer;
|
|
300
|
-
let scaleFactor = 1;
|
|
301
|
-
let originalWidth;
|
|
302
|
-
let originalHeight;
|
|
303
|
-
if (platform === "ios") {
|
|
304
|
-
const screenshot = await iosScreenshot();
|
|
305
|
-
if (!screenshot.success || !screenshot.data) {
|
|
306
|
-
return { success: false, reason: "Failed to capture iOS screenshot for OCR" };
|
|
307
|
-
}
|
|
308
|
-
imageBuffer = screenshot.data;
|
|
309
|
-
scaleFactor = screenshot.scaleFactor ?? 1;
|
|
310
|
-
originalWidth = screenshot.originalWidth;
|
|
311
|
-
originalHeight = screenshot.originalHeight;
|
|
312
|
-
}
|
|
313
|
-
else {
|
|
314
|
-
const { androidScreenshot } = await import("./android.js");
|
|
315
|
-
const screenshot = await androidScreenshot();
|
|
316
|
-
if (!screenshot.success || !screenshot.data) {
|
|
317
|
-
return { success: false, reason: "Failed to capture Android screenshot for OCR" };
|
|
318
|
-
}
|
|
319
|
-
imageBuffer = screenshot.data;
|
|
320
|
-
scaleFactor = screenshot.scaleFactor ?? 1;
|
|
321
|
-
originalWidth = screenshot.originalWidth;
|
|
322
|
-
originalHeight = screenshot.originalHeight;
|
|
323
|
-
}
|
|
324
|
-
const devicePixelRatio = (platform === "ios" && originalWidth && originalHeight)
|
|
325
|
-
? inferIOSDevicePixelRatio(originalWidth, originalHeight)
|
|
326
|
-
: 3;
|
|
327
|
-
const { recognizeText } = await import("./ocr.js");
|
|
328
|
-
const ocrResult = await recognizeText(imageBuffer, {
|
|
329
|
-
scaleFactor,
|
|
330
|
-
platform,
|
|
331
|
-
devicePixelRatio,
|
|
332
|
-
});
|
|
333
|
-
const lowerSearch = searchText.toLowerCase();
|
|
334
|
-
const matchingWord = ocrResult.words.find((w) => w.text.toLowerCase() === lowerSearch) || ocrResult.words.find((w) => w.text.toLowerCase().includes(lowerSearch));
|
|
335
|
-
if (!matchingWord) {
|
|
336
|
-
return { success: false, reason: `OCR did not find text "${searchText}" on screen` };
|
|
337
|
-
}
|
|
338
|
-
if (platform === "ios") {
|
|
339
|
-
await iosTap(matchingWord.tapCenter.x, matchingWord.tapCenter.y);
|
|
340
|
-
}
|
|
341
|
-
else {
|
|
342
|
-
await androidTap(matchingWord.tapCenter.x, matchingWord.tapCenter.y);
|
|
343
|
-
}
|
|
344
|
-
return {
|
|
345
|
-
success: true,
|
|
346
|
-
reason: "Tapped via OCR text recognition",
|
|
347
|
-
text: matchingWord.text,
|
|
348
|
-
convertedTo: {
|
|
349
|
-
x: matchingWord.tapCenter.x,
|
|
350
|
-
y: matchingWord.tapCenter.y,
|
|
351
|
-
unit: platform === "ios" ? "points" : "pixels",
|
|
352
|
-
},
|
|
353
|
-
};
|
|
354
|
-
}
|
|
355
|
-
catch (err) {
|
|
356
|
-
return {
|
|
357
|
-
success: false,
|
|
358
|
-
reason: `OCR strategy error: ${err instanceof Error ? err.message : String(err)}`,
|
|
359
|
-
};
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
async function tryCoordinateStrategy(pixelX, pixelY, platform, lastScreenshot) {
|
|
363
|
-
try {
|
|
364
|
-
if (platform === "ios") {
|
|
365
|
-
const scaleFactor = lastScreenshot?.scaleFactor ?? 1;
|
|
366
|
-
const originalWidth = lastScreenshot?.originalWidth;
|
|
367
|
-
const originalHeight = lastScreenshot?.originalHeight;
|
|
368
|
-
const devicePixelRatio = (originalWidth && originalHeight)
|
|
369
|
-
? inferIOSDevicePixelRatio(originalWidth, originalHeight)
|
|
370
|
-
: 3;
|
|
371
|
-
const converted = convertPixelsToPoints(pixelX, pixelY, "ios", devicePixelRatio, scaleFactor);
|
|
372
|
-
await iosTap(converted.x, converted.y);
|
|
373
|
-
// Best-effort: identify what was tapped via fiber tree
|
|
374
|
-
let screen = null;
|
|
375
|
-
try {
|
|
376
|
-
screen = await getCurrentScreen();
|
|
377
|
-
}
|
|
378
|
-
catch {
|
|
379
|
-
// Inspection failure is non-fatal
|
|
380
|
-
}
|
|
381
|
-
return {
|
|
382
|
-
success: true,
|
|
383
|
-
reason: "Tapped at coordinates (iOS)",
|
|
384
|
-
screen,
|
|
385
|
-
convertedTo: { x: converted.x, y: converted.y, unit: "points" },
|
|
386
|
-
};
|
|
387
|
-
}
|
|
388
|
-
else {
|
|
389
|
-
const scaleFactor = lastScreenshot?.scaleFactor ?? 1;
|
|
390
|
-
const converted = convertPixelsToPoints(pixelX, pixelY, "android", 1, scaleFactor);
|
|
391
|
-
await androidTap(converted.x, converted.y);
|
|
392
|
-
// Best-effort: identify what was tapped via fiber tree
|
|
393
|
-
let screen = null;
|
|
394
|
-
try {
|
|
395
|
-
screen = await getCurrentScreen();
|
|
396
|
-
}
|
|
397
|
-
catch {
|
|
398
|
-
// Inspection failure is non-fatal
|
|
399
|
-
}
|
|
400
|
-
return {
|
|
401
|
-
success: true,
|
|
402
|
-
reason: "Tapped at coordinates (Android)",
|
|
403
|
-
screen,
|
|
404
|
-
convertedTo: { x: converted.x, y: converted.y, unit: "pixels" },
|
|
405
|
-
};
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
catch (err) {
|
|
409
|
-
return {
|
|
410
|
-
success: false,
|
|
411
|
-
reason: `Coordinate strategy error: ${err instanceof Error ? err.message : String(err)}`,
|
|
412
|
-
};
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
// --- Orchestrator ---
|
|
416
|
-
export async function tap(options) {
|
|
417
|
-
const query = buildQuery(options);
|
|
418
|
-
const strategy = options.strategy || "auto";
|
|
419
|
-
const index = options.index;
|
|
420
|
-
const maxTraversalDepth = options.maxTraversalDepth;
|
|
421
|
-
// Validate inputs
|
|
422
|
-
const hasSearchParam = query.text || query.testID || query.component;
|
|
423
|
-
const hasCoordinates = query.x !== undefined || query.y !== undefined;
|
|
424
|
-
if (!hasSearchParam && !hasCoordinates) {
|
|
425
|
-
return {
|
|
426
|
-
success: false,
|
|
427
|
-
query,
|
|
428
|
-
error: "Must provide at least one of: text, testID, component, or x/y coordinates",
|
|
429
|
-
};
|
|
430
|
-
}
|
|
431
|
-
if (hasCoordinates && (query.x === undefined || query.y === undefined)) {
|
|
432
|
-
return {
|
|
433
|
-
success: false,
|
|
434
|
-
query,
|
|
435
|
-
error: "Both x and y coordinates must be provided",
|
|
436
|
-
};
|
|
437
|
-
}
|
|
438
|
-
// Get connected app — auto-connect if none
|
|
439
|
-
let apps = Array.from(connectedApps.values());
|
|
440
|
-
if (apps.length === 0) {
|
|
441
|
-
try {
|
|
442
|
-
clearReconnectionSuppression();
|
|
443
|
-
const openPorts = await scanMetroPorts();
|
|
444
|
-
for (const port of openPorts) {
|
|
445
|
-
const devices = await fetchDevices(port);
|
|
446
|
-
const mainDevice = selectMainDevice(devices);
|
|
447
|
-
if (mainDevice) {
|
|
448
|
-
await connectToDevice(mainDevice, port);
|
|
449
|
-
break;
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
apps = Array.from(connectedApps.values());
|
|
453
|
-
}
|
|
454
|
-
catch {
|
|
455
|
-
// Auto-connect failed, will fall through to error below
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
if (apps.length === 0) {
|
|
459
|
-
return {
|
|
460
|
-
success: false,
|
|
461
|
-
query,
|
|
462
|
-
error: "No connected app. Auto-connect failed — no Metro servers found. Run scan_metro manually.",
|
|
463
|
-
};
|
|
464
|
-
}
|
|
465
|
-
const app = apps[0];
|
|
466
|
-
const platform = app.platform;
|
|
467
|
-
// Determine strategies
|
|
468
|
-
const strategies = getAvailableStrategies(query, strategy);
|
|
469
|
-
const attempted = [];
|
|
470
|
-
// Execute strategies in order
|
|
471
|
-
for (const strat of strategies) {
|
|
472
|
-
let result;
|
|
473
|
-
switch (strat) {
|
|
474
|
-
case "fiber":
|
|
475
|
-
result = await tryFiberStrategy(query, index, maxTraversalDepth);
|
|
476
|
-
break;
|
|
477
|
-
case "accessibility":
|
|
478
|
-
result = await tryAccessibilityStrategy(query, index, platform);
|
|
479
|
-
break;
|
|
480
|
-
case "ocr":
|
|
481
|
-
result = await tryOcrStrategy(query, platform);
|
|
482
|
-
break;
|
|
483
|
-
case "coordinate":
|
|
484
|
-
result = await tryCoordinateStrategy(query.x, query.y, platform, app.lastScreenshot);
|
|
485
|
-
break;
|
|
486
|
-
default:
|
|
487
|
-
result = { success: false, reason: `Unknown strategy: ${strat}` };
|
|
488
|
-
}
|
|
489
|
-
if (result.success) {
|
|
490
|
-
return formatTapSuccess({
|
|
491
|
-
method: strat,
|
|
492
|
-
query,
|
|
493
|
-
pressed: result.pressed,
|
|
494
|
-
text: result.text,
|
|
495
|
-
screen: result.screen,
|
|
496
|
-
path: result.path,
|
|
497
|
-
component: result.component,
|
|
498
|
-
convertedTo: result.convertedTo,
|
|
499
|
-
platform,
|
|
500
|
-
});
|
|
501
|
-
}
|
|
502
|
-
attempted.push({ strategy: strat, reason: result.reason });
|
|
503
|
-
// If we got match suggestions from fiber, carry them forward
|
|
504
|
-
if (result.matches) {
|
|
505
|
-
return formatTapFailure({
|
|
506
|
-
query,
|
|
507
|
-
attempted,
|
|
508
|
-
suggestion: `Found ${result.matches.length} match(es) — specify index to select one`,
|
|
509
|
-
matches: result.matches,
|
|
510
|
-
});
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
// All strategies failed
|
|
514
|
-
const suggestion = buildSuggestion(query, strategies, platform);
|
|
515
|
-
return formatTapFailure({
|
|
516
|
-
query,
|
|
517
|
-
attempted,
|
|
518
|
-
suggestion,
|
|
519
|
-
});
|
|
520
|
-
}
|
|
521
|
-
function buildSuggestion(query, triedStrategies, platform) {
|
|
522
|
-
const suggestions = [];
|
|
523
|
-
if (!triedStrategies.includes("ocr") && query.text) {
|
|
524
|
-
suggestions.push("Try strategy='ocr' to find text visually on screen");
|
|
525
|
-
}
|
|
526
|
-
if (query.text && query.text.length <= 2) {
|
|
527
|
-
suggestions.push("Very short text is unreliable for OCR — use testID or coordinates instead");
|
|
528
|
-
}
|
|
529
|
-
if (query.text && isNonAscii(query.text)) {
|
|
530
|
-
suggestions.push("Non-ASCII text cannot use fiber strategy — use testID or coordinates instead");
|
|
531
|
-
}
|
|
532
|
-
if (query.component && triedStrategies.includes("fiber")) {
|
|
533
|
-
suggestions.push("Component not found or has no onPress handler — use find_components to discover exact component names, or use text/coordinates instead");
|
|
534
|
-
}
|
|
535
|
-
if (query.testID && !triedStrategies.includes("ocr")) {
|
|
536
|
-
suggestions.push("testID not found in fiber/accessibility tree — verify the element is on the current screen with a screenshot");
|
|
537
|
-
}
|
|
538
|
-
suggestions.push(`Take a screenshot (${platform === "ios" ? "ios_screenshot" : "android_screenshot"}) ` +
|
|
539
|
-
"to verify the element is visible, then use x/y coordinates");
|
|
540
|
-
return suggestions.join(". ");
|
|
541
|
-
}
|
|
542
|
-
//# sourceMappingURL=tap.js.map
|
package/build/core/tap.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tap.js","sourceRoot":"","sources":["../../src/core/tap.ts"],"names":[],"mappings":"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"}
|