react-native-ai-debugger 2.12.3 → 2.12.4
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 +15 -1
- package/build/__tests__/unit/autoReconnectOptOut.test.js +3 -0
- package/build/__tests__/unit/autoReconnectOptOut.test.js.map +1 -1
- package/build/__tests__/unit/cdpCommand.test.d.ts +2 -0
- package/build/__tests__/unit/cdpCommand.test.d.ts.map +1 -0
- package/build/__tests__/unit/cdpCommand.test.js +84 -0
- package/build/__tests__/unit/cdpCommand.test.js.map +1 -0
- package/build/__tests__/unit/chromium.test.d.ts +2 -0
- package/build/__tests__/unit/chromium.test.d.ts.map +1 -0
- package/build/__tests__/unit/chromium.test.js +118 -0
- package/build/__tests__/unit/chromium.test.js.map +1 -0
- package/build/__tests__/unit/chromiumDevice.test.d.ts +2 -0
- package/build/__tests__/unit/chromiumDevice.test.d.ts.map +1 -0
- package/build/__tests__/unit/chromiumDevice.test.js +115 -0
- package/build/__tests__/unit/chromiumDevice.test.js.map +1 -0
- package/build/__tests__/unit/chromiumDialogAnswer.test.d.ts +2 -0
- package/build/__tests__/unit/chromiumDialogAnswer.test.d.ts.map +1 -0
- package/build/__tests__/unit/chromiumDialogAnswer.test.js +71 -0
- package/build/__tests__/unit/chromiumDialogAnswer.test.js.map +1 -0
- package/build/__tests__/unit/chromiumDialogRaces.test.d.ts +2 -0
- package/build/__tests__/unit/chromiumDialogRaces.test.d.ts.map +1 -0
- package/build/__tests__/unit/chromiumDialogRaces.test.js +100 -0
- package/build/__tests__/unit/chromiumDialogRaces.test.js.map +1 -0
- package/build/__tests__/unit/chromiumDialogs.test.d.ts +2 -0
- package/build/__tests__/unit/chromiumDialogs.test.d.ts.map +1 -0
- package/build/__tests__/unit/chromiumDialogs.test.js +167 -0
- package/build/__tests__/unit/chromiumDialogs.test.js.map +1 -0
- package/build/__tests__/unit/chromiumDiscovery.test.d.ts +2 -0
- package/build/__tests__/unit/chromiumDiscovery.test.d.ts.map +1 -0
- package/build/__tests__/unit/chromiumDiscovery.test.js +302 -0
- package/build/__tests__/unit/chromiumDiscovery.test.js.map +1 -0
- package/build/__tests__/unit/chromiumDom.test.d.ts +2 -0
- package/build/__tests__/unit/chromiumDom.test.d.ts.map +1 -0
- package/build/__tests__/unit/chromiumDom.test.js +119 -0
- package/build/__tests__/unit/chromiumDom.test.js.map +1 -0
- package/build/__tests__/unit/chromiumGate.test.d.ts +2 -0
- package/build/__tests__/unit/chromiumGate.test.d.ts.map +1 -0
- package/build/__tests__/unit/chromiumGate.test.js +149 -0
- package/build/__tests__/unit/chromiumGate.test.js.map +1 -0
- package/build/__tests__/unit/chromiumInput.test.d.ts +2 -0
- package/build/__tests__/unit/chromiumInput.test.d.ts.map +1 -0
- package/build/__tests__/unit/chromiumInput.test.js +113 -0
- package/build/__tests__/unit/chromiumInput.test.js.map +1 -0
- package/build/__tests__/unit/chromiumKeys.test.d.ts +2 -0
- package/build/__tests__/unit/chromiumKeys.test.d.ts.map +1 -0
- package/build/__tests__/unit/chromiumKeys.test.js +26 -0
- package/build/__tests__/unit/chromiumKeys.test.js.map +1 -0
- package/build/__tests__/unit/chromiumScreen.test.d.ts +2 -0
- package/build/__tests__/unit/chromiumScreen.test.d.ts.map +1 -0
- package/build/__tests__/unit/chromiumScreen.test.js +390 -0
- package/build/__tests__/unit/chromiumScreen.test.js.map +1 -0
- package/build/__tests__/unit/chromiumStaleTarget.test.d.ts +2 -0
- package/build/__tests__/unit/chromiumStaleTarget.test.d.ts.map +1 -0
- package/build/__tests__/unit/chromiumStaleTarget.test.js +26 -0
- package/build/__tests__/unit/chromiumStaleTarget.test.js.map +1 -0
- package/build/__tests__/unit/connectionGaps.test.d.ts +2 -0
- package/build/__tests__/unit/connectionGaps.test.d.ts.map +1 -0
- package/build/__tests__/unit/connectionGaps.test.js +14 -0
- package/build/__tests__/unit/connectionGaps.test.js.map +1 -0
- package/build/__tests__/unit/contextPreambleGlobals.test.d.ts +2 -0
- package/build/__tests__/unit/contextPreambleGlobals.test.d.ts.map +1 -0
- package/build/__tests__/unit/contextPreambleGlobals.test.js +25 -0
- package/build/__tests__/unit/contextPreambleGlobals.test.js.map +1 -0
- package/build/__tests__/unit/deviceResolver.test.js +9 -0
- package/build/__tests__/unit/deviceResolver.test.js.map +1 -1
- package/build/__tests__/unit/electronLaunch.test.d.ts +2 -0
- package/build/__tests__/unit/electronLaunch.test.d.ts.map +1 -0
- package/build/__tests__/unit/electronLaunch.test.js +165 -0
- package/build/__tests__/unit/electronLaunch.test.js.map +1 -0
- package/build/__tests__/unit/fiberRoots.test.d.ts +2 -0
- package/build/__tests__/unit/fiberRoots.test.d.ts.map +1 -0
- package/build/__tests__/unit/fiberRoots.test.js +95 -0
- package/build/__tests__/unit/fiberRoots.test.js.map +1 -0
- package/build/__tests__/unit/fiberRootsDrift.test.d.ts +2 -0
- package/build/__tests__/unit/fiberRootsDrift.test.d.ts.map +1 -0
- package/build/__tests__/unit/fiberRootsDrift.test.js +23 -0
- package/build/__tests__/unit/fiberRootsDrift.test.js.map +1 -0
- package/build/__tests__/unit/hostAddress.test.d.ts +2 -0
- package/build/__tests__/unit/hostAddress.test.d.ts.map +1 -0
- package/build/__tests__/unit/hostAddress.test.js +38 -0
- package/build/__tests__/unit/hostAddress.test.js.map +1 -0
- package/build/__tests__/unit/measureComponent.test.js +1 -1
- package/build/__tests__/unit/measureComponent.test.js.map +1 -1
- package/build/__tests__/unit/networkInterceptorFetchMock.test.d.ts +2 -0
- package/build/__tests__/unit/networkInterceptorFetchMock.test.d.ts.map +1 -0
- package/build/__tests__/unit/networkInterceptorFetchMock.test.js +90 -0
- package/build/__tests__/unit/networkInterceptorFetchMock.test.js.map +1 -0
- package/build/__tests__/unit/networkMockTool.test.js +12 -1
- package/build/__tests__/unit/networkMockTool.test.js.map +1 -1
- package/build/__tests__/unit/pressKeyMobile.test.d.ts +2 -0
- package/build/__tests__/unit/pressKeyMobile.test.d.ts.map +1 -0
- package/build/__tests__/unit/pressKeyMobile.test.js +63 -0
- package/build/__tests__/unit/pressKeyMobile.test.js.map +1 -0
- package/build/__tests__/unit/reloadAppAutoConnect.test.js +4 -1
- package/build/__tests__/unit/reloadAppAutoConnect.test.js.map +1 -1
- package/build/__tests__/unit/tapAndroidSerial.test.js +16 -0
- package/build/__tests__/unit/tapAndroidSerial.test.js.map +1 -1
- package/build/core/android.d.ts +10 -0
- package/build/core/android.d.ts.map +1 -1
- package/build/core/android.js +17 -0
- package/build/core/android.js.map +1 -1
- package/build/core/appContext.d.ts.map +1 -1
- package/build/core/appContext.js +11 -13
- package/build/core/appContext.js.map +1 -1
- package/build/core/appDetection.d.ts.map +1 -1
- package/build/core/appDetection.js +7 -4
- package/build/core/appDetection.js.map +1 -1
- package/build/core/cdpCommand.d.ts +4 -0
- package/build/core/cdpCommand.d.ts.map +1 -0
- package/build/core/cdpCommand.js +58 -0
- package/build/core/cdpCommand.js.map +1 -0
- package/build/core/chromium.d.ts +157 -0
- package/build/core/chromium.d.ts.map +1 -0
- package/build/core/chromium.js +480 -0
- package/build/core/chromium.js.map +1 -0
- package/build/core/chromiumCapabilities.d.ts +11 -0
- package/build/core/chromiumCapabilities.d.ts.map +1 -0
- package/build/core/chromiumCapabilities.js +35 -0
- package/build/core/chromiumCapabilities.js.map +1 -0
- package/build/core/chromiumDialogAnswer.d.ts +11 -0
- package/build/core/chromiumDialogAnswer.d.ts.map +1 -0
- package/build/core/chromiumDialogAnswer.js +61 -0
- package/build/core/chromiumDialogAnswer.js.map +1 -0
- package/build/core/chromiumDialogs.d.ts +46 -0
- package/build/core/chromiumDialogs.d.ts.map +1 -0
- package/build/core/chromiumDialogs.js +88 -0
- package/build/core/chromiumDialogs.js.map +1 -0
- package/build/core/chromiumScreen.d.ts +97 -0
- package/build/core/chromiumScreen.d.ts.map +1 -0
- package/build/core/chromiumScreen.js +498 -0
- package/build/core/chromiumScreen.js.map +1 -0
- package/build/core/componentSearch.d.ts.map +1 -1
- package/build/core/componentSearch.js +7 -26
- package/build/core/componentSearch.js.map +1 -1
- package/build/core/componentSource.d.ts.map +1 -1
- package/build/core/componentSource.js +3 -11
- package/build/core/componentSource.js.map +1 -1
- package/build/core/componentTree.d.ts.map +1 -1
- package/build/core/componentTree.js +4 -18
- package/build/core/componentTree.js.map +1 -1
- package/build/core/connection.d.ts +13 -0
- package/build/core/connection.d.ts.map +1 -1
- package/build/core/connection.js +99 -18
- package/build/core/connection.js.map +1 -1
- package/build/core/connectionState.d.ts +2 -1
- package/build/core/connectionState.d.ts.map +1 -1
- package/build/core/connectionState.js +3 -0
- package/build/core/connectionState.js.map +1 -1
- package/build/core/deviceResolver.d.ts.map +1 -1
- package/build/core/deviceResolver.js +8 -5
- package/build/core/deviceResolver.js.map +1 -1
- package/build/core/electronLaunch.d.ts +25 -0
- package/build/core/electronLaunch.d.ts.map +1 -0
- package/build/core/electronLaunch.js +113 -0
- package/build/core/electronLaunch.js.map +1 -0
- package/build/core/errors.d.ts +1 -1
- package/build/core/errors.d.ts.map +1 -1
- package/build/core/errors.js.map +1 -1
- package/build/core/guides.d.ts.map +1 -1
- package/build/core/guides.js +9 -6
- package/build/core/guides.js.map +1 -1
- package/build/core/hostAddress.d.ts +6 -0
- package/build/core/hostAddress.d.ts.map +1 -0
- package/build/core/hostAddress.js +32 -0
- package/build/core/hostAddress.js.map +1 -0
- package/build/core/injected/fiberRoots.d.ts +2 -0
- package/build/core/injected/fiberRoots.d.ts.map +1 -0
- package/build/core/injected/fiberRoots.js +60 -0
- package/build/core/injected/fiberRoots.js.map +1 -0
- package/build/core/inputTarget.d.ts.map +1 -1
- package/build/core/inputTarget.js +4 -9
- package/build/core/inputTarget.js.map +1 -1
- package/build/core/inspector.d.ts.map +1 -1
- package/build/core/inspector.js +6 -22
- package/build/core/inspector.js.map +1 -1
- package/build/core/ios.d.ts +12 -0
- package/build/core/ios.d.ts.map +1 -1
- package/build/core/ios.js +32 -0
- package/build/core/ios.js.map +1 -1
- package/build/core/jsExecute.d.ts.map +1 -1
- package/build/core/jsExecute.js +20 -1
- package/build/core/jsExecute.js.map +1 -1
- package/build/core/measureComponent.d.ts.map +1 -1
- package/build/core/measureComponent.js +4 -8
- package/build/core/measureComponent.js.map +1 -1
- package/build/core/metro.d.ts +20 -1
- package/build/core/metro.d.ts.map +1 -1
- package/build/core/metro.js +146 -9
- package/build/core/metro.js.map +1 -1
- package/build/core/mockRules.d.ts +1 -0
- package/build/core/mockRules.d.ts.map +1 -1
- package/build/core/mockRules.js +8 -0
- package/build/core/mockRules.js.map +1 -1
- package/build/core/nativeLogs.js +1 -1
- package/build/core/nativeLogs.js.map +1 -1
- package/build/core/navigation.d.ts.map +1 -1
- package/build/core/navigation.js +4 -18
- package/build/core/navigation.js.map +1 -1
- package/build/core/networkInterceptor.d.ts +2 -2
- package/build/core/networkInterceptor.d.ts.map +1 -1
- package/build/core/networkInterceptor.js +90 -3
- package/build/core/networkInterceptor.js.map +1 -1
- package/build/core/pressables.d.ts.map +1 -1
- package/build/core/pressables.js +6 -13
- package/build/core/pressables.js.map +1 -1
- package/build/core/redux.d.ts.map +1 -1
- package/build/core/redux.js +6 -10
- package/build/core/redux.js.map +1 -1
- package/build/core/register.d.ts.map +1 -1
- package/build/core/register.js +5 -2
- package/build/core/register.js.map +1 -1
- package/build/core/rnGlobalsBootstrap.d.ts.map +1 -1
- package/build/core/rnGlobalsBootstrap.js +3 -1
- package/build/core/rnGlobalsBootstrap.js.map +1 -1
- package/build/core/screenLayout.d.ts.map +1 -1
- package/build/core/screenLayout.js +4 -13
- package/build/core/screenLayout.js.map +1 -1
- package/build/core/screenStaleness.d.ts.map +1 -1
- package/build/core/screenStaleness.js +2 -0
- package/build/core/screenStaleness.js.map +1 -1
- package/build/core/screenState.d.ts.map +1 -1
- package/build/core/screenState.js +4 -11
- package/build/core/screenState.js.map +1 -1
- package/build/core/swipeDiagnosis.d.ts.map +1 -1
- package/build/core/swipeDiagnosis.js +3 -10
- package/build/core/swipeDiagnosis.js.map +1 -1
- package/build/core/textEntry.d.ts +1 -1
- package/build/core/textEntry.d.ts.map +1 -1
- package/build/core/types.d.ts +4 -2
- package/build/core/types.d.ts.map +1 -1
- package/build/pro/chromiumKeys.d.ts +19 -0
- package/build/pro/chromiumKeys.d.ts.map +1 -0
- package/build/pro/chromiumKeys.js +68 -0
- package/build/pro/chromiumKeys.js.map +1 -0
- package/build/pro/chromiumSwipe.d.ts +35 -0
- package/build/pro/chromiumSwipe.d.ts.map +1 -0
- package/build/pro/chromiumSwipe.js +105 -0
- package/build/pro/chromiumSwipe.js.map +1 -0
- package/build/pro/chromiumTap.d.ts +12 -0
- package/build/pro/chromiumTap.d.ts.map +1 -0
- package/build/pro/chromiumTap.js +155 -0
- package/build/pro/chromiumTap.js.map +1 -0
- package/build/pro/tap.d.ts +1 -0
- package/build/pro/tap.d.ts.map +1 -1
- package/build/pro/tap.js +7 -1
- package/build/pro/tap.js.map +1 -1
- package/build/tools/componentTools.d.ts.map +1 -1
- package/build/tools/componentTools.js +31 -3
- package/build/tools/componentTools.js.map +1 -1
- package/build/tools/connectionTools.d.ts.map +1 -1
- package/build/tools/connectionTools.js +66 -28
- package/build/tools/connectionTools.js.map +1 -1
- package/build/tools/deviceTools.d.ts.map +1 -1
- package/build/tools/deviceTools.js +42 -1
- package/build/tools/deviceTools.js.map +1 -1
- package/build/tools/interactionTools.d.ts.map +1 -1
- package/build/tools/interactionTools.js +132 -7
- package/build/tools/interactionTools.js.map +1 -1
- package/build/tools/networkTools.d.ts.map +1 -1
- package/build/tools/networkTools.js +20 -5
- package/build/tools/networkTools.js.map +1 -1
- package/build/tools/screenshotTools.d.ts.map +1 -1
- package/build/tools/screenshotTools.js +452 -373
- package/build/tools/screenshotTools.js.map +1 -1
- package/package.json +1 -1
- package/tools.json +27 -1
package/README.md
CHANGED
|
@@ -64,9 +64,23 @@ Linking is only for the dashboard: it attaches your installs to your account so
|
|
|
64
64
|
- **Per-Device Buffers** - Logs and network requests are captured separately per device for clean debugging
|
|
65
65
|
- **Cross-Platform Comparison** - Debug iOS and Android side-by-side, comparing logs, network traffic, and component trees
|
|
66
66
|
|
|
67
|
+
### Electron & Chromium (experimental)
|
|
68
|
+
|
|
69
|
+
- **Desktop React apps over CDP** - An Electron window or a Chrome tab connects as a `chromium` target alongside your simulators, and every tool takes the same `device` argument
|
|
70
|
+
- **What works today** - Console logs, network capture, replay and mocking (`network_mock`, `network_condition`), `execute_in_app`, debug globals, Redux, `http_request` / `app_request`, React component inspection (`get_component_tree`, `find_components`, `inspect_component`), including on Vite apps whose DevTools hook has no renderers, plus `screenshot`, `tap`, `input_text`, `swipe` (mouse-wheel scroll, and a real drag with four coordinates) and `press_key` (Enter, Escape, Tab, arrows, shortcuts). JavaScript dialogs (`alert` / `confirm` / `prompt` / `beforeunload`) are reported by the tool that opened them instead of timing out, page tools refuse while one is open, and `handle_dialog` accepts or dismisses it. Taps find elements by `data-testid` / `id`, visible text or React component name and click with real CDP mouse events. Screen reading without a screenshot: `get_screen_state` (tap-ready elements, what an overlay blocks), `get_screen_layout`, `inspect_at_point` and `measure`
|
|
71
|
+
- **Not yet** - `pinch`, `navigate` and the other mobile-only tools refuse a chromium target with a message saying so, rather than acting on the wrong device. Native HTML5 drag and drop (`draggable`) and hover are not handled yet
|
|
72
|
+
- **Zero-config start** - `electron_launch_app({ projectPath: "path/to/app" })` starts an Electron project from its source folder with the debugging port open and connects its windows. It runs your project's own `electron` or `electron-vite`, never a packaged build
|
|
73
|
+
- **Or opt in** - Add one dev-only line to the Electron main process, then run `scan_metro`. Port 9222 is listed but not auto-connected, because connecting injects a network interceptor into the page. Attach with `connect_metro({ port: 9222, device: "<window title>" })`, or set `EXECBRO_CHROMIUM_PORTS=9222` to auto-connect
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
if (!app.isPackaged) app.commandLine.appendSwitch('remote-debugging-port', '9222')
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Keep the `!app.isPackaged` guard: an open debugging port on a packaged build lets anything that can reach it run code in your renderer
|
|
80
|
+
|
|
67
81
|
### Under the Hood
|
|
68
82
|
|
|
69
|
-
- **Auto-Discovery** - Scans Metro on ports 8081
|
|
83
|
+
- **Auto-Discovery** - Scans Metro on ports 8081-8090 automatically, and lists Chromium/Electron targets on 9222 (plus any ports in `EXECBRO_CHROMIUM_PORTS`)
|
|
70
84
|
- **Multi-Device Support** - Connects to all Bridgeless targets simultaneously, with per-device log and network buffers
|
|
71
85
|
- **Auto-Reconnection** - Exponential backoff (up to 8 attempts) when connection drops
|
|
72
86
|
- **Efficient Buffering** - Circular buffers: 500 logs, 200 network requests, 100 inspector selections
|
|
@@ -8,6 +8,9 @@ jest.unstable_mockModule("../../core/metro.js", () => ({
|
|
|
8
8
|
fetchDevices,
|
|
9
9
|
selectMainDevice,
|
|
10
10
|
filterDebuggableDevices,
|
|
11
|
+
isChromiumTarget: () => false,
|
|
12
|
+
pickReconnectTarget: jest.fn(),
|
|
13
|
+
pinChromiumName: (d) => d.deviceName,
|
|
11
14
|
}));
|
|
12
15
|
const { executeInApp, markConnectionEstablished } = await import("../../core/jsExecute.js");
|
|
13
16
|
const { connectedApps } = await import("../../core/state.js");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"autoReconnectOptOut.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/autoReconnectOptOut.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAgBrC,MAAM,cAAc,GAAG,IAAI,CAAC,EAAE,CAAM,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAGxD,MAAM,YAAY,GAAG,IAAI,CAAC,EAAE,CAAM,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;AAClD,MAAM,gBAAgB,GAAG,IAAI,CAAC,EAAE,CAAM,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;AAClD,MAAM,uBAAuB,GAAG,IAAI,CAAC,EAAE,CAAM,CAAC,OAAY,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC;AAExE,IAAI,CAAC,mBAAmB,CAAC,qBAAqB,EAAE,GAAG,EAAE,CAAC,CAAC;IACnD,cAAc;IACd,YAAY;IACZ,gBAAgB;IAChB,uBAAuB;
|
|
1
|
+
{"version":3,"file":"autoReconnectOptOut.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/autoReconnectOptOut.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAgBrC,MAAM,cAAc,GAAG,IAAI,CAAC,EAAE,CAAM,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAGxD,MAAM,YAAY,GAAG,IAAI,CAAC,EAAE,CAAM,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;AAClD,MAAM,gBAAgB,GAAG,IAAI,CAAC,EAAE,CAAM,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;AAClD,MAAM,uBAAuB,GAAG,IAAI,CAAC,EAAE,CAAM,CAAC,OAAY,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC;AAExE,IAAI,CAAC,mBAAmB,CAAC,qBAAqB,EAAE,GAAG,EAAE,CAAC,CAAC;IACnD,cAAc;IACd,YAAY;IACZ,gBAAgB;IAChB,uBAAuB;IACvB,gBAAgB,EAAE,GAAG,EAAE,CAAC,KAAK;IAC7B,mBAAmB,EAAE,IAAI,CAAC,EAAE,EAAE;IAC9B,eAAe,EAAE,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU;CAC5C,CAAC,CAAC,CAAC;AAEJ,MAAM,EAAE,YAAY,EAAE,yBAAyB,EAAE,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAC;AAC5F,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;AAE9D,QAAQ,CAAC,wCAAwC,EAAE,GAAG,EAAE;IACpD,UAAU,CAAC,GAAG,EAAE;QACZ,cAAc,CAAC,SAAS,EAAE,CAAC;QAC3B,aAAa,CAAC,KAAK,EAAE,CAAC;QAItB,yBAAyB,EAAE,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;QACzF,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE,KAAK,EAAE;YAC1C,UAAU,EAAE,CAAC;YACb,aAAa,EAAE,KAAK;YACpB,mBAAmB,EAAE,aAAa;SACrC,CAAC,CAAC;QAEH,MAAM,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAC9C,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEnC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;IAGH,EAAE,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE,mBAAmB,EAAE,KAAK,EAAE,CAAC,CAAC;QAE7F,MAAM,CAAC,cAAc,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAChD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cdpCommand.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/cdpCommand.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { describe, it, expect } from "@jest/globals";
|
|
2
|
+
import { EventEmitter } from "node:events";
|
|
3
|
+
import { sendCdpCommand, evaluateJson } from "../../core/cdpCommand.js";
|
|
4
|
+
import { noteDialogOpened } from "../../core/chromiumDialogs.js";
|
|
5
|
+
class FakeWs extends EventEmitter {
|
|
6
|
+
sent = [];
|
|
7
|
+
send(s) { this.sent.push(JSON.parse(s)); }
|
|
8
|
+
reply(msg) { this.emit("message", Buffer.from(JSON.stringify(msg))); }
|
|
9
|
+
}
|
|
10
|
+
const asWs = (f) => f;
|
|
11
|
+
describe("sendCdpCommand", () => {
|
|
12
|
+
it("resolves with the result of the response carrying its own id, ignoring others", async () => {
|
|
13
|
+
const ws = new FakeWs();
|
|
14
|
+
const p = sendCdpCommand(asWs(ws), "Page.captureScreenshot", { format: "png" });
|
|
15
|
+
const { id, method, params } = ws.sent[0];
|
|
16
|
+
expect(method).toBe("Page.captureScreenshot");
|
|
17
|
+
expect(params).toEqual({ format: "png" });
|
|
18
|
+
ws.reply({ id: id + 1000, result: { data: "wrong" } });
|
|
19
|
+
ws.reply({ method: "Runtime.consoleAPICalled", params: {} });
|
|
20
|
+
ws.reply({ id, result: { data: "abc" } });
|
|
21
|
+
await expect(p).resolves.toEqual({ data: "abc" });
|
|
22
|
+
expect(ws.listenerCount("message")).toBe(0);
|
|
23
|
+
});
|
|
24
|
+
it("rejects with the CDP error message, naming the method", async () => {
|
|
25
|
+
const ws = new FakeWs();
|
|
26
|
+
const p = sendCdpCommand(asWs(ws), "Input.insertText", { text: "x" });
|
|
27
|
+
ws.reply({ id: ws.sent[0].id, error: { code: -32000, message: "No focused element" } });
|
|
28
|
+
await expect(p).rejects.toThrow("Input.insertText: No focused element");
|
|
29
|
+
expect(ws.listenerCount("message")).toBe(0);
|
|
30
|
+
});
|
|
31
|
+
it("times out, and detaches its listener so a late reply is harmless", async () => {
|
|
32
|
+
const ws = new FakeWs();
|
|
33
|
+
const p = sendCdpCommand(asWs(ws), "Page.captureScreenshot", {}, 20);
|
|
34
|
+
await expect(p).rejects.toThrow("Page.captureScreenshot timed out after 20ms");
|
|
35
|
+
expect(ws.listenerCount("message")).toBe(0);
|
|
36
|
+
ws.reply({ id: ws.sent[0].id, result: {} });
|
|
37
|
+
});
|
|
38
|
+
it("rejects when send throws (socket already closed)", async () => {
|
|
39
|
+
const ws = new FakeWs();
|
|
40
|
+
ws.send = () => { throw new Error("WebSocket is not open"); };
|
|
41
|
+
await expect(sendCdpCommand(asWs(ws), "Page.captureScreenshot")).rejects.toThrow("WebSocket is not open");
|
|
42
|
+
expect(ws.listenerCount("message")).toBe(0);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
describe("evaluateJson", () => {
|
|
46
|
+
it("parses the JSON string the expression returns", async () => {
|
|
47
|
+
const ws = new FakeWs();
|
|
48
|
+
const p = evaluateJson(asWs(ws), "JSON.stringify({ w: 380 })");
|
|
49
|
+
expect(ws.sent[0].params).toEqual({ expression: "JSON.stringify({ w: 380 })", returnByValue: true });
|
|
50
|
+
ws.reply({ id: ws.sent[0].id, result: { result: { type: "string", value: "{\"w\":380}" } } });
|
|
51
|
+
await expect(p).resolves.toEqual({ w: 380 });
|
|
52
|
+
});
|
|
53
|
+
it("throws the page exception's description", async () => {
|
|
54
|
+
const ws = new FakeWs();
|
|
55
|
+
const p = evaluateJson(asWs(ws), "boom()");
|
|
56
|
+
ws.reply({ id: ws.sent[0].id, result: { result: { type: "object" }, exceptionDetails: { text: "Uncaught", exception: { description: "ReferenceError: boom is not defined" } } } });
|
|
57
|
+
await expect(p).rejects.toThrow("ReferenceError: boom is not defined");
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
describe("sendCdpCommand on a closing socket", () => {
|
|
61
|
+
it("rejects at once on a closed socket instead of waiting out its timeout", async () => {
|
|
62
|
+
const ws = Object.assign(new FakeWs(), { readyState: 3 });
|
|
63
|
+
await expect(sendCdpCommand(asWs(ws), "Page.captureScreenshot", {}, 60_000)).rejects.toThrow("socket is closed");
|
|
64
|
+
expect(ws.sent).toEqual([]);
|
|
65
|
+
});
|
|
66
|
+
it("rejects at once when the socket closes mid-wait, and detaches", async () => {
|
|
67
|
+
const ws = new FakeWs();
|
|
68
|
+
const p = sendCdpCommand(asWs(ws), "Page.captureScreenshot", {}, 60_000);
|
|
69
|
+
ws.emit("close");
|
|
70
|
+
await expect(p).rejects.toThrow("socket is closed");
|
|
71
|
+
expect(ws.listenerCount("message")).toBe(0);
|
|
72
|
+
expect(ws.listenerCount("close")).toBe(0);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
describe("evaluateJson and a dialog", () => {
|
|
76
|
+
it("reports a dialog that opens during the read instead of timing out", async () => {
|
|
77
|
+
const ws = new FakeWs();
|
|
78
|
+
const p = evaluateJson(asWs(ws), "1", 60_000);
|
|
79
|
+
noteDialogOpened(ws, { type: "alert", message: "Saved", url: "http://x/" });
|
|
80
|
+
await expect(p).rejects.toThrow(/alert dialog: "Saved".*handle_dialog/s);
|
|
81
|
+
ws.emit("close");
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
//# sourceMappingURL=cdpCommand.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cdpCommand.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/cdpCommand.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chromium.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/chromium.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { describe, it, expect } from "@jest/globals";
|
|
2
|
+
import { pxPerCss, CHROMIUM_MAX_DIMENSION, pickDomTarget, normText, buildDomCollectJs, buildDomPrepareJs, judgeTextEntry, maskPasswordEntry, buildDomFocusJs, buildDomReadJs } from "../../core/chromium.js";
|
|
3
|
+
describe("pxPerCss", () => {
|
|
4
|
+
it("is devicePixelRatio when the raw capture fits the cap (FluentTalk popover, 380x600 @2)", () => {
|
|
5
|
+
expect(pxPerCss({ w: 380, h: 600, dpr: 2 })).toBe(2);
|
|
6
|
+
});
|
|
7
|
+
it("is 1 on a non-retina window under the cap", () => {
|
|
8
|
+
expect(pxPerCss({ w: 1280, h: 800, dpr: 1 })).toBe(1);
|
|
9
|
+
});
|
|
10
|
+
it("drops below dpr so the longest side lands exactly on the cap (1440x900 @2 = 2880 raw)", () => {
|
|
11
|
+
const k = pxPerCss({ w: 1440, h: 900, dpr: 2 });
|
|
12
|
+
expect(k).toBeCloseTo(CHROMIUM_MAX_DIMENSION / 1440);
|
|
13
|
+
expect(Math.round(1440 * k)).toBe(CHROMIUM_MAX_DIMENSION);
|
|
14
|
+
});
|
|
15
|
+
it("uses the longest side for a portrait window", () => {
|
|
16
|
+
expect(Math.round(1200 * pxPerCss({ w: 700, h: 1200, dpr: 2 }))).toBe(CHROMIUM_MAX_DIMENSION);
|
|
17
|
+
});
|
|
18
|
+
it("round-trips a delivered pixel to CSS and back within half a pixel", () => {
|
|
19
|
+
const vp = { w: 1440, h: 900, dpr: 2 };
|
|
20
|
+
const k = pxPerCss(vp);
|
|
21
|
+
const px = { x: 1234, y: 567 };
|
|
22
|
+
const css = { x: px.x / k, y: px.y / k };
|
|
23
|
+
expect(Math.abs(Math.round(css.x * k) - px.x)).toBeLessThanOrEqual(0.5);
|
|
24
|
+
expect(Math.abs(Math.round(css.y * k) - px.y)).toBeLessThanOrEqual(0.5);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
const cand = (i, text, extra = {}) => ({
|
|
28
|
+
i, tag: "button", text, testID: null, label: null, placeholder: null, value: null,
|
|
29
|
+
rect: { x: 0, y: 0, w: 10, h: 10 }, ...extra,
|
|
30
|
+
});
|
|
31
|
+
describe("pickDomTarget", () => {
|
|
32
|
+
it("prefers an exact text match over case-insensitive and substring matches", () => {
|
|
33
|
+
const cs = [cand(0, "Save draft"), cand(1, "save"), cand(2, "Save")];
|
|
34
|
+
expect(pickDomTarget(cs, "Save", undefined)).toEqual({ kind: "ok", cand: cs[2] });
|
|
35
|
+
});
|
|
36
|
+
it("falls back to case-insensitive exact, then to substring", () => {
|
|
37
|
+
expect(pickDomTarget([cand(0, "Save draft"), cand(1, "SAVE")], "save", undefined)).toEqual({ kind: "ok", cand: cand(1, "SAVE") });
|
|
38
|
+
expect(pickDomTarget([cand(0, "Save draft")], "save", undefined)).toEqual({ kind: "ok", cand: cand(0, "Save draft") });
|
|
39
|
+
});
|
|
40
|
+
it("compares whitespace-collapsed text", () => {
|
|
41
|
+
expect(pickDomTarget([cand(0, "Sign in")], " Sign in ", undefined).kind).toBe("ok");
|
|
42
|
+
});
|
|
43
|
+
it("refuses to guess between several equally good matches", () => {
|
|
44
|
+
const cs = [cand(0, "Copy"), cand(1, "Copy")];
|
|
45
|
+
expect(pickDomTarget(cs, "Copy", undefined)).toEqual({ kind: "ambiguous", matches: cs });
|
|
46
|
+
});
|
|
47
|
+
it("index picks within the winning tier; out of range is none", () => {
|
|
48
|
+
const cs = [cand(0, "Copy"), cand(1, "Copy"), cand(2, "Copy link")];
|
|
49
|
+
expect(pickDomTarget(cs, "Copy", 1)).toEqual({ kind: "ok", cand: cs[1] });
|
|
50
|
+
expect(pickDomTarget(cs, "Copy", 5)).toEqual({ kind: "none" });
|
|
51
|
+
});
|
|
52
|
+
it("with no text (testID / component), every candidate is equally good", () => {
|
|
53
|
+
expect(pickDomTarget([cand(0, "")], undefined, undefined).kind).toBe("ok");
|
|
54
|
+
expect(pickDomTarget([cand(0, ""), cand(1, "")], undefined, undefined).kind).toBe("ambiguous");
|
|
55
|
+
expect(pickDomTarget([], undefined, undefined)).toEqual({ kind: "none" });
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
describe("normText", () => {
|
|
59
|
+
it("collapses runs of whitespace, including newlines", () => {
|
|
60
|
+
expect(normText(" a \n\t b ")).toBe("a b");
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
describe("injected DOM scripts are valid JavaScript", () => {
|
|
64
|
+
const parses = (js) => () => new Function(`return ${js};`);
|
|
65
|
+
it.each([
|
|
66
|
+
["tap/testID", { mode: "tap", testID: "save-btn" }],
|
|
67
|
+
["tap/text with quotes", { mode: "tap", text: "Don't \"stop\"" }],
|
|
68
|
+
["tap/component", { mode: "tap", component: "SpeakButton" }],
|
|
69
|
+
["input/textMatch", { mode: "input", textMatch: "Email" }],
|
|
70
|
+
["input/untargeted", { mode: "input" }],
|
|
71
|
+
])("collector: %s", (_n, q) => {
|
|
72
|
+
expect(parses(buildDomCollectJs(q))).not.toThrow();
|
|
73
|
+
});
|
|
74
|
+
it("prepare", () => expect(parses(buildDomPrepareJs(3))).not.toThrow());
|
|
75
|
+
});
|
|
76
|
+
describe("maskPasswordEntry", () => {
|
|
77
|
+
it("keeps the verdict of a password write but none of its text", () => {
|
|
78
|
+
const ok = maskPasswordEntry({ success: true, verified: true, value: "hunter2x", path: "cdp" });
|
|
79
|
+
expect(ok).toEqual({ success: true, verified: true, value: "[password, 8 chars]", path: "cdp" });
|
|
80
|
+
const bad = maskPasswordEntry({ success: false, error: "e", sent: "hunter2x", landed: "hunter2" });
|
|
81
|
+
expect(JSON.stringify(bad)).not.toContain("hunter");
|
|
82
|
+
expect(bad).toMatchObject({ sent: "[password, 8 chars]", landed: "[password, 7 chars]" });
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
describe("judgeTextEntry", () => {
|
|
86
|
+
it("verifies an append against the prior value", () => {
|
|
87
|
+
expect(judgeTextEntry({ before: "Hello", sent: " world", replace: false, landed: "Hello world", maxLength: null }))
|
|
88
|
+
.toEqual({ success: true, verified: true, value: "Hello world", path: "cdp" });
|
|
89
|
+
});
|
|
90
|
+
it("verifies a replace against the sent text alone", () => {
|
|
91
|
+
expect(judgeTextEntry({ before: "old", sent: "new", replace: true, landed: "new", maxLength: null }).verified).toBe(true);
|
|
92
|
+
});
|
|
93
|
+
it("reports a controlled input that reverted the write, with sent and landed", () => {
|
|
94
|
+
const r = judgeTextEntry({ before: "", sent: "abc1", replace: true, landed: "abc", maxLength: null });
|
|
95
|
+
expect(r.success).toBe(false);
|
|
96
|
+
expect(r.sent).toBe("abc1");
|
|
97
|
+
expect(r.landed).toBe("abc");
|
|
98
|
+
expect(r.error).toContain("does not hold");
|
|
99
|
+
});
|
|
100
|
+
it("names a maxLength truncation instead of a generic mismatch", () => {
|
|
101
|
+
const r = judgeTextEntry({ before: "", sent: "123456", replace: true, landed: "1234", maxLength: 4 });
|
|
102
|
+
expect(r.success).toBe(false);
|
|
103
|
+
expect(r.error).toContain("maxLength (4)");
|
|
104
|
+
});
|
|
105
|
+
it("treats a field that vanished as a failure", () => {
|
|
106
|
+
expect(judgeTextEntry({ before: "", sent: "x", replace: true, landed: null, maxLength: null }).success).toBe(false);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
describe("input scripts are valid JavaScript", () => {
|
|
110
|
+
const parses = (js) => () => new Function(`return ${js};`);
|
|
111
|
+
it("focus (append, replace, clear) and read", () => {
|
|
112
|
+
expect(parses(buildDomFocusJs(0, false, false))).not.toThrow();
|
|
113
|
+
expect(parses(buildDomFocusJs(1, true, false))).not.toThrow();
|
|
114
|
+
expect(parses(buildDomFocusJs(2, true, true))).not.toThrow();
|
|
115
|
+
expect(parses(buildDomReadJs(0))).not.toThrow();
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
//# sourceMappingURL=chromium.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chromium.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/chromium.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chromiumDevice.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/chromiumDevice.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { describe, it, expect } from "@jest/globals";
|
|
2
|
+
import { EventEmitter } from "node:events";
|
|
3
|
+
import sharp from "sharp";
|
|
4
|
+
import { chromiumCapture, chromiumInputText } from "../../core/chromium.js";
|
|
5
|
+
import { chromiumTap } from "../../pro/chromiumTap.js";
|
|
6
|
+
class ScriptedWs extends EventEmitter {
|
|
7
|
+
answer;
|
|
8
|
+
sent = [];
|
|
9
|
+
constructor(answer) {
|
|
10
|
+
super();
|
|
11
|
+
this.answer = answer;
|
|
12
|
+
}
|
|
13
|
+
send(s) {
|
|
14
|
+
const m = JSON.parse(s);
|
|
15
|
+
this.sent.push(m);
|
|
16
|
+
queueMicrotask(() => this.emit("message", Buffer.from(JSON.stringify({ id: m.id, result: this.answer(m) }))));
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
const value = (v) => ({ result: { type: "string", value: JSON.stringify(v) } });
|
|
20
|
+
const appOn = (ws) => ({ ws, deviceInfo: { deviceName: "FluentTalk" }, platform: "chromium" });
|
|
21
|
+
describe("chromiumCapture on a hidden window", () => {
|
|
22
|
+
it("fails immediately without asking Chromium for a frame it will never paint", async () => {
|
|
23
|
+
const ws = new ScriptedWs(() => value({ w: 380, h: 600, dpr: 1, hidden: true }));
|
|
24
|
+
await expect(chromiumCapture(appOn(ws))).rejects.toThrow(/hidden/);
|
|
25
|
+
expect(ws.sent.map((m) => m.method)).toEqual(["Runtime.evaluate"]);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
describe("chromiumTap scroll note", () => {
|
|
29
|
+
it("says when the target was scrolled into view first", async () => {
|
|
30
|
+
const ws = new ScriptedWs((m) => {
|
|
31
|
+
if (m.method !== "Runtime.evaluate")
|
|
32
|
+
return {};
|
|
33
|
+
if (m.params.expression.includes("__eb_domTargets = els")) {
|
|
34
|
+
return value({
|
|
35
|
+
viewport: { w: 380, h: 600, dpr: 1 }, focused: false, total: 1,
|
|
36
|
+
candidates: [{ i: 0, tag: "p", text: "back to life", testID: null, label: null, placeholder: null, value: null, rect: { x: 10, y: 700, w: 100, h: 20 } }],
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return value({ x: 60, y: 444, scrolled: true, covered: null });
|
|
40
|
+
});
|
|
41
|
+
const r = await chromiumTap(appOn(ws), { text: "back to life" }, { verify: false, screenshot: false });
|
|
42
|
+
expect(r.success).toBe(true);
|
|
43
|
+
expect(r.warning).toMatch(/scrolled into view/i);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
describe("chromiumTap on a hidden window", () => {
|
|
47
|
+
it("refuses before clicking, with verify:false too", async () => {
|
|
48
|
+
const ws = new ScriptedWs((m) => {
|
|
49
|
+
if (m.method !== "Runtime.evaluate")
|
|
50
|
+
return {};
|
|
51
|
+
if (m.params.expression.includes("__eb_domTargets = els")) {
|
|
52
|
+
return value({
|
|
53
|
+
viewport: { w: 380, h: 600, dpr: 1, hidden: true }, focused: false, total: 1,
|
|
54
|
+
candidates: [{ i: 0, tag: "button", text: "Save", testID: null, label: null, placeholder: null, value: null, rect: { x: 10, y: 10, w: 100, h: 20 } }],
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
return value({ w: 380, h: 600, dpr: 1, hidden: true, x: 60, y: 20, scrolled: false, covered: null });
|
|
58
|
+
});
|
|
59
|
+
const r = await chromiumTap(appOn(ws), { text: "Save" }, { verify: false, screenshot: false });
|
|
60
|
+
expect(r.success).toBe(false);
|
|
61
|
+
expect(r.error).toMatch(/hidden/);
|
|
62
|
+
expect(ws.sent.some((m) => m.method === "Input.dispatchMouseEvent")).toBe(false);
|
|
63
|
+
const c = await chromiumTap(appOn(ws), { x: 10, y: 10 }, { verify: false, screenshot: false });
|
|
64
|
+
expect(c.success).toBe(false);
|
|
65
|
+
expect(ws.sent.some((m) => m.method === "Input.dispatchMouseEvent")).toBe(false);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
describe("chromiumInputText into an empty rich-text editor", () => {
|
|
69
|
+
it("verifies an append when the editor's empty paragraph reads as a lone newline", async () => {
|
|
70
|
+
const ws = new ScriptedWs((m) => {
|
|
71
|
+
if (m.method === "Input.insertText")
|
|
72
|
+
return {};
|
|
73
|
+
const e = m.params.expression;
|
|
74
|
+
if (e.includes("__eb_domTargets = els")) {
|
|
75
|
+
return value({
|
|
76
|
+
viewport: { w: 380, h: 600, dpr: 1 }, focused: true, total: 1,
|
|
77
|
+
candidates: [{ i: 0, tag: "div", text: "", testID: null, label: null, placeholder: null, value: "\n", rect: { x: 0, y: 0, w: 300, h: 40 } }],
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
if (e.includes("el.focus()"))
|
|
81
|
+
return value({ before: "\n", field: false, focused: true, maxLength: null });
|
|
82
|
+
return value({ value: "hi\n" });
|
|
83
|
+
});
|
|
84
|
+
const r = await chromiumInputText(appOn(ws), { text: "hi" });
|
|
85
|
+
expect(r).toMatchObject({ success: true, verified: true, value: "hi" });
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
describe("chromiumTap when the click hides its own window", () => {
|
|
89
|
+
it("reports the delivered click as a success, not a failure an agent would retry", async () => {
|
|
90
|
+
const png = (await sharp({ create: { width: 4, height: 4, channels: 3, background: "#000" } }).png().toBuffer()).toString("base64");
|
|
91
|
+
let viewportReads = 0;
|
|
92
|
+
const ws = new ScriptedWs((m) => {
|
|
93
|
+
if (m.method === "Page.captureScreenshot")
|
|
94
|
+
return { data: png };
|
|
95
|
+
if (m.method !== "Runtime.evaluate")
|
|
96
|
+
return {};
|
|
97
|
+
const e = m.params.expression;
|
|
98
|
+
if (e.includes("__eb_domTargets = els")) {
|
|
99
|
+
return value({
|
|
100
|
+
viewport: { w: 4, h: 4, dpr: 1 }, focused: false, total: 1,
|
|
101
|
+
candidates: [{ i: 0, tag: "button", text: "Save & close", testID: null, label: null, placeholder: null, value: null, rect: { x: 0, y: 0, w: 4, h: 4 } }],
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
if (e.includes("elementFromPoint"))
|
|
105
|
+
return value({ x: 2, y: 2, scrolled: false, covered: null });
|
|
106
|
+
viewportReads++;
|
|
107
|
+
return value({ w: 4, h: 4, dpr: 1, hidden: viewportReads > 1 });
|
|
108
|
+
});
|
|
109
|
+
const r = await chromiumTap(appOn(ws), { text: "Save & close" }, {});
|
|
110
|
+
expect(r.success).toBe(true);
|
|
111
|
+
expect(ws.sent.filter((m) => m.params && m.params.type === "mousePressed")).toHaveLength(1);
|
|
112
|
+
expect(r.verification?.explanation).toMatch(/hid/);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
//# sourceMappingURL=chromiumDevice.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chromiumDevice.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/chromiumDevice.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chromiumDialogAnswer.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/chromiumDialogAnswer.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { describe, it, expect, jest } from "@jest/globals";
|
|
2
|
+
const { noteDialogOpened, noteDialogClosed } = await import("../../core/chromiumDialogs.js");
|
|
3
|
+
const calls = [];
|
|
4
|
+
const sendCdpCommand = jest.fn(async (ws, method, params = {}) => {
|
|
5
|
+
calls.push({ method, ...params });
|
|
6
|
+
if (method === "Page.handleJavaScriptDialog" && ws.gone)
|
|
7
|
+
throw new Error("Page.handleJavaScriptDialog: No dialog is showing");
|
|
8
|
+
if (method === "Page.handleJavaScriptDialog")
|
|
9
|
+
setTimeout(() => noteDialogClosed(ws, { result: params.accept === true, userInput: params.promptText }), 5);
|
|
10
|
+
return {};
|
|
11
|
+
});
|
|
12
|
+
jest.unstable_mockModule("../../core/cdpCommand.js", () => ({ sendCdpCommand, evaluateJson: jest.fn() }));
|
|
13
|
+
const { answerDialog, pickDialogApp } = await import("../../core/chromiumDialogAnswer.js");
|
|
14
|
+
const { connectedApps } = await import("../../core/state.js");
|
|
15
|
+
const mk = () => ({ ws: {}, deviceInfo: { deviceName: "page" } });
|
|
16
|
+
describe("answerDialog", () => {
|
|
17
|
+
it("accepts a prompt with text and reports the result", async () => {
|
|
18
|
+
const app = mk();
|
|
19
|
+
noteDialogOpened(app.ws, { type: "prompt", message: "Name?", url: "http://x/" });
|
|
20
|
+
const r = await answerDialog(app, { action: "accept", promptText: "eb" });
|
|
21
|
+
expect(r.isError).toBe(false);
|
|
22
|
+
expect(calls.at(-1)).toMatchObject({ method: "Page.handleJavaScriptDialog", accept: true, promptText: "eb" });
|
|
23
|
+
expect(JSON.parse(r.text)).toMatchObject({ answered: 'accepted a prompt dialog: "Name?"', result: true, userInput: "eb" });
|
|
24
|
+
});
|
|
25
|
+
it("with nothing open says so and names the last closed dialog, without calling CDP", async () => {
|
|
26
|
+
const app = mk();
|
|
27
|
+
noteDialogOpened(app.ws, { type: "alert", message: "Saved", url: "http://x/" });
|
|
28
|
+
noteDialogClosed(app.ws, { result: true });
|
|
29
|
+
const before = calls.length;
|
|
30
|
+
const r = await answerDialog(app, { action: "dismiss" });
|
|
31
|
+
expect(r.isError).toBe(true);
|
|
32
|
+
expect(r.text).toMatch(/No dialog is open/);
|
|
33
|
+
expect(r.text).toMatch(/alert dialog: "Saved"/);
|
|
34
|
+
expect(calls.length).toBe(before);
|
|
35
|
+
});
|
|
36
|
+
it("refuses promptText on a non-prompt dialog", async () => {
|
|
37
|
+
const app = mk();
|
|
38
|
+
noteDialogOpened(app.ws, { type: "confirm", message: "Sure?", url: "http://x/" });
|
|
39
|
+
const r = await answerDialog(app, { action: "accept", promptText: "x" });
|
|
40
|
+
expect(r.isError).toBe(true);
|
|
41
|
+
expect(r.text).toMatch(/promptText/);
|
|
42
|
+
});
|
|
43
|
+
it("a dialog closed by hand just before the answer reads as no dialog open, not a CDP error", async () => {
|
|
44
|
+
const app = mk();
|
|
45
|
+
noteDialogOpened(app.ws, { type: "alert", message: "Hi", url: "http://x/" });
|
|
46
|
+
app.ws.gone = true;
|
|
47
|
+
const r = await answerDialog(app, { action: "accept" });
|
|
48
|
+
expect(r.isError).toBe(true);
|
|
49
|
+
expect(r.text).toMatch(/No dialog is open/);
|
|
50
|
+
expect(r.text).toMatch(/alert dialog: "Hi"/);
|
|
51
|
+
});
|
|
52
|
+
it("a bare call picks the window that has the dialog, not just the first chromium window", () => {
|
|
53
|
+
const first = { ws: {}, platform: "chromium", deviceInfo: { deviceName: "W1" } };
|
|
54
|
+
const second = { ws: {}, platform: "chromium", deviceInfo: { deviceName: "W2" } };
|
|
55
|
+
connectedApps.set("9997-W1", first);
|
|
56
|
+
connectedApps.set("9997-W2", second);
|
|
57
|
+
try {
|
|
58
|
+
noteDialogOpened(second.ws, { type: "alert", message: "in W2", url: "http://x/" });
|
|
59
|
+
expect(pickDialogApp(first, undefined)).toBe(second);
|
|
60
|
+
expect(pickDialogApp(first, "W1")).toBe(first);
|
|
61
|
+
expect(pickDialogApp(null, undefined)).toBe(second);
|
|
62
|
+
expect(pickDialogApp(null, "iPhone")).toBeNull();
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
connectedApps.delete("9997-W1");
|
|
66
|
+
connectedApps.delete("9997-W2");
|
|
67
|
+
noteDialogClosed(second.ws, { result: true });
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
//# sourceMappingURL=chromiumDialogAnswer.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chromiumDialogAnswer.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/chromiumDialogAnswer.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chromiumDialogRaces.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/chromiumDialogRaces.test.ts"],"names":[],"mappings":""}
|