@monoes/monobrowse 1.0.11 → 1.0.13
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/dist/src/__tests__/adapters.test.js +5 -2
- package/dist/src/__tests__/adapters.test.js.map +1 -1
- package/dist/src/__tests__/batch-eval-parsing.test.js +4 -2
- package/dist/src/__tests__/batch-eval-parsing.test.js.map +1 -1
- package/dist/src/__tests__/box-model.test.js +9 -5
- package/dist/src/__tests__/box-model.test.js.map +1 -1
- package/dist/src/__tests__/browser-launch.test.d.ts +10 -0
- package/dist/src/__tests__/browser-launch.test.d.ts.map +1 -1
- package/dist/src/__tests__/browser-launch.test.js +17 -10
- package/dist/src/__tests__/browser-launch.test.js.map +1 -1
- package/dist/src/__tests__/cdp-client.test.js +9 -3
- package/dist/src/__tests__/cdp-client.test.js.map +1 -1
- package/dist/src/__tests__/close-browser.test.d.ts +13 -0
- package/dist/src/__tests__/close-browser.test.d.ts.map +1 -1
- package/dist/src/__tests__/close-browser.test.js +5 -5
- package/dist/src/__tests__/close-browser.test.js.map +1 -1
- package/dist/src/__tests__/console-log.test.js +17 -6
- package/dist/src/__tests__/console-log.test.js.map +1 -1
- package/dist/src/__tests__/find.test.js +26 -6
- package/dist/src/__tests__/find.test.js.map +1 -1
- package/dist/src/__tests__/frame-command.test.js +9 -3
- package/dist/src/__tests__/frame-command.test.js.map +1 -1
- package/dist/src/__tests__/open-url-navigate-error.test.js +1 -3
- package/dist/src/__tests__/open-url-navigate-error.test.js.map +1 -1
- package/dist/src/__tests__/output.test.js +1 -1
- package/dist/src/__tests__/output.test.js.map +1 -1
- package/dist/src/__tests__/profiler-heap.test.d.ts +2 -0
- package/dist/src/__tests__/profiler-heap.test.d.ts.map +1 -0
- package/dist/src/__tests__/profiler-heap.test.js +154 -0
- package/dist/src/__tests__/profiler-heap.test.js.map +1 -0
- package/dist/src/__tests__/reap-idle-browser.test.d.ts +15 -0
- package/dist/src/__tests__/reap-idle-browser.test.d.ts.map +1 -0
- package/dist/src/__tests__/reap-idle-browser.test.js +238 -0
- package/dist/src/__tests__/reap-idle-browser.test.js.map +1 -0
- package/dist/src/__tests__/ref-cache.test.js +18 -10
- package/dist/src/__tests__/ref-cache.test.js.map +1 -1
- package/dist/src/__tests__/report-a11y.test.d.ts +2 -0
- package/dist/src/__tests__/report-a11y.test.d.ts.map +1 -0
- package/dist/src/__tests__/report-a11y.test.js +147 -0
- package/dist/src/__tests__/report-a11y.test.js.map +1 -0
- package/dist/src/__tests__/report-analyze.test.d.ts +2 -0
- package/dist/src/__tests__/report-analyze.test.d.ts.map +1 -0
- package/dist/src/__tests__/report-analyze.test.js +157 -0
- package/dist/src/__tests__/report-analyze.test.js.map +1 -0
- package/dist/src/__tests__/report-budget.test.d.ts +2 -0
- package/dist/src/__tests__/report-budget.test.d.ts.map +1 -0
- package/dist/src/__tests__/report-budget.test.js +80 -0
- package/dist/src/__tests__/report-budget.test.js.map +1 -0
- package/dist/src/__tests__/report-diff.test.d.ts +2 -0
- package/dist/src/__tests__/report-diff.test.d.ts.map +1 -0
- package/dist/src/__tests__/report-diff.test.js +231 -0
- package/dist/src/__tests__/report-diff.test.js.map +1 -0
- package/dist/src/__tests__/report-evidence.test.d.ts +2 -0
- package/dist/src/__tests__/report-evidence.test.d.ts.map +1 -0
- package/dist/src/__tests__/report-evidence.test.js +214 -0
- package/dist/src/__tests__/report-evidence.test.js.map +1 -0
- package/dist/src/__tests__/report-flake.test.d.ts +2 -0
- package/dist/src/__tests__/report-flake.test.d.ts.map +1 -0
- package/dist/src/__tests__/report-flake.test.js +182 -0
- package/dist/src/__tests__/report-flake.test.js.map +1 -0
- package/dist/src/__tests__/report-history.test.d.ts +2 -0
- package/dist/src/__tests__/report-history.test.d.ts.map +1 -0
- package/dist/src/__tests__/report-history.test.js +229 -0
- package/dist/src/__tests__/report-history.test.js.map +1 -0
- package/dist/src/__tests__/report-output.test.d.ts +2 -0
- package/dist/src/__tests__/report-output.test.d.ts.map +1 -0
- package/dist/src/__tests__/report-output.test.js +169 -0
- package/dist/src/__tests__/report-output.test.js.map +1 -0
- package/dist/src/__tests__/report-png.test.d.ts +2 -0
- package/dist/src/__tests__/report-png.test.d.ts.map +1 -0
- package/dist/src/__tests__/report-png.test.js +84 -0
- package/dist/src/__tests__/report-png.test.js.map +1 -0
- package/dist/src/__tests__/report-render-extras.test.d.ts +2 -0
- package/dist/src/__tests__/report-render-extras.test.d.ts.map +1 -0
- package/dist/src/__tests__/report-render-extras.test.js +285 -0
- package/dist/src/__tests__/report-render-extras.test.js.map +1 -0
- package/dist/src/__tests__/report-render.test.d.ts +2 -0
- package/dist/src/__tests__/report-render.test.d.ts.map +1 -0
- package/dist/src/__tests__/report-render.test.js +143 -0
- package/dist/src/__tests__/report-render.test.js.map +1 -0
- package/dist/src/__tests__/report-run.test.d.ts +2 -0
- package/dist/src/__tests__/report-run.test.d.ts.map +1 -0
- package/dist/src/__tests__/report-run.test.js +234 -0
- package/dist/src/__tests__/report-run.test.js.map +1 -0
- package/dist/src/__tests__/session-state.test.d.ts +8 -0
- package/dist/src/__tests__/session-state.test.d.ts.map +1 -1
- package/dist/src/__tests__/session-state.test.js +10 -10
- package/dist/src/__tests__/session-state.test.js.map +1 -1
- package/dist/src/__tests__/snapshot.test.js +44 -14
- package/dist/src/__tests__/snapshot.test.js.map +1 -1
- package/dist/src/__tests__/storage-eval.test.js +14 -6
- package/dist/src/__tests__/storage-eval.test.js.map +1 -1
- package/dist/src/__tests__/tabs.test.js +25 -9
- package/dist/src/__tests__/tabs.test.js.map +1 -1
- package/dist/src/browser/action-builder/analyzer.d.ts +1 -1
- package/dist/src/browser/action-builder/analyzer.d.ts.map +1 -1
- package/dist/src/browser/action-builder/analyzer.js +25 -9
- package/dist/src/browser/action-builder/analyzer.js.map +1 -1
- package/dist/src/browser/action-builder/types.d.ts.map +1 -1
- package/dist/src/browser/actions.d.ts +1 -1
- package/dist/src/browser/actions.d.ts.map +1 -1
- package/dist/src/browser/actions.js +16 -6
- package/dist/src/browser/actions.js.map +1 -1
- package/dist/src/browser/adapters/gemini.d.ts.map +1 -1
- package/dist/src/browser/adapters/gemini.js.map +1 -1
- package/dist/src/browser/adapters/google.d.ts.map +1 -1
- package/dist/src/browser/adapters/google.js.map +1 -1
- package/dist/src/browser/adapters/index.d.ts.map +1 -1
- package/dist/src/browser/adapters/index.js +3 -3
- package/dist/src/browser/adapters/index.js.map +1 -1
- package/dist/src/browser/adapters/instagram.d.ts.map +1 -1
- package/dist/src/browser/adapters/instagram.js.map +1 -1
- package/dist/src/browser/adapters/linkedin.d.ts.map +1 -1
- package/dist/src/browser/adapters/linkedin.js.map +1 -1
- package/dist/src/browser/adapters/microsoft.d.ts.map +1 -1
- package/dist/src/browser/adapters/microsoft.js.map +1 -1
- package/dist/src/browser/adapters/x.d.ts.map +1 -1
- package/dist/src/browser/adapters/x.js.map +1 -1
- package/dist/src/browser/browser.d.ts +30 -0
- package/dist/src/browser/browser.d.ts.map +1 -1
- package/dist/src/browser/browser.js +122 -15
- package/dist/src/browser/browser.js.map +1 -1
- package/dist/src/browser/cdp.d.ts.map +1 -1
- package/dist/src/browser/cdp.js +21 -8
- package/dist/src/browser/cdp.js.map +1 -1
- package/dist/src/browser/console-log.d.ts.map +1 -1
- package/dist/src/browser/console-log.js +2 -2
- package/dist/src/browser/console-log.js.map +1 -1
- package/dist/src/browser/dashboard/server.d.ts.map +1 -1
- package/dist/src/browser/dashboard/server.js +29 -19
- package/dist/src/browser/dashboard/server.js.map +1 -1
- package/dist/src/browser/dashboard/ui.html +153 -165
- package/dist/src/browser/dialog.d.ts.map +1 -1
- package/dist/src/browser/dialog.js +3 -1
- package/dist/src/browser/dialog.js.map +1 -1
- package/dist/src/browser/emulation.d.ts.map +1 -1
- package/dist/src/browser/emulation.js +21 -6
- package/dist/src/browser/emulation.js.map +1 -1
- package/dist/src/browser/find.d.ts +4 -4
- package/dist/src/browser/find.d.ts.map +1 -1
- package/dist/src/browser/find.js +14 -6
- package/dist/src/browser/find.js.map +1 -1
- package/dist/src/browser/har.d.ts.map +1 -1
- package/dist/src/browser/har.js +14 -7
- package/dist/src/browser/har.js.map +1 -1
- package/dist/src/browser/index.d.ts +17 -16
- package/dist/src/browser/index.d.ts.map +1 -1
- package/dist/src/browser/index.js +17 -16
- package/dist/src/browser/index.js.map +1 -1
- package/dist/src/browser/network.d.ts.map +1 -1
- package/dist/src/browser/network.js +14 -4
- package/dist/src/browser/network.js.map +1 -1
- package/dist/src/browser/pdf.d.ts.map +1 -1
- package/dist/src/browser/pdf.js +3 -3
- package/dist/src/browser/pdf.js.map +1 -1
- package/dist/src/browser/profiler.d.ts.map +1 -1
- package/dist/src/browser/profiler.js +22 -20
- package/dist/src/browser/profiler.js.map +1 -1
- package/dist/src/browser/record.d.ts +1 -1
- package/dist/src/browser/record.d.ts.map +1 -1
- package/dist/src/browser/record.js +18 -7
- package/dist/src/browser/record.js.map +1 -1
- package/dist/src/browser/ref-cache.d.ts.map +1 -1
- package/dist/src/browser/ref-cache.js +9 -4
- package/dist/src/browser/ref-cache.js.map +1 -1
- package/dist/src/browser/screenshot.d.ts.map +1 -1
- package/dist/src/browser/screenshot.js +11 -7
- package/dist/src/browser/screenshot.js.map +1 -1
- package/dist/src/browser/session.d.ts +1 -1
- package/dist/src/browser/session.d.ts.map +1 -1
- package/dist/src/browser/session.js +27 -8
- package/dist/src/browser/session.js.map +1 -1
- package/dist/src/browser/snapshot.d.ts +1 -1
- package/dist/src/browser/snapshot.d.ts.map +1 -1
- package/dist/src/browser/snapshot.js +8 -4
- package/dist/src/browser/snapshot.js.map +1 -1
- package/dist/src/browser/storage.d.ts.map +1 -1
- package/dist/src/browser/storage.js.map +1 -1
- package/dist/src/browser/tabs.d.ts.map +1 -1
- package/dist/src/browser/tabs.js +9 -3
- package/dist/src/browser/tabs.js.map +1 -1
- package/dist/src/browser/trace.d.ts.map +1 -1
- package/dist/src/browser/trace.js +3 -3
- package/dist/src/browser/trace.js.map +1 -1
- package/dist/src/browser/types.d.ts.map +1 -1
- package/dist/src/browser/types.js +23 -4
- package/dist/src/browser/types.js.map +1 -1
- package/dist/src/browser/vitals.d.ts.map +1 -1
- package/dist/src/browser/vitals.js +1 -1
- package/dist/src/browser/vitals.js.map +1 -1
- package/dist/src/browser/wait.d.ts.map +1 -1
- package/dist/src/browser/wait.js +11 -5
- package/dist/src/browser/wait.js.map +1 -1
- package/dist/src/cli/action.d.ts.map +1 -1
- package/dist/src/cli/action.js +14 -11
- package/dist/src/cli/action.js.map +1 -1
- package/dist/src/cli/commands.d.ts.map +1 -1
- package/dist/src/cli/commands.js +707 -159
- package/dist/src/cli/commands.js.map +1 -1
- package/dist/src/cli/output.js +5 -5
- package/dist/src/cli/output.js.map +1 -1
- package/dist/src/cli/platform.d.ts.map +1 -1
- package/dist/src/cli/platform.js +15 -11
- package/dist/src/cli/platform.js.map +1 -1
- package/dist/src/cli/types.d.ts +1 -1
- package/dist/src/cli/types.d.ts.map +1 -1
- package/dist/src/cli.js +21 -9
- package/dist/src/cli.js.map +1 -1
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/report/a11y.d.ts +52 -0
- package/dist/src/report/a11y.d.ts.map +1 -0
- package/dist/src/report/a11y.js +231 -0
- package/dist/src/report/a11y.js.map +1 -0
- package/dist/src/report/analyze.d.ts +20 -0
- package/dist/src/report/analyze.d.ts.map +1 -0
- package/dist/src/report/analyze.js +136 -0
- package/dist/src/report/analyze.js.map +1 -0
- package/dist/src/report/budget.d.ts +27 -0
- package/dist/src/report/budget.d.ts.map +1 -0
- package/dist/src/report/budget.js +143 -0
- package/dist/src/report/budget.js.map +1 -0
- package/dist/src/report/collect-a11y.d.ts +25 -0
- package/dist/src/report/collect-a11y.d.ts.map +1 -0
- package/dist/src/report/collect-a11y.js +154 -0
- package/dist/src/report/collect-a11y.js.map +1 -0
- package/dist/src/report/collect.d.ts +45 -0
- package/dist/src/report/collect.d.ts.map +1 -0
- package/dist/src/report/collect.js +275 -0
- package/dist/src/report/collect.js.map +1 -0
- package/dist/src/report/evidence.d.ts +80 -0
- package/dist/src/report/evidence.d.ts.map +1 -0
- package/dist/src/report/evidence.js +279 -0
- package/dist/src/report/evidence.js.map +1 -0
- package/dist/src/report/flake.d.ts +88 -0
- package/dist/src/report/flake.d.ts.map +1 -0
- package/dist/src/report/flake.js +232 -0
- package/dist/src/report/flake.js.map +1 -0
- package/dist/src/report/history.d.ts +85 -0
- package/dist/src/report/history.d.ts.map +1 -0
- package/dist/src/report/history.js +176 -0
- package/dist/src/report/history.js.map +1 -0
- package/dist/src/report/index.d.ts +102 -0
- package/dist/src/report/index.d.ts.map +1 -0
- package/dist/src/report/index.js +216 -0
- package/dist/src/report/index.js.map +1 -0
- package/dist/src/report/pixel-diff.d.ts +30 -0
- package/dist/src/report/pixel-diff.d.ts.map +1 -0
- package/dist/src/report/pixel-diff.js +175 -0
- package/dist/src/report/pixel-diff.js.map +1 -0
- package/dist/src/report/png.d.ts +28 -0
- package/dist/src/report/png.d.ts.map +1 -0
- package/dist/src/report/png.js +259 -0
- package/dist/src/report/png.js.map +1 -0
- package/dist/src/report/render-evidence.d.ts +16 -0
- package/dist/src/report/render-evidence.d.ts.map +1 -0
- package/dist/src/report/render-evidence.js +174 -0
- package/dist/src/report/render-evidence.js.map +1 -0
- package/dist/src/report/render-trend.d.ts +16 -0
- package/dist/src/report/render-trend.d.ts.map +1 -0
- package/dist/src/report/render-trend.js +194 -0
- package/dist/src/report/render-trend.js.map +1 -0
- package/dist/src/report/render.d.ts +21 -0
- package/dist/src/report/render.d.ts.map +1 -0
- package/dist/src/report/render.js +286 -0
- package/dist/src/report/render.js.map +1 -0
- package/dist/src/report/run-diff.d.ts +18 -0
- package/dist/src/report/run-diff.d.ts.map +1 -0
- package/dist/src/report/run-diff.js +51 -0
- package/dist/src/report/run-diff.js.map +1 -0
- package/dist/src/report/structure.d.ts +41 -0
- package/dist/src/report/structure.d.ts.map +1 -0
- package/dist/src/report/structure.js +210 -0
- package/dist/src/report/structure.js.map +1 -0
- package/dist/src/report/trend.d.ts +26 -0
- package/dist/src/report/trend.d.ts.map +1 -0
- package/dist/src/report/trend.js +164 -0
- package/dist/src/report/trend.js.map +1 -0
- package/dist/src/report/types.d.ts +320 -0
- package/dist/src/report/types.d.ts.map +1 -0
- package/dist/src/report/types.js +11 -0
- package/dist/src/report/types.js.map +1 -0
- package/dist/src/report/util.d.ts +17 -0
- package/dist/src/report/util.d.ts.map +1 -0
- package/dist/src/report/util.js +45 -0
- package/dist/src/report/util.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/__tests__/adapters.test.ts +15 -8
- package/src/__tests__/batch-eval-parsing.test.ts +4 -2
- package/src/__tests__/box-model.test.ts +9 -5
- package/src/__tests__/browser-launch.test.ts +26 -15
- package/src/__tests__/cdp-client.test.ts +25 -9
- package/src/__tests__/close-browser.test.ts +11 -6
- package/src/__tests__/console-log.test.ts +36 -13
- package/src/__tests__/find.test.ts +58 -20
- package/src/__tests__/frame-command.test.ts +12 -6
- package/src/__tests__/open-url-navigate-error.test.ts +2 -4
- package/src/__tests__/output.test.ts +1 -1
- package/src/__tests__/profiler-heap.test.ts +191 -0
- package/src/__tests__/reap-idle-browser.test.ts +276 -0
- package/src/__tests__/ref-cache.test.ts +25 -12
- package/src/__tests__/report-a11y.test.ts +180 -0
- package/src/__tests__/report-analyze.test.ts +202 -0
- package/src/__tests__/report-budget.test.ts +92 -0
- package/src/__tests__/report-diff.test.ts +272 -0
- package/src/__tests__/report-evidence.test.ts +276 -0
- package/src/__tests__/report-flake.test.ts +214 -0
- package/src/__tests__/report-history.test.ts +293 -0
- package/src/__tests__/report-output.test.ts +210 -0
- package/src/__tests__/report-png.test.ts +95 -0
- package/src/__tests__/report-render-extras.test.ts +315 -0
- package/src/__tests__/report-render.test.ts +175 -0
- package/src/__tests__/report-run.test.ts +264 -0
- package/src/__tests__/session-state.test.ts +40 -28
- package/src/__tests__/snapshot.test.ts +60 -21
- package/src/__tests__/storage-eval.test.ts +30 -16
- package/src/__tests__/tabs.test.ts +26 -10
- package/src/browser/action-builder/analyzer.ts +39 -15
- package/src/browser/action-builder/types.ts +45 -8
- package/src/browser/actions.ts +288 -123
- package/src/browser/adapters/gemini.ts +7 -3
- package/src/browser/adapters/google.ts +5 -3
- package/src/browser/adapters/index.ts +5 -4
- package/src/browser/adapters/instagram.ts +4 -2
- package/src/browser/adapters/linkedin.ts +4 -2
- package/src/browser/adapters/microsoft.ts +9 -5
- package/src/browser/adapters/x.ts +7 -3
- package/src/browser/browser.ts +188 -42
- package/src/browser/cdp.ts +43 -11
- package/src/browser/console-log.ts +24 -7
- package/src/browser/dashboard/server.ts +44 -25
- package/src/browser/dashboard/ui.html +153 -165
- package/src/browser/dialog.ts +25 -8
- package/src/browser/emulation.ts +86 -36
- package/src/browser/find.ts +110 -47
- package/src/browser/har.ts +58 -26
- package/src/browser/index.ts +17 -16
- package/src/browser/network.ts +147 -46
- package/src/browser/pdf.ts +4 -4
- package/src/browser/profiler.ts +39 -19
- package/src/browser/record.ts +38 -19
- package/src/browser/ref-cache.ts +38 -17
- package/src/browser/screenshot.ts +58 -32
- package/src/browser/session.ts +51 -18
- package/src/browser/snapshot.ts +34 -20
- package/src/browser/storage.ts +73 -17
- package/src/browser/tabs.ts +29 -17
- package/src/browser/trace.ts +14 -10
- package/src/browser/types.ts +23 -4
- package/src/browser/vitals.ts +33 -16
- package/src/browser/wait.ts +47 -21
- package/src/cli/action.ts +52 -21
- package/src/cli/commands.ts +1365 -385
- package/src/cli/output.ts +5 -5
- package/src/cli/platform.ts +44 -23
- package/src/cli/types.ts +1 -1
- package/src/cli.ts +34 -18
- package/src/index.ts +2 -2
- package/src/report/a11y.ts +242 -0
- package/src/report/analyze.ts +181 -0
- package/src/report/budget.ts +155 -0
- package/src/report/collect-a11y.ts +200 -0
- package/src/report/collect.ts +408 -0
- package/src/report/evidence.ts +379 -0
- package/src/report/flake.ts +303 -0
- package/src/report/history.ts +219 -0
- package/src/report/index.ts +307 -0
- package/src/report/pixel-diff.ts +197 -0
- package/src/report/png.ts +290 -0
- package/src/report/render-evidence.ts +194 -0
- package/src/report/render-trend.ts +225 -0
- package/src/report/render.ts +314 -0
- package/src/report/run-diff.ts +63 -0
- package/src/report/structure.ts +212 -0
- package/src/report/trend.ts +189 -0
- package/src/report/types.ts +356 -0
- package/src/report/util.ts +48 -0
|
@@ -4,9 +4,14 @@
|
|
|
4
4
|
* resolves against. That transform is pure — the only browser interaction is
|
|
5
5
|
* the AX-tree fetch, which a stub answers from a literal node array.
|
|
6
6
|
*/
|
|
7
|
-
import { describe,
|
|
7
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
8
8
|
import type { CdpClient } from '../browser/cdp.js';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
captureSnapshot,
|
|
11
|
+
getElementBox,
|
|
12
|
+
getObjectIdForRef,
|
|
13
|
+
resolveRef,
|
|
14
|
+
} from '../browser/snapshot.js';
|
|
10
15
|
import type { ElementRef } from '../browser/types.js';
|
|
11
16
|
|
|
12
17
|
interface AXProp {
|
|
@@ -29,7 +34,7 @@ interface AXNode {
|
|
|
29
34
|
/** Client that serves a fixed AX tree plus location.href / document.title. */
|
|
30
35
|
function axClient(
|
|
31
36
|
nodes: AXNode[],
|
|
32
|
-
extra: { url?: string; title?: string; partial?: AXNode[]; selectorNodeId?: number } = {}
|
|
37
|
+
extra: { url?: string; title?: string; partial?: AXNode[]; selectorNodeId?: number } = {},
|
|
33
38
|
): { client: CdpClient; calls: string[] } {
|
|
34
39
|
const calls: string[] = [];
|
|
35
40
|
const client = {
|
|
@@ -49,8 +54,8 @@ function axClient(
|
|
|
49
54
|
result: {
|
|
50
55
|
value:
|
|
51
56
|
(params as { expression: string }).expression === 'location.href'
|
|
52
|
-
? extra.url ?? 'https://x.test/'
|
|
53
|
-
: extra.title ?? 'Test Page',
|
|
57
|
+
? (extra.url ?? 'https://x.test/')
|
|
58
|
+
: (extra.title ?? 'Test Page'),
|
|
54
59
|
},
|
|
55
60
|
};
|
|
56
61
|
default:
|
|
@@ -80,10 +85,14 @@ describe('captureSnapshot — tree shape', () => {
|
|
|
80
85
|
expect(snap.text).toBe(
|
|
81
86
|
'RootWebArea "Test Page" [ref=e1]\n' +
|
|
82
87
|
' form "Login" [ref=e2]\n' +
|
|
83
|
-
' button "Submit" [ref=e3]'
|
|
88
|
+
' button "Submit" [ref=e3]',
|
|
84
89
|
);
|
|
85
90
|
expect([...snap.refs.keys()]).toEqual(['e1', 'e2', 'e3']);
|
|
86
|
-
expect(snap.refs.get('e3')).toMatchObject({
|
|
91
|
+
expect(snap.refs.get('e3')).toMatchObject({
|
|
92
|
+
role: 'button',
|
|
93
|
+
name: 'Submit',
|
|
94
|
+
backendDOMNodeId: 30,
|
|
95
|
+
});
|
|
87
96
|
expect(snap).toMatchObject({ url: 'https://x.test/', title: 'Test Page' });
|
|
88
97
|
});
|
|
89
98
|
|
|
@@ -157,13 +166,13 @@ describe('captureSnapshot — options', () => {
|
|
|
157
166
|
});
|
|
158
167
|
|
|
159
168
|
it('compact drops indentation and descriptions', async () => {
|
|
160
|
-
const { client } = axClient([
|
|
161
|
-
button(1, 'Go', { description: { value: 'primary action' } }),
|
|
162
|
-
]);
|
|
169
|
+
const { client } = axClient([button(1, 'Go', { description: { value: 'primary action' } })]);
|
|
163
170
|
const spaced = await captureSnapshot(client, 'S1');
|
|
164
171
|
expect(spaced.text).toBe('button "Go" (primary action) [ref=e1]');
|
|
165
172
|
|
|
166
|
-
const { client: c2 } = axClient([
|
|
173
|
+
const { client: c2 } = axClient([
|
|
174
|
+
button(1, 'Go', { description: { value: 'primary action' } }),
|
|
175
|
+
]);
|
|
167
176
|
const compact = await captureSnapshot(c2, 'S1', { compact: true });
|
|
168
177
|
expect(compact.text).toBe('button "Go" [ref=e1]');
|
|
169
178
|
// The description is still available on the ref even when not printed.
|
|
@@ -198,7 +207,13 @@ describe('captureSnapshot — options', () => {
|
|
|
198
207
|
describe('captureSnapshot — property extraction and rendering', () => {
|
|
199
208
|
async function snapOf(props: AXProp[], over: Partial<AXNode> = {}) {
|
|
200
209
|
const { client } = axClient([
|
|
201
|
-
{
|
|
210
|
+
{
|
|
211
|
+
nodeId: 1,
|
|
212
|
+
role: { value: 'textbox' },
|
|
213
|
+
name: { value: 'Email' },
|
|
214
|
+
properties: props,
|
|
215
|
+
...over,
|
|
216
|
+
},
|
|
202
217
|
]);
|
|
203
218
|
return captureSnapshot(client, 'S1');
|
|
204
219
|
}
|
|
@@ -210,14 +225,18 @@ describe('captureSnapshot — property extraction and rendering', () => {
|
|
|
210
225
|
{ name: 'required', value: { value: true } },
|
|
211
226
|
]);
|
|
212
227
|
expect(snap.text).toBe(
|
|
213
|
-
'textbox "Email" [ref=e1, value="a@b.c", placeholder="you@example.com", required]'
|
|
228
|
+
'textbox "Email" [ref=e1, value="a@b.c", placeholder="you@example.com", required]',
|
|
214
229
|
);
|
|
215
230
|
expect(snap.refs.get('e1')).toMatchObject({ value: 'a@b.c', placeholder: 'you@example.com' });
|
|
216
231
|
});
|
|
217
232
|
|
|
218
233
|
it('renders disabled as a bare flag only when true', async () => {
|
|
219
|
-
expect((await snapOf([{ name: 'disabled', value: { value: true } }])).text).toContain(
|
|
220
|
-
|
|
234
|
+
expect((await snapOf([{ name: 'disabled', value: { value: true } }])).text).toContain(
|
|
235
|
+
', disabled]',
|
|
236
|
+
);
|
|
237
|
+
expect((await snapOf([{ name: 'disabled', value: { value: false } }])).text).not.toContain(
|
|
238
|
+
'disabled',
|
|
239
|
+
);
|
|
221
240
|
});
|
|
222
241
|
|
|
223
242
|
it('accepts checked/expanded as either the boolean or the string "true"', async () => {
|
|
@@ -280,12 +299,14 @@ describe('resolveRef', () => {
|
|
|
280
299
|
const refs = new Map<string, ElementRef>([
|
|
281
300
|
['e1', { ref: 'e1', role: 'button', name: 'Go', nodeId: 1 }],
|
|
282
301
|
]);
|
|
283
|
-
await expect(resolveRef({} as CdpClient, 'S1', refs, 'e1')).resolves.toMatchObject({
|
|
302
|
+
await expect(resolveRef({} as CdpClient, 'S1', refs, 'e1')).resolves.toMatchObject({
|
|
303
|
+
ref: 'e1',
|
|
304
|
+
});
|
|
284
305
|
});
|
|
285
306
|
|
|
286
307
|
it('throws a snapshot-first hint when the ref is unknown', async () => {
|
|
287
308
|
await expect(resolveRef({} as CdpClient, 'S1', new Map(), 'e9')).rejects.toThrow(
|
|
288
|
-
'Element ref @e9 not found. Run snapshot first.'
|
|
309
|
+
'Element ref @e9 not found. Run snapshot first.',
|
|
289
310
|
);
|
|
290
311
|
});
|
|
291
312
|
});
|
|
@@ -295,7 +316,7 @@ describe('getObjectIdForRef', () => {
|
|
|
295
316
|
const send = vi.fn();
|
|
296
317
|
const client = { send } as unknown as CdpClient;
|
|
297
318
|
await expect(
|
|
298
|
-
getObjectIdForRef(client, 'S1', { ref: 'e1', role: 'button', name: '', nodeId: 1 })
|
|
319
|
+
getObjectIdForRef(client, 'S1', { ref: 'e1', role: 'button', name: '', nodeId: 1 }),
|
|
299
320
|
).resolves.toBeNull();
|
|
300
321
|
expect(send).not.toHaveBeenCalled();
|
|
301
322
|
});
|
|
@@ -304,7 +325,13 @@ describe('getObjectIdForRef', () => {
|
|
|
304
325
|
const send = vi.fn(async () => ({ object: { objectId: 'OBJ' } }));
|
|
305
326
|
const client = { send } as unknown as CdpClient;
|
|
306
327
|
await expect(
|
|
307
|
-
getObjectIdForRef(client, 'S1', {
|
|
328
|
+
getObjectIdForRef(client, 'S1', {
|
|
329
|
+
ref: 'e1',
|
|
330
|
+
role: 'button',
|
|
331
|
+
name: '',
|
|
332
|
+
nodeId: 1,
|
|
333
|
+
backendDOMNodeId: 77,
|
|
334
|
+
}),
|
|
308
335
|
).resolves.toBe('OBJ');
|
|
309
336
|
expect(send.mock.calls[0]).toEqual(['DOM.resolveNode', { backendNodeId: 77 }, 'S1']);
|
|
310
337
|
});
|
|
@@ -312,7 +339,13 @@ describe('getObjectIdForRef', () => {
|
|
|
312
339
|
it('returns null when the node no longer resolves to an object', async () => {
|
|
313
340
|
const client = { send: vi.fn(async () => ({ object: {} })) } as unknown as CdpClient;
|
|
314
341
|
await expect(
|
|
315
|
-
getObjectIdForRef(client, 'S1', {
|
|
342
|
+
getObjectIdForRef(client, 'S1', {
|
|
343
|
+
ref: 'e1',
|
|
344
|
+
role: 'button',
|
|
345
|
+
name: '',
|
|
346
|
+
nodeId: 1,
|
|
347
|
+
backendDOMNodeId: 77,
|
|
348
|
+
}),
|
|
316
349
|
).resolves.toBeNull();
|
|
317
350
|
});
|
|
318
351
|
});
|
|
@@ -325,7 +358,13 @@ describe('getElementBox', () => {
|
|
|
325
358
|
})),
|
|
326
359
|
} as unknown as CdpClient;
|
|
327
360
|
await expect(
|
|
328
|
-
getElementBox(client, 'S1', {
|
|
361
|
+
getElementBox(client, 'S1', {
|
|
362
|
+
ref: 'e1',
|
|
363
|
+
role: 'button',
|
|
364
|
+
name: '',
|
|
365
|
+
nodeId: 1,
|
|
366
|
+
backendDOMNodeId: 5,
|
|
367
|
+
}),
|
|
329
368
|
).resolves.toEqual({ x: 60, y: 40, width: 100, height: 40 });
|
|
330
369
|
});
|
|
331
370
|
});
|
|
@@ -5,24 +5,27 @@
|
|
|
5
5
|
* evaluateJs's error/timeout contract is what this file pins down.
|
|
6
6
|
* Fake client throughout — no browser.
|
|
7
7
|
*/
|
|
8
|
-
import { describe,
|
|
9
|
-
import type { CdpClient } from '../browser/cdp.js';
|
|
8
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
10
9
|
import { evaluateJs } from '../browser/actions.js';
|
|
10
|
+
import type { CdpClient } from '../browser/cdp.js';
|
|
11
11
|
import {
|
|
12
|
-
getLocalStorageKey,
|
|
13
|
-
setLocalStorageKey,
|
|
14
|
-
removeLocalStorageKey,
|
|
15
12
|
clearLocalStorage,
|
|
13
|
+
clearSessionStorage,
|
|
16
14
|
getAllLocalStorage,
|
|
15
|
+
getAllSessionStorage,
|
|
16
|
+
getLocalStorageKey,
|
|
17
17
|
getSessionStorageKey,
|
|
18
|
-
|
|
18
|
+
removeLocalStorageKey,
|
|
19
19
|
removeSessionStorageKey,
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
setLocalStorageKey,
|
|
21
|
+
setSessionStorageKey,
|
|
22
22
|
} from '../browser/storage.js';
|
|
23
23
|
|
|
24
24
|
/** Client stub returning a fixed Runtime.evaluate value, recording expressions. */
|
|
25
|
-
function stubClient(
|
|
25
|
+
function stubClient(
|
|
26
|
+
value?: unknown,
|
|
27
|
+
exceptionDetails?: unknown,
|
|
28
|
+
): {
|
|
26
29
|
client: CdpClient;
|
|
27
30
|
exprs: string[];
|
|
28
31
|
sids: Array<string | undefined>;
|
|
@@ -33,7 +36,9 @@ function stubClient(value?: unknown, exceptionDetails?: unknown): {
|
|
|
33
36
|
send: vi.fn(async (_m: string, params: { expression: string }, sid?: string) => {
|
|
34
37
|
exprs.push(params.expression);
|
|
35
38
|
sids.push(sid);
|
|
36
|
-
return exceptionDetails
|
|
39
|
+
return exceptionDetails
|
|
40
|
+
? { result: {}, exceptionDetails }
|
|
41
|
+
: { result: { value, type: 'string' } };
|
|
37
42
|
}),
|
|
38
43
|
} as unknown as CdpClient;
|
|
39
44
|
return { client, exprs, sids };
|
|
@@ -58,19 +63,21 @@ describe('evaluateJs', () => {
|
|
|
58
63
|
exception: { description: 'ReferenceError: foo is not defined' },
|
|
59
64
|
});
|
|
60
65
|
await expect(evaluateJs(client, 'S1', 'foo')).rejects.toThrow(
|
|
61
|
-
'JS evaluation error: ReferenceError: foo is not defined'
|
|
66
|
+
'JS evaluation error: ReferenceError: foo is not defined',
|
|
62
67
|
);
|
|
63
68
|
});
|
|
64
69
|
|
|
65
70
|
it('falls back to exceptionDetails.text when there is no description', async () => {
|
|
66
71
|
const { client } = stubClient(undefined, { text: 'Uncaught SyntaxError' });
|
|
67
72
|
await expect(evaluateJs(client, 'S1', '{{')).rejects.toThrow(
|
|
68
|
-
'JS evaluation error: Uncaught SyntaxError'
|
|
73
|
+
'JS evaluation error: Uncaught SyntaxError',
|
|
69
74
|
);
|
|
70
75
|
});
|
|
71
76
|
|
|
72
77
|
it('returns undefined for an expression with no value', async () => {
|
|
73
|
-
const client = {
|
|
78
|
+
const client = {
|
|
79
|
+
send: vi.fn(async () => ({ result: { type: 'undefined' } })),
|
|
80
|
+
} as unknown as CdpClient;
|
|
74
81
|
await expect(evaluateJs(client, 'S1', 'void 0')).resolves.toBeUndefined();
|
|
75
82
|
});
|
|
76
83
|
|
|
@@ -79,14 +86,19 @@ describe('evaluateJs', () => {
|
|
|
79
86
|
// without the race; a 20ms budget proves the timer is armed.
|
|
80
87
|
const client = { send: vi.fn(() => new Promise(() => {})) } as unknown as CdpClient;
|
|
81
88
|
await expect(evaluateJs(client, 'S1', 'new Promise(() => {})', 20)).rejects.toThrow(
|
|
82
|
-
'JS evaluation timed out after 20ms'
|
|
89
|
+
'JS evaluation timed out after 20ms',
|
|
83
90
|
);
|
|
84
91
|
});
|
|
85
92
|
|
|
86
93
|
it('waits indefinitely when the timeout is disabled with 0', async () => {
|
|
87
94
|
let resolveSend: (v: unknown) => void = () => {};
|
|
88
95
|
const client = {
|
|
89
|
-
send: vi.fn(
|
|
96
|
+
send: vi.fn(
|
|
97
|
+
() =>
|
|
98
|
+
new Promise((r) => {
|
|
99
|
+
resolveSend = r;
|
|
100
|
+
}),
|
|
101
|
+
),
|
|
90
102
|
} as unknown as CdpClient;
|
|
91
103
|
const p = evaluateJs(client, 'S1', 'slow()', 0);
|
|
92
104
|
resolveSend({ result: { value: 'done', type: 'string' } });
|
|
@@ -165,7 +177,9 @@ describe('sessionStorage helpers mirror the localStorage ones', () => {
|
|
|
165
177
|
});
|
|
166
178
|
|
|
167
179
|
it('getAll parses, and degrades to {} on garbage', async () => {
|
|
168
|
-
await expect(getAllSessionStorage(stubClient('{"s":"1"}').client, 'S1')).resolves.toEqual({
|
|
180
|
+
await expect(getAllSessionStorage(stubClient('{"s":"1"}').client, 'S1')).resolves.toEqual({
|
|
181
|
+
s: '1',
|
|
182
|
+
});
|
|
169
183
|
await expect(getAllSessionStorage(stubClient('<html>').client, 'S1')).resolves.toEqual({});
|
|
170
184
|
});
|
|
171
185
|
});
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* tabs.ts — target filtering and the CDP command sequences for
|
|
3
3
|
* close/activate/frame-switch. Fake fetch + fake client; no browser.
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
5
|
+
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
6
6
|
import type { CdpClient } from '../browser/cdp.js';
|
|
7
|
-
import {
|
|
7
|
+
import { activateTab, closeTab, listTabs, newTab, switchToFrame } from '../browser/tabs.js';
|
|
8
8
|
|
|
9
9
|
const realFetch = globalThis.fetch;
|
|
10
10
|
afterEach(() => {
|
|
@@ -55,7 +55,7 @@ describe('listTabs', () => {
|
|
|
55
55
|
|
|
56
56
|
it('propagates a failed /json/list', async () => {
|
|
57
57
|
globalThis.fetch = vi.fn(() =>
|
|
58
|
-
Promise.resolve(new Response('', { status: 502, statusText: 'Bad Gateway' }))
|
|
58
|
+
Promise.resolve(new Response('', { status: 502, statusText: 'Bad Gateway' })),
|
|
59
59
|
) as unknown as typeof fetch;
|
|
60
60
|
await expect(listTabs(9222)).rejects.toThrow('Failed to fetch targets: Bad Gateway');
|
|
61
61
|
});
|
|
@@ -66,7 +66,7 @@ describe('newTab', () => {
|
|
|
66
66
|
const fn = stubFetch({ id: 'T1', type: 'page' });
|
|
67
67
|
await newTab(9222);
|
|
68
68
|
expect(fn.mock.calls[0]![0]).toBe(
|
|
69
|
-
|
|
69
|
+
`http://127.0.0.1:9222/json/new?${encodeURIComponent('about:blank')}`,
|
|
70
70
|
);
|
|
71
71
|
});
|
|
72
72
|
|
|
@@ -81,7 +81,9 @@ describe('closeTab', () => {
|
|
|
81
81
|
it('sends Target.closeTarget for the given targetId', async () => {
|
|
82
82
|
const { client, calls } = stubClient();
|
|
83
83
|
await closeTab(client, 'S1', 'T9');
|
|
84
|
-
expect(calls).toEqual([
|
|
84
|
+
expect(calls).toEqual([
|
|
85
|
+
{ method: 'Target.closeTarget', params: { targetId: 'T9' }, sid: undefined },
|
|
86
|
+
]);
|
|
85
87
|
});
|
|
86
88
|
});
|
|
87
89
|
|
|
@@ -129,7 +131,10 @@ describe('switchToFrame', () => {
|
|
|
129
131
|
'Runtime.evaluate': { result: { result: { value: null } } },
|
|
130
132
|
'Page.getFrameTree': { frameTree: {} },
|
|
131
133
|
});
|
|
132
|
-
await expect(switchToFrame(client, 'S1', 'div.not-a-frame')).resolves.toEqual({
|
|
134
|
+
await expect(switchToFrame(client, 'S1', 'div.not-a-frame')).resolves.toEqual({
|
|
135
|
+
url: null,
|
|
136
|
+
sessionId: null,
|
|
137
|
+
});
|
|
133
138
|
// The selector is embedded as a JSON string literal, never interpolated raw.
|
|
134
139
|
const expr = (calls[0]!.params as { expression: string }).expression;
|
|
135
140
|
expect(expr).toContain('document.querySelector("div.not-a-frame")');
|
|
@@ -149,9 +154,14 @@ describe('switchToFrame', () => {
|
|
|
149
154
|
const { client, calls } = stubClient({
|
|
150
155
|
'Runtime.evaluate': { result: { result: { value: 'https://f.test/frame' } } },
|
|
151
156
|
'Page.getFrameTree': frameTreeWith('https://f.test/frame'),
|
|
152
|
-
'Target.getTargets': {
|
|
157
|
+
'Target.getTargets': {
|
|
158
|
+
targetInfos: [{ targetId: 'T1', type: 'page', url: 'https://x.test' }],
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
await expect(switchToFrame(client, 'S1', 'iframe')).resolves.toEqual({
|
|
162
|
+
url: 'https://f.test/frame',
|
|
163
|
+
sessionId: null,
|
|
153
164
|
});
|
|
154
|
-
await expect(switchToFrame(client, 'S1', 'iframe')).resolves.toEqual({ url: 'https://f.test/frame', sessionId: null });
|
|
155
165
|
expect(calls.map((c) => c.method)).not.toContain('Target.attachToTarget');
|
|
156
166
|
});
|
|
157
167
|
|
|
@@ -167,7 +177,10 @@ describe('switchToFrame', () => {
|
|
|
167
177
|
},
|
|
168
178
|
'Target.attachToTarget': { sessionId: 'S-FRAME' },
|
|
169
179
|
});
|
|
170
|
-
await expect(switchToFrame(client, 'S1', 'iframe')).resolves.toEqual({
|
|
180
|
+
await expect(switchToFrame(client, 'S1', 'iframe')).resolves.toEqual({
|
|
181
|
+
url: 'https://f.test/frame',
|
|
182
|
+
sessionId: 'S-FRAME',
|
|
183
|
+
});
|
|
171
184
|
const attach = calls.find((c) => c.method === 'Target.attachToTarget');
|
|
172
185
|
expect(attach!.params).toEqual({ targetId: 'T-OOPIF', flatten: true });
|
|
173
186
|
});
|
|
@@ -177,7 +190,10 @@ describe('switchToFrame', () => {
|
|
|
177
190
|
'Runtime.evaluate': { result: { result: { value: 'https://f.test/frame' } } },
|
|
178
191
|
'Page.getFrameTree': frameTreeWith('https://other.test/elsewhere'),
|
|
179
192
|
});
|
|
180
|
-
await expect(switchToFrame(client, 'S1', 'iframe')).resolves.toEqual({
|
|
193
|
+
await expect(switchToFrame(client, 'S1', 'iframe')).resolves.toEqual({
|
|
194
|
+
url: 'https://f.test/frame',
|
|
195
|
+
sessionId: null,
|
|
196
|
+
});
|
|
181
197
|
expect(calls.map((c) => c.method)).not.toContain('Target.getTargets');
|
|
182
198
|
});
|
|
183
199
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/browser/action-builder/analyzer.ts
|
|
2
|
-
import { spawn } from 'child_process';
|
|
2
|
+
import { spawn } from 'node:child_process';
|
|
3
3
|
import type { ActionDef } from './types.js';
|
|
4
4
|
|
|
5
5
|
export interface AnalyzerPage {
|
|
@@ -45,7 +45,15 @@ function claudeCliCall(prompt: string): Promise<string> {
|
|
|
45
45
|
return new Promise((resolve, reject) => {
|
|
46
46
|
const child = spawn(
|
|
47
47
|
'claude',
|
|
48
|
-
[
|
|
48
|
+
[
|
|
49
|
+
'--print',
|
|
50
|
+
'--model',
|
|
51
|
+
'haiku',
|
|
52
|
+
'--strict-mcp-config',
|
|
53
|
+
'--no-session-persistence',
|
|
54
|
+
'--',
|
|
55
|
+
prompt,
|
|
56
|
+
],
|
|
49
57
|
{ stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true },
|
|
50
58
|
);
|
|
51
59
|
let stdout = '';
|
|
@@ -54,11 +62,19 @@ function claudeCliCall(prompt: string): Promise<string> {
|
|
|
54
62
|
const timer = setTimeout(() => {
|
|
55
63
|
if (settled) return;
|
|
56
64
|
settled = true;
|
|
57
|
-
try {
|
|
65
|
+
try {
|
|
66
|
+
child.kill('SIGTERM');
|
|
67
|
+
} catch {
|
|
68
|
+
/* ignore */
|
|
69
|
+
}
|
|
58
70
|
reject(new Error('claude --print timed out after 60s'));
|
|
59
71
|
}, 60_000);
|
|
60
|
-
child.stdout.on('data', (d: Buffer) => {
|
|
61
|
-
|
|
72
|
+
child.stdout.on('data', (d: Buffer) => {
|
|
73
|
+
stdout += d.toString();
|
|
74
|
+
});
|
|
75
|
+
child.stderr.on('data', (d: Buffer) => {
|
|
76
|
+
stderr += d.toString();
|
|
77
|
+
});
|
|
62
78
|
child.on('close', (code) => {
|
|
63
79
|
if (settled) return;
|
|
64
80
|
settled = true;
|
|
@@ -70,7 +86,11 @@ function claudeCliCall(prompt: string): Promise<string> {
|
|
|
70
86
|
if (settled) return;
|
|
71
87
|
settled = true;
|
|
72
88
|
clearTimeout(timer);
|
|
73
|
-
reject(
|
|
89
|
+
reject(
|
|
90
|
+
new Error(
|
|
91
|
+
`claude CLI not found — is Claude Code installed? (${(err as NodeJS.ErrnoException).code})`,
|
|
92
|
+
),
|
|
93
|
+
);
|
|
74
94
|
});
|
|
75
95
|
});
|
|
76
96
|
}
|
|
@@ -103,7 +123,7 @@ ActionDef schema:
|
|
|
103
123
|
export async function analyzePageForAction(
|
|
104
124
|
page: AnalyzerPage,
|
|
105
125
|
task: string,
|
|
106
|
-
|
|
126
|
+
_options: AnalyzerOptions = {},
|
|
107
127
|
): Promise<ActionDef> {
|
|
108
128
|
const url = await page.url();
|
|
109
129
|
const title = await page.evaluate<string>('document.title');
|
|
@@ -119,13 +139,15 @@ export async function analyzePageForAction(
|
|
|
119
139
|
const domContext = `URL: ${url}
|
|
120
140
|
Title: ${title}
|
|
121
141
|
Interactive elements (${elements.length}):
|
|
122
|
-
${elements
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}
|
|
142
|
+
${elements
|
|
143
|
+
.map((el, i) => {
|
|
144
|
+
const attrs = Object.entries(el.attrs)
|
|
145
|
+
.filter(([, v]) => v)
|
|
146
|
+
.map(([k, v]) => `${k}="${v}"`)
|
|
147
|
+
.join(' ');
|
|
148
|
+
return `${i + 1}. <${el.tag}${attrs ? ` ${attrs}` : ''}>${el.text}</${el.tag}>`;
|
|
149
|
+
})
|
|
150
|
+
.join('\n')}`;
|
|
129
151
|
|
|
130
152
|
const fullPrompt = `${SYSTEM_PROMPT}\n\nTask: ${task}\n\nPage context:\n${domContext}`;
|
|
131
153
|
const responseText = await claudeCliCall(fullPrompt);
|
|
@@ -138,7 +160,9 @@ ${elements.map((el, i) => {
|
|
|
138
160
|
}
|
|
139
161
|
|
|
140
162
|
if (!actionDef.id || !actionDef.steps || !Array.isArray(actionDef.steps)) {
|
|
141
|
-
throw new Error(
|
|
163
|
+
throw new Error(
|
|
164
|
+
`Claude returned invalid ActionDef: missing id or steps\n${responseText.slice(0, 500)}`,
|
|
165
|
+
);
|
|
142
166
|
}
|
|
143
167
|
|
|
144
168
|
return actionDef;
|
|
@@ -1,12 +1,49 @@
|
|
|
1
|
-
export interface NavigateStep {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export interface
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
export interface NavigateStep {
|
|
2
|
+
type: 'navigate';
|
|
3
|
+
url: string;
|
|
4
|
+
}
|
|
5
|
+
export interface FindStep {
|
|
6
|
+
type: 'find';
|
|
7
|
+
selectors: string[];
|
|
8
|
+
as: string;
|
|
9
|
+
}
|
|
10
|
+
export interface ClickStep {
|
|
11
|
+
type: 'click';
|
|
12
|
+
target: string;
|
|
13
|
+
}
|
|
14
|
+
export interface TypeStep {
|
|
15
|
+
type: 'type';
|
|
16
|
+
target: string;
|
|
17
|
+
text: string;
|
|
18
|
+
humanDelay?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface WaitStep {
|
|
21
|
+
type: 'wait';
|
|
22
|
+
condition: 'network_idle' | 'selector' | 'duration';
|
|
23
|
+
timeout?: number;
|
|
24
|
+
selector?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface ExtractStep {
|
|
27
|
+
type: 'extract';
|
|
28
|
+
target: string;
|
|
29
|
+
as: string;
|
|
30
|
+
attribute?: string;
|
|
31
|
+
}
|
|
32
|
+
export interface ConditionStep {
|
|
33
|
+
type: 'condition';
|
|
34
|
+
expression: string;
|
|
35
|
+
then: StepDef[];
|
|
36
|
+
else?: StepDef[];
|
|
37
|
+
}
|
|
8
38
|
|
|
9
|
-
export type StepDef =
|
|
39
|
+
export type StepDef =
|
|
40
|
+
| NavigateStep
|
|
41
|
+
| FindStep
|
|
42
|
+
| ClickStep
|
|
43
|
+
| TypeStep
|
|
44
|
+
| WaitStep
|
|
45
|
+
| ExtractStep
|
|
46
|
+
| ConditionStep;
|
|
10
47
|
|
|
11
48
|
export interface ActionDef {
|
|
12
49
|
id: string;
|