agent-web-interface 4.0.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/LICENSE +21 -0
- package/README.md +226 -0
- package/dist/src/browser/ensure-browser.d.ts +39 -0
- package/dist/src/browser/ensure-browser.d.ts.map +1 -0
- package/dist/src/browser/ensure-browser.js +65 -0
- package/dist/src/browser/ensure-browser.js.map +1 -0
- package/dist/src/browser/index.d.ts +8 -0
- package/dist/src/browser/index.d.ts.map +1 -0
- package/dist/src/browser/index.js +8 -0
- package/dist/src/browser/index.js.map +1 -0
- package/dist/src/browser/page-network-tracker.d.ts +96 -0
- package/dist/src/browser/page-network-tracker.d.ts.map +1 -0
- package/dist/src/browser/page-network-tracker.js +235 -0
- package/dist/src/browser/page-network-tracker.js.map +1 -0
- package/dist/src/browser/page-registry.d.ts +137 -0
- package/dist/src/browser/page-registry.d.ts.map +1 -0
- package/dist/src/browser/page-registry.js +194 -0
- package/dist/src/browser/page-registry.js.map +1 -0
- package/dist/src/browser/page-stabilization.d.ts +35 -0
- package/dist/src/browser/page-stabilization.d.ts.map +1 -0
- package/dist/src/browser/page-stabilization.js +42 -0
- package/dist/src/browser/page-stabilization.js.map +1 -0
- package/dist/src/browser/session-manager.d.ts +336 -0
- package/dist/src/browser/session-manager.d.ts.map +1 -0
- package/dist/src/browser/session-manager.js +964 -0
- package/dist/src/browser/session-manager.js.map +1 -0
- package/dist/src/cdp/cdp-client.interface.d.ts +193 -0
- package/dist/src/cdp/cdp-client.interface.d.ts.map +1 -0
- package/dist/src/cdp/cdp-client.interface.js +9 -0
- package/dist/src/cdp/cdp-client.interface.js.map +1 -0
- package/dist/src/cdp/index.d.ts +9 -0
- package/dist/src/cdp/index.d.ts.map +1 -0
- package/dist/src/cdp/index.js +8 -0
- package/dist/src/cdp/index.js.map +1 -0
- package/dist/src/cdp/puppeteer-cdp-client.d.ts +97 -0
- package/dist/src/cdp/puppeteer-cdp-client.d.ts.map +1 -0
- package/dist/src/cdp/puppeteer-cdp-client.js +273 -0
- package/dist/src/cdp/puppeteer-cdp-client.js.map +1 -0
- package/dist/src/cli/args.d.ts +35 -0
- package/dist/src/cli/args.d.ts.map +1 -0
- package/dist/src/cli/args.js +76 -0
- package/dist/src/cli/args.js.map +1 -0
- package/dist/src/delta/dom-stabilizer.d.ts +46 -0
- package/dist/src/delta/dom-stabilizer.d.ts.map +1 -0
- package/dist/src/delta/dom-stabilizer.js +121 -0
- package/dist/src/delta/dom-stabilizer.js.map +1 -0
- package/dist/src/delta/index.d.ts +8 -0
- package/dist/src/delta/index.d.ts.map +1 -0
- package/dist/src/delta/index.js +7 -0
- package/dist/src/delta/index.js.map +1 -0
- package/dist/src/factpack/action-selector.d.ts +36 -0
- package/dist/src/factpack/action-selector.d.ts.map +1 -0
- package/dist/src/factpack/action-selector.js +367 -0
- package/dist/src/factpack/action-selector.js.map +1 -0
- package/dist/src/factpack/dialog-detector.d.ts +19 -0
- package/dist/src/factpack/dialog-detector.d.ts.map +1 -0
- package/dist/src/factpack/dialog-detector.js +354 -0
- package/dist/src/factpack/dialog-detector.js.map +1 -0
- package/dist/src/factpack/form-detector.d.ts +28 -0
- package/dist/src/factpack/form-detector.d.ts.map +1 -0
- package/dist/src/factpack/form-detector.js +555 -0
- package/dist/src/factpack/form-detector.js.map +1 -0
- package/dist/src/factpack/index.d.ts +32 -0
- package/dist/src/factpack/index.d.ts.map +1 -0
- package/dist/src/factpack/index.js +73 -0
- package/dist/src/factpack/index.js.map +1 -0
- package/dist/src/factpack/page-classifier.d.ts +22 -0
- package/dist/src/factpack/page-classifier.d.ts.map +1 -0
- package/dist/src/factpack/page-classifier.js +526 -0
- package/dist/src/factpack/page-classifier.js.map +1 -0
- package/dist/src/factpack/types.d.ts +307 -0
- package/dist/src/factpack/types.d.ts.map +1 -0
- package/dist/src/factpack/types.js +12 -0
- package/dist/src/factpack/types.js.map +1 -0
- package/dist/src/form/dependency-tracker.d.ts +108 -0
- package/dist/src/form/dependency-tracker.d.ts.map +1 -0
- package/dist/src/form/dependency-tracker.js +298 -0
- package/dist/src/form/dependency-tracker.js.map +1 -0
- package/dist/src/form/field-extractor.d.ts +32 -0
- package/dist/src/form/field-extractor.d.ts.map +1 -0
- package/dist/src/form/field-extractor.js +544 -0
- package/dist/src/form/field-extractor.js.map +1 -0
- package/dist/src/form/form-detector.d.ts +103 -0
- package/dist/src/form/form-detector.d.ts.map +1 -0
- package/dist/src/form/form-detector.js +704 -0
- package/dist/src/form/form-detector.js.map +1 -0
- package/dist/src/form/form-state.d.ts +23 -0
- package/dist/src/form/form-state.d.ts.map +1 -0
- package/dist/src/form/form-state.js +39 -0
- package/dist/src/form/form-state.js.map +1 -0
- package/dist/src/form/index.d.ts +23 -0
- package/dist/src/form/index.d.ts.map +1 -0
- package/dist/src/form/index.js +27 -0
- package/dist/src/form/index.js.map +1 -0
- package/dist/src/form/runtime-value-reader.d.ts +72 -0
- package/dist/src/form/runtime-value-reader.d.ts.map +1 -0
- package/dist/src/form/runtime-value-reader.js +232 -0
- package/dist/src/form/runtime-value-reader.js.map +1 -0
- package/dist/src/form/types.d.ts +384 -0
- package/dist/src/form/types.d.ts.map +1 -0
- package/dist/src/form/types.js +17 -0
- package/dist/src/form/types.js.map +1 -0
- package/dist/src/index.d.ts +8 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +212 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/lib/constants.d.ts +27 -0
- package/dist/src/lib/constants.d.ts.map +1 -0
- package/dist/src/lib/constants.js +63 -0
- package/dist/src/lib/constants.js.map +1 -0
- package/dist/src/lib/index.d.ts +12 -0
- package/dist/src/lib/index.d.ts.map +1 -0
- package/dist/src/lib/index.js +17 -0
- package/dist/src/lib/index.js.map +1 -0
- package/dist/src/lib/regions.d.ts +29 -0
- package/dist/src/lib/regions.d.ts.map +1 -0
- package/dist/src/lib/regions.js +93 -0
- package/dist/src/lib/regions.js.map +1 -0
- package/dist/src/lib/scoring.d.ts +47 -0
- package/dist/src/lib/scoring.d.ts.map +1 -0
- package/dist/src/lib/scoring.js +79 -0
- package/dist/src/lib/scoring.js.map +1 -0
- package/dist/src/lib/selectors.d.ts +42 -0
- package/dist/src/lib/selectors.d.ts.map +1 -0
- package/dist/src/lib/selectors.js +138 -0
- package/dist/src/lib/selectors.js.map +1 -0
- package/dist/src/lib/text-utils.d.ts +155 -0
- package/dist/src/lib/text-utils.d.ts.map +1 -0
- package/dist/src/lib/text-utils.js +391 -0
- package/dist/src/lib/text-utils.js.map +1 -0
- package/dist/src/observation/eid-linker.d.ts +104 -0
- package/dist/src/observation/eid-linker.d.ts.map +1 -0
- package/dist/src/observation/eid-linker.js +403 -0
- package/dist/src/observation/eid-linker.js.map +1 -0
- package/dist/src/observation/index.d.ts +12 -0
- package/dist/src/observation/index.d.ts.map +1 -0
- package/dist/src/observation/index.js +15 -0
- package/dist/src/observation/index.js.map +1 -0
- package/dist/src/observation/observation-accumulator.d.ts +58 -0
- package/dist/src/observation/observation-accumulator.d.ts.map +1 -0
- package/dist/src/observation/observation-accumulator.js +213 -0
- package/dist/src/observation/observation-accumulator.js.map +1 -0
- package/dist/src/observation/observation.types.d.ts +139 -0
- package/dist/src/observation/observation.types.d.ts.map +1 -0
- package/dist/src/observation/observation.types.js +59 -0
- package/dist/src/observation/observation.types.js.map +1 -0
- package/dist/src/observation/observer-script.d.ts +19 -0
- package/dist/src/observation/observer-script.d.ts.map +1 -0
- package/dist/src/observation/observer-script.js +569 -0
- package/dist/src/observation/observer-script.js.map +1 -0
- package/dist/src/query/index.d.ts +9 -0
- package/dist/src/query/index.d.ts.map +1 -0
- package/dist/src/query/index.js +10 -0
- package/dist/src/query/index.js.map +1 -0
- package/dist/src/query/query-engine.d.ts +111 -0
- package/dist/src/query/query-engine.d.ts.map +1 -0
- package/dist/src/query/query-engine.js +509 -0
- package/dist/src/query/query-engine.js.map +1 -0
- package/dist/src/query/types/index.d.ts +5 -0
- package/dist/src/query/types/index.d.ts.map +1 -0
- package/dist/src/query/types/index.js +5 -0
- package/dist/src/query/types/index.js.map +1 -0
- package/dist/src/query/types/query.types.d.ts +141 -0
- package/dist/src/query/types/query.types.d.ts.map +1 -0
- package/dist/src/query/types/query.types.js +19 -0
- package/dist/src/query/types/query.types.js.map +1 -0
- package/dist/src/renderer/budget-manager.d.ts +46 -0
- package/dist/src/renderer/budget-manager.d.ts.map +1 -0
- package/dist/src/renderer/budget-manager.js +133 -0
- package/dist/src/renderer/budget-manager.js.map +1 -0
- package/dist/src/renderer/constants.d.ts +38 -0
- package/dist/src/renderer/constants.d.ts.map +1 -0
- package/dist/src/renderer/constants.js +29 -0
- package/dist/src/renderer/constants.js.map +1 -0
- package/dist/src/renderer/index.d.ts +12 -0
- package/dist/src/renderer/index.d.ts.map +1 -0
- package/dist/src/renderer/index.js +16 -0
- package/dist/src/renderer/index.js.map +1 -0
- package/dist/src/renderer/section-renderers.d.ts +42 -0
- package/dist/src/renderer/section-renderers.d.ts.map +1 -0
- package/dist/src/renderer/section-renderers.js +252 -0
- package/dist/src/renderer/section-renderers.js.map +1 -0
- package/dist/src/renderer/token-counter.d.ts +45 -0
- package/dist/src/renderer/token-counter.d.ts.map +1 -0
- package/dist/src/renderer/token-counter.js +65 -0
- package/dist/src/renderer/token-counter.js.map +1 -0
- package/dist/src/renderer/types.d.ts +71 -0
- package/dist/src/renderer/types.d.ts.map +1 -0
- package/dist/src/renderer/types.js +7 -0
- package/dist/src/renderer/types.js.map +1 -0
- package/dist/src/renderer/xml-renderer.d.ts +42 -0
- package/dist/src/renderer/xml-renderer.d.ts.map +1 -0
- package/dist/src/renderer/xml-renderer.js +103 -0
- package/dist/src/renderer/xml-renderer.js.map +1 -0
- package/dist/src/server/index.d.ts +8 -0
- package/dist/src/server/index.d.ts.map +1 -0
- package/dist/src/server/index.js +8 -0
- package/dist/src/server/index.js.map +1 -0
- package/dist/src/server/mcp-server.d.ts +59 -0
- package/dist/src/server/mcp-server.d.ts.map +1 -0
- package/dist/src/server/mcp-server.js +140 -0
- package/dist/src/server/mcp-server.js.map +1 -0
- package/dist/src/server/server-config.d.ts +41 -0
- package/dist/src/server/server-config.d.ts.map +1 -0
- package/dist/src/server/server-config.js +80 -0
- package/dist/src/server/server-config.js.map +1 -0
- package/dist/src/server/session-store.d.ts +148 -0
- package/dist/src/server/session-store.d.ts.map +1 -0
- package/dist/src/server/session-store.js +224 -0
- package/dist/src/server/session-store.js.map +1 -0
- package/dist/src/shared/errors/browser-session.error.d.ts +102 -0
- package/dist/src/shared/errors/browser-session.error.d.ts.map +1 -0
- package/dist/src/shared/errors/browser-session.error.js +153 -0
- package/dist/src/shared/errors/browser-session.error.js.map +1 -0
- package/dist/src/shared/errors/index.d.ts +5 -0
- package/dist/src/shared/errors/index.d.ts.map +1 -0
- package/dist/src/shared/errors/index.js +5 -0
- package/dist/src/shared/errors/index.js.map +1 -0
- package/dist/src/shared/services/dom-transformer.service.d.ts +71 -0
- package/dist/src/shared/services/dom-transformer.service.d.ts.map +1 -0
- package/dist/src/shared/services/dom-transformer.service.js +190 -0
- package/dist/src/shared/services/dom-transformer.service.js.map +1 -0
- package/dist/src/shared/services/index.d.ts +7 -0
- package/dist/src/shared/services/index.d.ts.map +1 -0
- package/dist/src/shared/services/index.js +7 -0
- package/dist/src/shared/services/index.js.map +1 -0
- package/dist/src/shared/services/logging.service.d.ts +154 -0
- package/dist/src/shared/services/logging.service.d.ts.map +1 -0
- package/dist/src/shared/services/logging.service.js +267 -0
- package/dist/src/shared/services/logging.service.js.map +1 -0
- package/dist/src/shared/services/selector-builder.service.d.ts +53 -0
- package/dist/src/shared/services/selector-builder.service.d.ts.map +1 -0
- package/dist/src/shared/services/selector-builder.service.js +240 -0
- package/dist/src/shared/services/selector-builder.service.js.map +1 -0
- package/dist/src/shared/types/base.types.d.ts +45 -0
- package/dist/src/shared/types/base.types.d.ts.map +1 -0
- package/dist/src/shared/types/base.types.js +8 -0
- package/dist/src/shared/types/base.types.js.map +1 -0
- package/dist/src/shared/types/index.d.ts +5 -0
- package/dist/src/shared/types/index.d.ts.map +1 -0
- package/dist/src/shared/types/index.js +5 -0
- package/dist/src/shared/types/index.js.map +1 -0
- package/dist/src/snapshot/element-resolver.d.ts +102 -0
- package/dist/src/snapshot/element-resolver.d.ts.map +1 -0
- package/dist/src/snapshot/element-resolver.js +379 -0
- package/dist/src/snapshot/element-resolver.js.map +1 -0
- package/dist/src/snapshot/extractors/attribute-extractor.d.ts +40 -0
- package/dist/src/snapshot/extractors/attribute-extractor.d.ts.map +1 -0
- package/dist/src/snapshot/extractors/attribute-extractor.js +237 -0
- package/dist/src/snapshot/extractors/attribute-extractor.js.map +1 -0
- package/dist/src/snapshot/extractors/ax-extractor.d.ts +36 -0
- package/dist/src/snapshot/extractors/ax-extractor.d.ts.map +1 -0
- package/dist/src/snapshot/extractors/ax-extractor.js +144 -0
- package/dist/src/snapshot/extractors/ax-extractor.js.map +1 -0
- package/dist/src/snapshot/extractors/dom-extractor.d.ts +21 -0
- package/dist/src/snapshot/extractors/dom-extractor.d.ts.map +1 -0
- package/dist/src/snapshot/extractors/dom-extractor.js +137 -0
- package/dist/src/snapshot/extractors/dom-extractor.js.map +1 -0
- package/dist/src/snapshot/extractors/grouping-resolver.d.ts +39 -0
- package/dist/src/snapshot/extractors/grouping-resolver.d.ts.map +1 -0
- package/dist/src/snapshot/extractors/grouping-resolver.js +260 -0
- package/dist/src/snapshot/extractors/grouping-resolver.js.map +1 -0
- package/dist/src/snapshot/extractors/index.d.ts +19 -0
- package/dist/src/snapshot/extractors/index.d.ts.map +1 -0
- package/dist/src/snapshot/extractors/index.js +27 -0
- package/dist/src/snapshot/extractors/index.js.map +1 -0
- package/dist/src/snapshot/extractors/label-resolver.d.ts +44 -0
- package/dist/src/snapshot/extractors/label-resolver.d.ts.map +1 -0
- package/dist/src/snapshot/extractors/label-resolver.js +173 -0
- package/dist/src/snapshot/extractors/label-resolver.js.map +1 -0
- package/dist/src/snapshot/extractors/layout-extractor.d.ts +52 -0
- package/dist/src/snapshot/extractors/layout-extractor.d.ts.map +1 -0
- package/dist/src/snapshot/extractors/layout-extractor.js +382 -0
- package/dist/src/snapshot/extractors/layout-extractor.js.map +1 -0
- package/dist/src/snapshot/extractors/locator-builder.d.ts +27 -0
- package/dist/src/snapshot/extractors/locator-builder.d.ts.map +1 -0
- package/dist/src/snapshot/extractors/locator-builder.js +223 -0
- package/dist/src/snapshot/extractors/locator-builder.js.map +1 -0
- package/dist/src/snapshot/extractors/region-resolver.d.ts +31 -0
- package/dist/src/snapshot/extractors/region-resolver.d.ts.map +1 -0
- package/dist/src/snapshot/extractors/region-resolver.js +168 -0
- package/dist/src/snapshot/extractors/region-resolver.js.map +1 -0
- package/dist/src/snapshot/extractors/state-extractor.d.ts +30 -0
- package/dist/src/snapshot/extractors/state-extractor.d.ts.map +1 -0
- package/dist/src/snapshot/extractors/state-extractor.js +181 -0
- package/dist/src/snapshot/extractors/state-extractor.js.map +1 -0
- package/dist/src/snapshot/extractors/types.d.ts +213 -0
- package/dist/src/snapshot/extractors/types.d.ts.map +1 -0
- package/dist/src/snapshot/extractors/types.js +145 -0
- package/dist/src/snapshot/extractors/types.js.map +1 -0
- package/dist/src/snapshot/index.d.ts +14 -0
- package/dist/src/snapshot/index.d.ts.map +1 -0
- package/dist/src/snapshot/index.js +18 -0
- package/dist/src/snapshot/index.js.map +1 -0
- package/dist/src/snapshot/snapshot-compiler.d.ts +73 -0
- package/dist/src/snapshot/snapshot-compiler.d.ts.map +1 -0
- package/dist/src/snapshot/snapshot-compiler.js +763 -0
- package/dist/src/snapshot/snapshot-compiler.js.map +1 -0
- package/dist/src/snapshot/snapshot-health.d.ts +97 -0
- package/dist/src/snapshot/snapshot-health.d.ts.map +1 -0
- package/dist/src/snapshot/snapshot-health.js +214 -0
- package/dist/src/snapshot/snapshot-health.js.map +1 -0
- package/dist/src/snapshot/snapshot-store.d.ts +137 -0
- package/dist/src/snapshot/snapshot-store.d.ts.map +1 -0
- package/dist/src/snapshot/snapshot-store.js +202 -0
- package/dist/src/snapshot/snapshot-store.js.map +1 -0
- package/dist/src/snapshot/snapshot.types.d.ts +250 -0
- package/dist/src/snapshot/snapshot.types.d.ts.map +1 -0
- package/dist/src/snapshot/snapshot.types.js +54 -0
- package/dist/src/snapshot/snapshot.types.js.map +1 -0
- package/dist/src/state/actionables-filter.d.ts +47 -0
- package/dist/src/state/actionables-filter.d.ts.map +1 -0
- package/dist/src/state/actionables-filter.js +173 -0
- package/dist/src/state/actionables-filter.js.map +1 -0
- package/dist/src/state/atoms-extractor.d.ts +23 -0
- package/dist/src/state/atoms-extractor.d.ts.map +1 -0
- package/dist/src/state/atoms-extractor.js +160 -0
- package/dist/src/state/atoms-extractor.js.map +1 -0
- package/dist/src/state/constants.d.ts +125 -0
- package/dist/src/state/constants.d.ts.map +1 -0
- package/dist/src/state/constants.js +131 -0
- package/dist/src/state/constants.js.map +1 -0
- package/dist/src/state/diff-engine.d.ts +23 -0
- package/dist/src/state/diff-engine.d.ts.map +1 -0
- package/dist/src/state/diff-engine.js +475 -0
- package/dist/src/state/diff-engine.js.map +1 -0
- package/dist/src/state/element-identity.d.ts +75 -0
- package/dist/src/state/element-identity.d.ts.map +1 -0
- package/dist/src/state/element-identity.js +129 -0
- package/dist/src/state/element-identity.js.map +1 -0
- package/dist/src/state/element-ref.types.d.ts +135 -0
- package/dist/src/state/element-ref.types.d.ts.map +1 -0
- package/dist/src/state/element-ref.types.js +13 -0
- package/dist/src/state/element-ref.types.js.map +1 -0
- package/dist/src/state/element-registry.d.ts +118 -0
- package/dist/src/state/element-registry.d.ts.map +1 -0
- package/dist/src/state/element-registry.js +222 -0
- package/dist/src/state/element-registry.js.map +1 -0
- package/dist/src/state/health.types.d.ts +93 -0
- package/dist/src/state/health.types.d.ts.map +1 -0
- package/dist/src/state/health.types.js +56 -0
- package/dist/src/state/health.types.js.map +1 -0
- package/dist/src/state/layer-detector.d.ts +23 -0
- package/dist/src/state/layer-detector.d.ts.map +1 -0
- package/dist/src/state/layer-detector.js +368 -0
- package/dist/src/state/layer-detector.js.map +1 -0
- package/dist/src/state/locator-generator.d.ts +21 -0
- package/dist/src/state/locator-generator.d.ts.map +1 -0
- package/dist/src/state/locator-generator.js +137 -0
- package/dist/src/state/locator-generator.js.map +1 -0
- package/dist/src/state/state-manager.d.ts +104 -0
- package/dist/src/state/state-manager.d.ts.map +1 -0
- package/dist/src/state/state-manager.js +618 -0
- package/dist/src/state/state-manager.js.map +1 -0
- package/dist/src/state/state-renderer.d.ts +63 -0
- package/dist/src/state/state-renderer.d.ts.map +1 -0
- package/dist/src/state/state-renderer.js +340 -0
- package/dist/src/state/state-renderer.js.map +1 -0
- package/dist/src/state/types.d.ts +353 -0
- package/dist/src/state/types.d.ts.map +1 -0
- package/dist/src/state/types.js +8 -0
- package/dist/src/state/types.js.map +1 -0
- package/dist/src/tools/browser-tools.d.ts +140 -0
- package/dist/src/tools/browser-tools.d.ts.map +1 -0
- package/dist/src/tools/browser-tools.js +657 -0
- package/dist/src/tools/browser-tools.js.map +1 -0
- package/dist/src/tools/errors.d.ts +63 -0
- package/dist/src/tools/errors.d.ts.map +1 -0
- package/dist/src/tools/errors.js +86 -0
- package/dist/src/tools/errors.js.map +1 -0
- package/dist/src/tools/execute-action.d.ts +135 -0
- package/dist/src/tools/execute-action.d.ts.map +1 -0
- package/dist/src/tools/execute-action.js +579 -0
- package/dist/src/tools/execute-action.js.map +1 -0
- package/dist/src/tools/form-tools.d.ts +109 -0
- package/dist/src/tools/form-tools.d.ts.map +1 -0
- package/dist/src/tools/form-tools.js +434 -0
- package/dist/src/tools/form-tools.js.map +1 -0
- package/dist/src/tools/index.d.ts +11 -0
- package/dist/src/tools/index.d.ts.map +1 -0
- package/dist/src/tools/index.js +49 -0
- package/dist/src/tools/index.js.map +1 -0
- package/dist/src/tools/response-builder.d.ts +98 -0
- package/dist/src/tools/response-builder.d.ts.map +1 -0
- package/dist/src/tools/response-builder.js +219 -0
- package/dist/src/tools/response-builder.js.map +1 -0
- package/dist/src/tools/tool-schemas.d.ts +2482 -0
- package/dist/src/tools/tool-schemas.d.ts.map +1 -0
- package/dist/src/tools/tool-schemas.js +606 -0
- package/dist/src/tools/tool-schemas.js.map +1 -0
- package/dist/vitest.config.d.ts +3 -0
- package/dist/vitest.config.d.ts.map +1 -0
- package/dist/vitest.config.js +16 -0
- package/dist/vitest.config.js.map +1 -0
- package/package.json +76 -0
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layout Extractor
|
|
3
|
+
*
|
|
4
|
+
* Gets bounding boxes and CSS layout info for nodes.
|
|
5
|
+
*
|
|
6
|
+
* @module snapshot/extractors/layout-extractor
|
|
7
|
+
*
|
|
8
|
+
* CDP Domains:
|
|
9
|
+
* - DOM.getBoxModel: Get bounding box for a node
|
|
10
|
+
* - CSS.getComputedStyleForNode: Get computed CSS properties
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Compute bounding box from CDP box model content array.
|
|
14
|
+
* CDP returns 8 values representing the 4 corners of the quad.
|
|
15
|
+
*
|
|
16
|
+
* @param content - Array of 8 values: [x1,y1, x2,y2, x3,y3, x4,y4]
|
|
17
|
+
* @param width - Width from box model
|
|
18
|
+
* @param height - Height from box model
|
|
19
|
+
* @returns BBox object
|
|
20
|
+
*/
|
|
21
|
+
function boxModelToBBox(content, width, height) {
|
|
22
|
+
// For a simple rectangle, x1,y1 is the top-left corner
|
|
23
|
+
const x = content[0];
|
|
24
|
+
const y = content[1];
|
|
25
|
+
return { x, y, w: width, h: height };
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Compute screen zone based on element position relative to viewport.
|
|
29
|
+
*
|
|
30
|
+
* @param bbox - Element bounding box
|
|
31
|
+
* @param viewport - Viewport dimensions
|
|
32
|
+
* @returns ScreenZone classification
|
|
33
|
+
*/
|
|
34
|
+
export function computeScreenZone(bbox, viewport) {
|
|
35
|
+
// Check if below fold first
|
|
36
|
+
if (bbox.y >= viewport.height) {
|
|
37
|
+
return 'below-fold';
|
|
38
|
+
}
|
|
39
|
+
// Calculate center point of element
|
|
40
|
+
const centerX = bbox.x + bbox.w / 2;
|
|
41
|
+
const centerY = bbox.y + bbox.h / 2;
|
|
42
|
+
// Divide viewport into 3x3 grid
|
|
43
|
+
const xThird = viewport.width / 3;
|
|
44
|
+
const yThird = viewport.height / 3;
|
|
45
|
+
// Determine horizontal zone
|
|
46
|
+
let horizontal;
|
|
47
|
+
if (centerX < xThird) {
|
|
48
|
+
horizontal = 'left';
|
|
49
|
+
}
|
|
50
|
+
else if (centerX < xThird * 2) {
|
|
51
|
+
horizontal = 'center';
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
horizontal = 'right';
|
|
55
|
+
}
|
|
56
|
+
// Determine vertical zone
|
|
57
|
+
let vertical;
|
|
58
|
+
if (centerY < yThird) {
|
|
59
|
+
vertical = 'top';
|
|
60
|
+
}
|
|
61
|
+
else if (centerY < yThird * 2) {
|
|
62
|
+
vertical = 'middle';
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
vertical = 'bottom';
|
|
66
|
+
}
|
|
67
|
+
return `${vertical}-${horizontal}`;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Compute visibility from display, visibility CSS properties and bbox.
|
|
71
|
+
*
|
|
72
|
+
* @param bbox - Element bounding box
|
|
73
|
+
* @param display - CSS display value
|
|
74
|
+
* @param visibility - CSS visibility value
|
|
75
|
+
* @returns true if element is visible
|
|
76
|
+
*/
|
|
77
|
+
export function computeVisibility(bbox, display, visibility) {
|
|
78
|
+
// Check CSS display
|
|
79
|
+
if (display === 'none') {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
// Check CSS visibility
|
|
83
|
+
if (visibility === 'hidden' || visibility === 'collapse') {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
// Check size (zero-size elements are not visible)
|
|
87
|
+
if (bbox.w === 0 || bbox.h === 0) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Extract layout information for a single node.
|
|
94
|
+
*
|
|
95
|
+
* @param ctx - Extractor context
|
|
96
|
+
* @param backendNodeId - Backend node ID (used for DOM.getBoxModel)
|
|
97
|
+
* @param nodeId - Ephemeral node ID (used for CSS.getComputedStyleForNode)
|
|
98
|
+
* @returns NodeLayoutInfo
|
|
99
|
+
*/
|
|
100
|
+
async function extractNodeLayout(ctx, backendNodeId, nodeId) {
|
|
101
|
+
const { cdp, viewport } = ctx;
|
|
102
|
+
let bbox = { x: 0, y: 0, w: 0, h: 0 };
|
|
103
|
+
let display;
|
|
104
|
+
let visibility;
|
|
105
|
+
let zIndex;
|
|
106
|
+
let boxModelError = false;
|
|
107
|
+
// Get box model (uses backendNodeId)
|
|
108
|
+
try {
|
|
109
|
+
const boxResponse = await cdp.send('DOM.getBoxModel', {
|
|
110
|
+
backendNodeId,
|
|
111
|
+
});
|
|
112
|
+
bbox = boxModelToBBox(boxResponse.model.content, boxResponse.model.width, boxResponse.model.height);
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
// Element may not be rendered (display:none, not in DOM, etc.)
|
|
116
|
+
boxModelError = true;
|
|
117
|
+
}
|
|
118
|
+
// Get computed styles (requires ephemeral nodeId, not backendNodeId)
|
|
119
|
+
if (nodeId !== undefined) {
|
|
120
|
+
try {
|
|
121
|
+
const styleResponse = await cdp.send('CSS.getComputedStyleForNode', {
|
|
122
|
+
nodeId,
|
|
123
|
+
});
|
|
124
|
+
for (const prop of styleResponse.computedStyle) {
|
|
125
|
+
if (prop.name === 'display') {
|
|
126
|
+
display = prop.value;
|
|
127
|
+
}
|
|
128
|
+
else if (prop.name === 'visibility') {
|
|
129
|
+
visibility = prop.value;
|
|
130
|
+
}
|
|
131
|
+
else if (prop.name === 'z-index') {
|
|
132
|
+
// Parse z-index; 'auto' results in NaN which we ignore
|
|
133
|
+
const parsed = parseInt(prop.value, 10);
|
|
134
|
+
if (!isNaN(parsed)) {
|
|
135
|
+
zIndex = parsed;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
// Styles may not be available
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const isVisible = boxModelError ? false : computeVisibility(bbox, display, visibility);
|
|
145
|
+
const screenZone = isVisible ? computeScreenZone(bbox, viewport) : undefined;
|
|
146
|
+
return {
|
|
147
|
+
bbox,
|
|
148
|
+
display,
|
|
149
|
+
visibility,
|
|
150
|
+
isVisible,
|
|
151
|
+
screenZone,
|
|
152
|
+
zIndex,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Extract layout information for multiple nodes.
|
|
157
|
+
*
|
|
158
|
+
* Uses a batch strategy via Runtime.evaluate to minimize roundtrips.
|
|
159
|
+
* Falls back to individual CDP calls for nodes that cannot be resolved via batch (e.g. inside closed shadow roots).
|
|
160
|
+
*
|
|
161
|
+
* @param ctx - Extractor context with CDP client and options
|
|
162
|
+
* @param backendNodeIds - Array of backend node IDs to extract layout for
|
|
163
|
+
* @param domNodes - Map of backendNodeId to DOM node
|
|
164
|
+
* @returns LayoutExtractionResult with layouts map
|
|
165
|
+
*/
|
|
166
|
+
export async function extractLayout(ctx, backendNodeIds, domNodes) {
|
|
167
|
+
const layouts = new Map();
|
|
168
|
+
if (backendNodeIds.length === 0) {
|
|
169
|
+
return { layouts };
|
|
170
|
+
}
|
|
171
|
+
// Identify nodes that need fallback
|
|
172
|
+
const processedIds = new Set();
|
|
173
|
+
const fallbackIds = [];
|
|
174
|
+
// Try batch extraction if we have the DOM tree
|
|
175
|
+
if (domNodes instanceof Map) {
|
|
176
|
+
try {
|
|
177
|
+
const batchResults = await extractLayoutBatch(ctx, backendNodeIds, domNodes);
|
|
178
|
+
for (const { backendNodeId, layout } of batchResults) {
|
|
179
|
+
if (layout?.bbox) {
|
|
180
|
+
// Compute derived fields that weren't in the batch script
|
|
181
|
+
const isVisible = computeVisibility(layout.bbox, layout.display, layout.visibility);
|
|
182
|
+
const screenZone = isVisible ? computeScreenZone(layout.bbox, ctx.viewport) : undefined;
|
|
183
|
+
layouts.set(backendNodeId, {
|
|
184
|
+
...layout,
|
|
185
|
+
bbox: layout.bbox, // Explicitly set bbox to satisfy TS
|
|
186
|
+
isVisible,
|
|
187
|
+
screenZone,
|
|
188
|
+
});
|
|
189
|
+
processedIds.add(backendNodeId);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
// If batch fails entirely, we will fallback for all because processedIds is empty
|
|
195
|
+
// console.warn('Batch layout extraction failed:', err);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// Identify fallback candidates (either batch failed or wasn't tried)
|
|
199
|
+
for (const id of backendNodeIds) {
|
|
200
|
+
if (!processedIds.has(id)) {
|
|
201
|
+
fallbackIds.push(id);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
// Process fallbacks
|
|
205
|
+
for (const backendNodeId of fallbackIds) {
|
|
206
|
+
// Look up ephemeral nodeId from DOM nodes map
|
|
207
|
+
// We handle both possible Map types (NodeIdLookup or Map<number, RawDomNode>)
|
|
208
|
+
// RawDomNode has .nodeId, NodeIdLookup values have .nodeId
|
|
209
|
+
const nodeData = domNodes?.get(backendNodeId);
|
|
210
|
+
// Use type assertion or check properties since types overlap on .nodeId
|
|
211
|
+
const nodeId = nodeData?.nodeId;
|
|
212
|
+
const layout = await extractNodeLayout(ctx, backendNodeId, nodeId);
|
|
213
|
+
layouts.set(backendNodeId, layout);
|
|
214
|
+
}
|
|
215
|
+
return { layouts };
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Helper to build a selector path for a node.
|
|
219
|
+
* Returns array of selector segments (splitting at shadow/frame boundaries).
|
|
220
|
+
*/
|
|
221
|
+
function buildPath(nodeId, domNodes) {
|
|
222
|
+
const path = [];
|
|
223
|
+
let currentSegment = '';
|
|
224
|
+
let currentId = nodeId;
|
|
225
|
+
// Safety break
|
|
226
|
+
let depth = 0;
|
|
227
|
+
const MAX_DEPTH = 100;
|
|
228
|
+
while (currentId !== undefined && depth < MAX_DEPTH) {
|
|
229
|
+
const node = domNodes.get(currentId);
|
|
230
|
+
if (!node)
|
|
231
|
+
return undefined;
|
|
232
|
+
// Check parent
|
|
233
|
+
const parentId = node.parentId;
|
|
234
|
+
// If no parent, we are at root (or detached)
|
|
235
|
+
if (parentId === undefined) {
|
|
236
|
+
if (node.nodeName === '#document') {
|
|
237
|
+
// Root document, we are done with this segment
|
|
238
|
+
if (currentSegment) {
|
|
239
|
+
path.unshift(currentSegment);
|
|
240
|
+
}
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
// Detached node?
|
|
244
|
+
return undefined;
|
|
245
|
+
}
|
|
246
|
+
const parent = domNodes.get(parentId);
|
|
247
|
+
if (!parent)
|
|
248
|
+
return undefined;
|
|
249
|
+
// Handle Node Types
|
|
250
|
+
if (node.nodeType === 1) {
|
|
251
|
+
// ELEMENT_NODE
|
|
252
|
+
// Calculate nth-child index among ELEMENT siblings
|
|
253
|
+
let index = 1;
|
|
254
|
+
if (parent.childNodeIds) {
|
|
255
|
+
for (const childId of parent.childNodeIds) {
|
|
256
|
+
if (childId === currentId)
|
|
257
|
+
break;
|
|
258
|
+
const sibling = domNodes.get(childId);
|
|
259
|
+
if (sibling?.nodeType === 1) {
|
|
260
|
+
index++;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
const segment = `${node.nodeName.toLowerCase()}:nth-child(${index})`;
|
|
265
|
+
currentSegment = currentSegment ? `${segment} > ${currentSegment}` : segment;
|
|
266
|
+
}
|
|
267
|
+
else if (node.nodeType === 11) {
|
|
268
|
+
// DOCUMENT_FRAGMENT_NODE (Shadow Root)
|
|
269
|
+
// Boundary reached. Push current segment.
|
|
270
|
+
if (currentSegment) {
|
|
271
|
+
path.unshift(currentSegment);
|
|
272
|
+
currentSegment = '';
|
|
273
|
+
}
|
|
274
|
+
// Next iteration will handle the HOST (parent of shadow root)
|
|
275
|
+
// The parent of shadow root in RawDomNode tree is the host element.
|
|
276
|
+
}
|
|
277
|
+
else if (node.nodeType === 9) {
|
|
278
|
+
// DOCUMENT_NODE (in Iframe)
|
|
279
|
+
// Boundary reached. Push current segment.
|
|
280
|
+
if (currentSegment) {
|
|
281
|
+
path.unshift(currentSegment);
|
|
282
|
+
currentSegment = '';
|
|
283
|
+
}
|
|
284
|
+
// Parent is the iframe element
|
|
285
|
+
}
|
|
286
|
+
currentId = parentId;
|
|
287
|
+
depth++;
|
|
288
|
+
}
|
|
289
|
+
return path;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Execute batch extraction via Runtime.evaluate
|
|
293
|
+
*/
|
|
294
|
+
async function extractLayoutBatch(ctx, backendNodeIds, domNodes) {
|
|
295
|
+
const paths = [];
|
|
296
|
+
for (const id of backendNodeIds) {
|
|
297
|
+
const path = buildPath(id, domNodes);
|
|
298
|
+
if (path) {
|
|
299
|
+
paths.push({ id, path });
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
if (paths.length === 0)
|
|
303
|
+
return [];
|
|
304
|
+
// Script to resolve paths and get layout
|
|
305
|
+
const expression = `
|
|
306
|
+
(function(items) {
|
|
307
|
+
function resolve(path) {
|
|
308
|
+
let ctx = document;
|
|
309
|
+
for (const segment of path) {
|
|
310
|
+
if (!ctx) return null;
|
|
311
|
+
|
|
312
|
+
if (ctx instanceof HTMLIFrameElement) {
|
|
313
|
+
try {
|
|
314
|
+
ctx = ctx.contentDocument;
|
|
315
|
+
} catch (e) { return null; }
|
|
316
|
+
} else if (ctx.shadowRoot) {
|
|
317
|
+
ctx = ctx.shadowRoot;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (!ctx) return null;
|
|
321
|
+
|
|
322
|
+
ctx = ctx.querySelector(segment);
|
|
323
|
+
}
|
|
324
|
+
return ctx;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return items.map(item => {
|
|
328
|
+
try {
|
|
329
|
+
const node = resolve(item.path);
|
|
330
|
+
if (!node || node.nodeType !== 1) return null;
|
|
331
|
+
|
|
332
|
+
const rect = node.getBoundingClientRect();
|
|
333
|
+
const style = window.getComputedStyle(node);
|
|
334
|
+
const zIndexValue = style.zIndex;
|
|
335
|
+
const zIndex = zIndexValue === 'auto' ? null : parseInt(zIndexValue, 10);
|
|
336
|
+
|
|
337
|
+
return {
|
|
338
|
+
x: rect.x,
|
|
339
|
+
y: rect.y,
|
|
340
|
+
w: rect.width,
|
|
341
|
+
h: rect.height,
|
|
342
|
+
display: style.display,
|
|
343
|
+
visibility: style.visibility,
|
|
344
|
+
zIndex: isNaN(zIndex) ? null : zIndex
|
|
345
|
+
};
|
|
346
|
+
} catch (e) {
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
})(${JSON.stringify(paths)})
|
|
351
|
+
`;
|
|
352
|
+
try {
|
|
353
|
+
const response = await ctx.cdp.send('Runtime.evaluate', {
|
|
354
|
+
expression,
|
|
355
|
+
returnByValue: true,
|
|
356
|
+
awaitPromise: false,
|
|
357
|
+
});
|
|
358
|
+
const results = response.result.value;
|
|
359
|
+
if (!Array.isArray(results) || results.length !== paths.length) {
|
|
360
|
+
return [];
|
|
361
|
+
}
|
|
362
|
+
return paths.map((item, index) => {
|
|
363
|
+
const res = results[index];
|
|
364
|
+
if (!res)
|
|
365
|
+
return { backendNodeId: item.id };
|
|
366
|
+
return {
|
|
367
|
+
backendNodeId: item.id,
|
|
368
|
+
layout: {
|
|
369
|
+
bbox: { x: res.x, y: res.y, w: res.w, h: res.h },
|
|
370
|
+
display: res.display,
|
|
371
|
+
visibility: res.visibility,
|
|
372
|
+
zIndex: res.zIndex ?? undefined,
|
|
373
|
+
},
|
|
374
|
+
};
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
catch {
|
|
378
|
+
// console.error('Batch eval failed', e);
|
|
379
|
+
return [];
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
//# sourceMappingURL=layout-extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout-extractor.js","sourceRoot":"","sources":["../../../../src/snapshot/extractors/layout-extractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Locator Builder
|
|
3
|
+
*
|
|
4
|
+
* Generates stable locators for element interaction.
|
|
5
|
+
*
|
|
6
|
+
* @module snapshot/extractors/locator-builder
|
|
7
|
+
*
|
|
8
|
+
* Strategies (priority order):
|
|
9
|
+
* 1. test-id (data-testid, data-test, data-cy)
|
|
10
|
+
* 2. Role + accessible name
|
|
11
|
+
* 3. CSS ID selector
|
|
12
|
+
* 4. Role + unique attribute
|
|
13
|
+
* 5. CSS selector (class combo)
|
|
14
|
+
* 6. Tag-based fallback
|
|
15
|
+
*/
|
|
16
|
+
import type { NodeLocators } from '../snapshot.types.js';
|
|
17
|
+
import type { RawDomNode, RawAxNode } from './types.js';
|
|
18
|
+
/**
|
|
19
|
+
* Build locators for an element.
|
|
20
|
+
*
|
|
21
|
+
* @param domNode - Raw DOM node data (optional)
|
|
22
|
+
* @param axNode - Raw AX node data (optional)
|
|
23
|
+
* @param label - Resolved accessible label
|
|
24
|
+
* @returns NodeLocators with primary and alternates
|
|
25
|
+
*/
|
|
26
|
+
export declare function buildLocators(domNode: RawDomNode | undefined, axNode: RawAxNode | undefined, _label: string): NodeLocators;
|
|
27
|
+
//# sourceMappingURL=locator-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locator-builder.d.ts","sourceRoot":"","sources":["../../../../src/snapshot/extractors/locator-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAqGxD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,UAAU,GAAG,SAAS,EAC/B,MAAM,EAAE,SAAS,GAAG,SAAS,EAC7B,MAAM,EAAE,MAAM,GACb,YAAY,CA6Hd"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Locator Builder
|
|
3
|
+
*
|
|
4
|
+
* Generates stable locators for element interaction.
|
|
5
|
+
*
|
|
6
|
+
* @module snapshot/extractors/locator-builder
|
|
7
|
+
*
|
|
8
|
+
* Strategies (priority order):
|
|
9
|
+
* 1. test-id (data-testid, data-test, data-cy)
|
|
10
|
+
* 2. Role + accessible name
|
|
11
|
+
* 3. CSS ID selector
|
|
12
|
+
* 4. Role + unique attribute
|
|
13
|
+
* 5. CSS selector (class combo)
|
|
14
|
+
* 6. Tag-based fallback
|
|
15
|
+
*/
|
|
16
|
+
import { escapeAttrSelectorValue, escapeRoleLocatorName, cssEscape, normalizeText, } from '../../lib/text-utils.js';
|
|
17
|
+
/**
|
|
18
|
+
* Test ID attributes to check (in priority order)
|
|
19
|
+
*/
|
|
20
|
+
const TEST_ID_ATTRS = ['data-testid', 'data-test', 'data-cy', 'data-test-id'];
|
|
21
|
+
/** Prevent oversized locators that can bloat snapshots or break consumers. */
|
|
22
|
+
const MAX_LOCATOR_VALUE_LENGTH = 200;
|
|
23
|
+
function isLocatorValueWithinLimit(value) {
|
|
24
|
+
return value.length <= MAX_LOCATOR_VALUE_LENGTH;
|
|
25
|
+
}
|
|
26
|
+
function hasControlCharacters(value) {
|
|
27
|
+
for (let i = 0; i < value.length; i++) {
|
|
28
|
+
const codeUnit = value.charCodeAt(i);
|
|
29
|
+
if (codeUnit <= 0x1f || codeUnit === 0x7f) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
function canUseRoleName(value) {
|
|
36
|
+
return isLocatorValueWithinLimit(value) && !hasControlCharacters(value);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Build a CSS attribute selector for exact match.
|
|
40
|
+
* Uses raw value with only quote escaping (no truncation/normalization).
|
|
41
|
+
*
|
|
42
|
+
* @param attr - Attribute name
|
|
43
|
+
* @param value - Attribute value (raw)
|
|
44
|
+
* @returns CSS attribute selector string
|
|
45
|
+
*/
|
|
46
|
+
function attrSelector(attr, value) {
|
|
47
|
+
return `[${attr}="${escapeAttrSelectorValue(value)}"]`;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Build a role-based locator using raw accessible name.
|
|
51
|
+
* Uses escapeRoleLocatorName for Playwright-style role selectors
|
|
52
|
+
* (only escapes quotes/backslashes, keeps control chars raw).
|
|
53
|
+
*
|
|
54
|
+
* @param role - AX role
|
|
55
|
+
* @param name - Raw accessible name (not normalized/truncated)
|
|
56
|
+
* @returns Role locator string
|
|
57
|
+
*/
|
|
58
|
+
function roleLocator(role, name) {
|
|
59
|
+
if (name) {
|
|
60
|
+
return `role=${role}[name="${escapeRoleLocatorName(name)}"]`;
|
|
61
|
+
}
|
|
62
|
+
return `role=${role}`;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get the first non-generic class name from a class list.
|
|
66
|
+
*
|
|
67
|
+
* @param classList - Space-separated class names
|
|
68
|
+
* @returns First meaningful class or undefined
|
|
69
|
+
*/
|
|
70
|
+
function getFirstMeaningfulClass(classList) {
|
|
71
|
+
if (!classList)
|
|
72
|
+
return undefined;
|
|
73
|
+
const genericClasses = new Set([
|
|
74
|
+
'container',
|
|
75
|
+
'wrapper',
|
|
76
|
+
'inner',
|
|
77
|
+
'outer',
|
|
78
|
+
'content',
|
|
79
|
+
'row',
|
|
80
|
+
'col',
|
|
81
|
+
'column',
|
|
82
|
+
'flex',
|
|
83
|
+
'grid',
|
|
84
|
+
'block',
|
|
85
|
+
'inline',
|
|
86
|
+
'hidden',
|
|
87
|
+
'visible',
|
|
88
|
+
]);
|
|
89
|
+
const classes = classList.split(/\s+/).filter(Boolean);
|
|
90
|
+
// Return first non-generic class
|
|
91
|
+
for (const cls of classes) {
|
|
92
|
+
if (!genericClasses.has(cls.toLowerCase())) {
|
|
93
|
+
return cls;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// If all are generic, return first one
|
|
97
|
+
return classes[0];
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Build locators for an element.
|
|
101
|
+
*
|
|
102
|
+
* @param domNode - Raw DOM node data (optional)
|
|
103
|
+
* @param axNode - Raw AX node data (optional)
|
|
104
|
+
* @param label - Resolved accessible label
|
|
105
|
+
* @returns NodeLocators with primary and alternates
|
|
106
|
+
*/
|
|
107
|
+
export function buildLocators(domNode, axNode, _label) {
|
|
108
|
+
const attributes = domNode?.attributes ?? {};
|
|
109
|
+
const role = axNode?.role;
|
|
110
|
+
const nodeName = domNode?.nodeName?.toLowerCase();
|
|
111
|
+
const alternates = [];
|
|
112
|
+
let primary;
|
|
113
|
+
// 1. Test ID (highest priority)
|
|
114
|
+
for (const testIdAttr of TEST_ID_ATTRS) {
|
|
115
|
+
const testId = attributes[testIdAttr];
|
|
116
|
+
if (testId && isLocatorValueWithinLimit(testId)) {
|
|
117
|
+
if (!primary) {
|
|
118
|
+
primary = attrSelector(testIdAttr, testId);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
alternates.push(attrSelector(testIdAttr, testId));
|
|
122
|
+
}
|
|
123
|
+
break; // Only use first test ID found
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// 2. Role + name locator - use RAW accessible name (not normalized label)
|
|
127
|
+
if (role) {
|
|
128
|
+
// Prefer axNode.name if present and non-empty after trim
|
|
129
|
+
// For aria-label fallback, normalize whitespace to match typical AX behavior
|
|
130
|
+
let rawName;
|
|
131
|
+
if (axNode?.name?.trim()) {
|
|
132
|
+
// Use raw AX name as-is (preserves its original whitespace)
|
|
133
|
+
rawName = axNode.name;
|
|
134
|
+
}
|
|
135
|
+
else if (attributes['aria-label']) {
|
|
136
|
+
// Fallback: normalize aria-label whitespace to match typical AX computed behavior
|
|
137
|
+
const normalized = normalizeText(attributes['aria-label']);
|
|
138
|
+
rawName = normalized || undefined;
|
|
139
|
+
}
|
|
140
|
+
if (rawName && canUseRoleName(rawName)) {
|
|
141
|
+
const roleSelector = roleLocator(role, rawName);
|
|
142
|
+
if (!primary) {
|
|
143
|
+
primary = roleSelector;
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
// Add as alternate since it has a specific name
|
|
147
|
+
alternates.push(roleSelector);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
// No name available - emit bare role locator as fallback (not specific enough for alternate)
|
|
152
|
+
primary ??= roleLocator(role);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// 3. CSS ID selector (use cssEscape for proper escaping of special chars)
|
|
156
|
+
const id = attributes.id;
|
|
157
|
+
if (id && isLocatorValueWithinLimit(id)) {
|
|
158
|
+
const idSelector = `#${cssEscape(id)}`;
|
|
159
|
+
if (!primary) {
|
|
160
|
+
primary = idSelector;
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
alternates.push(idSelector);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// 4. aria-label selector
|
|
167
|
+
const ariaLabel = attributes['aria-label'];
|
|
168
|
+
if (ariaLabel && isLocatorValueWithinLimit(ariaLabel)) {
|
|
169
|
+
const ariaSelector = attrSelector('aria-label', ariaLabel);
|
|
170
|
+
if (!primary) {
|
|
171
|
+
primary = ariaSelector;
|
|
172
|
+
}
|
|
173
|
+
else if (!alternates.includes(ariaSelector)) {
|
|
174
|
+
alternates.push(ariaSelector);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// 5. Form name attribute (for inputs)
|
|
178
|
+
const nameAttr = attributes.name;
|
|
179
|
+
if (nameAttr &&
|
|
180
|
+
isLocatorValueWithinLimit(nameAttr) &&
|
|
181
|
+
(nodeName === 'input' || nodeName === 'select' || nodeName === 'textarea')) {
|
|
182
|
+
const nameSelector = attrSelector('name', nameAttr);
|
|
183
|
+
if (!primary) {
|
|
184
|
+
primary = nameSelector;
|
|
185
|
+
}
|
|
186
|
+
else if (!alternates.includes(nameSelector)) {
|
|
187
|
+
alternates.push(nameSelector);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// 6. Class-based selector (use cssEscape for proper escaping of special chars)
|
|
191
|
+
const className = getFirstMeaningfulClass(attributes.class);
|
|
192
|
+
if (className && nodeName && isLocatorValueWithinLimit(className)) {
|
|
193
|
+
const classSelector = `${nodeName}.${cssEscape(className)}`;
|
|
194
|
+
if (!primary) {
|
|
195
|
+
primary = classSelector;
|
|
196
|
+
}
|
|
197
|
+
else if (!alternates.includes(classSelector)) {
|
|
198
|
+
alternates.push(classSelector);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// 7. Tag-based fallback
|
|
202
|
+
primary ??= nodeName ?? '*';
|
|
203
|
+
// Build result
|
|
204
|
+
const result = {
|
|
205
|
+
primary,
|
|
206
|
+
};
|
|
207
|
+
// Filter out duplicates and limit alternates
|
|
208
|
+
const uniqueAlternates = [...new Set(alternates)]
|
|
209
|
+
.filter((alt) => alt !== primary && alt.length > 0)
|
|
210
|
+
.slice(0, 3); // Limit to 3 alternates
|
|
211
|
+
if (uniqueAlternates.length > 0) {
|
|
212
|
+
result.alternates = uniqueAlternates;
|
|
213
|
+
}
|
|
214
|
+
// Include frame/shadow paths if present (for cross-boundary element targeting)
|
|
215
|
+
if (domNode?.framePath && domNode.framePath.length > 0) {
|
|
216
|
+
result.frame_path = domNode.framePath.map(String);
|
|
217
|
+
}
|
|
218
|
+
if (domNode?.shadowPath && domNode.shadowPath.length > 0) {
|
|
219
|
+
result.shadow_path = domNode.shadowPath.map(String);
|
|
220
|
+
}
|
|
221
|
+
return result;
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=locator-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locator-builder.js","sourceRoot":"","sources":["../../../../src/snapshot/extractors/locator-builder.ts"],"names":[],"mappings":"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"}
|