@sun-asterisk/sungen 1.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 +490 -0
- package/bin/sungen.js +12 -0
- package/dist/cli/commands/auto-tag-command.d.ts +8 -0
- package/dist/cli/commands/auto-tag-command.d.ts.map +1 -0
- package/dist/cli/commands/auto-tag-command.js +104 -0
- package/dist/cli/commands/auto-tag-command.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +196 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config/ai-providers.yaml +56 -0
- package/dist/config/config-loader.d.ts +51 -0
- package/dist/config/config-loader.d.ts.map +1 -0
- package/dist/config/config-loader.js +216 -0
- package/dist/config/config-loader.js.map +1 -0
- package/dist/config/config-schema.d.ts +121 -0
- package/dist/config/config-schema.d.ts.map +1 -0
- package/dist/config/config-schema.js +7 -0
- package/dist/config/config-schema.js.map +1 -0
- package/dist/config/default.config.yaml +101 -0
- package/dist/config/framework.config.yaml +52 -0
- package/dist/config/routes.yaml +31 -0
- package/dist/core/selector-base/annotation-handler.d.ts +45 -0
- package/dist/core/selector-base/annotation-handler.d.ts.map +1 -0
- package/dist/core/selector-base/annotation-handler.js +102 -0
- package/dist/core/selector-base/annotation-handler.js.map +1 -0
- package/dist/core/selector-base/base-generator.d.ts +49 -0
- package/dist/core/selector-base/base-generator.d.ts.map +1 -0
- package/dist/core/selector-base/base-generator.js +214 -0
- package/dist/core/selector-base/base-generator.js.map +1 -0
- package/dist/core/selector-base/gherkin-parser.d.ts +24 -0
- package/dist/core/selector-base/gherkin-parser.d.ts.map +1 -0
- package/dist/core/selector-base/gherkin-parser.js +42 -0
- package/dist/core/selector-base/gherkin-parser.js.map +1 -0
- package/dist/core/selector-mapper/priority-mapper.d.ts +74 -0
- package/dist/core/selector-mapper/priority-mapper.d.ts.map +1 -0
- package/dist/core/selector-mapper/priority-mapper.js +477 -0
- package/dist/core/selector-mapper/priority-mapper.js.map +1 -0
- package/dist/core/ui-scanner/heuristics/base-heuristic.d.ts +91 -0
- package/dist/core/ui-scanner/heuristics/base-heuristic.d.ts.map +1 -0
- package/dist/core/ui-scanner/heuristics/base-heuristic.js +175 -0
- package/dist/core/ui-scanner/heuristics/base-heuristic.js.map +1 -0
- package/dist/core/ui-scanner/react-scanner.d.ts +32 -0
- package/dist/core/ui-scanner/react-scanner.d.ts.map +1 -0
- package/dist/core/ui-scanner/react-scanner.js +163 -0
- package/dist/core/ui-scanner/react-scanner.js.map +1 -0
- package/dist/core/ui-scanner/scanner-interface.d.ts +94 -0
- package/dist/core/ui-scanner/scanner-interface.d.ts.map +1 -0
- package/dist/core/ui-scanner/scanner-interface.js +33 -0
- package/dist/core/ui-scanner/scanner-interface.js.map +1 -0
- package/dist/core/ui-scanner/strict-scanner.d.ts +81 -0
- package/dist/core/ui-scanner/strict-scanner.d.ts.map +1 -0
- package/dist/core/ui-scanner/strict-scanner.js +511 -0
- package/dist/core/ui-scanner/strict-scanner.js.map +1 -0
- package/dist/executor/playwright/playwright-generator.d.ts +33 -0
- package/dist/executor/playwright/playwright-generator.d.ts.map +1 -0
- package/dist/executor/playwright/playwright-generator.js +136 -0
- package/dist/executor/playwright/playwright-generator.js.map +1 -0
- package/dist/executor/test-generator.d.ts +63 -0
- package/dist/executor/test-generator.d.ts.map +1 -0
- package/dist/executor/test-generator.js +30 -0
- package/dist/executor/test-generator.js.map +1 -0
- package/dist/external/ai-provider.d.ts +60 -0
- package/dist/external/ai-provider.d.ts.map +1 -0
- package/dist/external/ai-provider.js +30 -0
- package/dist/external/ai-provider.js.map +1 -0
- package/dist/external/anthropic-provider.d.ts +29 -0
- package/dist/external/anthropic-provider.d.ts.map +1 -0
- package/dist/external/anthropic-provider.js +85 -0
- package/dist/external/anthropic-provider.js.map +1 -0
- package/dist/generators/cache/cache-manager.d.ts +66 -0
- package/dist/generators/cache/cache-manager.d.ts.map +1 -0
- package/dist/generators/cache/cache-manager.js +286 -0
- package/dist/generators/cache/cache-manager.js.map +1 -0
- package/dist/generators/cli.d.ts +7 -0
- package/dist/generators/cli.d.ts.map +1 -0
- package/dist/generators/cli.js +570 -0
- package/dist/generators/cli.js.map +1 -0
- package/dist/generators/dsl-writer/index.d.ts +33 -0
- package/dist/generators/dsl-writer/index.d.ts.map +1 -0
- package/dist/generators/dsl-writer/index.js +226 -0
- package/dist/generators/dsl-writer/index.js.map +1 -0
- package/dist/generators/gherkin-parser/index.d.ts +47 -0
- package/dist/generators/gherkin-parser/index.d.ts.map +1 -0
- package/dist/generators/gherkin-parser/index.js +149 -0
- package/dist/generators/gherkin-parser/index.js.map +1 -0
- package/dist/generators/gherkin-parser/selector-extractor.d.ts +37 -0
- package/dist/generators/gherkin-parser/selector-extractor.d.ts.map +1 -0
- package/dist/generators/gherkin-parser/selector-extractor.js +108 -0
- package/dist/generators/gherkin-parser/selector-extractor.js.map +1 -0
- package/dist/generators/scaffold-generator/index.d.ts +111 -0
- package/dist/generators/scaffold-generator/index.d.ts.map +1 -0
- package/dist/generators/scaffold-generator/index.js +408 -0
- package/dist/generators/scaffold-generator/index.js.map +1 -0
- package/dist/generators/selector-mapper/ai-mapper.d.ts +56 -0
- package/dist/generators/selector-mapper/ai-mapper.d.ts.map +1 -0
- package/dist/generators/selector-mapper/ai-mapper.js +457 -0
- package/dist/generators/selector-mapper/ai-mapper.js.map +1 -0
- package/dist/generators/selector-mapper/hybrid-mapper.d.ts +67 -0
- package/dist/generators/selector-mapper/hybrid-mapper.d.ts.map +1 -0
- package/dist/generators/selector-mapper/hybrid-mapper.js +349 -0
- package/dist/generators/selector-mapper/hybrid-mapper.js.map +1 -0
- package/dist/generators/selector-mapper/index.d.ts +8 -0
- package/dist/generators/selector-mapper/index.d.ts.map +1 -0
- package/dist/generators/selector-mapper/index.js +12 -0
- package/dist/generators/selector-mapper/index.js.map +1 -0
- package/dist/generators/selector-mapper/intelligent-mapper.d.ts +125 -0
- package/dist/generators/selector-mapper/intelligent-mapper.d.ts.map +1 -0
- package/dist/generators/selector-mapper/intelligent-mapper.js +391 -0
- package/dist/generators/selector-mapper/intelligent-mapper.js.map +1 -0
- package/dist/generators/test-generator/adapters/adapter-interface.d.ts +49 -0
- package/dist/generators/test-generator/adapters/adapter-interface.d.ts.map +1 -0
- package/dist/generators/test-generator/adapters/adapter-interface.js +7 -0
- package/dist/generators/test-generator/adapters/adapter-interface.js.map +1 -0
- package/dist/generators/test-generator/adapters/adapter-registry.d.ts +29 -0
- package/dist/generators/test-generator/adapters/adapter-registry.d.ts.map +1 -0
- package/dist/generators/test-generator/adapters/adapter-registry.js +50 -0
- package/dist/generators/test-generator/adapters/adapter-registry.js.map +1 -0
- package/dist/generators/test-generator/adapters/index.d.ts +4 -0
- package/dist/generators/test-generator/adapters/index.d.ts.map +1 -0
- package/dist/generators/test-generator/adapters/index.js +13 -0
- package/dist/generators/test-generator/adapters/index.js.map +1 -0
- package/dist/generators/test-generator/adapters/playwright/playwright-adapter.d.ts +23 -0
- package/dist/generators/test-generator/adapters/playwright/playwright-adapter.d.ts.map +1 -0
- package/dist/generators/test-generator/adapters/playwright/playwright-adapter.js +38 -0
- package/dist/generators/test-generator/adapters/playwright/playwright-adapter.js.map +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/before-each.hbs +8 -0
- package/dist/generators/test-generator/adapters/playwright/templates/imports.hbs +5 -0
- package/dist/generators/test-generator/adapters/playwright/templates/scenario.hbs +8 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/check-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/clear-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/click-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/double-click-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/fill-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/hover-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/press-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/select-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/uncheck-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/active-state-assertion.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/ai-response-assertion-selector.hbs +5 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/ai-response-assertion-simple.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/application-running.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/checked-assertion.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/contain-text-assertion.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/count-assertion.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-assertion.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/empty-assertion.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/enabled-assertion.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/focused-assertion.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/have-text-assertion.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/not-checked-assertion.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/not-visible-assertion.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-assertion.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/check-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/checkbox.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/checked-assertion.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/clear-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/clear-auth.hbs +6 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/clear-browser-state.hbs +6 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/clear-database.hbs +4 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/clear.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/click-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/click.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/contain-text-assertion.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/contains-text-assertion.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/count-assertion.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/count-greater-than.hbs +3 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/count-less-than.hbs +3 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/disabled-assertion.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/displayed-containing-text.hbs +3 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/displayed-with-text.hbs +3 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/double-click-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/empty-assertion-advanced.hbs +3 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/empty-assertion.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/enabled-assertion.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/error-message-assertion.hbs +3 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/fill-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/fill.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/focused-assertion.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/generic-message-assertion.hbs +3 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/has-attribute.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/has-class.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/has-count.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/has-image-src.hbs +3 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/has-link.hbs +3 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/has-placeholder.hbs +3 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/has-value.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/have-text-assertion.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/hover-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/html5-validation-check.hbs +4 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/is-checked.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/is-editable.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/is-focused.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/is-hidden.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/is-unchecked.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/locator.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/login.hbs +8 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/message-assertion-body.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/message-assertion-selector.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/message-count-assertion.hbs +3 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/navigation/navigation.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/navigation/route-assertion.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/navigation/wait-for-element.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/navigation/wait-timeout.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/navigation.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/not-checked-assertion.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/not-visible-assertion.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/not-visible.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/notification-assertion.hbs +4 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/press-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/press-enter.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/redirect-assertion.hbs +3 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/route-assertion.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/screen-navigation.hbs +3 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/scroll-bottom-assertion.hbs +5 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/select-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/select.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/setup/application-running.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/setup/clear-auth.hbs +6 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/setup/clear-browser-state.hbs +6 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/setup/clear-database.hbs +4 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/setup/user-login-todo.hbs +6 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/text-matches-pattern.hbs +3 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/uncheck-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/user-login-todo.hbs +6 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/visibility-assertion.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/visible-assertion.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/wait-for-element.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/wait-timeout.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/wait.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/test-file.hbs +19 -0
- package/dist/generators/test-generator/ai-step-mapper.d.ts +27 -0
- package/dist/generators/test-generator/ai-step-mapper.d.ts.map +1 -0
- package/dist/generators/test-generator/ai-step-mapper.js +204 -0
- package/dist/generators/test-generator/ai-step-mapper.js.map +1 -0
- package/dist/generators/test-generator/code-generator.d.ts +52 -0
- package/dist/generators/test-generator/code-generator.d.ts.map +1 -0
- package/dist/generators/test-generator/code-generator.js +191 -0
- package/dist/generators/test-generator/code-generator.js.map +1 -0
- package/dist/generators/test-generator/patterns/assertion-patterns.d.ts +7 -0
- package/dist/generators/test-generator/patterns/assertion-patterns.d.ts.map +1 -0
- package/dist/generators/test-generator/patterns/assertion-patterns.js +173 -0
- package/dist/generators/test-generator/patterns/assertion-patterns.js.map +1 -0
- package/dist/generators/test-generator/patterns/form-patterns.d.ts +8 -0
- package/dist/generators/test-generator/patterns/form-patterns.d.ts.map +1 -0
- package/dist/generators/test-generator/patterns/form-patterns.js +110 -0
- package/dist/generators/test-generator/patterns/form-patterns.js.map +1 -0
- package/dist/generators/test-generator/patterns/index.d.ts +45 -0
- package/dist/generators/test-generator/patterns/index.d.ts.map +1 -0
- package/dist/generators/test-generator/patterns/index.js +106 -0
- package/dist/generators/test-generator/patterns/index.js.map +1 -0
- package/dist/generators/test-generator/patterns/interaction-patterns.d.ts +7 -0
- package/dist/generators/test-generator/patterns/interaction-patterns.d.ts.map +1 -0
- package/dist/generators/test-generator/patterns/interaction-patterns.js +100 -0
- package/dist/generators/test-generator/patterns/interaction-patterns.js.map +1 -0
- package/dist/generators/test-generator/patterns/navigation-patterns.d.ts +8 -0
- package/dist/generators/test-generator/patterns/navigation-patterns.d.ts.map +1 -0
- package/dist/generators/test-generator/patterns/navigation-patterns.js +92 -0
- package/dist/generators/test-generator/patterns/navigation-patterns.js.map +1 -0
- package/dist/generators/test-generator/patterns/setup-patterns.d.ts +7 -0
- package/dist/generators/test-generator/patterns/setup-patterns.d.ts.map +1 -0
- package/dist/generators/test-generator/patterns/setup-patterns.js +84 -0
- package/dist/generators/test-generator/patterns/setup-patterns.js.map +1 -0
- package/dist/generators/test-generator/patterns/types.d.ts +38 -0
- package/dist/generators/test-generator/patterns/types.d.ts.map +1 -0
- package/dist/generators/test-generator/patterns/types.js +3 -0
- package/dist/generators/test-generator/patterns/types.js.map +1 -0
- package/dist/generators/test-generator/step-mapper-old.d.ts +180 -0
- package/dist/generators/test-generator/step-mapper-old.d.ts.map +1 -0
- package/dist/generators/test-generator/step-mapper-old.js +752 -0
- package/dist/generators/test-generator/step-mapper-old.js.map +1 -0
- package/dist/generators/test-generator/step-mapper-refactored.d.ts +47 -0
- package/dist/generators/test-generator/step-mapper-refactored.d.ts.map +1 -0
- package/dist/generators/test-generator/step-mapper-refactored.js +182 -0
- package/dist/generators/test-generator/step-mapper-refactored.js.map +1 -0
- package/dist/generators/test-generator/step-mapper.d.ts +66 -0
- package/dist/generators/test-generator/step-mapper.d.ts.map +1 -0
- package/dist/generators/test-generator/step-mapper.js +248 -0
- package/dist/generators/test-generator/step-mapper.js.map +1 -0
- package/dist/generators/test-generator/template-engine.d.ts +33 -0
- package/dist/generators/test-generator/template-engine.d.ts.map +1 -0
- package/dist/generators/test-generator/template-engine.js +129 -0
- package/dist/generators/test-generator/template-engine.js.map +1 -0
- package/dist/generators/test-generator/utils/data-resolver.d.ts +39 -0
- package/dist/generators/test-generator/utils/data-resolver.d.ts.map +1 -0
- package/dist/generators/test-generator/utils/data-resolver.js +162 -0
- package/dist/generators/test-generator/utils/data-resolver.js.map +1 -0
- package/dist/generators/test-generator/utils/path-inference.d.ts +49 -0
- package/dist/generators/test-generator/utils/path-inference.d.ts.map +1 -0
- package/dist/generators/test-generator/utils/path-inference.js +286 -0
- package/dist/generators/test-generator/utils/path-inference.js.map +1 -0
- package/dist/generators/test-generator/utils/selector-resolver.d.ts +93 -0
- package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -0
- package/dist/generators/test-generator/utils/selector-resolver.js +408 -0
- package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -0
- package/dist/generators/types.d.ts +118 -0
- package/dist/generators/types.d.ts.map +1 -0
- package/dist/generators/types.js +48 -0
- package/dist/generators/types.js.map +1 -0
- package/dist/generators/ui-model-builder/deep-scanner.d.ts +121 -0
- package/dist/generators/ui-model-builder/deep-scanner.d.ts.map +1 -0
- package/dist/generators/ui-model-builder/deep-scanner.js +1113 -0
- package/dist/generators/ui-model-builder/deep-scanner.js.map +1 -0
- package/dist/generators/ui-model-builder/enhanced-deep-scanner.d.ts +110 -0
- package/dist/generators/ui-model-builder/enhanced-deep-scanner.d.ts.map +1 -0
- package/dist/generators/ui-model-builder/enhanced-deep-scanner.js +608 -0
- package/dist/generators/ui-model-builder/enhanced-deep-scanner.js.map +1 -0
- package/dist/generators/ui-model-builder/react-scanner.d.ts +107 -0
- package/dist/generators/ui-model-builder/react-scanner.d.ts.map +1 -0
- package/dist/generators/ui-model-builder/react-scanner.js +797 -0
- package/dist/generators/ui-model-builder/react-scanner.js.map +1 -0
- package/dist/input/cli-adapter.d.ts +63 -0
- package/dist/input/cli-adapter.d.ts.map +1 -0
- package/dist/input/cli-adapter.js +173 -0
- package/dist/input/cli-adapter.js.map +1 -0
- package/dist/input/config-adapter.d.ts +25 -0
- package/dist/input/config-adapter.d.ts.map +1 -0
- package/dist/input/config-adapter.js +70 -0
- package/dist/input/config-adapter.js.map +1 -0
- package/dist/input/input-adapter.d.ts +28 -0
- package/dist/input/input-adapter.d.ts.map +1 -0
- package/dist/input/input-adapter.js +17 -0
- package/dist/input/input-adapter.js.map +1 -0
- package/dist/input/vscode-adapter.d.ts +62 -0
- package/dist/input/vscode-adapter.d.ts.map +1 -0
- package/dist/input/vscode-adapter.js +64 -0
- package/dist/input/vscode-adapter.js.map +1 -0
- package/dist/orchestrator/cache-manager.d.ts +37 -0
- package/dist/orchestrator/cache-manager.d.ts.map +1 -0
- package/dist/orchestrator/cache-manager.js +148 -0
- package/dist/orchestrator/cache-manager.js.map +1 -0
- package/dist/orchestrator/pipeline.d.ts +73 -0
- package/dist/orchestrator/pipeline.d.ts.map +1 -0
- package/dist/orchestrator/pipeline.js +607 -0
- package/dist/orchestrator/pipeline.js.map +1 -0
- package/dist/orchestrator/project-initializer.d.ts +51 -0
- package/dist/orchestrator/project-initializer.d.ts.map +1 -0
- package/dist/orchestrator/project-initializer.js +326 -0
- package/dist/orchestrator/project-initializer.js.map +1 -0
- package/dist/orchestrator/reporter.d.ts +15 -0
- package/dist/orchestrator/reporter.d.ts.map +1 -0
- package/dist/orchestrator/reporter.js +30 -0
- package/dist/orchestrator/reporter.js.map +1 -0
- package/dist/orchestrator/screen-manager.d.ts +47 -0
- package/dist/orchestrator/screen-manager.d.ts.map +1 -0
- package/dist/orchestrator/screen-manager.js +271 -0
- package/dist/orchestrator/screen-manager.js.map +1 -0
- package/dist/tools/auto-tagger.d.ts +107 -0
- package/dist/tools/auto-tagger.d.ts.map +1 -0
- package/dist/tools/auto-tagger.js +502 -0
- package/dist/tools/auto-tagger.js.map +1 -0
- package/package.json +73 -0
- package/src/cli/commands/auto-tag-command.ts +80 -0
- package/src/cli/index.ts +205 -0
- package/src/config/ai-providers.yaml +56 -0
- package/src/config/config-loader.ts +248 -0
- package/src/config/config-schema.ts +148 -0
- package/src/config/default.config.yaml +101 -0
- package/src/config/framework.config.yaml +52 -0
- package/src/config/routes.yaml +31 -0
- package/src/core/selector-base/annotation-handler.ts +127 -0
- package/src/core/selector-base/base-generator.ts +234 -0
- package/src/core/selector-base/gherkin-parser.ts +57 -0
- package/src/core/selector-mapper/priority-mapper.ts +607 -0
- package/src/core/ui-scanner/heuristics/base-heuristic.ts +216 -0
- package/src/core/ui-scanner/react-scanner.ts +156 -0
- package/src/core/ui-scanner/scanner-interface.ts +133 -0
- package/src/core/ui-scanner/strict-scanner.ts +629 -0
- package/src/executor/playwright/playwright-generator.ts +125 -0
- package/src/executor/test-generator.ts +90 -0
- package/src/external/ai-provider.ts +90 -0
- package/src/external/anthropic-provider.ts +114 -0
- package/src/generators/README.md +410 -0
- package/src/generators/cache/cache-manager.ts +322 -0
- package/src/generators/cli.ts +640 -0
- package/src/generators/dsl-writer/index.ts +253 -0
- package/src/generators/gherkin-parser/index.ts +155 -0
- package/src/generators/gherkin-parser/selector-extractor.ts +142 -0
- package/src/generators/scaffold-generator/index.ts +524 -0
- package/src/generators/selector-mapper/ai-mapper.ts +528 -0
- package/src/generators/selector-mapper/hybrid-mapper.ts +427 -0
- package/src/generators/selector-mapper/index.ts +10 -0
- package/src/generators/selector-mapper/intelligent-mapper.ts +530 -0
- package/src/generators/test-generator/adapters/adapter-interface.ts +49 -0
- package/src/generators/test-generator/adapters/adapter-registry.ts +56 -0
- package/src/generators/test-generator/adapters/index.ts +9 -0
- package/src/generators/test-generator/adapters/playwright/playwright-adapter.ts +40 -0
- package/src/generators/test-generator/adapters/playwright/templates/before-each.hbs +8 -0
- package/src/generators/test-generator/adapters/playwright/templates/imports.hbs +5 -0
- package/src/generators/test-generator/adapters/playwright/templates/scenario.hbs +8 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/check-action.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/clear-action.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/click-action.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/double-click-action.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/fill-action.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/hover-action.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/press-action.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/select-action.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/uncheck-action.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/checked-assertion.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/contain-text-assertion.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/count-assertion.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-assertion.hbs +2 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/empty-assertion.hbs +2 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/enabled-assertion.hbs +2 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/focused-assertion.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/have-text-assertion.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/not-checked-assertion.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/not-visible-assertion.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-assertion.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/navigation/navigation.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/navigation/route-assertion.hbs +2 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/navigation/wait-for-element.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/navigation/wait-timeout.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/setup/application-running.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/setup/clear-auth.hbs +6 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/setup/clear-browser-state.hbs +6 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/setup/clear-database.hbs +4 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/setup/user-login-todo.hbs +6 -0
- package/src/generators/test-generator/adapters/playwright/templates/test-file.hbs +19 -0
- package/src/generators/test-generator/ai-step-mapper.ts +224 -0
- package/src/generators/test-generator/code-generator.ts +235 -0
- package/src/generators/test-generator/patterns/assertion-patterns.ts +183 -0
- package/src/generators/test-generator/patterns/form-patterns.ts +124 -0
- package/src/generators/test-generator/patterns/index.ts +97 -0
- package/src/generators/test-generator/patterns/interaction-patterns.ts +119 -0
- package/src/generators/test-generator/patterns/navigation-patterns.ts +110 -0
- package/src/generators/test-generator/patterns/setup-patterns.ts +94 -0
- package/src/generators/test-generator/patterns/types.ts +41 -0
- package/src/generators/test-generator/step-mapper.ts +254 -0
- package/src/generators/test-generator/template-engine.ts +160 -0
- package/src/generators/test-generator/utils/data-resolver.ts +147 -0
- package/src/generators/test-generator/utils/path-inference.ts +344 -0
- package/src/generators/test-generator/utils/selector-resolver.ts +480 -0
- package/src/generators/types.ts +226 -0
- package/src/generators/ui-model-builder/deep-scanner.ts +1244 -0
- package/src/generators/ui-model-builder/enhanced-deep-scanner.ts +731 -0
- package/src/generators/ui-model-builder/react-scanner.ts +959 -0
- package/src/input/cli-adapter.ts +185 -0
- package/src/input/config-adapter.ts +71 -0
- package/src/input/input-adapter.ts +32 -0
- package/src/input/vscode-adapter.ts +90 -0
- package/src/orchestrator/cache-manager.ts +138 -0
- package/src/orchestrator/pipeline.ts +713 -0
- package/src/orchestrator/project-initializer.ts +315 -0
- package/src/orchestrator/reporter.ts +36 -0
- package/src/orchestrator/screen-manager.ts +268 -0
- package/src/tools/auto-tagger.ts +572 -0
|
@@ -0,0 +1,528 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* AI-Assisted Selector Mapper
|
|
4
|
+
* Uses AI (Claude/Gemini) to map Gherkin element IDs to CSS selectors
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
8
|
+
import { GoogleGenerativeAI } from '@google/generative-ai';
|
|
9
|
+
import { UIModel, UIElement, SelectorDSL, SelectorEntry } from '../types';
|
|
10
|
+
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// Configuration
|
|
13
|
+
// ============================================================================
|
|
14
|
+
|
|
15
|
+
export interface AIMapperConfig {
|
|
16
|
+
provider: 'anthropic' | 'google';
|
|
17
|
+
model?: string;
|
|
18
|
+
apiKey?: string;
|
|
19
|
+
verbose?: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface MappingRequest {
|
|
23
|
+
uiModel: UIModel;
|
|
24
|
+
elementIds: string[]; // e.g., ["[login.email]", "[login.password]", "[login.submit]"]
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface MappingResult {
|
|
28
|
+
selectors: SelectorDSL;
|
|
29
|
+
metadata: {
|
|
30
|
+
aiModel: string;
|
|
31
|
+
tokenCost?: number;
|
|
32
|
+
provider: string;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// ============================================================================
|
|
37
|
+
// AI Mapper Class
|
|
38
|
+
// ============================================================================
|
|
39
|
+
|
|
40
|
+
export class AIMapper {
|
|
41
|
+
private config: AIMapperConfig;
|
|
42
|
+
private anthropic?: Anthropic;
|
|
43
|
+
private googleAI?: GoogleGenerativeAI;
|
|
44
|
+
|
|
45
|
+
constructor(config: AIMapperConfig) {
|
|
46
|
+
this.config = config;
|
|
47
|
+
|
|
48
|
+
// Initialize AI clients
|
|
49
|
+
if (config.provider === 'anthropic') {
|
|
50
|
+
const apiKey = config.apiKey || process.env.ANTHROPIC_API_KEY;
|
|
51
|
+
if (!apiKey) {
|
|
52
|
+
throw new Error('ANTHROPIC_API_KEY not found');
|
|
53
|
+
}
|
|
54
|
+
this.anthropic = new Anthropic({ apiKey });
|
|
55
|
+
} else if (config.provider === 'google') {
|
|
56
|
+
const apiKey = config.apiKey || process.env.GEMINI_API_KEY;
|
|
57
|
+
if (!apiKey) {
|
|
58
|
+
throw new Error('GEMINI_API_KEY not found');
|
|
59
|
+
}
|
|
60
|
+
this.googleAI = new GoogleGenerativeAI(apiKey);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Map element IDs to selectors using AI
|
|
66
|
+
*/
|
|
67
|
+
async mapSelectors(request: MappingRequest): Promise<MappingResult> {
|
|
68
|
+
const prompt = this.buildPrompt(request);
|
|
69
|
+
|
|
70
|
+
if (this.config.verbose) {
|
|
71
|
+
console.log('\n📤 Sending request to AI...');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
let response: string;
|
|
75
|
+
let aiModel: string;
|
|
76
|
+
let tokenCost: number | undefined;
|
|
77
|
+
|
|
78
|
+
if (this.config.provider === 'anthropic') {
|
|
79
|
+
const result = await this.callAnthropic(prompt);
|
|
80
|
+
response = result.response;
|
|
81
|
+
aiModel = result.model;
|
|
82
|
+
tokenCost = result.tokenCost;
|
|
83
|
+
} else {
|
|
84
|
+
const result = await this.callGoogle(prompt);
|
|
85
|
+
response = result.response;
|
|
86
|
+
aiModel = result.model;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Parse AI response
|
|
90
|
+
const selectors = this.parseResponse(response, request.elementIds);
|
|
91
|
+
|
|
92
|
+
// UPDATED: Phase 1 - Task 3 - Don't create fake fallback placeholders
|
|
93
|
+
// Return null selectors with confidence "none" for missing elements
|
|
94
|
+
for (const elementId of request.elementIds) {
|
|
95
|
+
// CRITICAL FIX: Use clean ID to match heuristic format
|
|
96
|
+
const cleanId = elementId.replace(/[\[\]]/g, '').split('.').pop() || elementId;
|
|
97
|
+
|
|
98
|
+
if (!selectors[cleanId]) {
|
|
99
|
+
selectors[cleanId] = {
|
|
100
|
+
selector: null,
|
|
101
|
+
type: 'unknown',
|
|
102
|
+
description: 'Element not found in UI Model - re-scan or add manually',
|
|
103
|
+
discoveryMethod: 'ai-static-analysis',
|
|
104
|
+
locatorType: 'css',
|
|
105
|
+
confidence: 'none',
|
|
106
|
+
reason: 'not-in-ui-model',
|
|
107
|
+
suggestedAction: 'Run discovery again or add data-testid to source code'
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
selectors,
|
|
114
|
+
metadata: {
|
|
115
|
+
aiModel,
|
|
116
|
+
tokenCost,
|
|
117
|
+
provider: this.config.provider
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Build prompt for AI
|
|
124
|
+
*/
|
|
125
|
+
private buildPrompt(request: MappingRequest): string {
|
|
126
|
+
const { uiModel, elementIds } = request;
|
|
127
|
+
|
|
128
|
+
// Extract ALL relevant attributes from UI model (DON'T simplify!)
|
|
129
|
+
const enrichedElements = uiModel.elements.map(el => {
|
|
130
|
+
// Extract critical props from the props object
|
|
131
|
+
const props = el.props || {};
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
key: el.key,
|
|
135
|
+
tag: el.tag,
|
|
136
|
+
// Top-level attributes
|
|
137
|
+
id: el.id,
|
|
138
|
+
name: el.name,
|
|
139
|
+
placeholder: el.placeholder,
|
|
140
|
+
ariaLabel: el.ariaLabel,
|
|
141
|
+
testId: el.testId,
|
|
142
|
+
text: el.text,
|
|
143
|
+
role: el.role,
|
|
144
|
+
// CRITICAL: Extract props that AI needs for selector generation
|
|
145
|
+
type: props.type, // button type="submit", input type="password"
|
|
146
|
+
href: props.href, // link href="/auth/register"
|
|
147
|
+
value: props.value, // input value
|
|
148
|
+
disabled: props.disabled, // button disabled
|
|
149
|
+
required: props.required, // input required
|
|
150
|
+
autoComplete: props.autoComplete, // input autocomplete
|
|
151
|
+
// Keep full props for AI to reference if needed
|
|
152
|
+
allProps: props
|
|
153
|
+
};
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
const prompt = `You are a test automation expert. Given a UI Model and a list of element IDs from Gherkin test scenarios, generate CSS selectors for each element.
|
|
157
|
+
|
|
158
|
+
**CRITICAL: Use Semantic Understanding**
|
|
159
|
+
The element IDs come from QA-written Gherkin scenarios and use human-readable names. You MUST understand the semantic meaning of each ID and match it to the appropriate UI element.
|
|
160
|
+
|
|
161
|
+
**PHASE 2 ENHANCEMENT: Semantic Aliases & Context Awareness**
|
|
162
|
+
|
|
163
|
+
Gherkin names often use INTENT-based naming while UI uses IMPLEMENTATION-based text. You must bridge this semantic gap:
|
|
164
|
+
|
|
165
|
+
**Common Semantic Aliases:**
|
|
166
|
+
|
|
167
|
+
**Action Buttons:**
|
|
168
|
+
- "clear" / "clear-button" ≈ "New Chat" button (clears chat history)
|
|
169
|
+
- "send" / "send-button" ≈ "Send", "Submit", "→", "➤" button
|
|
170
|
+
- "submit" / "submit-button" ≈ "Submit", "Continue", "Sign In", "Register" button
|
|
171
|
+
- "cancel" / "cancel-button" ≈ "Cancel", "Back", "Close" button
|
|
172
|
+
- "delete" / "delete-button" ≈ "Delete", "Remove", "×" button
|
|
173
|
+
- "edit" / "edit-button" ≈ "Edit", "Modify", "✎" button
|
|
174
|
+
- "save" / "save-button" ≈ "Save", "Update", "Confirm" button
|
|
175
|
+
|
|
176
|
+
**Brand/Identity Elements:**
|
|
177
|
+
- "logo" ≈ heading with brand name OR image with alt="logo"
|
|
178
|
+
- "title" ≈ main heading (h1) with brand/app name
|
|
179
|
+
- "tagline" ≈ subtitle or description text
|
|
180
|
+
|
|
181
|
+
**Navigation:**
|
|
182
|
+
- "login-link" / "signin-link" ≈ link with text "Login", "Sign In", "Log In"
|
|
183
|
+
- "register-link" / "signup-link" ≈ link with text "Register", "Sign Up", "Create Account"
|
|
184
|
+
- "logout-link" / "signout-link" ≈ link/button with text "Logout", "Sign Out", "Log Out"
|
|
185
|
+
- "back-link" ≈ link with text "Back", "←", "Return"
|
|
186
|
+
|
|
187
|
+
**Input Fields (aliases for same field):**
|
|
188
|
+
- "email" / "email-input" / "email-field" → input[type='email'] OR input[name='email']
|
|
189
|
+
- "password" / "pass" / "password-input" / "pw" → input[type='password']
|
|
190
|
+
- "message" / "message-input" / "input" / "textarea" → textarea for messages
|
|
191
|
+
- "search" / "search-input" → input[type='search'] OR placeholder containing "search"
|
|
192
|
+
|
|
193
|
+
**Container Elements:**
|
|
194
|
+
- "messages" / "messages-container" / "messages-list" → div with overflow-y-auto OR flex-1 (scrollable area)
|
|
195
|
+
- "empty-state" → text/paragraph shown when no content (e.g., "No messages yet", "Start a conversation")
|
|
196
|
+
- "error" / "error-message" → text with red color (text-red-*) OR bg-red-*
|
|
197
|
+
|
|
198
|
+
**Conditional Elements (may have isConditional marker):**
|
|
199
|
+
- "timestamp" / "message-timestamp" → small text with time format (text-xs, text-gray-500)
|
|
200
|
+
- "error" / "field-error" → conditionally rendered error message
|
|
201
|
+
- "copy-button" → button that appears on hover (opacity-0 group-hover:opacity-100)
|
|
202
|
+
- "tooltip" → conditionally shown helper text
|
|
203
|
+
|
|
204
|
+
**Context Clues:**
|
|
205
|
+
- If Gherkin says "clear-button" but UI has "New Chat" button → Match if button clears/resets state
|
|
206
|
+
- If Gherkin says "logo" but UI has h1 text → Match heading with brand name
|
|
207
|
+
- If Gherkin says "send" but UI has "Submit" → Match if button submits form
|
|
208
|
+
- If multiple buttons exist, use context: submit buttons usually have type='submit', cancel buttons may have type='button'
|
|
209
|
+
|
|
210
|
+
**Examples of semantic matching:**
|
|
211
|
+
- \`[auth-login.email]\` OR \`[auth-login.email-input]\` → input with name="email" or id="email-address"
|
|
212
|
+
- \`[auth-login.password]\` OR \`[auth-login.pass]\` → input with type="password" or name="password"
|
|
213
|
+
- \`[auth-login.submit]\` OR \`[auth-login.login-button]\` → button with type="submit" OR button:has-text("Sign In")
|
|
214
|
+
- \`[auth-login.signup-link]\` OR \`[auth-login.register-link]\` → link (a tag) pointing to signup/register
|
|
215
|
+
- \`[chat.input]\` OR \`[chat.message-input]\` → textarea or input for chat messages
|
|
216
|
+
- \`[chat.send-button]\` OR \`[chat.send]\` → button to send messages OR button:has-text("Send")
|
|
217
|
+
- \`[chat.clear-button]\` → button:has-text("New Chat") (semantic alias: clear ≈ new chat)
|
|
218
|
+
- \`[home.logo]\` → h1:has-text("PEU AI-Native Workflow") (logo as text heading)
|
|
219
|
+
|
|
220
|
+
**Screen:** ${uiModel.screenId}
|
|
221
|
+
**Framework:** ${uiModel.framework}
|
|
222
|
+
|
|
223
|
+
**UI Elements Available:**
|
|
224
|
+
${JSON.stringify(enrichedElements, null, 2)}
|
|
225
|
+
|
|
226
|
+
**Element IDs to Resolve (from Gherkin):**
|
|
227
|
+
${elementIds.map(id => `- ${id}`).join('\n')}
|
|
228
|
+
|
|
229
|
+
**CRITICAL INSTRUCTIONS - MUST FOLLOW:**
|
|
230
|
+
|
|
231
|
+
1. **Use EXACT attributes from UI Model** - Each element has \`type\`, \`href\`, \`id\`, \`name\`, etc. Use these EXACT values!
|
|
232
|
+
|
|
233
|
+
2. **MANDATORY Selector Priority:**
|
|
234
|
+
|
|
235
|
+
**FOR BUTTONS (tag="button"):**
|
|
236
|
+
- If element has \`type\` attribute → **MUST use** \`button[type="..."]\`
|
|
237
|
+
- Example: \`type: "submit"\` → \`button[type='submit']\` (NOT \`button[role='button']\`!)
|
|
238
|
+
- Only use text if no type: \`button:has-text("...")\`
|
|
239
|
+
|
|
240
|
+
**FOR LINKS (tag="a", tag="link"):**
|
|
241
|
+
- If element has \`href\` → **MUST use** \`a[href="..."]\`
|
|
242
|
+
- Use EXACT href from UI Model
|
|
243
|
+
- Example: \`href: "/auth/register"\` → \`a[href='/auth/register']\`
|
|
244
|
+
|
|
245
|
+
**FOR INPUTS (tag="input"):**
|
|
246
|
+
- Priority: \`id\` > \`name\` > \`type\` + \`placeholder\`
|
|
247
|
+
- Example: \`id: "email-address"\` → \`#email-address\`
|
|
248
|
+
- Example: \`name: "password"\` → \`input[name='password']\`
|
|
249
|
+
|
|
250
|
+
**FOR TEXTAREA:**
|
|
251
|
+
- Priority: \`id\` > \`name\` > \`placeholder\`
|
|
252
|
+
- Example: \`placeholder: "Type your message"\` → \`textarea[placeholder*='Type your message']\`
|
|
253
|
+
|
|
254
|
+
3. **NEVER use these (BANNED):**
|
|
255
|
+
- Generic \`role\` attribute for buttons/inputs
|
|
256
|
+
- Class names NOT in UI Model
|
|
257
|
+
- Invented/guessed selectors
|
|
258
|
+
- Just tag name without attributes (e.g., \`button\`, \`textarea\`)
|
|
259
|
+
|
|
260
|
+
4. **Semantic matching:** "email", "email-input", "email-field" all = same element
|
|
261
|
+
|
|
262
|
+
5. **Confidence levels:**
|
|
263
|
+
- \`high\`: Used id/name/type/href from UI Model - exact match
|
|
264
|
+
- \`medium\`: Used placeholder/text from UI Model OR semantic alias match (e.g., "clear" → "New Chat")
|
|
265
|
+
- \`low\`: Ambiguous match - multiple elements could match
|
|
266
|
+
- \`none\`: Element not found in UI Model (needs manual review)
|
|
267
|
+
|
|
268
|
+
6. **PHASE 2: Ambiguity Detection & Helpful Messages**
|
|
269
|
+
|
|
270
|
+
If you find MULTIPLE elements that could match a Gherkin ID:
|
|
271
|
+
- Set confidence to \`low\`
|
|
272
|
+
- In description, list ALL potential matches
|
|
273
|
+
- Example:
|
|
274
|
+
\`\`\`json
|
|
275
|
+
{
|
|
276
|
+
"[chat.messages]": {
|
|
277
|
+
"selector": "div.flex-1.overflow-y-auto",
|
|
278
|
+
"type": "container",
|
|
279
|
+
"description": "AMBIGUOUS: Could be (1) messages container (div.flex-1), (2) messages list (div.max-w-4xl), or (3) message items. Recommend using [chat.messages-container] for container, [chat.messages-list] for list, or [chat.messages-item] for items.",
|
|
280
|
+
"confidence": "low"
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
\`\`\`
|
|
284
|
+
|
|
285
|
+
If element uses semantic alias:
|
|
286
|
+
- Set confidence to \`medium\`
|
|
287
|
+
- Explain the alias in description
|
|
288
|
+
- Example:
|
|
289
|
+
\`\`\`json
|
|
290
|
+
{
|
|
291
|
+
"[chat.clear-button]": {
|
|
292
|
+
"selector": "button:has-text('New Chat')",
|
|
293
|
+
"type": "button",
|
|
294
|
+
"description": "Semantic match: 'clear-button' maps to 'New Chat' button (clears chat history)",
|
|
295
|
+
"confidence": "medium"
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
\`\`\`
|
|
299
|
+
|
|
300
|
+
7. **IF ELEMENT NOT FOUND IN UI MODEL:**
|
|
301
|
+
- DO NOT guess selectors or invent className patterns like \`div[className*='...']\`
|
|
302
|
+
- DO NOT create fake data-testid attributes like \`[data-testid="messages"]\`
|
|
303
|
+
- RETURN exactly:
|
|
304
|
+
\`\`\`json
|
|
305
|
+
{
|
|
306
|
+
"[element-id]": {
|
|
307
|
+
"selector": null,
|
|
308
|
+
"type": "unknown",
|
|
309
|
+
"description": "Element not found in UI Model",
|
|
310
|
+
"confidence": "none"
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
\`\`\`
|
|
314
|
+
|
|
315
|
+
**Return ONLY valid JSON with this structure:**
|
|
316
|
+
\`\`\`json
|
|
317
|
+
{
|
|
318
|
+
"[element-id]": {
|
|
319
|
+
"selector": "css-selector-string",
|
|
320
|
+
"type": "input|button|link|textarea|text|container",
|
|
321
|
+
"description": "Human readable description",
|
|
322
|
+
"confidence": "high|medium|low"
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
\`\`\`
|
|
326
|
+
|
|
327
|
+
**Example Response (showing CORRECT usage):**
|
|
328
|
+
\`\`\`json
|
|
329
|
+
{
|
|
330
|
+
"[auth-login.email]": {
|
|
331
|
+
"selector": "#email-address",
|
|
332
|
+
"type": "input",
|
|
333
|
+
"description": "Email input field",
|
|
334
|
+
"confidence": "high"
|
|
335
|
+
},
|
|
336
|
+
"[auth-login.submit]": {
|
|
337
|
+
"selector": "button[type='submit']",
|
|
338
|
+
"type": "button",
|
|
339
|
+
"description": "Login submit button",
|
|
340
|
+
"confidence": "high"
|
|
341
|
+
},
|
|
342
|
+
"[auth-login.signup-link]": {
|
|
343
|
+
"selector": "a[href='/auth/register']",
|
|
344
|
+
"type": "link",
|
|
345
|
+
"description": "Sign up link",
|
|
346
|
+
"confidence": "high"
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
\`\`\`
|
|
350
|
+
|
|
351
|
+
**WRONG Examples (NEVER do this):**
|
|
352
|
+
❌ \`"selector": "button[role='button']"\` - DON'T use role when type exists!
|
|
353
|
+
❌ \`"selector": "button"\` - DON'T use tag only!
|
|
354
|
+
❌ \`"selector": ".submit-btn"\` - DON'T invent class names!
|
|
355
|
+
❌ \`"selector": "div[className*='chat-messages']"\` - DON'T guess className patterns!
|
|
356
|
+
❌ \`"selector": "[data-testid='messages']"\` - DON'T create fake testids!
|
|
357
|
+
✅ \`"selector": "button[type='submit']"\` - CORRECT! Uses type from UI Model!
|
|
358
|
+
✅ \`"selector": null, "confidence": "none"\` - CORRECT! If not found in UI Model!
|
|
359
|
+
|
|
360
|
+
**IMPORTANT:** Return ONLY the JSON object, no markdown, no additional text.`;
|
|
361
|
+
|
|
362
|
+
return prompt;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Call Anthropic API
|
|
367
|
+
*/
|
|
368
|
+
private async callAnthropic(prompt: string): Promise<{
|
|
369
|
+
response: string;
|
|
370
|
+
model: string;
|
|
371
|
+
tokenCost: number;
|
|
372
|
+
}> {
|
|
373
|
+
if (!this.anthropic) {
|
|
374
|
+
throw new Error('Anthropic client not initialized');
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
const model = this.config.model || 'claude-3-5-haiku-20241022';
|
|
378
|
+
|
|
379
|
+
const message = await this.anthropic.messages.create({
|
|
380
|
+
model,
|
|
381
|
+
max_tokens: 4096,
|
|
382
|
+
messages: [{
|
|
383
|
+
role: 'user',
|
|
384
|
+
content: prompt
|
|
385
|
+
}]
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
const response = message.content[0].type === 'text' ? message.content[0].text : '';
|
|
389
|
+
const tokenCost = message.usage.input_tokens + message.usage.output_tokens;
|
|
390
|
+
|
|
391
|
+
if (this.config.verbose) {
|
|
392
|
+
console.log(`✅ Response received (${tokenCost} tokens)`);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
return { response, model, tokenCost };
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Call Google Gemini API
|
|
400
|
+
*/
|
|
401
|
+
private async callGoogle(prompt: string): Promise<{
|
|
402
|
+
response: string;
|
|
403
|
+
model: string;
|
|
404
|
+
}> {
|
|
405
|
+
if (!this.googleAI) {
|
|
406
|
+
throw new Error('Google AI client not initialized');
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
const model = this.config.model || 'gemini-2.0-flash-exp';
|
|
410
|
+
const genModel = this.googleAI.getGenerativeModel({ model });
|
|
411
|
+
|
|
412
|
+
const result = await genModel.generateContent(prompt);
|
|
413
|
+
const response = result.response.text();
|
|
414
|
+
|
|
415
|
+
if (this.config.verbose) {
|
|
416
|
+
console.log(`✅ Response received from ${model}`);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
return { response, model };
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Parse AI response into SelectorDSL
|
|
424
|
+
*/
|
|
425
|
+
private parseResponse(response: string, elementIds: string[]): SelectorDSL {
|
|
426
|
+
// Extract JSON from response (handle markdown code blocks)
|
|
427
|
+
let jsonStr = response.trim();
|
|
428
|
+
|
|
429
|
+
// Remove markdown code blocks if present
|
|
430
|
+
const codeBlockMatch = jsonStr.match(/```(?:json)?\s*(\{[\s\S]*\})\s*```/);
|
|
431
|
+
if (codeBlockMatch) {
|
|
432
|
+
jsonStr = codeBlockMatch[1];
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
try {
|
|
436
|
+
const parsed = JSON.parse(jsonStr);
|
|
437
|
+
const selectors: SelectorDSL = {};
|
|
438
|
+
|
|
439
|
+
// Convert to SelectorDSL format
|
|
440
|
+
for (const elementId of elementIds) {
|
|
441
|
+
if (parsed[elementId]) {
|
|
442
|
+
const entry = parsed[elementId];
|
|
443
|
+
|
|
444
|
+
// CRITICAL FIX: Clean element ID to match heuristic format
|
|
445
|
+
// [auth-login.email] → email
|
|
446
|
+
// [chat.message-input] → message-input
|
|
447
|
+
const cleanId = elementId.replace(/[\[\]]/g, '').split('.').pop() || elementId;
|
|
448
|
+
|
|
449
|
+
selectors[cleanId] = {
|
|
450
|
+
selector: entry.selector,
|
|
451
|
+
type: entry.type,
|
|
452
|
+
description: entry.description,
|
|
453
|
+
discoveryMethod: 'ai-static-analysis',
|
|
454
|
+
locatorType: 'css',
|
|
455
|
+
confidence: entry.confidence || 'medium'
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
return selectors;
|
|
461
|
+
} catch (error) {
|
|
462
|
+
console.error('Failed to parse AI response:', error);
|
|
463
|
+
console.error('Response:', response);
|
|
464
|
+
throw new Error('AI response is not valid JSON');
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Create fallback selector using heuristic rules
|
|
470
|
+
*/
|
|
471
|
+
private createFallbackSelector(elementId: string, uiModel: UIModel): SelectorEntry {
|
|
472
|
+
// Extract element name from ID
|
|
473
|
+
// e.g., "[login.email]" -> "email"
|
|
474
|
+
const match = elementId.match(/\[([^.]+)\.([^\]]+)\]/);
|
|
475
|
+
const elementName = match ? match[2] : 'unknown';
|
|
476
|
+
|
|
477
|
+
// Try to find matching element by name
|
|
478
|
+
const matchingElement = uiModel.elements.find(el =>
|
|
479
|
+
el.name === elementName ||
|
|
480
|
+
el.id === elementName ||
|
|
481
|
+
el.testId?.includes(elementName)
|
|
482
|
+
);
|
|
483
|
+
|
|
484
|
+
if (matchingElement) {
|
|
485
|
+
// Build selector
|
|
486
|
+
let selector = matchingElement.tag;
|
|
487
|
+
if (matchingElement.testId) {
|
|
488
|
+
selector = `[data-testid="${matchingElement.testId}"]`;
|
|
489
|
+
} else if (matchingElement.id) {
|
|
490
|
+
selector = `#${matchingElement.id}`;
|
|
491
|
+
} else if (matchingElement.name) {
|
|
492
|
+
selector = `${matchingElement.tag}[name="${matchingElement.name}"]`;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
return {
|
|
496
|
+
selector,
|
|
497
|
+
type: matchingElement.tag,
|
|
498
|
+
description: `Fallback selector for ${elementName}`,
|
|
499
|
+
discoveryMethod: 'ai-static-analysis',
|
|
500
|
+
locatorType: 'css',
|
|
501
|
+
confidence: 'low'
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// Ultimate fallback
|
|
506
|
+
return {
|
|
507
|
+
selector: `[data-testid="${elementName}"]`,
|
|
508
|
+
type: 'unknown',
|
|
509
|
+
description: `Placeholder selector for ${elementName} - needs manual review`,
|
|
510
|
+
discoveryMethod: 'ai-static-analysis',
|
|
511
|
+
locatorType: 'css',
|
|
512
|
+
confidence: 'low'
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// ============================================================================
|
|
518
|
+
// Factory Function
|
|
519
|
+
// ============================================================================
|
|
520
|
+
|
|
521
|
+
export async function mapSelectors(
|
|
522
|
+
uiModel: UIModel,
|
|
523
|
+
elementIds: string[],
|
|
524
|
+
config: AIMapperConfig
|
|
525
|
+
): Promise<MappingResult> {
|
|
526
|
+
const mapper = new AIMapper(config);
|
|
527
|
+
return mapper.mapSelectors({ uiModel, elementIds });
|
|
528
|
+
}
|