tabwright 1.0.0 → 1.0.1
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/aria-snapshot.d.ts +0 -1
- package/dist/aria-snapshot.js +9 -1
- package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.d.ts +0 -1
- package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.js +0 -1
- package/dist/bippy.js +1 -1
- package/dist/browser-config.d.ts +0 -1
- package/dist/browser-config.js +0 -1
- package/dist/browser-install.d.ts +0 -1
- package/dist/browser-install.js +0 -1
- package/dist/browser-launch.d.ts +0 -1
- package/dist/browser-launch.js +0 -1
- package/dist/builtin-capabilities.d.ts +0 -1
- package/dist/builtin-capabilities.js +0 -1
- package/dist/capability-agent-skill.d.ts +0 -1
- package/dist/capability-agent-skill.js +0 -1
- package/dist/capability-auth-state.d.ts +0 -1
- package/dist/capability-auth-state.js +0 -1
- package/dist/capability-auth.d.ts +0 -1
- package/dist/capability-auth.js +0 -1
- package/dist/capability-options.d.ts +0 -1
- package/dist/capability-options.js +0 -1
- package/dist/capability-package.d.ts +0 -1
- package/dist/capability-package.js +0 -1
- package/dist/capability-registry.d.ts +0 -1
- package/dist/capability-registry.js +0 -1
- package/dist/capability-runner.d.ts +0 -1
- package/dist/capability-runner.js +0 -1
- package/dist/capability-studio.d.ts +0 -1
- package/dist/capability-studio.js +0 -1
- package/dist/cdp-log.d.ts +0 -1
- package/dist/cdp-log.js +0 -1
- package/dist/cdp-relay.d.ts +0 -1
- package/dist/cdp-relay.js +0 -1
- package/dist/cdp-session.d.ts +0 -1
- package/dist/cdp-session.js +0 -1
- package/dist/cdp-types.d.ts +0 -1
- package/dist/cdp-types.js +0 -1
- package/dist/chrome-discovery.d.ts +0 -1
- package/dist/chrome-discovery.js +0 -1
- package/dist/clean-html.d.ts +0 -1
- package/dist/clean-html.js +0 -1
- package/dist/cli.d.ts +0 -1
- package/dist/cli.js +9 -2
- package/dist/cloud-client.d.ts +0 -1
- package/dist/cloud-client.js +0 -1
- package/dist/create-logger.d.ts +0 -1
- package/dist/create-logger.js +0 -1
- package/dist/debugger-examples-types.d.ts +0 -1
- package/dist/debugger-examples-types.js +0 -1
- package/dist/debugger-examples.d.ts +0 -1
- package/dist/debugger-examples.js +0 -1
- package/dist/debugger.d.ts +0 -1
- package/dist/debugger.js +0 -1
- package/dist/diff-utils.d.ts +0 -1
- package/dist/diff-utils.js +0 -1
- package/dist/doctor.d.ts +0 -1
- package/dist/doctor.js +5 -7
- package/dist/editor-examples.d.ts +0 -1
- package/dist/editor-examples.js +0 -1
- package/dist/editor.d.ts +0 -1
- package/dist/editor.js +0 -1
- package/dist/env-compat.d.ts +0 -1
- package/dist/env-compat.js +0 -1
- package/dist/executor.d.ts +0 -1
- package/dist/executor.js +1 -2
- package/dist/extension/background.js +7 -3
- package/dist/extension/manifest.json +1 -1
- package/dist/ghost-browser.d.ts +0 -1
- package/dist/ghost-browser.js +0 -1
- package/dist/ghost-cursor-controller.d.ts +0 -1
- package/dist/ghost-cursor-controller.js +0 -1
- package/dist/ghost-cursor.d.ts +0 -1
- package/dist/ghost-cursor.js +0 -1
- package/dist/htmlrewrite.d.ts +0 -1
- package/dist/htmlrewrite.js +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/kill-port.d.ts +0 -1
- package/dist/kill-port.js +0 -1
- package/dist/kitty-graphics.d.ts +0 -1
- package/dist/kitty-graphics.js +0 -1
- package/dist/mcp.d.ts +0 -1
- package/dist/mcp.js +0 -1
- package/dist/package-paths.d.ts +0 -1
- package/dist/package-paths.js +0 -1
- package/dist/page-markdown.d.ts +0 -1
- package/dist/page-markdown.js +0 -1
- package/dist/performance-examples.d.ts +0 -1
- package/dist/performance-examples.js +0 -1
- package/dist/playwright-import.d.ts +0 -1
- package/dist/playwright-import.js +0 -1
- package/dist/product-paths.d.ts +0 -1
- package/dist/product-paths.js +0 -1
- package/dist/protocol.d.ts +0 -1
- package/dist/protocol.js +0 -1
- package/dist/react-source.d.ts +0 -1
- package/dist/react-source.js +0 -1
- package/dist/readability.js +1 -1
- package/dist/relay-client.d.ts +0 -1
- package/dist/relay-client.js +0 -1
- package/dist/relay-state.d.ts +0 -1
- package/dist/relay-state.js +0 -1
- package/dist/replay-ai-index.d.ts +0 -1
- package/dist/replay-ai-index.js +0 -1
- package/dist/replay-eval.d.ts +0 -1
- package/dist/replay-eval.js +0 -1
- package/dist/replay-handoff.d.ts +0 -1
- package/dist/replay-handoff.js +0 -1
- package/dist/replay-workflow-compiler.d.ts +0 -1
- package/dist/replay-workflow-compiler.js +0 -1
- package/dist/rrweb-recording-relay.d.ts +0 -1
- package/dist/rrweb-recording-relay.js +0 -1
- package/dist/rrweb-recording.d.ts +0 -1
- package/dist/rrweb-recording.js +0 -1
- package/dist/scoped-fs.d.ts +0 -1
- package/dist/scoped-fs.js +0 -1
- package/dist/selector-generator.js +1 -1
- package/dist/start-relay-server.d.ts +0 -1
- package/dist/start-relay-server.js +0 -1
- package/dist/styles-examples.d.ts +0 -1
- package/dist/styles-examples.js +0 -1
- package/dist/styles.d.ts +0 -1
- package/dist/styles.js +0 -1
- package/dist/tabwright-agent-skill.d.ts +0 -1
- package/dist/tabwright-agent-skill.js +0 -1
- package/dist/test-declarations.d.ts +0 -1
- package/dist/test-declarations.js +0 -1
- package/dist/utils.d.ts +0 -1
- package/dist/utils.js +2 -2
- package/dist/wait-for-page-load.d.ts +0 -1
- package/dist/wait-for-page-load.js +0 -1
- package/dist/workflow-capability.d.ts +0 -1
- package/dist/workflow-capability.js +0 -1
- package/package.json +9 -4
- package/readme.md +35 -0
- package/dist/aria-snapshot.d.ts.map +0 -1
- package/dist/aria-snapshot.js.map +0 -1
- package/dist/aria-snapshot.test.d.ts +0 -2
- package/dist/aria-snapshot.test.d.ts.map +0 -1
- package/dist/aria-snapshot.test.js +0 -270
- package/dist/aria-snapshot.test.js.map +0 -1
- package/dist/aria-snapshot.unit.test.d.ts +0 -2
- package/dist/aria-snapshot.unit.test.d.ts.map +0 -1
- package/dist/aria-snapshot.unit.test.js +0 -542
- package/dist/aria-snapshot.unit.test.js.map +0 -1
- package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.d.ts.map +0 -1
- package/dist/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.js.map +0 -1
- package/dist/browser-config.d.ts.map +0 -1
- package/dist/browser-config.js.map +0 -1
- package/dist/browser-install.d.ts.map +0 -1
- package/dist/browser-install.js.map +0 -1
- package/dist/browser-launch.d.ts.map +0 -1
- package/dist/browser-launch.js.map +0 -1
- package/dist/builtin-capabilities.d.ts.map +0 -1
- package/dist/builtin-capabilities.js.map +0 -1
- package/dist/capability-agent-skill.d.ts.map +0 -1
- package/dist/capability-agent-skill.js.map +0 -1
- package/dist/capability-auth-state.d.ts.map +0 -1
- package/dist/capability-auth-state.js.map +0 -1
- package/dist/capability-auth.d.ts.map +0 -1
- package/dist/capability-auth.js.map +0 -1
- package/dist/capability-cli-confirmation.test.d.ts +0 -2
- package/dist/capability-cli-confirmation.test.d.ts.map +0 -1
- package/dist/capability-cli-confirmation.test.js +0 -79
- package/dist/capability-cli-confirmation.test.js.map +0 -1
- package/dist/capability-options.d.ts.map +0 -1
- package/dist/capability-options.js.map +0 -1
- package/dist/capability-options.test.d.ts +0 -2
- package/dist/capability-options.test.d.ts.map +0 -1
- package/dist/capability-options.test.js +0 -81
- package/dist/capability-options.test.js.map +0 -1
- package/dist/capability-package.d.ts.map +0 -1
- package/dist/capability-package.js.map +0 -1
- package/dist/capability-package.test.d.ts +0 -2
- package/dist/capability-package.test.d.ts.map +0 -1
- package/dist/capability-package.test.js +0 -179
- package/dist/capability-package.test.js.map +0 -1
- package/dist/capability-registry.d.ts.map +0 -1
- package/dist/capability-registry.js.map +0 -1
- package/dist/capability-registry.test.d.ts +0 -2
- package/dist/capability-registry.test.d.ts.map +0 -1
- package/dist/capability-registry.test.js +0 -1683
- package/dist/capability-registry.test.js.map +0 -1
- package/dist/capability-runner.d.ts.map +0 -1
- package/dist/capability-runner.js.map +0 -1
- package/dist/capability-search-relevance.test.d.ts +0 -2
- package/dist/capability-search-relevance.test.d.ts.map +0 -1
- package/dist/capability-search-relevance.test.js +0 -67
- package/dist/capability-search-relevance.test.js.map +0 -1
- package/dist/capability-studio.d.ts.map +0 -1
- package/dist/capability-studio.js.map +0 -1
- package/dist/capability-studio.test.d.ts +0 -2
- package/dist/capability-studio.test.d.ts.map +0 -1
- package/dist/capability-studio.test.js +0 -41
- package/dist/capability-studio.test.js.map +0 -1
- package/dist/cdp-log.d.ts.map +0 -1
- package/dist/cdp-log.js.map +0 -1
- package/dist/cdp-log.test.d.ts +0 -2
- package/dist/cdp-log.test.d.ts.map +0 -1
- package/dist/cdp-log.test.js +0 -109
- package/dist/cdp-log.test.js.map +0 -1
- package/dist/cdp-relay.d.ts.map +0 -1
- package/dist/cdp-relay.js.map +0 -1
- package/dist/cdp-session.d.ts.map +0 -1
- package/dist/cdp-session.js.map +0 -1
- package/dist/cdp-types.d.ts.map +0 -1
- package/dist/cdp-types.js.map +0 -1
- package/dist/channel-owner-inspect.test.d.ts +0 -2
- package/dist/channel-owner-inspect.test.d.ts.map +0 -1
- package/dist/channel-owner-inspect.test.js +0 -75
- package/dist/channel-owner-inspect.test.js.map +0 -1
- package/dist/chrome-discovery.d.ts.map +0 -1
- package/dist/chrome-discovery.js.map +0 -1
- package/dist/chrome-discovery.test.d.ts +0 -2
- package/dist/chrome-discovery.test.d.ts.map +0 -1
- package/dist/chrome-discovery.test.js +0 -41
- package/dist/chrome-discovery.test.js.map +0 -1
- package/dist/clean-html.d.ts.map +0 -1
- package/dist/clean-html.js.map +0 -1
- package/dist/cli-help.test.d.ts +0 -2
- package/dist/cli-help.test.d.ts.map +0 -1
- package/dist/cli-help.test.js +0 -98
- package/dist/cli-help.test.js.map +0 -1
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/cloud-client.d.ts.map +0 -1
- package/dist/cloud-client.js.map +0 -1
- package/dist/create-logger.d.ts.map +0 -1
- package/dist/create-logger.js.map +0 -1
- package/dist/debugger-examples-types.d.ts.map +0 -1
- package/dist/debugger-examples-types.js.map +0 -1
- package/dist/debugger-examples.d.ts.map +0 -1
- package/dist/debugger-examples.js.map +0 -1
- package/dist/debugger.d.ts.map +0 -1
- package/dist/debugger.js.map +0 -1
- package/dist/diff-utils.d.ts.map +0 -1
- package/dist/diff-utils.js.map +0 -1
- package/dist/diff-utils.test.d.ts +0 -2
- package/dist/diff-utils.test.d.ts.map +0 -1
- package/dist/diff-utils.test.js +0 -137
- package/dist/diff-utils.test.js.map +0 -1
- package/dist/doctor.d.ts.map +0 -1
- package/dist/doctor.js.map +0 -1
- package/dist/doctor.test.d.ts +0 -2
- package/dist/doctor.test.d.ts.map +0 -1
- package/dist/doctor.test.js +0 -208
- package/dist/doctor.test.js.map +0 -1
- package/dist/editor-examples.d.ts.map +0 -1
- package/dist/editor-examples.js.map +0 -1
- package/dist/editor.d.ts.map +0 -1
- package/dist/editor.js.map +0 -1
- package/dist/env-compat.d.ts.map +0 -1
- package/dist/env-compat.js.map +0 -1
- package/dist/executor.d.ts.map +0 -1
- package/dist/executor.js.map +0 -1
- package/dist/executor.unit.test.d.ts +0 -2
- package/dist/executor.unit.test.d.ts.map +0 -1
- package/dist/executor.unit.test.js +0 -143
- package/dist/executor.unit.test.js.map +0 -1
- package/dist/extension-connection.test.d.ts +0 -2
- package/dist/extension-connection.test.d.ts.map +0 -1
- package/dist/extension-connection.test.js +0 -708
- package/dist/extension-connection.test.js.map +0 -1
- package/dist/extension-icon-warning.test.d.ts +0 -2
- package/dist/extension-icon-warning.test.d.ts.map +0 -1
- package/dist/extension-icon-warning.test.js +0 -33
- package/dist/extension-icon-warning.test.js.map +0 -1
- package/dist/ghost-browser.d.ts.map +0 -1
- package/dist/ghost-browser.js.map +0 -1
- package/dist/ghost-cursor-controller.d.ts.map +0 -1
- package/dist/ghost-cursor-controller.js.map +0 -1
- package/dist/ghost-cursor.d.ts.map +0 -1
- package/dist/ghost-cursor.js.map +0 -1
- package/dist/htmlrewrite.d.ts.map +0 -1
- package/dist/htmlrewrite.js.map +0 -1
- package/dist/htmlrewrite.test.d.ts +0 -2
- package/dist/htmlrewrite.test.d.ts.map +0 -1
- package/dist/htmlrewrite.test.js +0 -7975
- package/dist/htmlrewrite.test.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/kill-port.d.ts.map +0 -1
- package/dist/kill-port.js.map +0 -1
- package/dist/kitty-graphics.d.ts.map +0 -1
- package/dist/kitty-graphics.js.map +0 -1
- package/dist/kitty-graphics.test.d.ts +0 -2
- package/dist/kitty-graphics.test.d.ts.map +0 -1
- package/dist/kitty-graphics.test.js +0 -125
- package/dist/kitty-graphics.test.js.map +0 -1
- package/dist/locator-selector.test.d.ts +0 -2
- package/dist/locator-selector.test.d.ts.map +0 -1
- package/dist/locator-selector.test.js +0 -98
- package/dist/locator-selector.test.js.map +0 -1
- package/dist/mcp-client.d.ts +0 -20
- package/dist/mcp-client.d.ts.map +0 -1
- package/dist/mcp-client.js +0 -56
- package/dist/mcp-client.js.map +0 -1
- package/dist/mcp.d.ts.map +0 -1
- package/dist/mcp.js.map +0 -1
- package/dist/on-mouse-action.test.d.ts +0 -2
- package/dist/on-mouse-action.test.d.ts.map +0 -1
- package/dist/on-mouse-action.test.js +0 -180
- package/dist/on-mouse-action.test.js.map +0 -1
- package/dist/options-page.test.d.ts +0 -2
- package/dist/options-page.test.d.ts.map +0 -1
- package/dist/options-page.test.js +0 -773
- package/dist/options-page.test.js.map +0 -1
- package/dist/package-paths.d.ts.map +0 -1
- package/dist/package-paths.js.map +0 -1
- package/dist/page-markdown.d.ts.map +0 -1
- package/dist/page-markdown.js.map +0 -1
- package/dist/performance-examples.d.ts.map +0 -1
- package/dist/performance-examples.js.map +0 -1
- package/dist/playwright-import.d.ts.map +0 -1
- package/dist/playwright-import.js.map +0 -1
- package/dist/popup-relocation.test.d.ts +0 -7
- package/dist/popup-relocation.test.d.ts.map +0 -1
- package/dist/popup-relocation.test.js +0 -139
- package/dist/popup-relocation.test.js.map +0 -1
- package/dist/product-paths.d.ts.map +0 -1
- package/dist/product-paths.js.map +0 -1
- package/dist/product-paths.test.d.ts +0 -2
- package/dist/product-paths.test.d.ts.map +0 -1
- package/dist/product-paths.test.js +0 -39
- package/dist/product-paths.test.js.map +0 -1
- package/dist/protocol.d.ts.map +0 -1
- package/dist/protocol.js.map +0 -1
- package/dist/protocol.test.d.ts +0 -2
- package/dist/protocol.test.d.ts.map +0 -1
- package/dist/protocol.test.js +0 -31
- package/dist/protocol.test.js.map +0 -1
- package/dist/react-source.d.ts.map +0 -1
- package/dist/react-source.js.map +0 -1
- package/dist/relay-client.d.ts.map +0 -1
- package/dist/relay-client.js.map +0 -1
- package/dist/relay-client.test.d.ts +0 -2
- package/dist/relay-client.test.d.ts.map +0 -1
- package/dist/relay-client.test.js +0 -305
- package/dist/relay-client.test.js.map +0 -1
- package/dist/relay-core.test.d.ts +0 -2
- package/dist/relay-core.test.d.ts.map +0 -1
- package/dist/relay-core.test.js +0 -1427
- package/dist/relay-core.test.js.map +0 -1
- package/dist/relay-navigation.test.d.ts +0 -2
- package/dist/relay-navigation.test.d.ts.map +0 -1
- package/dist/relay-navigation.test.js +0 -661
- package/dist/relay-navigation.test.js.map +0 -1
- package/dist/relay-session.test.d.ts +0 -2
- package/dist/relay-session.test.d.ts.map +0 -1
- package/dist/relay-session.test.js +0 -1121
- package/dist/relay-session.test.js.map +0 -1
- package/dist/relay-state.d.ts.map +0 -1
- package/dist/relay-state.js.map +0 -1
- package/dist/relay-state.test.d.ts +0 -2
- package/dist/relay-state.test.d.ts.map +0 -1
- package/dist/relay-state.test.js +0 -594
- package/dist/relay-state.test.js.map +0 -1
- package/dist/replay-ai-index.d.ts.map +0 -1
- package/dist/replay-ai-index.js.map +0 -1
- package/dist/replay-ai-index.test.d.ts +0 -2
- package/dist/replay-ai-index.test.d.ts.map +0 -1
- package/dist/replay-ai-index.test.js +0 -255
- package/dist/replay-ai-index.test.js.map +0 -1
- package/dist/replay-cli.test.d.ts +0 -2
- package/dist/replay-cli.test.d.ts.map +0 -1
- package/dist/replay-cli.test.js +0 -275
- package/dist/replay-cli.test.js.map +0 -1
- package/dist/replay-eval.d.ts.map +0 -1
- package/dist/replay-eval.js.map +0 -1
- package/dist/replay-handoff.d.ts.map +0 -1
- package/dist/replay-handoff.js.map +0 -1
- package/dist/replay-handoff.test.d.ts +0 -2
- package/dist/replay-handoff.test.d.ts.map +0 -1
- package/dist/replay-handoff.test.js +0 -123
- package/dist/replay-handoff.test.js.map +0 -1
- package/dist/replay-workflow-compiler.d.ts.map +0 -1
- package/dist/replay-workflow-compiler.js.map +0 -1
- package/dist/replay-workflow-compiler.test.d.ts +0 -2
- package/dist/replay-workflow-compiler.test.d.ts.map +0 -1
- package/dist/replay-workflow-compiler.test.js +0 -223
- package/dist/replay-workflow-compiler.test.js.map +0 -1
- package/dist/rrweb-recording-relay.d.ts.map +0 -1
- package/dist/rrweb-recording-relay.js.map +0 -1
- package/dist/rrweb-recording-relay.test.d.ts +0 -2
- package/dist/rrweb-recording-relay.test.d.ts.map +0 -1
- package/dist/rrweb-recording-relay.test.js +0 -85
- package/dist/rrweb-recording-relay.test.js.map +0 -1
- package/dist/rrweb-recording.d.ts.map +0 -1
- package/dist/rrweb-recording.js.map +0 -1
- package/dist/scoped-fs.d.ts.map +0 -1
- package/dist/scoped-fs.js.map +0 -1
- package/dist/scoped-fs.test.d.ts +0 -5
- package/dist/scoped-fs.test.d.ts.map +0 -1
- package/dist/scoped-fs.test.js +0 -73
- package/dist/scoped-fs.test.js.map +0 -1
- package/dist/skill-stub.test.d.ts +0 -2
- package/dist/skill-stub.test.d.ts.map +0 -1
- package/dist/skill-stub.test.js +0 -22
- package/dist/skill-stub.test.js.map +0 -1
- package/dist/snapshot-tools.test.d.ts +0 -2
- package/dist/snapshot-tools.test.d.ts.map +0 -1
- package/dist/snapshot-tools.test.js +0 -856
- package/dist/snapshot-tools.test.js.map +0 -1
- package/dist/start-relay-server.d.ts.map +0 -1
- package/dist/start-relay-server.js.map +0 -1
- package/dist/styles-examples.d.ts.map +0 -1
- package/dist/styles-examples.js.map +0 -1
- package/dist/styles.d.ts.map +0 -1
- package/dist/styles.js.map +0 -1
- package/dist/tabwright-agent-skill.d.ts.map +0 -1
- package/dist/tabwright-agent-skill.js.map +0 -1
- package/dist/tabwright-agent-skill.test.d.ts +0 -2
- package/dist/tabwright-agent-skill.test.d.ts.map +0 -1
- package/dist/tabwright-agent-skill.test.js +0 -51
- package/dist/tabwright-agent-skill.test.js.map +0 -1
- package/dist/test-declarations.d.ts.map +0 -1
- package/dist/test-declarations.js.map +0 -1
- package/dist/test-utils.d.ts +0 -69
- package/dist/test-utils.d.ts.map +0 -1
- package/dist/test-utils.js +0 -448
- package/dist/test-utils.js.map +0 -1
- package/dist/test-utils.test.d.ts +0 -2
- package/dist/test-utils.test.d.ts.map +0 -1
- package/dist/test-utils.test.js +0 -55
- package/dist/test-utils.test.js.map +0 -1
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js.map +0 -1
- package/dist/wait-for-page-load.d.ts.map +0 -1
- package/dist/wait-for-page-load.js.map +0 -1
- package/dist/workflow-capability.d.ts.map +0 -1
- package/dist/workflow-capability.js.map +0 -1
- package/dist/workflow-script-flow.test.d.ts +0 -2
- package/dist/workflow-script-flow.test.d.ts.map +0 -1
- package/dist/workflow-script-flow.test.js +0 -285
- package/dist/workflow-script-flow.test.js.map +0 -1
- package/src/__snapshots__/x.com.processed.html +0 -1003
- package/src/__snapshots__/x.com.processed.withStyles.html +0 -2720
- package/src/a11y-client.ts +0 -241
- package/src/aria-snapshot.test.ts +0 -311
- package/src/aria-snapshot.ts +0 -1681
- package/src/aria-snapshot.unit.test.ts +0 -615
- package/src/aria-snapshots/github-interactive.txt +0 -193
- package/src/aria-snapshots/github-raw.txt +0 -309
- package/src/aria-snapshots/hackernews-interactive.txt +0 -477
- package/src/aria-snapshots/hackernews-raw.txt +0 -428
- package/src/aria-snapshots/prosemirror-interactive.txt +0 -66
- package/src/aria-snapshots/prosemirror-raw.txt +0 -145
- package/src/assets/aria-labels-hacker-news.png +0 -0
- package/src/assets/aria-labels-old-reddit.png +0 -0
- package/src/assets/cursors/screen-studio/pointer-macos-tahoe-data-url.ts +0 -5
- package/src/assets/cursors/screen-studio/pointer-macos-tahoe.svg +0 -18
- package/src/assets/x.com.html +0 -32946
- package/src/browser-config.ts +0 -179
- package/src/browser-install.ts +0 -284
- package/src/browser-launch.ts +0 -75
- package/src/builtin-capabilities.ts +0 -2765
- package/src/capability-agent-skill.ts +0 -305
- package/src/capability-auth-state.ts +0 -197
- package/src/capability-auth.ts +0 -249
- package/src/capability-cli-confirmation.test.ts +0 -90
- package/src/capability-options.test.ts +0 -89
- package/src/capability-options.ts +0 -57
- package/src/capability-package.test.ts +0 -204
- package/src/capability-package.ts +0 -555
- package/src/capability-registry.test.ts +0 -1905
- package/src/capability-registry.ts +0 -1234
- package/src/capability-runner.ts +0 -801
- package/src/capability-search-relevance.test.ts +0 -73
- package/src/capability-studio.test.ts +0 -45
- package/src/capability-studio.ts +0 -641
- package/src/cdp-log.test.ts +0 -131
- package/src/cdp-log.ts +0 -112
- package/src/cdp-relay.ts +0 -2944
- package/src/cdp-session.ts +0 -77
- package/src/cdp-types.ts +0 -158
- package/src/channel-owner-inspect.test.ts +0 -94
- package/src/chrome-discovery.test.ts +0 -50
- package/src/chrome-discovery.ts +0 -220
- package/src/clean-html.ts +0 -141
- package/src/cli-help.test.ts +0 -123
- package/src/cli.ts +0 -3181
- package/src/cloud-client.ts +0 -179
- package/src/create-logger.ts +0 -38
- package/src/debugger-examples-types.ts +0 -16
- package/src/debugger-examples.ts +0 -66
- package/src/debugger.ts +0 -708
- package/src/diff-utils.test.ts +0 -152
- package/src/diff-utils.ts +0 -70
- package/src/doctor.test.ts +0 -244
- package/src/doctor.ts +0 -321
- package/src/editor-examples.ts +0 -158
- package/src/editor.ts +0 -426
- package/src/env-compat.ts +0 -28
- package/src/executor.ts +0 -1824
- package/src/executor.unit.test.ts +0 -168
- package/src/extension-connection.test.ts +0 -855
- package/src/extension-icon-warning.test.ts +0 -45
- package/src/ghost-browser.ts +0 -149
- package/src/ghost-cursor-client.ts +0 -494
- package/src/ghost-cursor-controller.ts +0 -129
- package/src/ghost-cursor.ts +0 -123
- package/src/htmlrewrite.test.ts +0 -8008
- package/src/htmlrewrite.ts +0 -390
- package/src/index.ts +0 -53
- package/src/kill-port.ts +0 -219
- package/src/kitty-graphics.test.ts +0 -139
- package/src/kitty-graphics.ts +0 -79
- package/src/locator-selector.test.ts +0 -119
- package/src/mcp-client.ts +0 -78
- package/src/mcp.ts +0 -629
- package/src/on-mouse-action.test.ts +0 -226
- package/src/options-page.test.ts +0 -839
- package/src/package-paths.ts +0 -38
- package/src/page-markdown.ts +0 -240
- package/src/performance-examples.ts +0 -186
- package/src/playwright-import.ts +0 -59
- package/src/popup-relocation.test.ts +0 -163
- package/src/product-paths.test.ts +0 -47
- package/src/product-paths.ts +0 -28
- package/src/protocol.test.ts +0 -52
- package/src/protocol.ts +0 -351
- package/src/react-source.ts +0 -379
- package/src/relay-client.test.ts +0 -375
- package/src/relay-client.ts +0 -572
- package/src/relay-core.test.ts +0 -1603
- package/src/relay-navigation.test.ts +0 -790
- package/src/relay-session.test.ts +0 -1375
- package/src/relay-state.test.ts +0 -729
- package/src/relay-state.ts +0 -561
- package/src/replay-ai-index.test.ts +0 -278
- package/src/replay-ai-index.ts +0 -872
- package/src/replay-cli.test.ts +0 -325
- package/src/replay-eval.ts +0 -1039
- package/src/replay-handoff.test.ts +0 -163
- package/src/replay-handoff.ts +0 -109
- package/src/replay-workflow-compiler.test.ts +0 -250
- package/src/replay-workflow-compiler.ts +0 -700
- package/src/resource.md +0 -409
- package/src/rrweb-recording-relay.test.ts +0 -99
- package/src/rrweb-recording-relay.ts +0 -400
- package/src/rrweb-recording.ts +0 -322
- package/src/scoped-fs.test.ts +0 -80
- package/src/scoped-fs.ts +0 -420
- package/src/skill-stub.test.ts +0 -24
- package/src/snapshot-tools.test.ts +0 -1017
- package/src/snapshots/hacker-news-accessibility-full.md +0 -81
- package/src/snapshots/hacker-news-accessibility-interactive.md +0 -43
- package/src/snapshots/page-markdown-output.txt +0 -16
- package/src/snapshots/shadcn-ui-accessibility-full.md +0 -201
- package/src/snapshots/shadcn-ui-accessibility-interactive.md +0 -109
- package/src/start-relay-server.ts +0 -69
- package/src/styles-examples.ts +0 -84
- package/src/styles.ts +0 -343
- package/src/tabwright-agent-skill.test.ts +0 -61
- package/src/tabwright-agent-skill.ts +0 -105
- package/src/test-declarations.ts +0 -13
- package/src/test-utils.test.ts +0 -70
- package/src/test-utils.ts +0 -566
- package/src/utils.ts +0 -78
- package/src/wait-for-page-load.ts +0 -198
- package/src/workflow-capability.ts +0 -417
- package/src/workflow-script-flow.test.ts +0 -388
package/src/a11y-client.ts
DELETED
|
@@ -1,241 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Browser-side accessibility label renderer.
|
|
3
|
-
* Bundled and injected into page context via CDP.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export interface LabelBox {
|
|
7
|
-
x: number
|
|
8
|
-
y: number
|
|
9
|
-
width: number
|
|
10
|
-
height: number
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface A11yLabel {
|
|
14
|
-
ref: string
|
|
15
|
-
role: string
|
|
16
|
-
box: LabelBox
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// ============================================================================
|
|
20
|
-
// Constants
|
|
21
|
-
// ============================================================================
|
|
22
|
-
|
|
23
|
-
const LABELS_CONTAINER_ID = '__tabwright_labels__'
|
|
24
|
-
const LABELS_TIMER_KEY = '__tabwright_labels_timer__'
|
|
25
|
-
|
|
26
|
-
// Color scheme for labels by role
|
|
27
|
-
const ROLE_COLORS: Record<string, [string, string, string]> = {
|
|
28
|
-
link: ['#FFF785', '#FFC542', '#E3BE23'],
|
|
29
|
-
button: ['#FFE0B2', '#FFCC80', '#FFB74D'],
|
|
30
|
-
textbox: ['#FFCDD2', '#EF9A9A', '#E57373'],
|
|
31
|
-
combobox: ['#F8BBD0', '#F48FB1', '#F06292'],
|
|
32
|
-
searchbox: ['#F8BBD0', '#F48FB1', '#F06292'],
|
|
33
|
-
checkbox: ['#C8E6C9', '#A5D6A7', '#81C784'],
|
|
34
|
-
radio: ['#C8E6C9', '#A5D6A7', '#81C784'],
|
|
35
|
-
slider: ['#BBDEFB', '#90CAF9', '#64B5F6'],
|
|
36
|
-
spinbutton: ['#BBDEFB', '#90CAF9', '#64B5F6'],
|
|
37
|
-
switch: ['#D1C4E9', '#B39DDB', '#9575CD'],
|
|
38
|
-
menuitem: ['#FFE0B2', '#FFCC80', '#FFB74D'],
|
|
39
|
-
menuitemcheckbox: ['#FFE0B2', '#FFCC80', '#FFB74D'],
|
|
40
|
-
menuitemradio: ['#FFE0B2', '#FFCC80', '#FFB74D'],
|
|
41
|
-
option: ['#FFE0B2', '#FFCC80', '#FFB74D'],
|
|
42
|
-
tab: ['#FFE0B2', '#FFCC80', '#FFB74D'],
|
|
43
|
-
treeitem: ['#FFE0B2', '#FFCC80', '#FFB74D'],
|
|
44
|
-
img: ['#B3E5FC', '#81D4FA', '#4FC3F7'],
|
|
45
|
-
video: ['#B3E5FC', '#81D4FA', '#4FC3F7'],
|
|
46
|
-
audio: ['#B3E5FC', '#81D4FA', '#4FC3F7'],
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const DEFAULT_COLORS: [string, string, string] = ['#FFF9C4', '#FFF59D', '#FFEB3B']
|
|
50
|
-
|
|
51
|
-
// ============================================================================
|
|
52
|
-
// Label Rendering
|
|
53
|
-
// ============================================================================
|
|
54
|
-
|
|
55
|
-
function renderA11yLabels(labels: A11yLabel[]): number {
|
|
56
|
-
const doc = document
|
|
57
|
-
const win = window as typeof window & { [LABELS_TIMER_KEY]?: number | null }
|
|
58
|
-
|
|
59
|
-
// Cancel any pending auto-hide timer
|
|
60
|
-
if (win[LABELS_TIMER_KEY]) {
|
|
61
|
-
win.clearTimeout(win[LABELS_TIMER_KEY])
|
|
62
|
-
win[LABELS_TIMER_KEY] = null
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Remove existing labels
|
|
66
|
-
doc.getElementById(LABELS_CONTAINER_ID)?.remove()
|
|
67
|
-
|
|
68
|
-
// Create container
|
|
69
|
-
const container = doc.createElement('div')
|
|
70
|
-
container.id = LABELS_CONTAINER_ID
|
|
71
|
-
container.style.cssText = 'position:absolute;left:0;top:0;z-index:2147483647;pointer-events:none;'
|
|
72
|
-
|
|
73
|
-
// Inject styles
|
|
74
|
-
const style = doc.createElement('style')
|
|
75
|
-
style.textContent = `
|
|
76
|
-
.__pw_label__ {
|
|
77
|
-
position: absolute;
|
|
78
|
-
font: bold 12px Helvetica, Arial, sans-serif;
|
|
79
|
-
padding: 1px 4px;
|
|
80
|
-
border-radius: 3px;
|
|
81
|
-
color: black;
|
|
82
|
-
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6);
|
|
83
|
-
white-space: nowrap;
|
|
84
|
-
}
|
|
85
|
-
`
|
|
86
|
-
container.appendChild(style)
|
|
87
|
-
|
|
88
|
-
// Create SVG for connector lines
|
|
89
|
-
const svg = doc.createElementNS('http://www.w3.org/2000/svg', 'svg')
|
|
90
|
-
svg.style.cssText = 'position:absolute;left:0;top:0;pointer-events:none;overflow:visible;'
|
|
91
|
-
svg.setAttribute('width', `${doc.documentElement.scrollWidth}`)
|
|
92
|
-
svg.setAttribute('height', `${doc.documentElement.scrollHeight}`)
|
|
93
|
-
|
|
94
|
-
// Arrow markers
|
|
95
|
-
const defs = doc.createElementNS('http://www.w3.org/2000/svg', 'defs')
|
|
96
|
-
svg.appendChild(defs)
|
|
97
|
-
const markerCache: Record<string, string> = {}
|
|
98
|
-
|
|
99
|
-
function getArrowMarkerId(color: string): string {
|
|
100
|
-
if (markerCache[color]) {
|
|
101
|
-
return markerCache[color]
|
|
102
|
-
}
|
|
103
|
-
const markerId = `arrow-${color.replace('#', '')}`
|
|
104
|
-
const marker = doc.createElementNS('http://www.w3.org/2000/svg', 'marker')
|
|
105
|
-
marker.setAttribute('id', markerId)
|
|
106
|
-
marker.setAttribute('viewBox', '0 0 10 10')
|
|
107
|
-
marker.setAttribute('refX', '9')
|
|
108
|
-
marker.setAttribute('refY', '5')
|
|
109
|
-
marker.setAttribute('markerWidth', '6')
|
|
110
|
-
marker.setAttribute('markerHeight', '6')
|
|
111
|
-
marker.setAttribute('orient', 'auto-start-reverse')
|
|
112
|
-
const path = doc.createElementNS('http://www.w3.org/2000/svg', 'path')
|
|
113
|
-
path.setAttribute('d', 'M 0 0 L 10 5 L 0 10 z')
|
|
114
|
-
path.setAttribute('fill', color)
|
|
115
|
-
marker.appendChild(path)
|
|
116
|
-
defs.appendChild(marker)
|
|
117
|
-
markerCache[color] = markerId
|
|
118
|
-
return markerId
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
container.appendChild(svg)
|
|
122
|
-
|
|
123
|
-
// Track placed labels for overlap detection
|
|
124
|
-
const placedLabels: Array<{ left: number; top: number; right: number; bottom: number }> = []
|
|
125
|
-
const LABEL_HEIGHT = 17
|
|
126
|
-
const LABEL_CHAR_WIDTH = 7
|
|
127
|
-
|
|
128
|
-
const viewportLeft = win.scrollX
|
|
129
|
-
const viewportTop = win.scrollY
|
|
130
|
-
const viewportRight = viewportLeft + win.innerWidth
|
|
131
|
-
const viewportBottom = viewportTop + win.innerHeight
|
|
132
|
-
|
|
133
|
-
let count = 0
|
|
134
|
-
for (const { ref, role, box } of labels) {
|
|
135
|
-
const rectLeft = box.x
|
|
136
|
-
const rectTop = box.y
|
|
137
|
-
const rectRight = rectLeft + box.width
|
|
138
|
-
const rectBottom = rectTop + box.height
|
|
139
|
-
|
|
140
|
-
if (box.width <= 0 || box.height <= 0) {
|
|
141
|
-
continue
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Skip if outside viewport
|
|
145
|
-
if (rectRight < viewportLeft || rectLeft > viewportRight || rectBottom < viewportTop || rectTop > viewportBottom) {
|
|
146
|
-
continue
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Calculate label position
|
|
150
|
-
const labelWidth = ref.length * LABEL_CHAR_WIDTH + 8
|
|
151
|
-
const labelLeft = rectLeft
|
|
152
|
-
const labelTop = Math.max(0, rectTop - LABEL_HEIGHT)
|
|
153
|
-
const labelRect = {
|
|
154
|
-
left: labelLeft,
|
|
155
|
-
top: labelTop,
|
|
156
|
-
right: labelLeft + labelWidth,
|
|
157
|
-
bottom: labelTop + LABEL_HEIGHT,
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Check overlap
|
|
161
|
-
let overlaps = false
|
|
162
|
-
for (const placed of placedLabels) {
|
|
163
|
-
if (
|
|
164
|
-
labelRect.left < placed.right &&
|
|
165
|
-
labelRect.right > placed.left &&
|
|
166
|
-
labelRect.top < placed.bottom &&
|
|
167
|
-
labelRect.bottom > placed.top
|
|
168
|
-
) {
|
|
169
|
-
overlaps = true
|
|
170
|
-
break
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
if (overlaps) {
|
|
174
|
-
continue
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Get colors
|
|
178
|
-
const [gradTop, gradBottom, border] = ROLE_COLORS[role] || DEFAULT_COLORS
|
|
179
|
-
|
|
180
|
-
// Create label
|
|
181
|
-
const label = doc.createElement('div')
|
|
182
|
-
label.className = '__pw_label__'
|
|
183
|
-
label.textContent = ref
|
|
184
|
-
label.style.background = `linear-gradient(to bottom, ${gradTop} 0%, ${gradBottom} 100%)`
|
|
185
|
-
label.style.border = `1px solid ${border}`
|
|
186
|
-
label.style.left = `${labelLeft}px`
|
|
187
|
-
label.style.top = `${labelTop}px`
|
|
188
|
-
container.appendChild(label)
|
|
189
|
-
|
|
190
|
-
// Draw connector line
|
|
191
|
-
const line = doc.createElementNS('http://www.w3.org/2000/svg', 'line')
|
|
192
|
-
const labelCenterX = labelLeft + labelWidth / 2
|
|
193
|
-
const labelBottomY = labelTop + LABEL_HEIGHT
|
|
194
|
-
const elementCenterX = rectLeft + box.width / 2
|
|
195
|
-
const elementCenterY = rectTop + box.height / 2
|
|
196
|
-
line.setAttribute('x1', `${labelCenterX}`)
|
|
197
|
-
line.setAttribute('y1', `${labelBottomY}`)
|
|
198
|
-
line.setAttribute('x2', `${elementCenterX}`)
|
|
199
|
-
line.setAttribute('y2', `${elementCenterY}`)
|
|
200
|
-
line.setAttribute('stroke', border)
|
|
201
|
-
line.setAttribute('stroke-width', '1.5')
|
|
202
|
-
line.setAttribute('marker-end', `url(#${getArrowMarkerId(border)})`)
|
|
203
|
-
svg.appendChild(line)
|
|
204
|
-
|
|
205
|
-
placedLabels.push(labelRect)
|
|
206
|
-
count++
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
doc.documentElement.appendChild(container)
|
|
210
|
-
|
|
211
|
-
// Auto-hide after 30 seconds
|
|
212
|
-
win[LABELS_TIMER_KEY] = win.setTimeout(() => {
|
|
213
|
-
doc.getElementById(LABELS_CONTAINER_ID)?.remove()
|
|
214
|
-
win[LABELS_TIMER_KEY] = null
|
|
215
|
-
}, 30000)
|
|
216
|
-
|
|
217
|
-
return count
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// ============================================================================
|
|
221
|
-
// Hide Labels
|
|
222
|
-
// ============================================================================
|
|
223
|
-
|
|
224
|
-
export function hideA11yLabels(): void {
|
|
225
|
-
const win = window as typeof window & { [LABELS_TIMER_KEY]?: number | null }
|
|
226
|
-
if (win[LABELS_TIMER_KEY]) {
|
|
227
|
-
win.clearTimeout(win[LABELS_TIMER_KEY])
|
|
228
|
-
win[LABELS_TIMER_KEY] = null
|
|
229
|
-
}
|
|
230
|
-
document.getElementById(LABELS_CONTAINER_ID)?.remove()
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// ============================================================================
|
|
234
|
-
// Expose on globalThis for injection
|
|
235
|
-
// ============================================================================
|
|
236
|
-
|
|
237
|
-
;(globalThis as { __a11y?: { renderA11yLabels: (labels: A11yLabel[]) => number; hideA11yLabels: () => void } }).__a11y =
|
|
238
|
-
{
|
|
239
|
-
renderA11yLabels,
|
|
240
|
-
hideA11yLabels,
|
|
241
|
-
}
|
|
@@ -1,311 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeAll, afterAll } from 'vitest'
|
|
2
|
-
import http from 'node:http'
|
|
3
|
-
import net from 'node:net'
|
|
4
|
-
import { Page } from '@xmorse/playwright-core'
|
|
5
|
-
import fs from 'node:fs'
|
|
6
|
-
import path from 'node:path'
|
|
7
|
-
import { getAriaSnapshot } from './aria-snapshot.js'
|
|
8
|
-
import { getCdpUrl } from './utils.js'
|
|
9
|
-
import { getCDPSessionForPage } from './cdp-session.js'
|
|
10
|
-
import { setupTestContext, cleanupTestContext, getExtensionServiceWorker, type TestContext } from './test-utils.js'
|
|
11
|
-
|
|
12
|
-
const TEST_PORT = 19986
|
|
13
|
-
const SNAPSHOTS_DIR = path.join(import.meta.dirname, 'aria-snapshots')
|
|
14
|
-
const AX_DEBUG_DIR = path.join(import.meta.dirname, '__snapshots__', 'ax-debug')
|
|
15
|
-
const SHOULD_DUMP_AX = process.env.PLAYWRITER_DUMP_AX === '1'
|
|
16
|
-
|
|
17
|
-
type HtmlServer = {
|
|
18
|
-
baseUrl: string
|
|
19
|
-
close: () => Promise<void>
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
async function createHtmlServer({ htmlByPath }: { htmlByPath: Record<string, string> }): Promise<HtmlServer> {
|
|
23
|
-
const openSockets: Set<net.Socket> = new Set()
|
|
24
|
-
const server = http.createServer((req, res) => {
|
|
25
|
-
const requestUrl = req.url || '/'
|
|
26
|
-
const html = htmlByPath[requestUrl]
|
|
27
|
-
if (!html) {
|
|
28
|
-
res.writeHead(404, { 'Content-Type': 'text/plain' })
|
|
29
|
-
res.end('Not found')
|
|
30
|
-
return
|
|
31
|
-
}
|
|
32
|
-
res.writeHead(200, { 'Content-Type': 'text/html' })
|
|
33
|
-
res.end(html)
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
server.on('connection', (socket) => {
|
|
37
|
-
openSockets.add(socket)
|
|
38
|
-
socket.on('close', () => {
|
|
39
|
-
openSockets.delete(socket)
|
|
40
|
-
})
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
await new Promise<void>((resolve) => {
|
|
44
|
-
server.listen(0, '127.0.0.1', resolve)
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
const address = server.address()
|
|
48
|
-
if (!address || typeof address === 'string') {
|
|
49
|
-
throw new Error('Failed to bind test server')
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return {
|
|
53
|
-
baseUrl: `http://127.0.0.1:${address.port}`,
|
|
54
|
-
close: () => {
|
|
55
|
-
for (const socket of openSockets) {
|
|
56
|
-
socket.destroy()
|
|
57
|
-
}
|
|
58
|
-
return new Promise((resolve, reject) => {
|
|
59
|
-
server.close((error) => {
|
|
60
|
-
if (error) {
|
|
61
|
-
reject(error)
|
|
62
|
-
return
|
|
63
|
-
}
|
|
64
|
-
resolve()
|
|
65
|
-
})
|
|
66
|
-
})
|
|
67
|
-
},
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
describe('aria-snapshot', () => {
|
|
72
|
-
let ctx: TestContext
|
|
73
|
-
let page: Page
|
|
74
|
-
|
|
75
|
-
beforeAll(async () => {
|
|
76
|
-
ctx = await setupTestContext({ port: TEST_PORT, tempDirPrefix: 'aria-snapshot-test-', toggleExtension: true })
|
|
77
|
-
page = await ctx.browserContext.newPage()
|
|
78
|
-
const serviceWorker = await getExtensionServiceWorker(ctx.browserContext)
|
|
79
|
-
await page.goto('about:blank')
|
|
80
|
-
await serviceWorker.evaluate(async () => {
|
|
81
|
-
await (globalThis as any).toggleExtensionForActiveTab()
|
|
82
|
-
})
|
|
83
|
-
if (!fs.existsSync(SNAPSHOTS_DIR)) {
|
|
84
|
-
fs.mkdirSync(SNAPSHOTS_DIR, { recursive: true })
|
|
85
|
-
}
|
|
86
|
-
if (SHOULD_DUMP_AX && !fs.existsSync(AX_DEBUG_DIR)) {
|
|
87
|
-
fs.mkdirSync(AX_DEBUG_DIR, { recursive: true })
|
|
88
|
-
}
|
|
89
|
-
}, 60000)
|
|
90
|
-
|
|
91
|
-
afterAll(async () => {
|
|
92
|
-
await cleanupTestContext(ctx)
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
const sites = [
|
|
96
|
-
{ name: 'hackernews', url: 'https://news.ycombinator.com' },
|
|
97
|
-
{ name: 'github', url: 'https://github.com' },
|
|
98
|
-
{ name: 'prosemirror', url: 'https://prosemirror.net/' },
|
|
99
|
-
]
|
|
100
|
-
|
|
101
|
-
for (const site of sites) {
|
|
102
|
-
it(`${site.name} - snapshot`, async () => {
|
|
103
|
-
await page.goto(site.url, { waitUntil: 'domcontentloaded' })
|
|
104
|
-
await page.waitForTimeout(1000)
|
|
105
|
-
|
|
106
|
-
if (SHOULD_DUMP_AX) {
|
|
107
|
-
const cdp = await getCDPSessionForPage({ page })
|
|
108
|
-
try {
|
|
109
|
-
await cdp.send('DOM.enable')
|
|
110
|
-
await cdp.send('Accessibility.enable')
|
|
111
|
-
const axTree = await cdp.send('Accessibility.getFullAXTree')
|
|
112
|
-
const domTree = await cdp.send('DOM.getFlattenedDocument', { depth: -1, pierce: true })
|
|
113
|
-
fs.writeFileSync(path.join(AX_DEBUG_DIR, `${site.name}-ax-tree.json`), JSON.stringify(axTree, null, 2))
|
|
114
|
-
fs.writeFileSync(path.join(AX_DEBUG_DIR, `${site.name}-dom-flat.json`), JSON.stringify(domTree, null, 2))
|
|
115
|
-
} finally {
|
|
116
|
-
await cdp.detach()
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const { snapshot } = await getAriaSnapshot({ page })
|
|
121
|
-
expect(snapshot.length).toBeGreaterThan(0)
|
|
122
|
-
// Check for locator format: attribute selector or role selector
|
|
123
|
-
expect(snapshot).toMatch(/(?:\[id="|\[data-[\w-]+="|role=)/)
|
|
124
|
-
const wrapperLines = snapshot.split('\n').filter((line) => {
|
|
125
|
-
const trimmed = line.trim()
|
|
126
|
-
return /^-\s+(generic|group|none|presentation)\s*:?$/.test(trimmed)
|
|
127
|
-
})
|
|
128
|
-
expect(wrapperLines).toEqual([])
|
|
129
|
-
fs.writeFileSync(path.join(SNAPSHOTS_DIR, `${site.name}-raw.txt`), snapshot)
|
|
130
|
-
console.log(`\n📊 ${site.name.toUpperCase()} snapshot size: ${snapshot.length} bytes`)
|
|
131
|
-
|
|
132
|
-
const { snapshot: interactiveSnapshot } = await getAriaSnapshot({
|
|
133
|
-
page,
|
|
134
|
-
interactiveOnly: true,
|
|
135
|
-
})
|
|
136
|
-
expect(interactiveSnapshot).not.toMatch(/^-\s+heading\b/m)
|
|
137
|
-
// Check for locator format: attribute selector or role selector
|
|
138
|
-
expect(interactiveSnapshot).toMatch(/(?:\[id="|\[data-[\w-]+="|role=)/)
|
|
139
|
-
fs.writeFileSync(path.join(SNAPSHOTS_DIR, `${site.name}-interactive.txt`), interactiveSnapshot)
|
|
140
|
-
}, 30000)
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
it('prosemirror editor - contenteditable appears in snapshot and is interactable', async () => {
|
|
144
|
-
await page.goto('https://prosemirror.net/', { waitUntil: 'domcontentloaded' })
|
|
145
|
-
await page.waitForTimeout(2000)
|
|
146
|
-
|
|
147
|
-
const { snapshot: interactiveSnapshot } = await getAriaSnapshot({ page, interactiveOnly: true })
|
|
148
|
-
|
|
149
|
-
fs.writeFileSync(path.join(SNAPSHOTS_DIR, 'prosemirror-interactive.txt'), interactiveSnapshot)
|
|
150
|
-
console.log('\n--- PROSEMIRROR INTERACTIVE SNAPSHOT ---')
|
|
151
|
-
console.log(interactiveSnapshot)
|
|
152
|
-
|
|
153
|
-
// The ProseMirror editor uses a bare <div contenteditable="true"> without role="textbox".
|
|
154
|
-
// After the contenteditable promotion fix, it should appear as a textbox.
|
|
155
|
-
expect(interactiveSnapshot).toContain('textbox')
|
|
156
|
-
expect(interactiveSnapshot).toContain('[contenteditable="true"]')
|
|
157
|
-
|
|
158
|
-
// The generated locator should actually work in Playwright
|
|
159
|
-
const editor = page.locator('[contenteditable="true"]')
|
|
160
|
-
const editorCount = await editor.count()
|
|
161
|
-
expect(editorCount).toBe(1)
|
|
162
|
-
|
|
163
|
-
// Click on the editor and type content
|
|
164
|
-
await editor.click()
|
|
165
|
-
// Select all existing content and replace it
|
|
166
|
-
await page.keyboard.press('ControlOrMeta+A')
|
|
167
|
-
await page.keyboard.type('Hello from Tabwright test!')
|
|
168
|
-
|
|
169
|
-
const content = await editor.innerText()
|
|
170
|
-
expect(content).toContain('Hello from Tabwright test!')
|
|
171
|
-
|
|
172
|
-
// Take full snapshot again and verify the new content is visible
|
|
173
|
-
const { snapshot: afterSnapshot } = await getAriaSnapshot({ page })
|
|
174
|
-
expect(afterSnapshot).toContain('Hello from Tabwright test')
|
|
175
|
-
}, 30000)
|
|
176
|
-
|
|
177
|
-
it('bare contenteditable without role=textbox shows in snapshot', async () => {
|
|
178
|
-
// Reproduces the core issue: bare contenteditable divs (like ProseMirror uses)
|
|
179
|
-
// have no explicit role="textbox", so Chrome's AX tree reports them as "generic".
|
|
180
|
-
// Our fix promotes them to textbox.
|
|
181
|
-
const htmlServer = await createHtmlServer({
|
|
182
|
-
htmlByPath: {
|
|
183
|
-
'/': `<!doctype html>
|
|
184
|
-
<html>
|
|
185
|
-
<head><meta charset="utf-8"><title>ContentEditable Test</title></head>
|
|
186
|
-
<body>
|
|
187
|
-
<h1>Rich Text Editor Test</h1>
|
|
188
|
-
<div id="editor-with-id" contenteditable="true"
|
|
189
|
-
style="border: 1px solid #ccc; padding: 8px; min-height: 60px;">
|
|
190
|
-
<p>Editor with id, no role attribute.</p>
|
|
191
|
-
</div>
|
|
192
|
-
<div class="ProseMirror" contenteditable="true"
|
|
193
|
-
style="border: 1px solid #ccc; padding: 8px; min-height: 60px;">
|
|
194
|
-
<p>Bare ProseMirror-style editor, no role, no id.</p>
|
|
195
|
-
</div>
|
|
196
|
-
<div contenteditable=""
|
|
197
|
-
style="border: 1px solid #ccc; padding: 8px; min-height: 60px;">
|
|
198
|
-
<p>Editor with empty contenteditable attr.</p>
|
|
199
|
-
</div>
|
|
200
|
-
<div contenteditable="plaintext-only"
|
|
201
|
-
style="border: 1px solid #ccc; padding: 8px; min-height: 60px;">
|
|
202
|
-
<p>Plaintext-only editor.</p>
|
|
203
|
-
</div>
|
|
204
|
-
<div contenteditable="true" role="textbox" aria-label="Labeled editor"
|
|
205
|
-
style="border: 1px solid #ccc; padding: 8px; min-height: 60px;">
|
|
206
|
-
<p>Editor with explicit role=textbox.</p>
|
|
207
|
-
</div>
|
|
208
|
-
<input type="text" placeholder="Normal input" />
|
|
209
|
-
</body>
|
|
210
|
-
</html>`,
|
|
211
|
-
},
|
|
212
|
-
})
|
|
213
|
-
|
|
214
|
-
try {
|
|
215
|
-
await page.goto(htmlServer.baseUrl, { waitUntil: 'domcontentloaded' })
|
|
216
|
-
await page.waitForTimeout(500)
|
|
217
|
-
|
|
218
|
-
const { snapshot: interactiveSnapshot } = await getAriaSnapshot({ page, interactiveOnly: true })
|
|
219
|
-
console.log('\n--- CONTENTEDITABLE INTERACTIVE SNAPSHOT ---')
|
|
220
|
-
console.log(interactiveSnapshot)
|
|
221
|
-
|
|
222
|
-
// All contenteditable divs should appear as textbox
|
|
223
|
-
const textboxLines = interactiveSnapshot.split('\n').filter((line) => {
|
|
224
|
-
return line.includes('textbox')
|
|
225
|
-
})
|
|
226
|
-
// 5 contenteditable (id, bare, empty-attr, plaintext-only, explicit-role) + 1 input = 6
|
|
227
|
-
expect(textboxLines.length).toBeGreaterThanOrEqual(6)
|
|
228
|
-
|
|
229
|
-
// The editor with id should use [id="editor-with-id"] as locator
|
|
230
|
-
expect(interactiveSnapshot).toContain('[id="editor-with-id"]')
|
|
231
|
-
|
|
232
|
-
// The bare contenteditable without id/role should use [contenteditable="true"]
|
|
233
|
-
expect(interactiveSnapshot).toContain('[contenteditable="true"]')
|
|
234
|
-
|
|
235
|
-
// Try clicking and typing in the bare contenteditable (no role, no id)
|
|
236
|
-
const bareEditors = page.locator('[contenteditable="true"]')
|
|
237
|
-
const bareCount = await bareEditors.count()
|
|
238
|
-
expect(bareCount).toBeGreaterThanOrEqual(2) // at least the 2 bare ones
|
|
239
|
-
|
|
240
|
-
// Click the first bare contenteditable and type
|
|
241
|
-
await bareEditors.first().click()
|
|
242
|
-
await page.keyboard.press('ControlOrMeta+A')
|
|
243
|
-
await page.keyboard.type('Typed via locator!')
|
|
244
|
-
|
|
245
|
-
const content = await bareEditors.first().innerText()
|
|
246
|
-
expect(content).toContain('Typed via locator!')
|
|
247
|
-
} finally {
|
|
248
|
-
await htmlServer.close()
|
|
249
|
-
}
|
|
250
|
-
}, 30000)
|
|
251
|
-
|
|
252
|
-
it('scopes snapshot to cross-origin iframe locator', async () => {
|
|
253
|
-
const iframeServer = await createHtmlServer({
|
|
254
|
-
htmlByPath: {
|
|
255
|
-
'/iframe.html': `<!doctype html>
|
|
256
|
-
<html>
|
|
257
|
-
<head>
|
|
258
|
-
<meta charset="utf-8" />
|
|
259
|
-
<title>Iframe Content</title>
|
|
260
|
-
</head>
|
|
261
|
-
<body>
|
|
262
|
-
<h1>Iframe Heading</h1>
|
|
263
|
-
<button data-testid="iframe-button">Iframe Button</button>
|
|
264
|
-
</body>
|
|
265
|
-
</html>`,
|
|
266
|
-
},
|
|
267
|
-
})
|
|
268
|
-
|
|
269
|
-
const outerServer = await createHtmlServer({
|
|
270
|
-
htmlByPath: {
|
|
271
|
-
'/': `<!doctype html>
|
|
272
|
-
<html>
|
|
273
|
-
<head>
|
|
274
|
-
<meta charset="utf-8" />
|
|
275
|
-
<title>Outer Page</title>
|
|
276
|
-
</head>
|
|
277
|
-
<body>
|
|
278
|
-
<h1>Outer Heading</h1>
|
|
279
|
-
<iframe data-testid="external-iframe" src="${iframeServer.baseUrl}/iframe.html"></iframe>
|
|
280
|
-
</body>
|
|
281
|
-
</html>`,
|
|
282
|
-
},
|
|
283
|
-
})
|
|
284
|
-
|
|
285
|
-
try {
|
|
286
|
-
await page.goto(outerServer.baseUrl, { waitUntil: 'domcontentloaded', timeout: 10000 })
|
|
287
|
-
await page.locator('[data-testid="external-iframe"]').waitFor({ timeout: 5000 })
|
|
288
|
-
await page
|
|
289
|
-
.frameLocator('[data-testid="external-iframe"]')
|
|
290
|
-
.locator('[data-testid="iframe-button"]')
|
|
291
|
-
.waitFor({ timeout: 5000 })
|
|
292
|
-
|
|
293
|
-
// Convert iframe Locator to Frame
|
|
294
|
-
const iframeHandle = await page.locator('[data-testid="external-iframe"]').elementHandle()
|
|
295
|
-
const iframeFrame = await iframeHandle!.contentFrame()
|
|
296
|
-
|
|
297
|
-
const { snapshot } = await getAriaSnapshot({
|
|
298
|
-
page,
|
|
299
|
-
frame: iframeFrame!,
|
|
300
|
-
})
|
|
301
|
-
|
|
302
|
-
expect(snapshot).toContain('Iframe Heading')
|
|
303
|
-
// TODO we seem to be using name with higher priority than test id for some reason in snapshots
|
|
304
|
-
// expect(snapshot).toContain('[data-testid="iframe-button"]')
|
|
305
|
-
expect(snapshot).not.toContain('Outer Heading')
|
|
306
|
-
} finally {
|
|
307
|
-
await outerServer.close()
|
|
308
|
-
await iframeServer.close()
|
|
309
|
-
}
|
|
310
|
-
}, 30000)
|
|
311
|
-
})
|