@roxybrowser/playwright 2.0.2-beta.0
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 +115 -0
- package/dist/apiRequestContext.d.ts +52 -0
- package/dist/apiRequestContext.d.ts.map +1 -0
- package/dist/apiRequestContext.js +632 -0
- package/dist/apiRequestContext.js.map +1 -0
- package/dist/ariaSnapshot.d.ts +38 -0
- package/dist/ariaSnapshot.d.ts.map +1 -0
- package/dist/ariaSnapshot.js +1137 -0
- package/dist/ariaSnapshot.js.map +1 -0
- package/dist/assertions.d.ts +2 -0
- package/dist/assertions.d.ts.map +1 -0
- package/dist/assertions.js +6 -0
- package/dist/assertions.js.map +1 -0
- package/dist/bin/roxybrowser-mcp.d.ts +3 -0
- package/dist/bin/roxybrowser-mcp.d.ts.map +1 -0
- package/dist/bin/roxybrowser-mcp.js +7 -0
- package/dist/bin/roxybrowser-mcp.js.map +1 -0
- package/dist/browser.d.ts +15 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +67 -0
- package/dist/browser.js.map +1 -0
- package/dist/browserContext.d.ts +156 -0
- package/dist/browserContext.d.ts.map +1 -0
- package/dist/browserContext.js +1129 -0
- package/dist/browserContext.js.map +1 -0
- package/dist/browserContextClock.d.ts +54 -0
- package/dist/browserContextClock.d.ts.map +1 -0
- package/dist/browserContextClock.js +147 -0
- package/dist/browserContextClock.js.map +1 -0
- package/dist/browserType.d.ts +16 -0
- package/dist/browserType.d.ts.map +1 -0
- package/dist/browserType.js +68 -0
- package/dist/browserType.js.map +1 -0
- package/dist/bundle.d.ts +20 -0
- package/dist/bundle.d.ts.map +1 -0
- package/dist/bundle.js +20 -0
- package/dist/bundle.js.map +1 -0
- package/dist/clock.d.ts +43 -0
- package/dist/clock.d.ts.map +1 -0
- package/dist/clock.js +70 -0
- package/dist/clock.js.map +1 -0
- package/dist/elementHandle.d.ts +100 -0
- package/dist/elementHandle.d.ts.map +1 -0
- package/dist/elementHandle.js +423 -0
- package/dist/elementHandle.js.map +1 -0
- package/dist/errors.d.ts +10 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +19 -0
- package/dist/errors.js.map +1 -0
- package/dist/evaluation.d.ts +4 -0
- package/dist/evaluation.d.ts.map +1 -0
- package/dist/evaluation.js +9 -0
- package/dist/evaluation.js.map +1 -0
- package/dist/frame.d.ts +139 -0
- package/dist/frame.d.ts.map +1 -0
- package/dist/frame.js +451 -0
- package/dist/frame.js.map +1 -0
- package/dist/httpHeaders.d.ts +6 -0
- package/dist/httpHeaders.d.ts.map +1 -0
- package/dist/httpHeaders.js +23 -0
- package/dist/httpHeaders.js.map +1 -0
- package/dist/human/controller.d.ts +15 -0
- package/dist/human/controller.d.ts.map +1 -0
- package/dist/human/controller.js +67 -0
- package/dist/human/controller.js.map +1 -0
- package/dist/human/profile.d.ts +5 -0
- package/dist/human/profile.d.ts.map +1 -0
- package/dist/human/profile.js +50 -0
- package/dist/human/profile.js.map +1 -0
- package/dist/human/types.d.ts +28 -0
- package/dist/human/types.d.ts.map +1 -0
- package/dist/human/types.js +2 -0
- package/dist/human/types.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/inputFiles.d.ts +18 -0
- package/dist/inputFiles.d.ts.map +1 -0
- package/dist/inputFiles.js +192 -0
- package/dist/inputFiles.js.map +1 -0
- package/dist/jsHandle.d.ts +32 -0
- package/dist/jsHandle.d.ts.map +1 -0
- package/dist/jsHandle.js +148 -0
- package/dist/jsHandle.js.map +1 -0
- package/dist/locator.d.ts +190 -0
- package/dist/locator.d.ts.map +1 -0
- package/dist/locator.js +883 -0
- package/dist/locator.js.map +1 -0
- package/dist/locatorSelectors.d.ts +11 -0
- package/dist/locatorSelectors.d.ts.map +1 -0
- package/dist/locatorSelectors.js +50 -0
- package/dist/locatorSelectors.js.map +1 -0
- package/dist/mcp/backend/common.d.ts +4 -0
- package/dist/mcp/backend/common.d.ts.map +1 -0
- package/dist/mcp/backend/common.js +40 -0
- package/dist/mcp/backend/common.js.map +1 -0
- package/dist/mcp/backend/connect.d.ts +10 -0
- package/dist/mcp/backend/connect.d.ts.map +1 -0
- package/dist/mcp/backend/connect.js +30 -0
- package/dist/mcp/backend/connect.js.map +1 -0
- package/dist/mcp/backend/console.d.ts +13 -0
- package/dist/mcp/backend/console.d.ts.map +1 -0
- package/dist/mcp/backend/console.js +36 -0
- package/dist/mcp/backend/console.js.map +1 -0
- package/dist/mcp/backend/context.d.ts +27 -0
- package/dist/mcp/backend/context.d.ts.map +1 -0
- package/dist/mcp/backend/context.js +33 -0
- package/dist/mcp/backend/context.js.map +1 -0
- package/dist/mcp/backend/dialogs.d.ts +7 -0
- package/dist/mcp/backend/dialogs.d.ts.map +1 -0
- package/dist/mcp/backend/dialogs.js +24 -0
- package/dist/mcp/backend/dialogs.js.map +1 -0
- package/dist/mcp/backend/evaluate.d.ts +9 -0
- package/dist/mcp/backend/evaluate.d.ts.map +1 -0
- package/dist/mcp/backend/evaluate.js +31 -0
- package/dist/mcp/backend/evaluate.js.map +1 -0
- package/dist/mcp/backend/files.d.ts +9 -0
- package/dist/mcp/backend/files.d.ts.map +1 -0
- package/dist/mcp/backend/files.js +39 -0
- package/dist/mcp/backend/files.js.map +1 -0
- package/dist/mcp/backend/keyboard.d.ts +22 -0
- package/dist/mcp/backend/keyboard.d.ts.map +1 -0
- package/dist/mcp/backend/keyboard.js +67 -0
- package/dist/mcp/backend/keyboard.js.map +1 -0
- package/dist/mcp/backend/navigate.d.ts +4 -0
- package/dist/mcp/backend/navigate.d.ts.map +1 -0
- package/dist/mcp/backend/navigate.js +82 -0
- package/dist/mcp/backend/navigate.js.map +1 -0
- package/dist/mcp/backend/network.d.ts +17 -0
- package/dist/mcp/backend/network.d.ts.map +1 -0
- package/dist/mcp/backend/network.js +144 -0
- package/dist/mcp/backend/network.js.map +1 -0
- package/dist/mcp/backend/response.d.ts +26 -0
- package/dist/mcp/backend/response.d.ts.map +1 -0
- package/dist/mcp/backend/response.js +109 -0
- package/dist/mcp/backend/response.js.map +1 -0
- package/dist/mcp/backend/runCode.d.ts +6 -0
- package/dist/mcp/backend/runCode.d.ts.map +1 -0
- package/dist/mcp/backend/runCode.js +20 -0
- package/dist/mcp/backend/runCode.js.map +1 -0
- package/dist/mcp/backend/screenshot.d.ts +13 -0
- package/dist/mcp/backend/screenshot.d.ts.map +1 -0
- package/dist/mcp/backend/screenshot.js +37 -0
- package/dist/mcp/backend/screenshot.js.map +1 -0
- package/dist/mcp/backend/snapshot.d.ts +70 -0
- package/dist/mcp/backend/snapshot.d.ts.map +1 -0
- package/dist/mcp/backend/snapshot.js +185 -0
- package/dist/mcp/backend/snapshot.js.map +1 -0
- package/dist/mcp/backend/tab.d.ts +72 -0
- package/dist/mcp/backend/tab.d.ts.map +1 -0
- package/dist/mcp/backend/tab.js +99 -0
- package/dist/mcp/backend/tab.js.map +1 -0
- package/dist/mcp/backend/tabs.d.ts +13 -0
- package/dist/mcp/backend/tabs.d.ts.map +1 -0
- package/dist/mcp/backend/tabs.js +44 -0
- package/dist/mcp/backend/tabs.js.map +1 -0
- package/dist/mcp/backend/tool.d.ts +52 -0
- package/dist/mcp/backend/tool.d.ts.map +1 -0
- package/dist/mcp/backend/tool.js +28 -0
- package/dist/mcp/backend/tool.js.map +1 -0
- package/dist/mcp/backend/tools.d.ts +4 -0
- package/dist/mcp/backend/tools.d.ts.map +1 -0
- package/dist/mcp/backend/tools.js +30 -0
- package/dist/mcp/backend/tools.js.map +1 -0
- package/dist/mcp/connectedBrowser.d.ts +3 -0
- package/dist/mcp/connectedBrowser.d.ts.map +1 -0
- package/dist/mcp/connectedBrowser.js +2153 -0
- package/dist/mcp/connectedBrowser.js.map +1 -0
- package/dist/mcp/errors.d.ts +6 -0
- package/dist/mcp/errors.d.ts.map +1 -0
- package/dist/mcp/errors.js +12 -0
- package/dist/mcp/errors.js.map +1 -0
- package/dist/mcp/format.d.ts +12 -0
- package/dist/mcp/format.d.ts.map +1 -0
- package/dist/mcp/format.js +48 -0
- package/dist/mcp/format.js.map +1 -0
- package/dist/mcp/index.d.ts +6 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +5 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/output.d.ts +7 -0
- package/dist/mcp/output.d.ts.map +1 -0
- package/dist/mcp/output.js +39 -0
- package/dist/mcp/output.js.map +1 -0
- package/dist/mcp/runtime.d.ts +122 -0
- package/dist/mcp/runtime.d.ts.map +1 -0
- package/dist/mcp/runtime.js +524 -0
- package/dist/mcp/runtime.js.map +1 -0
- package/dist/mcp/schemas.d.ts +61 -0
- package/dist/mcp/schemas.d.ts.map +1 -0
- package/dist/mcp/schemas.js +41 -0
- package/dist/mcp/schemas.js.map +1 -0
- package/dist/mcp/server.d.ts +3 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +117 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/snapshot.d.ts +3 -0
- package/dist/mcp/snapshot.d.ts.map +1 -0
- package/dist/mcp/snapshot.js +3 -0
- package/dist/mcp/snapshot.js.map +1 -0
- package/dist/mcp/tool.d.ts +19 -0
- package/dist/mcp/tool.d.ts.map +1 -0
- package/dist/mcp/tool.js +10 -0
- package/dist/mcp/tool.js.map +1 -0
- package/dist/mcp/tools/common.d.ts +6 -0
- package/dist/mcp/tools/common.d.ts.map +1 -0
- package/dist/mcp/tools/common.js +34 -0
- package/dist/mcp/tools/common.js.map +1 -0
- package/dist/mcp/tools/connect.d.ts +6 -0
- package/dist/mcp/tools/connect.d.ts.map +1 -0
- package/dist/mcp/tools/connect.js +28 -0
- package/dist/mcp/tools/connect.js.map +1 -0
- package/dist/mcp/tools/console.d.ts +6 -0
- package/dist/mcp/tools/console.d.ts.map +1 -0
- package/dist/mcp/tools/console.js +36 -0
- package/dist/mcp/tools/console.js.map +1 -0
- package/dist/mcp/tools/dialog.d.ts +6 -0
- package/dist/mcp/tools/dialog.d.ts.map +1 -0
- package/dist/mcp/tools/dialog.js +22 -0
- package/dist/mcp/tools/dialog.js.map +1 -0
- package/dist/mcp/tools/evaluate.d.ts +6 -0
- package/dist/mcp/tools/evaluate.d.ts.map +1 -0
- package/dist/mcp/tools/evaluate.js +31 -0
- package/dist/mcp/tools/evaluate.js.map +1 -0
- package/dist/mcp/tools/form.d.ts +6 -0
- package/dist/mcp/tools/form.d.ts.map +1 -0
- package/dist/mcp/tools/form.js +129 -0
- package/dist/mcp/tools/form.js.map +1 -0
- package/dist/mcp/tools/index.d.ts +3 -0
- package/dist/mcp/tools/index.d.ts.map +1 -0
- package/dist/mcp/tools/index.js +7 -0
- package/dist/mcp/tools/index.js.map +1 -0
- package/dist/mcp/tools/keyboard.d.ts +3 -0
- package/dist/mcp/tools/keyboard.d.ts.map +1 -0
- package/dist/mcp/tools/keyboard.js +44 -0
- package/dist/mcp/tools/keyboard.js.map +1 -0
- package/dist/mcp/tools/mouse.d.ts +3 -0
- package/dist/mcp/tools/mouse.d.ts.map +1 -0
- package/dist/mcp/tools/mouse.js +89 -0
- package/dist/mcp/tools/mouse.js.map +1 -0
- package/dist/mcp/tools/navigate.d.ts +6 -0
- package/dist/mcp/tools/navigate.d.ts.map +1 -0
- package/dist/mcp/tools/navigate.js +74 -0
- package/dist/mcp/tools/navigate.js.map +1 -0
- package/dist/mcp/tools/network.d.ts +6 -0
- package/dist/mcp/tools/network.d.ts.map +1 -0
- package/dist/mcp/tools/network.js +142 -0
- package/dist/mcp/tools/network.js.map +1 -0
- package/dist/mcp/tools/runCode.d.ts +6 -0
- package/dist/mcp/tools/runCode.d.ts.map +1 -0
- package/dist/mcp/tools/runCode.js +24 -0
- package/dist/mcp/tools/runCode.js.map +1 -0
- package/dist/mcp/tools/screenshot.d.ts +6 -0
- package/dist/mcp/tools/screenshot.d.ts.map +1 -0
- package/dist/mcp/tools/screenshot.js +46 -0
- package/dist/mcp/tools/screenshot.js.map +1 -0
- package/dist/mcp/tools/snapshot.d.ts +6 -0
- package/dist/mcp/tools/snapshot.d.ts.map +1 -0
- package/dist/mcp/tools/snapshot.js +56 -0
- package/dist/mcp/tools/snapshot.js.map +1 -0
- package/dist/mcp/tools/tabs.d.ts +6 -0
- package/dist/mcp/tools/tabs.d.ts.map +1 -0
- package/dist/mcp/tools/tabs.js +34 -0
- package/dist/mcp/tools/tabs.js.map +1 -0
- package/dist/mcp/transports/http.d.ts +3 -0
- package/dist/mcp/transports/http.d.ts.map +1 -0
- package/dist/mcp/transports/http.js +134 -0
- package/dist/mcp/transports/http.js.map +1 -0
- package/dist/mcp/transports/inMemory.d.ts +3 -0
- package/dist/mcp/transports/inMemory.d.ts.map +1 -0
- package/dist/mcp/transports/inMemory.js +18 -0
- package/dist/mcp/transports/inMemory.js.map +1 -0
- package/dist/mcp/transports/stdio.d.ts +3 -0
- package/dist/mcp/transports/stdio.d.ts.map +1 -0
- package/dist/mcp/transports/stdio.js +16 -0
- package/dist/mcp/transports/stdio.js.map +1 -0
- package/dist/mcp/types.d.ts +193 -0
- package/dist/mcp/types.d.ts.map +1 -0
- package/dist/mcp/types.js +2 -0
- package/dist/mcp/types.js.map +1 -0
- package/dist/navigationResult.d.ts +10 -0
- package/dist/navigationResult.d.ts.map +1 -0
- package/dist/navigationResult.js +15 -0
- package/dist/navigationResult.js.map +1 -0
- package/dist/page.d.ts +907 -0
- package/dist/page.d.ts.map +1 -0
- package/dist/page.js +6385 -0
- package/dist/page.js.map +1 -0
- package/dist/pageApiReport.d.ts +31 -0
- package/dist/pageApiReport.d.ts.map +1 -0
- package/dist/pageApiReport.js +218 -0
- package/dist/pageApiReport.js.map +1 -0
- package/dist/pageResponse.d.ts +18 -0
- package/dist/pageResponse.d.ts.map +1 -0
- package/dist/pageResponse.js +23 -0
- package/dist/pageResponse.js.map +1 -0
- package/dist/processCleanup.d.ts +8 -0
- package/dist/processCleanup.d.ts.map +1 -0
- package/dist/processCleanup.js +413 -0
- package/dist/processCleanup.js.map +1 -0
- package/dist/protocol/adapter.d.ts +406 -0
- package/dist/protocol/adapter.d.ts.map +1 -0
- package/dist/protocol/adapter.js +8 -0
- package/dist/protocol/adapter.js.map +1 -0
- package/dist/protocol/bidi/backend.d.ts +8 -0
- package/dist/protocol/bidi/backend.d.ts.map +1 -0
- package/dist/protocol/bidi/backend.js +3616 -0
- package/dist/protocol/bidi/backend.js.map +1 -0
- package/dist/protocol/bidi/client.d.ts +104 -0
- package/dist/protocol/bidi/client.d.ts.map +1 -0
- package/dist/protocol/bidi/client.js +228 -0
- package/dist/protocol/bidi/client.js.map +1 -0
- package/dist/protocol/capabilities.d.ts +11 -0
- package/dist/protocol/capabilities.d.ts.map +1 -0
- package/dist/protocol/capabilities.js +2 -0
- package/dist/protocol/capabilities.js.map +1 -0
- package/dist/protocol/cdp/backend.d.ts +24 -0
- package/dist/protocol/cdp/backend.d.ts.map +1 -0
- package/dist/protocol/cdp/backend.js +8428 -0
- package/dist/protocol/cdp/backend.js.map +1 -0
- package/dist/protocol/evaluate.d.ts +2 -0
- package/dist/protocol/evaluate.d.ts.map +1 -0
- package/dist/protocol/evaluate.js +14 -0
- package/dist/protocol/evaluate.js.map +1 -0
- package/dist/protocol/evaluationSerializer.d.ts +6 -0
- package/dist/protocol/evaluationSerializer.d.ts.map +1 -0
- package/dist/protocol/evaluationSerializer.js +234 -0
- package/dist/protocol/evaluationSerializer.js.map +1 -0
- package/dist/protocol/keyboardInput.d.ts +34 -0
- package/dist/protocol/keyboardInput.d.ts.map +1 -0
- package/dist/protocol/keyboardInput.js +246 -0
- package/dist/protocol/keyboardInput.js.map +1 -0
- package/dist/protocol/routing.d.ts +40 -0
- package/dist/protocol/routing.d.ts.map +1 -0
- package/dist/protocol/routing.js +2 -0
- package/dist/protocol/routing.js.map +1 -0
- package/dist/protocol/selectorRuntime.d.ts +30 -0
- package/dist/protocol/selectorRuntime.d.ts.map +1 -0
- package/dist/protocol/selectorRuntime.js +1814 -0
- package/dist/protocol/selectorRuntime.js.map +1 -0
- package/dist/protocol/webdriver-classic/backend.d.ts +6 -0
- package/dist/protocol/webdriver-classic/backend.d.ts.map +1 -0
- package/dist/protocol/webdriver-classic/backend.js +158 -0
- package/dist/protocol/webdriver-classic/backend.js.map +1 -0
- package/dist/routeHandler.d.ts +15 -0
- package/dist/routeHandler.d.ts.map +1 -0
- package/dist/routeHandler.js +2 -0
- package/dist/routeHandler.js.map +1 -0
- package/dist/roxybrowser.bundle.js +78236 -0
- package/dist/roxybrowser.bundle.js.map +1 -0
- package/dist/screencast.d.ts +57 -0
- package/dist/screencast.d.ts.map +1 -0
- package/dist/screencast.js +155 -0
- package/dist/screencast.js.map +1 -0
- package/dist/screencastActions.d.ts +2 -0
- package/dist/screencastActions.d.ts.map +1 -0
- package/dist/screencastActions.js +183 -0
- package/dist/screencastActions.js.map +1 -0
- package/dist/screencastOverlay.d.ts +3 -0
- package/dist/screencastOverlay.d.ts.map +1 -0
- package/dist/screencastOverlay.js +119 -0
- package/dist/screencastOverlay.js.map +1 -0
- package/dist/screenshotOptions.d.ts +26 -0
- package/dist/screenshotOptions.d.ts.map +1 -0
- package/dist/screenshotOptions.js +171 -0
- package/dist/screenshotOptions.js.map +1 -0
- package/dist/screenshotPreparation.d.ts +21 -0
- package/dist/screenshotPreparation.d.ts.map +1 -0
- package/dist/screenshotPreparation.js +199 -0
- package/dist/screenshotPreparation.js.map +1 -0
- package/dist/selectOptionValues.d.ts +10 -0
- package/dist/selectOptionValues.d.ts.map +1 -0
- package/dist/selectOptionValues.js +60 -0
- package/dist/selectOptionValues.js.map +1 -0
- package/dist/selectors.d.ts +3 -0
- package/dist/selectors.d.ts.map +1 -0
- package/dist/selectors.js +287 -0
- package/dist/selectors.js.map +1 -0
- package/dist/types/api.d.ts +2164 -0
- package/dist/types/api.d.ts.map +1 -0
- package/dist/types/api.js +2 -0
- package/dist/types/api.js.map +1 -0
- package/dist/types/events.d.ts +158 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +2 -0
- package/dist/types/events.js.map +1 -0
- package/dist/types/options.d.ts +263 -0
- package/dist/types/options.d.ts.map +1 -0
- package/dist/types/options.js +2 -0
- package/dist/types/options.js.map +1 -0
- package/dist/urlMatch.d.ts +19 -0
- package/dist/urlMatch.d.ts.map +1 -0
- package/dist/urlMatch.js +183 -0
- package/dist/urlMatch.js.map +1 -0
- package/dist/utilityScriptSerializers.d.ts +61 -0
- package/dist/utilityScriptSerializers.d.ts.map +1 -0
- package/dist/utilityScriptSerializers.js +297 -0
- package/dist/utilityScriptSerializers.js.map +1 -0
- package/dist/vendor/playwright/ariaSnapshotEvaluate.d.ts +2 -0
- package/dist/vendor/playwright/ariaSnapshotEvaluate.d.ts.map +1 -0
- package/dist/vendor/playwright/ariaSnapshotEvaluate.js +207 -0
- package/dist/vendor/playwright/ariaSnapshotEvaluate.js.map +1 -0
- package/dist/vendor/playwright/generated/clockSource.d.ts +9 -0
- package/dist/vendor/playwright/generated/clockSource.d.ts.map +1 -0
- package/dist/vendor/playwright/generated/clockSource.js +9 -0
- package/dist/vendor/playwright/generated/clockSource.js.map +1 -0
- package/dist/vendor/playwright/generated/injectedScriptSource.d.ts +9 -0
- package/dist/vendor/playwright/generated/injectedScriptSource.d.ts.map +1 -0
- package/dist/vendor/playwright/generated/injectedScriptSource.js +9 -0
- package/dist/vendor/playwright/generated/injectedScriptSource.js.map +1 -0
- package/dist/video.d.ts +39 -0
- package/dist/video.d.ts.map +1 -0
- package/dist/video.js +235 -0
- package/dist/video.js.map +1 -0
- package/dist/waitForSelector.d.ts +7 -0
- package/dist/waitForSelector.d.ts.map +1 -0
- package/dist/waitForSelector.js +23 -0
- package/dist/waitForSelector.js.map +1 -0
- package/dist/worker.d.ts +45 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +192 -0
- package/dist/worker.js.map +1 -0
- package/package.json +82 -0
package/dist/locator.js
ADDED
|
@@ -0,0 +1,883 @@
|
|
|
1
|
+
import { readFile, stat } from "node:fs/promises";
|
|
2
|
+
import { basename, extname, resolve } from "node:path";
|
|
3
|
+
import { TimeoutError } from "./errors.js";
|
|
4
|
+
import { assertFillValue } from "./assertions.js";
|
|
5
|
+
import { resolveHumanizationOptions } from "./human/profile.js";
|
|
6
|
+
import { assertMaxArguments, serializePageFunction } from "./evaluation.js";
|
|
7
|
+
import { RoxyElementHandle, serializeEvaluationArgument } from "./elementHandle.js";
|
|
8
|
+
import { convertInputFiles } from "./inputFiles.js";
|
|
9
|
+
import { normalizeSelectOptionValues } from "./selectOptionValues.js";
|
|
10
|
+
import { createRemoteJSHandle, createSmartHandle } from "./jsHandle.js";
|
|
11
|
+
import { createAltTextLocatorSelector, createInternalTextLocatorSelector, createLabelLocatorSelector, createPlaceholderLocatorSelector, createRoleLocatorSelector, createTestIdLocatorSelector, createTextLocatorSelector, createTitleLocatorSelector } from "./locatorSelectors.js";
|
|
12
|
+
import { parseSelectorChain } from "./selectors.js";
|
|
13
|
+
const ENTER_FRAME_SELECTOR = {
|
|
14
|
+
strategy: "control",
|
|
15
|
+
value: "enter-frame"
|
|
16
|
+
};
|
|
17
|
+
const FIRST_SELECTOR = {
|
|
18
|
+
strategy: "control",
|
|
19
|
+
value: "pick",
|
|
20
|
+
pick: { kind: "first" }
|
|
21
|
+
};
|
|
22
|
+
const LAST_SELECTOR = {
|
|
23
|
+
strategy: "control",
|
|
24
|
+
value: "pick",
|
|
25
|
+
pick: { kind: "last" }
|
|
26
|
+
};
|
|
27
|
+
const DEFAULT_LOCATOR_HUMAN_DEFAULTS = resolveHumanizationOptions({ enabled: false });
|
|
28
|
+
const DEFAULT_WAIT_TIMEOUT_MS = 30_000;
|
|
29
|
+
function cloneLocatorSelector(selector) {
|
|
30
|
+
return {
|
|
31
|
+
...selector,
|
|
32
|
+
...(selector.hasChain ? { hasChain: selector.hasChain.map(cloneLocatorSelector) } : {})
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function cloneLocatorSelectorChain(chain) {
|
|
36
|
+
return chain.map(cloneLocatorSelector);
|
|
37
|
+
}
|
|
38
|
+
function selectorChainForLocator(locator, optionName) {
|
|
39
|
+
const chain = locator._roxySelectorChain?.();
|
|
40
|
+
if (!chain) {
|
|
41
|
+
throw new Error(`Inner "${optionName}" locator must belong to the same frame.`);
|
|
42
|
+
}
|
|
43
|
+
return cloneLocatorSelectorChain(chain);
|
|
44
|
+
}
|
|
45
|
+
function frameIdentityForLocator(locator) {
|
|
46
|
+
return locator._roxyFrameIdentity?.();
|
|
47
|
+
}
|
|
48
|
+
function assertSameFrameLocator(currentFrameIdentity, locator, errorMessage) {
|
|
49
|
+
const innerFrameIdentity = frameIdentityForLocator(locator);
|
|
50
|
+
if (currentFrameIdentity !== undefined &&
|
|
51
|
+
innerFrameIdentity !== undefined &&
|
|
52
|
+
currentFrameIdentity !== innerFrameIdentity) {
|
|
53
|
+
throw new Error(errorMessage);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function selectorChainForSameFrameLocator(currentFrameIdentity, locator, errorMessage) {
|
|
57
|
+
assertSameFrameLocator(currentFrameIdentity, locator, errorMessage);
|
|
58
|
+
const chain = locator._roxySelectorChain?.();
|
|
59
|
+
if (!chain) {
|
|
60
|
+
throw new Error(errorMessage);
|
|
61
|
+
}
|
|
62
|
+
return cloneLocatorSelectorChain(chain);
|
|
63
|
+
}
|
|
64
|
+
class DisposableStub {
|
|
65
|
+
callback;
|
|
66
|
+
constructor(callback) {
|
|
67
|
+
this.callback = callback;
|
|
68
|
+
}
|
|
69
|
+
dispose() {
|
|
70
|
+
return this.callback();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async function convertDropFiles(files) {
|
|
74
|
+
if (files === undefined) {
|
|
75
|
+
return [];
|
|
76
|
+
}
|
|
77
|
+
const items = Array.isArray(files) ? files : [files];
|
|
78
|
+
if (items.every((item) => typeof item === "string")) {
|
|
79
|
+
return Promise.all(items.map(async (filePath) => {
|
|
80
|
+
const resolved = resolve(filePath);
|
|
81
|
+
const [buffer, fileStat] = await Promise.all([
|
|
82
|
+
readFile(resolved),
|
|
83
|
+
stat(resolved)
|
|
84
|
+
]);
|
|
85
|
+
return {
|
|
86
|
+
buffer: buffer.toString("base64"),
|
|
87
|
+
lastModifiedMs: fileStat.mtimeMs,
|
|
88
|
+
mimeType: inferDropMimeType(resolved),
|
|
89
|
+
name: basename(resolved)
|
|
90
|
+
};
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
const resolved = await convertInputFiles(items);
|
|
94
|
+
return resolved.payloads.map((payload) => ({
|
|
95
|
+
buffer: payload.base64,
|
|
96
|
+
mimeType: payload.mimeType,
|
|
97
|
+
name: payload.name,
|
|
98
|
+
...(payload.lastModifiedMs === undefined ? {} : { lastModifiedMs: payload.lastModifiedMs })
|
|
99
|
+
}));
|
|
100
|
+
}
|
|
101
|
+
function inferDropMimeType(filePath) {
|
|
102
|
+
const extension = extname(filePath).toLowerCase();
|
|
103
|
+
switch (extension) {
|
|
104
|
+
case ".avif":
|
|
105
|
+
return "image/avif";
|
|
106
|
+
case ".bmp":
|
|
107
|
+
return "image/bmp";
|
|
108
|
+
case ".css":
|
|
109
|
+
return "text/css";
|
|
110
|
+
case ".csv":
|
|
111
|
+
return "text/csv";
|
|
112
|
+
case ".gif":
|
|
113
|
+
return "image/gif";
|
|
114
|
+
case ".htm":
|
|
115
|
+
case ".html":
|
|
116
|
+
return "text/html";
|
|
117
|
+
case ".jpg":
|
|
118
|
+
case ".jpeg":
|
|
119
|
+
return "image/jpeg";
|
|
120
|
+
case ".js":
|
|
121
|
+
case ".mjs":
|
|
122
|
+
return "text/javascript";
|
|
123
|
+
case ".json":
|
|
124
|
+
return "application/json";
|
|
125
|
+
case ".md":
|
|
126
|
+
return "text/markdown";
|
|
127
|
+
case ".pdf":
|
|
128
|
+
return "application/pdf";
|
|
129
|
+
case ".png":
|
|
130
|
+
return "image/png";
|
|
131
|
+
case ".svg":
|
|
132
|
+
return "image/svg+xml";
|
|
133
|
+
case ".txt":
|
|
134
|
+
return "text/plain";
|
|
135
|
+
case ".webp":
|
|
136
|
+
return "image/webp";
|
|
137
|
+
case ".xml":
|
|
138
|
+
return "application/xml";
|
|
139
|
+
case ".zip":
|
|
140
|
+
return "application/zip";
|
|
141
|
+
default:
|
|
142
|
+
return "application/octet-stream";
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function chainLocator(adapter, selector) {
|
|
146
|
+
const chain = parseSelectorChain(selector);
|
|
147
|
+
const [first, ...rest] = chain;
|
|
148
|
+
if (!first) {
|
|
149
|
+
throw new Error("Selector must not be empty.");
|
|
150
|
+
}
|
|
151
|
+
let current = adapter.locator(first);
|
|
152
|
+
for (const part of rest) {
|
|
153
|
+
current = current.locator(part);
|
|
154
|
+
}
|
|
155
|
+
return current;
|
|
156
|
+
}
|
|
157
|
+
export class RoxyLocator {
|
|
158
|
+
adapter;
|
|
159
|
+
humanController;
|
|
160
|
+
beforeAction;
|
|
161
|
+
humanDefaults;
|
|
162
|
+
frameResolver;
|
|
163
|
+
ownerPage;
|
|
164
|
+
frameIdentity;
|
|
165
|
+
selectorChain;
|
|
166
|
+
constructor(adapter, humanController, selectorChain = null, beforeAction, humanDefaults = DEFAULT_LOCATOR_HUMAN_DEFAULTS, frameResolver, ownerPage, frameIdentity) {
|
|
167
|
+
this.adapter = adapter;
|
|
168
|
+
this.humanController = humanController;
|
|
169
|
+
this.beforeAction = beforeAction;
|
|
170
|
+
this.humanDefaults = humanDefaults;
|
|
171
|
+
this.frameResolver = frameResolver;
|
|
172
|
+
this.ownerPage = ownerPage;
|
|
173
|
+
this.frameIdentity = frameIdentity;
|
|
174
|
+
this.selectorChain = selectorChain ? cloneLocatorSelectorChain(selectorChain) : null;
|
|
175
|
+
}
|
|
176
|
+
_roxySelectorChain() {
|
|
177
|
+
return this.selectorChain ? cloneLocatorSelectorChain(this.selectorChain) : null;
|
|
178
|
+
}
|
|
179
|
+
_roxyFrameIdentity() {
|
|
180
|
+
return this.frameIdentity;
|
|
181
|
+
}
|
|
182
|
+
page() {
|
|
183
|
+
if (!this.ownerPage) {
|
|
184
|
+
throw new Error("Locator is not associated with a page.");
|
|
185
|
+
}
|
|
186
|
+
return this.ownerPage;
|
|
187
|
+
}
|
|
188
|
+
cloneWith(adapter, selectorChain = this.selectorChain) {
|
|
189
|
+
return new RoxyLocator(adapter, this.humanController, selectorChain, this.beforeAction, this.humanDefaults, this.frameResolver, this.ownerPage, this.frameIdentity);
|
|
190
|
+
}
|
|
191
|
+
locator(selectorOrLocator, options) {
|
|
192
|
+
if (typeof selectorOrLocator !== "string") {
|
|
193
|
+
const selector = {
|
|
194
|
+
strategy: "control",
|
|
195
|
+
value: "chain",
|
|
196
|
+
composite: "chain",
|
|
197
|
+
hasChain: selectorChainForSameFrameLocator(this.frameIdentity, selectorOrLocator, "Locators must belong to the same frame.")
|
|
198
|
+
};
|
|
199
|
+
const locator = this.cloneWith(this.adapter.locator(selector), [...(this.selectorChain ?? []), selector]);
|
|
200
|
+
return options ? locator.filter(options) : locator;
|
|
201
|
+
}
|
|
202
|
+
const selector = selectorOrLocator;
|
|
203
|
+
const chain = parseSelectorChain(selector);
|
|
204
|
+
const locator = new RoxyLocator(chainLocator(this.adapter, selector), this.humanController, [...(this.selectorChain ?? []), ...chain], this.beforeAction, this.humanDefaults, this.frameResolver, this.ownerPage, this.frameIdentity);
|
|
205
|
+
return options ? locator.filter(options) : locator;
|
|
206
|
+
}
|
|
207
|
+
_roxyLocatorFromChain(chain, options) {
|
|
208
|
+
let adapter = this.adapter;
|
|
209
|
+
for (const selector of chain) {
|
|
210
|
+
adapter = adapter.locator(selector);
|
|
211
|
+
}
|
|
212
|
+
const locator = this.cloneWith(adapter, [...(this.selectorChain ?? []), ...cloneLocatorSelectorChain(chain)]);
|
|
213
|
+
return options ? locator.filter(options) : locator;
|
|
214
|
+
}
|
|
215
|
+
frameLocator(selector) {
|
|
216
|
+
return this.locator(selector).contentFrame();
|
|
217
|
+
}
|
|
218
|
+
contentFrame() {
|
|
219
|
+
return new RoxyFrameLocator(this, new RoxyLocator(this.adapter.locator(ENTER_FRAME_SELECTOR), this.humanController, [...(this.selectorChain ?? []), ENTER_FRAME_SELECTOR], this.beforeAction, this.humanDefaults, this.frameResolver, this.ownerPage, this.frameIdentity));
|
|
220
|
+
}
|
|
221
|
+
getByText(text, options) {
|
|
222
|
+
return new RoxyLocator(this.adapter.getByText(text, options), this.humanController, this.extendSelectorChain("getByText", text, options), this.beforeAction, this.humanDefaults, this.frameResolver, this.ownerPage, this.frameIdentity);
|
|
223
|
+
}
|
|
224
|
+
getByAltText(text, options) {
|
|
225
|
+
return new RoxyLocator(this.adapter.getByAltText(text, options), this.humanController, this.extendSelectorChain("getByAltText", text, options), this.beforeAction, this.humanDefaults, this.frameResolver, this.ownerPage, this.frameIdentity);
|
|
226
|
+
}
|
|
227
|
+
getByLabel(text, options) {
|
|
228
|
+
return new RoxyLocator(this.adapter.getByLabel(text, options), this.humanController, this.extendSelectorChain("getByLabel", text, options), this.beforeAction, this.humanDefaults, this.frameResolver, this.ownerPage, this.frameIdentity);
|
|
229
|
+
}
|
|
230
|
+
getByPlaceholder(text, options) {
|
|
231
|
+
return new RoxyLocator(this.adapter.getByPlaceholder(text, options), this.humanController, this.extendSelectorChain("getByPlaceholder", text, options), this.beforeAction, this.humanDefaults, this.frameResolver, this.ownerPage, this.frameIdentity);
|
|
232
|
+
}
|
|
233
|
+
getByTestId(testId) {
|
|
234
|
+
return new RoxyLocator(this.adapter.getByTestId(testId), this.humanController, this.extendSelectorChain("getByTestId", testId), this.beforeAction, this.humanDefaults, this.frameResolver, this.ownerPage, this.frameIdentity);
|
|
235
|
+
}
|
|
236
|
+
getByRole(role, options) {
|
|
237
|
+
return new RoxyLocator(this.adapter.getByRole(role, options), this.humanController, this.extendSelectorChain("getByRole", role, options), this.beforeAction, this.humanDefaults, this.frameResolver, this.ownerPage, this.frameIdentity);
|
|
238
|
+
}
|
|
239
|
+
getByTitle(text, options) {
|
|
240
|
+
return new RoxyLocator(this.adapter.getByTitle(text, options), this.humanController, this.extendSelectorChain("getByTitle", text, options), this.beforeAction, this.humanDefaults, this.frameResolver, this.ownerPage, this.frameIdentity);
|
|
241
|
+
}
|
|
242
|
+
first() {
|
|
243
|
+
return this.cloneWith(this.adapter.first(), [...(this.selectorChain ?? []), FIRST_SELECTOR]);
|
|
244
|
+
}
|
|
245
|
+
last() {
|
|
246
|
+
return this.cloneWith(this.adapter.last(), [...(this.selectorChain ?? []), LAST_SELECTOR]);
|
|
247
|
+
}
|
|
248
|
+
nth(index) {
|
|
249
|
+
if (this.selectorChain?.some((selector) => selector.capture)) {
|
|
250
|
+
throw new Error("Can't query n-th element");
|
|
251
|
+
}
|
|
252
|
+
return this.cloneWith(this.adapter.nth(index), [
|
|
253
|
+
...(this.selectorChain ?? []),
|
|
254
|
+
{
|
|
255
|
+
strategy: "control",
|
|
256
|
+
value: "pick",
|
|
257
|
+
pick: { kind: "nth", index }
|
|
258
|
+
}
|
|
259
|
+
]);
|
|
260
|
+
}
|
|
261
|
+
filter(options) {
|
|
262
|
+
let adapter = this.adapter;
|
|
263
|
+
const chain = [...(this.selectorChain ?? [])];
|
|
264
|
+
if (options?.has !== undefined) {
|
|
265
|
+
const selector = {
|
|
266
|
+
strategy: "control",
|
|
267
|
+
value: "has",
|
|
268
|
+
filter: true,
|
|
269
|
+
hasChain: selectorChainForSameFrameLocator(this.frameIdentity, options.has, 'Inner "has" locator must belong to the same frame.')
|
|
270
|
+
};
|
|
271
|
+
adapter = adapter.locator(selector);
|
|
272
|
+
chain.push(selector);
|
|
273
|
+
}
|
|
274
|
+
if (options?.hasNot !== undefined) {
|
|
275
|
+
const selector = {
|
|
276
|
+
strategy: "control",
|
|
277
|
+
value: "has-not",
|
|
278
|
+
filter: true,
|
|
279
|
+
negate: true,
|
|
280
|
+
hasChain: selectorChainForSameFrameLocator(this.frameIdentity, options.hasNot, 'Inner "hasNot" locator must belong to the same frame.')
|
|
281
|
+
};
|
|
282
|
+
adapter = adapter.locator(selector);
|
|
283
|
+
chain.push(selector);
|
|
284
|
+
}
|
|
285
|
+
if (options?.hasText !== undefined) {
|
|
286
|
+
const selector = {
|
|
287
|
+
...createInternalTextLocatorSelector(options.hasText),
|
|
288
|
+
filter: true
|
|
289
|
+
};
|
|
290
|
+
adapter = adapter.locator(selector);
|
|
291
|
+
chain.push(selector);
|
|
292
|
+
}
|
|
293
|
+
if (options?.hasNotText !== undefined) {
|
|
294
|
+
const selector = {
|
|
295
|
+
...createInternalTextLocatorSelector(options.hasNotText),
|
|
296
|
+
filter: true,
|
|
297
|
+
negate: true
|
|
298
|
+
};
|
|
299
|
+
adapter = adapter.locator(selector);
|
|
300
|
+
chain.push(selector);
|
|
301
|
+
}
|
|
302
|
+
if (options?.visible !== undefined) {
|
|
303
|
+
const selector = {
|
|
304
|
+
strategy: "control",
|
|
305
|
+
value: "visible",
|
|
306
|
+
filter: true,
|
|
307
|
+
visible: options.visible
|
|
308
|
+
};
|
|
309
|
+
adapter = adapter.locator(selector);
|
|
310
|
+
chain.push(selector);
|
|
311
|
+
}
|
|
312
|
+
return this.cloneWith(adapter, chain);
|
|
313
|
+
}
|
|
314
|
+
and(locator) {
|
|
315
|
+
const selector = {
|
|
316
|
+
strategy: "control",
|
|
317
|
+
value: "and",
|
|
318
|
+
composite: "and",
|
|
319
|
+
hasChain: selectorChainForSameFrameLocator(this.frameIdentity, locator, "Locators must belong to the same frame.")
|
|
320
|
+
};
|
|
321
|
+
return this.cloneWith(this.adapter.locator(selector), [...(this.selectorChain ?? []), selector]);
|
|
322
|
+
}
|
|
323
|
+
or(locator) {
|
|
324
|
+
const selector = {
|
|
325
|
+
strategy: "control",
|
|
326
|
+
value: "or",
|
|
327
|
+
composite: "or",
|
|
328
|
+
hasChain: selectorChainForSameFrameLocator(this.frameIdentity, locator, "Locators must belong to the same frame.")
|
|
329
|
+
};
|
|
330
|
+
return this.cloneWith(this.adapter.locator(selector), [...(this.selectorChain ?? []), selector]);
|
|
331
|
+
}
|
|
332
|
+
describe(description) {
|
|
333
|
+
return this.cloneWith(this.adapter, [
|
|
334
|
+
...(this.selectorChain ?? []),
|
|
335
|
+
{ strategy: "control", value: "describe", description }
|
|
336
|
+
]);
|
|
337
|
+
}
|
|
338
|
+
description() {
|
|
339
|
+
const lastSelector = this.selectorChain?.[this.selectorChain.length - 1];
|
|
340
|
+
return lastSelector?.strategy === "control" && lastSelector.value === "describe"
|
|
341
|
+
? lastSelector.description ?? null
|
|
342
|
+
: null;
|
|
343
|
+
}
|
|
344
|
+
async all() {
|
|
345
|
+
return Array.from({ length: await this.count() }, (_value, index) => this.nth(index));
|
|
346
|
+
}
|
|
347
|
+
async allInnerTexts() {
|
|
348
|
+
return this.evaluateAll((elements) => elements.map((element) => element.innerText));
|
|
349
|
+
}
|
|
350
|
+
async allTextContents() {
|
|
351
|
+
return this.evaluateAll((elements) => elements.map((element) => element.textContent || ""));
|
|
352
|
+
}
|
|
353
|
+
async count() {
|
|
354
|
+
return this.adapter.count();
|
|
355
|
+
}
|
|
356
|
+
async evaluate(pageFunction, argOrOptions, options) {
|
|
357
|
+
assertMaxArguments(arguments.length, 3);
|
|
358
|
+
const hasArg = arguments.length >= 2 && (arguments.length !== 2 || !looksLikeTimeoutOptions(argOrOptions));
|
|
359
|
+
void (hasArg ? options : argOrOptions);
|
|
360
|
+
return this.adapter.evaluate(serializePageFunction(pageFunction), serializeEvaluationArgument(hasArg ? argOrOptions : undefined), typeof pageFunction === "function");
|
|
361
|
+
}
|
|
362
|
+
async evaluateAll(pageFunction, arg) {
|
|
363
|
+
assertMaxArguments(arguments.length, 2);
|
|
364
|
+
return this.adapter.evaluateAll(serializePageFunction(pageFunction), serializeEvaluationArgument(arg), typeof pageFunction === "function");
|
|
365
|
+
}
|
|
366
|
+
async evaluateHandle(pageFunction, argOrOptions, options) {
|
|
367
|
+
assertMaxArguments(arguments.length, 3);
|
|
368
|
+
const hasArg = arguments.length >= 2 && (arguments.length !== 2 || !looksLikeTimeoutOptions(argOrOptions));
|
|
369
|
+
void (hasArg ? options : argOrOptions);
|
|
370
|
+
if (this.adapter.evaluateHandle) {
|
|
371
|
+
return await createRemoteJSHandle(await this.adapter.evaluateHandle(serializePageFunction(pageFunction), serializeEvaluationArgument(hasArg ? argOrOptions : undefined), typeof pageFunction === "function"), (reference) => this.frameResolver?.createElementHandleFromReference(reference)
|
|
372
|
+
?? new RoxyElementHandle(this.adapter.elementHandle(), this.humanDefaults, this.frameResolver));
|
|
373
|
+
}
|
|
374
|
+
return createSmartHandle(await this.evaluate(pageFunction, hasArg ? argOrOptions : undefined));
|
|
375
|
+
}
|
|
376
|
+
async boundingBox(options) {
|
|
377
|
+
void options;
|
|
378
|
+
return this.adapter.boundingBox();
|
|
379
|
+
}
|
|
380
|
+
async actionPoint(options = {}) {
|
|
381
|
+
const box = await this.boundingBox(options.timeout === undefined ? undefined : { timeout: options.timeout });
|
|
382
|
+
if (!box) {
|
|
383
|
+
throw new Error("locator.dragTo: Element is not visible.");
|
|
384
|
+
}
|
|
385
|
+
const position = options.position ?? {
|
|
386
|
+
x: box.width / 2,
|
|
387
|
+
y: box.height / 2
|
|
388
|
+
};
|
|
389
|
+
return {
|
|
390
|
+
x: box.x + position.x,
|
|
391
|
+
y: box.y + position.y
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
async dblclick(options) {
|
|
395
|
+
const actionOptions = this.withBeforeActionRetry(options);
|
|
396
|
+
await this.beforeAction?.(this, actionOptions);
|
|
397
|
+
await this.adapter.dblclick(actionOptions);
|
|
398
|
+
}
|
|
399
|
+
async check(options) {
|
|
400
|
+
const actionOptions = this.withBeforeActionRetry(options);
|
|
401
|
+
await this.beforeAction?.(this, actionOptions);
|
|
402
|
+
await this.adapter.check(actionOptions);
|
|
403
|
+
}
|
|
404
|
+
async clear(options) {
|
|
405
|
+
await this.fill("", options);
|
|
406
|
+
}
|
|
407
|
+
async click(options) {
|
|
408
|
+
const actionOptions = this.withBeforeActionRetry(options);
|
|
409
|
+
await this.beforeAction?.(this, actionOptions);
|
|
410
|
+
await this.humanController.click(this.adapter, actionOptions);
|
|
411
|
+
}
|
|
412
|
+
async hover(options) {
|
|
413
|
+
const actionOptions = this.withBeforeActionRetry(options);
|
|
414
|
+
await this.beforeAction?.(this, actionOptions);
|
|
415
|
+
await this.humanController.hover(this.adapter, actionOptions);
|
|
416
|
+
}
|
|
417
|
+
async fill(value, options) {
|
|
418
|
+
assertFillValue(value);
|
|
419
|
+
await this.beforeAction?.(this, options);
|
|
420
|
+
await this.humanController.fill(this.adapter, value, options);
|
|
421
|
+
}
|
|
422
|
+
async type(value, options) {
|
|
423
|
+
await this.beforeAction?.(this, options);
|
|
424
|
+
await this.humanController.type(this.adapter, value, options);
|
|
425
|
+
}
|
|
426
|
+
async press(key, options) {
|
|
427
|
+
await this.beforeAction?.(this, options);
|
|
428
|
+
await this.humanController.press(this.adapter, key, options);
|
|
429
|
+
}
|
|
430
|
+
async pressSequentially(text, options) {
|
|
431
|
+
await this.type(text, options);
|
|
432
|
+
}
|
|
433
|
+
async focus() {
|
|
434
|
+
await this.adapter.focus();
|
|
435
|
+
}
|
|
436
|
+
async blur(options) {
|
|
437
|
+
void options;
|
|
438
|
+
await this.adapter.blur();
|
|
439
|
+
}
|
|
440
|
+
async dispatchEvent(type, eventInit, options) {
|
|
441
|
+
await this.adapter.dispatchEvent(type, eventInit, options);
|
|
442
|
+
}
|
|
443
|
+
async dragTo(target, options) {
|
|
444
|
+
const sourcePoint = await this.actionPoint({
|
|
445
|
+
...(options?.sourcePosition === undefined ? {} : { position: options.sourcePosition }),
|
|
446
|
+
...(options?.timeout === undefined ? {} : { timeout: options.timeout })
|
|
447
|
+
});
|
|
448
|
+
if (!(target instanceof RoxyLocator)) {
|
|
449
|
+
throw new Error("locator.dragTo: Target must be a Roxy locator.");
|
|
450
|
+
}
|
|
451
|
+
const targetPoint = await target.actionPoint({
|
|
452
|
+
...(options?.targetPosition === undefined ? {} : { position: options.targetPosition }),
|
|
453
|
+
...(options?.timeout === undefined ? {} : { timeout: options.timeout })
|
|
454
|
+
});
|
|
455
|
+
if (options?.trial) {
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
const mouse = this.page().mouse;
|
|
459
|
+
await mouse.move(sourcePoint.x, sourcePoint.y);
|
|
460
|
+
await mouse.down();
|
|
461
|
+
await mouse.move(targetPoint.x, targetPoint.y, options?.steps === undefined ? undefined : { steps: options.steps });
|
|
462
|
+
await mouse.up();
|
|
463
|
+
}
|
|
464
|
+
async drop(payload, options) {
|
|
465
|
+
const hasFiles = payload.files !== undefined && (Array.isArray(payload.files) ? payload.files.length > 0 : true);
|
|
466
|
+
const hasData = payload.data !== undefined && Object.keys(payload.data).length > 0;
|
|
467
|
+
if (!hasFiles && !hasData) {
|
|
468
|
+
throw new Error('At least one of "files" or "data" must be provided.');
|
|
469
|
+
}
|
|
470
|
+
const handle = await this.elementHandle(options?.timeout === undefined ? {} : { timeout: options.timeout });
|
|
471
|
+
if (!handle) {
|
|
472
|
+
throw new Error("No element found.");
|
|
473
|
+
}
|
|
474
|
+
const files = hasFiles ? await convertDropFiles(payload.files) : [];
|
|
475
|
+
const data = payload.data ?? {};
|
|
476
|
+
const result = await handle.evaluate((element, dropPayload) => {
|
|
477
|
+
if (!element.isConnected) {
|
|
478
|
+
return "error:notconnected";
|
|
479
|
+
}
|
|
480
|
+
const dataTransfer = new DataTransfer();
|
|
481
|
+
for (const file of dropPayload.files) {
|
|
482
|
+
const bytes = Uint8Array.from(atob(file.buffer), (char) => char.charCodeAt(0));
|
|
483
|
+
const fileOptions = { type: file.mimeType || "application/octet-stream" };
|
|
484
|
+
if (file.lastModifiedMs !== undefined) {
|
|
485
|
+
fileOptions.lastModified = file.lastModifiedMs;
|
|
486
|
+
}
|
|
487
|
+
dataTransfer.items.add(new File([bytes], file.name, fileOptions));
|
|
488
|
+
}
|
|
489
|
+
for (const [type, value] of Object.entries(dropPayload.data)) {
|
|
490
|
+
dataTransfer.setData(type, value);
|
|
491
|
+
}
|
|
492
|
+
const rect = element.getBoundingClientRect();
|
|
493
|
+
const point = dropPayload.position ?? {
|
|
494
|
+
x: rect.width / 2,
|
|
495
|
+
y: rect.height / 2
|
|
496
|
+
};
|
|
497
|
+
const clientX = rect.left + point.x;
|
|
498
|
+
const clientY = rect.top + point.y;
|
|
499
|
+
const makeEvent = (type) => new DragEvent(type, {
|
|
500
|
+
bubbles: true,
|
|
501
|
+
cancelable: true,
|
|
502
|
+
clientX,
|
|
503
|
+
clientY,
|
|
504
|
+
composed: true,
|
|
505
|
+
dataTransfer
|
|
506
|
+
});
|
|
507
|
+
element.dispatchEvent(makeEvent("dragenter"));
|
|
508
|
+
const over = makeEvent("dragover");
|
|
509
|
+
element.dispatchEvent(over);
|
|
510
|
+
if (!over.defaultPrevented) {
|
|
511
|
+
element.dispatchEvent(makeEvent("dragleave"));
|
|
512
|
+
return "not-accepted";
|
|
513
|
+
}
|
|
514
|
+
element.dispatchEvent(makeEvent("drop"));
|
|
515
|
+
return "accepted";
|
|
516
|
+
}, {
|
|
517
|
+
data,
|
|
518
|
+
files,
|
|
519
|
+
position: options?.position
|
|
520
|
+
});
|
|
521
|
+
if (result === "error:notconnected") {
|
|
522
|
+
throw new Error("Element is not attached to the DOM.");
|
|
523
|
+
}
|
|
524
|
+
if (result === "not-accepted") {
|
|
525
|
+
throw new Error("Drop target did not accept the drop; its dragover handler did not call preventDefault().");
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
async getAttribute(name) {
|
|
529
|
+
return this.adapter.getAttribute(name);
|
|
530
|
+
}
|
|
531
|
+
async highlight(_options = {}) {
|
|
532
|
+
return new DisposableStub(() => this.hideHighlight());
|
|
533
|
+
}
|
|
534
|
+
async hideHighlight() { }
|
|
535
|
+
async innerHTML() {
|
|
536
|
+
return this.adapter.innerHTML();
|
|
537
|
+
}
|
|
538
|
+
async innerText() {
|
|
539
|
+
return this.adapter.innerText();
|
|
540
|
+
}
|
|
541
|
+
async inputValue() {
|
|
542
|
+
return this.adapter.inputValue();
|
|
543
|
+
}
|
|
544
|
+
async isChecked() {
|
|
545
|
+
return this.adapter.isChecked();
|
|
546
|
+
}
|
|
547
|
+
async isDisabled() {
|
|
548
|
+
return this.adapter.isDisabled();
|
|
549
|
+
}
|
|
550
|
+
async isEditable() {
|
|
551
|
+
return this.adapter.isEditable();
|
|
552
|
+
}
|
|
553
|
+
async isEnabled() {
|
|
554
|
+
return this.adapter.isEnabled();
|
|
555
|
+
}
|
|
556
|
+
async isHidden() {
|
|
557
|
+
return this.adapter.isHidden();
|
|
558
|
+
}
|
|
559
|
+
async ariaSnapshot(options) {
|
|
560
|
+
void options;
|
|
561
|
+
const handle = await this.elementHandle();
|
|
562
|
+
if (!handle) {
|
|
563
|
+
throw new Error("No element found.");
|
|
564
|
+
}
|
|
565
|
+
return handle.evaluate((element) => element.textContent ?? "");
|
|
566
|
+
}
|
|
567
|
+
async normalize() {
|
|
568
|
+
return this;
|
|
569
|
+
}
|
|
570
|
+
async textContent() {
|
|
571
|
+
return this.adapter.textContent();
|
|
572
|
+
}
|
|
573
|
+
async uncheck(options) {
|
|
574
|
+
const actionOptions = this.withBeforeActionRetry(options);
|
|
575
|
+
await this.beforeAction?.(this, actionOptions);
|
|
576
|
+
await this.adapter.uncheck(actionOptions);
|
|
577
|
+
}
|
|
578
|
+
async selectOption(values, options) {
|
|
579
|
+
await this.beforeAction?.(this, options);
|
|
580
|
+
const handle = await this.elementHandle(options?.timeout === undefined ? {} : { timeout: options.timeout });
|
|
581
|
+
if (!handle) {
|
|
582
|
+
throw new TimeoutError(`locator.elementHandle: Timeout ${options?.timeout ?? DEFAULT_WAIT_TIMEOUT_MS}ms exceeded.`);
|
|
583
|
+
}
|
|
584
|
+
return this.adapter.selectOption(await normalizeSelectOptionValues(handle, values), options);
|
|
585
|
+
}
|
|
586
|
+
async screenshot(options) {
|
|
587
|
+
const handle = await this.elementHandle(options?.timeout === undefined ? {} : { timeout: options.timeout });
|
|
588
|
+
if (!handle) {
|
|
589
|
+
throw new Error("No element found.");
|
|
590
|
+
}
|
|
591
|
+
return handle.screenshot(options);
|
|
592
|
+
}
|
|
593
|
+
async scrollIntoViewIfNeeded(options) {
|
|
594
|
+
const handle = await this.elementHandle(options?.timeout === undefined ? {} : { timeout: options.timeout });
|
|
595
|
+
if (!handle) {
|
|
596
|
+
throw new Error("No element found.");
|
|
597
|
+
}
|
|
598
|
+
await handle.scrollIntoViewIfNeeded(options);
|
|
599
|
+
}
|
|
600
|
+
async selectText(options = {}) {
|
|
601
|
+
const handle = await this.elementHandle(options.timeout === undefined ? {} : { timeout: options.timeout });
|
|
602
|
+
if (!handle) {
|
|
603
|
+
throw new Error("No element found.");
|
|
604
|
+
}
|
|
605
|
+
await handle.selectText(options);
|
|
606
|
+
}
|
|
607
|
+
async setChecked(checked, options) {
|
|
608
|
+
if (checked) {
|
|
609
|
+
await this.check(options);
|
|
610
|
+
return;
|
|
611
|
+
}
|
|
612
|
+
await this.uncheck(options);
|
|
613
|
+
}
|
|
614
|
+
async setInputFiles(files, options) {
|
|
615
|
+
const handle = await this.elementHandle(options?.timeout === undefined ? {} : { timeout: options.timeout });
|
|
616
|
+
if (!handle) {
|
|
617
|
+
throw new Error("No element found.");
|
|
618
|
+
}
|
|
619
|
+
await handle.setInputFiles(files, options);
|
|
620
|
+
}
|
|
621
|
+
async tap(options) {
|
|
622
|
+
await this.beforeAction?.(this, options);
|
|
623
|
+
await this.adapter.tap(options);
|
|
624
|
+
}
|
|
625
|
+
async isVisible() {
|
|
626
|
+
return this.adapter.isVisible();
|
|
627
|
+
}
|
|
628
|
+
async waitFor(options = {}) {
|
|
629
|
+
const state = options.state ?? "visible";
|
|
630
|
+
const timeout = options.timeout ?? DEFAULT_WAIT_TIMEOUT_MS;
|
|
631
|
+
const startTime = Date.now();
|
|
632
|
+
while (timeout === 0 || Date.now() - startTime <= timeout) {
|
|
633
|
+
await this.beforeAction?.(this, {
|
|
634
|
+
timeout: timeout === 0 ? 0 : Math.max(0, timeout - (Date.now() - startTime))
|
|
635
|
+
});
|
|
636
|
+
const count = await this.count().catch((error) => {
|
|
637
|
+
if (shouldRethrowWaitForResolutionError(error)) {
|
|
638
|
+
throw error;
|
|
639
|
+
}
|
|
640
|
+
return 0;
|
|
641
|
+
});
|
|
642
|
+
const attached = count > 0;
|
|
643
|
+
const visible = attached
|
|
644
|
+
? await this.isVisible().catch((error) => {
|
|
645
|
+
if (shouldRethrowWaitForResolutionError(error)) {
|
|
646
|
+
throw error;
|
|
647
|
+
}
|
|
648
|
+
return false;
|
|
649
|
+
})
|
|
650
|
+
: false;
|
|
651
|
+
if (state === "attached" && attached)
|
|
652
|
+
return;
|
|
653
|
+
if (state === "visible" && visible)
|
|
654
|
+
return;
|
|
655
|
+
if (state === "hidden" && !visible)
|
|
656
|
+
return;
|
|
657
|
+
if (state === "detached" && !attached)
|
|
658
|
+
return;
|
|
659
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
660
|
+
}
|
|
661
|
+
throw new TimeoutError(`Timeout ${timeout}ms exceeded.`);
|
|
662
|
+
}
|
|
663
|
+
async elementHandle(options = {}) {
|
|
664
|
+
const timeout = options.timeout ?? DEFAULT_WAIT_TIMEOUT_MS;
|
|
665
|
+
const startTime = Date.now();
|
|
666
|
+
let lastError;
|
|
667
|
+
while (timeout === 0 || Date.now() - startTime <= timeout) {
|
|
668
|
+
try {
|
|
669
|
+
return new RoxyElementHandle(await this.adapter.elementHandle(), this.humanDefaults, this.frameResolver);
|
|
670
|
+
}
|
|
671
|
+
catch (error) {
|
|
672
|
+
lastError = error;
|
|
673
|
+
if (timeout === 0) {
|
|
674
|
+
break;
|
|
675
|
+
}
|
|
676
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
if (lastError) {
|
|
680
|
+
throw lastError;
|
|
681
|
+
}
|
|
682
|
+
throw new TimeoutError(`Timeout ${timeout}ms exceeded.`);
|
|
683
|
+
}
|
|
684
|
+
async elementHandles() {
|
|
685
|
+
const handles = await this.adapter.elementHandles();
|
|
686
|
+
return handles.map((handle) => new RoxyElementHandle(handle, this.humanDefaults, this.frameResolver));
|
|
687
|
+
}
|
|
688
|
+
toString() {
|
|
689
|
+
return this.description() ?? formatLocatorChain(this.selectorChain ?? []);
|
|
690
|
+
}
|
|
691
|
+
extendSelectorChain(kind, value, options) {
|
|
692
|
+
const current = this.selectorChain ?? [];
|
|
693
|
+
switch (kind) {
|
|
694
|
+
case "getByText":
|
|
695
|
+
return [...current, createTextLocatorSelector(value, options)];
|
|
696
|
+
case "getByAltText":
|
|
697
|
+
return [...current, createAltTextLocatorSelector(value, options)];
|
|
698
|
+
case "getByLabel":
|
|
699
|
+
return [...current, createLabelLocatorSelector(value, options)];
|
|
700
|
+
case "getByPlaceholder":
|
|
701
|
+
return [
|
|
702
|
+
...current,
|
|
703
|
+
createPlaceholderLocatorSelector(value, options)
|
|
704
|
+
];
|
|
705
|
+
case "getByTestId":
|
|
706
|
+
return [...current, createTestIdLocatorSelector(value)];
|
|
707
|
+
case "getByRole":
|
|
708
|
+
return [
|
|
709
|
+
...current,
|
|
710
|
+
createRoleLocatorSelector(String(value), options)
|
|
711
|
+
];
|
|
712
|
+
case "getByTitle":
|
|
713
|
+
return [...current, createTitleLocatorSelector(value, options)];
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
withBeforeActionRetry(options) {
|
|
717
|
+
if (!this.beforeAction) {
|
|
718
|
+
return options;
|
|
719
|
+
}
|
|
720
|
+
return {
|
|
721
|
+
...(options ?? {}),
|
|
722
|
+
__roxyBeforeActionRetry: async () => {
|
|
723
|
+
return await this.beforeAction?.(this, options);
|
|
724
|
+
}
|
|
725
|
+
};
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
export class RoxyFrameLocator {
|
|
729
|
+
ownerLocator;
|
|
730
|
+
contentLocator;
|
|
731
|
+
constructor(ownerLocator, contentLocator) {
|
|
732
|
+
this.ownerLocator = ownerLocator;
|
|
733
|
+
this.contentLocator = contentLocator;
|
|
734
|
+
}
|
|
735
|
+
first() {
|
|
736
|
+
return this.ownerLocator.first().contentFrame();
|
|
737
|
+
}
|
|
738
|
+
last() {
|
|
739
|
+
return this.ownerLocator.last().contentFrame();
|
|
740
|
+
}
|
|
741
|
+
nth(index) {
|
|
742
|
+
return this.ownerLocator.nth(index).contentFrame();
|
|
743
|
+
}
|
|
744
|
+
frameLocator(selector) {
|
|
745
|
+
return this.contentLocator.frameLocator(selector);
|
|
746
|
+
}
|
|
747
|
+
locator(selectorOrLocator, options) {
|
|
748
|
+
if (typeof selectorOrLocator !== "string") {
|
|
749
|
+
const chain = selectorOrLocator._roxySelectorChain?.();
|
|
750
|
+
if (!chain) {
|
|
751
|
+
throw new Error("Locators must belong to the same frame.");
|
|
752
|
+
}
|
|
753
|
+
return this.contentLocator._roxyLocatorFromChain(chain, options);
|
|
754
|
+
}
|
|
755
|
+
const locator = this.contentLocator.locator(selectorOrLocator);
|
|
756
|
+
return options ? locator.filter(options) : locator;
|
|
757
|
+
}
|
|
758
|
+
getByText(text, options) {
|
|
759
|
+
return this.contentLocator.getByText(text, options);
|
|
760
|
+
}
|
|
761
|
+
getByAltText(text, options) {
|
|
762
|
+
return this.contentLocator.getByAltText(text, options);
|
|
763
|
+
}
|
|
764
|
+
getByLabel(text, options) {
|
|
765
|
+
return this.contentLocator.getByLabel(text, options);
|
|
766
|
+
}
|
|
767
|
+
getByPlaceholder(text, options) {
|
|
768
|
+
return this.contentLocator.getByPlaceholder(text, options);
|
|
769
|
+
}
|
|
770
|
+
getByTestId(testId) {
|
|
771
|
+
return this.contentLocator.getByTestId(testId);
|
|
772
|
+
}
|
|
773
|
+
getByRole(role, options) {
|
|
774
|
+
return this.contentLocator.getByRole(role, options);
|
|
775
|
+
}
|
|
776
|
+
getByTitle(text, options) {
|
|
777
|
+
return this.contentLocator.getByTitle(text, options);
|
|
778
|
+
}
|
|
779
|
+
owner() {
|
|
780
|
+
return this.ownerLocator;
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
function looksLikeTimeoutOptions(value) {
|
|
784
|
+
return Boolean(value
|
|
785
|
+
&& typeof value === "object"
|
|
786
|
+
&& "timeout" in value
|
|
787
|
+
&& Object.keys(value).every((key) => key === "timeout"));
|
|
788
|
+
}
|
|
789
|
+
function shouldRethrowWaitForResolutionError(error) {
|
|
790
|
+
const message = String(error instanceof Error ? error.message : error);
|
|
791
|
+
return (message.includes("strict mode violation")
|
|
792
|
+
|| message.includes("Can't query n-th element")
|
|
793
|
+
|| message.includes("<iframe> was expected"));
|
|
794
|
+
}
|
|
795
|
+
function formatLocatorChain(chain) {
|
|
796
|
+
const formatted = chain
|
|
797
|
+
.map(formatLocatorSelector)
|
|
798
|
+
.filter((part) => Boolean(part));
|
|
799
|
+
return formatted.length ? formatted.join(".") : "locator('')";
|
|
800
|
+
}
|
|
801
|
+
function formatLocatorSelector(selector) {
|
|
802
|
+
if (selector.strategy === "control" && selector.value === "describe") {
|
|
803
|
+
return null;
|
|
804
|
+
}
|
|
805
|
+
if (selector.strategy === "css") {
|
|
806
|
+
switch (selector.label) {
|
|
807
|
+
case "alt":
|
|
808
|
+
return formatTextLocatorCall("getByAltText", selector);
|
|
809
|
+
case "label":
|
|
810
|
+
return formatTextLocatorCall("getByLabel", selector);
|
|
811
|
+
case "placeholder":
|
|
812
|
+
return formatTextLocatorCall("getByPlaceholder", selector);
|
|
813
|
+
case "testId":
|
|
814
|
+
return formatTextLocatorCall("getByTestId", selector);
|
|
815
|
+
case "title":
|
|
816
|
+
return formatTextLocatorCall("getByTitle", selector);
|
|
817
|
+
default:
|
|
818
|
+
return `locator(${quote(selector.value)})`;
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
if (selector.strategy === "text") {
|
|
822
|
+
return formatTextLocatorCall("getByText", selector);
|
|
823
|
+
}
|
|
824
|
+
if (selector.strategy === "role") {
|
|
825
|
+
const options = formatLocatorOptions([
|
|
826
|
+
formatMaybeRegexOption("name", selector.name, selector.nameIsRegex, selector.nameRegexFlags),
|
|
827
|
+
typeof selector.name === "string" && selector.exact ? "exact: true" : null
|
|
828
|
+
]);
|
|
829
|
+
return `getByRole(${quote(selector.value)}${options})`;
|
|
830
|
+
}
|
|
831
|
+
if (selector.strategy === "control") {
|
|
832
|
+
if (selector.value === "enter-frame") {
|
|
833
|
+
return "contentFrame()";
|
|
834
|
+
}
|
|
835
|
+
if (selector.value === "pick" && selector.pick) {
|
|
836
|
+
if (selector.pick.kind === "nth") {
|
|
837
|
+
return `nth(${selector.pick.index})`;
|
|
838
|
+
}
|
|
839
|
+
return `${selector.pick.kind}()`;
|
|
840
|
+
}
|
|
841
|
+
if (selector.value === "chain" && selector.hasChain) {
|
|
842
|
+
return `locator(${formatLocatorChain(selector.hasChain)})`;
|
|
843
|
+
}
|
|
844
|
+
if (selector.value === "and" && selector.hasChain) {
|
|
845
|
+
return `and(${formatLocatorChain(selector.hasChain)})`;
|
|
846
|
+
}
|
|
847
|
+
if (selector.value === "or" && selector.hasChain) {
|
|
848
|
+
return `or(${formatLocatorChain(selector.hasChain)})`;
|
|
849
|
+
}
|
|
850
|
+
if (selector.value === "has" && selector.hasChain) {
|
|
851
|
+
return `filter({ has: ${formatLocatorChain(selector.hasChain)} })`;
|
|
852
|
+
}
|
|
853
|
+
if (selector.value === "has-not" && selector.hasChain) {
|
|
854
|
+
return `filter({ hasNot: ${formatLocatorChain(selector.hasChain)} })`;
|
|
855
|
+
}
|
|
856
|
+
return `locator(${quote(`internal:control=${selector.value}`)})`;
|
|
857
|
+
}
|
|
858
|
+
return `locator(${quote(`${selector.strategy}=${selector.value}`)})`;
|
|
859
|
+
}
|
|
860
|
+
function formatTextLocatorCall(method, selector) {
|
|
861
|
+
const value = formatMaybeRegexValue(selector.value, selector.isRegex, selector.regexFlags);
|
|
862
|
+
const options = typeof selector.value === "string" && selector.exact
|
|
863
|
+
? ", { exact: true }"
|
|
864
|
+
: "";
|
|
865
|
+
return `${method}(${value}${options})`;
|
|
866
|
+
}
|
|
867
|
+
function formatMaybeRegexOption(name, value, isRegex, flags) {
|
|
868
|
+
if (value === undefined) {
|
|
869
|
+
return null;
|
|
870
|
+
}
|
|
871
|
+
return `${name}: ${formatMaybeRegexValue(value, isRegex, flags)}`;
|
|
872
|
+
}
|
|
873
|
+
function formatMaybeRegexValue(value, isRegex, flags) {
|
|
874
|
+
return isRegex ? `/${value.replace(/\//g, "\\/")}/${flags ?? ""}` : quote(value);
|
|
875
|
+
}
|
|
876
|
+
function formatLocatorOptions(options) {
|
|
877
|
+
const filtered = options.filter((option) => Boolean(option));
|
|
878
|
+
return filtered.length ? `, { ${filtered.join(", ")} }` : "";
|
|
879
|
+
}
|
|
880
|
+
function quote(value) {
|
|
881
|
+
return `'${JSON.stringify(value).slice(1, -1).replace(/'/g, "\\'")}'`;
|
|
882
|
+
}
|
|
883
|
+
//# sourceMappingURL=locator.js.map
|