@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,94 @@
|
|
|
1
|
+
import { ParsedStep } from '../../gherkin-parser';
|
|
2
|
+
import { StepPattern } from './types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Setup and precondition patterns: application setup, authentication state, etc.
|
|
6
|
+
* Uses templates for framework-agnostic code generation
|
|
7
|
+
*/
|
|
8
|
+
export const setupPatterns: StepPattern[] = [
|
|
9
|
+
{
|
|
10
|
+
name: 'application-running',
|
|
11
|
+
matcher: (step: ParsedStep) =>
|
|
12
|
+
step.text.includes('application is running') ||
|
|
13
|
+
step.text.includes('application running') ||
|
|
14
|
+
step.text.includes('app is running'),
|
|
15
|
+
generator: (step, context) => {
|
|
16
|
+
const code = context.templateEngine.renderStep('application-running', {});
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
code,
|
|
20
|
+
comment: `Setup: Application is running`,
|
|
21
|
+
};
|
|
22
|
+
},
|
|
23
|
+
priority: 5,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: 'user-not-logged-in',
|
|
27
|
+
matcher: (step: ParsedStep) =>
|
|
28
|
+
step.text.includes('user is not logged in') ||
|
|
29
|
+
step.text.includes('not logged in') ||
|
|
30
|
+
step.text.includes('logged out'),
|
|
31
|
+
generator: (step, context) => {
|
|
32
|
+
const code = context.templateEngine.renderStep('clear-auth', {});
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
code,
|
|
36
|
+
comment: `Clear authentication state (ensure user is logged out)`,
|
|
37
|
+
};
|
|
38
|
+
},
|
|
39
|
+
priority: 9,
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: 'user-logged-in',
|
|
43
|
+
matcher: (step: ParsedStep) =>
|
|
44
|
+
(step.text.includes('user is logged in') ||
|
|
45
|
+
step.text.includes('logged in as')) &&
|
|
46
|
+
!step.text.includes('not logged in'),
|
|
47
|
+
generator: (step, context) => {
|
|
48
|
+
// Check if there's a data reference for user credentials
|
|
49
|
+
const userRef = step.dataRef || 'valid_user';
|
|
50
|
+
|
|
51
|
+
const code = context.templateEngine.renderStep('user-login-todo', {
|
|
52
|
+
userRef,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
code,
|
|
57
|
+
comment: `Setup: User logged in as ${userRef}`,
|
|
58
|
+
};
|
|
59
|
+
},
|
|
60
|
+
priority: 9,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'clear-database',
|
|
64
|
+
matcher: (step: ParsedStep) =>
|
|
65
|
+
step.text.includes('database is empty') ||
|
|
66
|
+
step.text.includes('database is cleared') ||
|
|
67
|
+
step.text.includes('clear database'),
|
|
68
|
+
generator: (step, context) => {
|
|
69
|
+
const code = context.templateEngine.renderStep('clear-database', {});
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
code,
|
|
73
|
+
comment: `Setup: Clear/reset database`,
|
|
74
|
+
};
|
|
75
|
+
},
|
|
76
|
+
priority: 7,
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: 'browser-state-clean',
|
|
80
|
+
matcher: (step: ParsedStep) =>
|
|
81
|
+
step.text.includes('clean browser state') ||
|
|
82
|
+
step.text.includes('fresh browser') ||
|
|
83
|
+
step.text.includes('new browser session'),
|
|
84
|
+
generator: (step, context) => {
|
|
85
|
+
const code = context.templateEngine.renderStep('clear-browser-state', {});
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
code,
|
|
89
|
+
comment: `Clear browser state (cookies, storage)`,
|
|
90
|
+
};
|
|
91
|
+
},
|
|
92
|
+
priority: 8,
|
|
93
|
+
},
|
|
94
|
+
];
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ParsedStep } from '../../gherkin-parser';
|
|
2
|
+
import { MappedStep } from '../step-mapper';
|
|
3
|
+
import { SelectorResolver } from '../utils/selector-resolver';
|
|
4
|
+
import { DataResolver } from '../utils/data-resolver';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Pattern matcher function or regex
|
|
8
|
+
*/
|
|
9
|
+
export type PatternMatcher = RegExp | ((step: ParsedStep) => boolean);
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Pattern generator function
|
|
13
|
+
*/
|
|
14
|
+
export type PatternGenerator = (step: ParsedStep, context: PatternContext) => MappedStep;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Context passed to pattern generators
|
|
18
|
+
*/
|
|
19
|
+
export interface PatternContext {
|
|
20
|
+
stepCounter: number;
|
|
21
|
+
extractScreenId: (selectorRef: string) => string;
|
|
22
|
+
templateEngine: any;
|
|
23
|
+
selectorResolver: SelectorResolver;
|
|
24
|
+
dataResolver: DataResolver;
|
|
25
|
+
renderLocator: (resolved: any) => string;
|
|
26
|
+
baseURL?: string; // Base URL from config (e.g., 'http://localhost:3000')
|
|
27
|
+
featureName?: string; // Feature name for data resolution (e.g., 'login')
|
|
28
|
+
screenName?: string; // Screen name for path inference (e.g., 'sign-in')
|
|
29
|
+
featurePath?: string; // Path metadata from feature file (e.g., '/login')
|
|
30
|
+
scenarioSteps?: ParsedStep[]; // All steps in scenario for path variable extraction
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Step pattern definition
|
|
35
|
+
*/
|
|
36
|
+
export interface StepPattern {
|
|
37
|
+
name: string;
|
|
38
|
+
matcher: PatternMatcher;
|
|
39
|
+
generator: PatternGenerator;
|
|
40
|
+
priority?: number; // Higher priority = checked first (default: 0)
|
|
41
|
+
}
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import { ParsedStep } from '../gherkin-parser';
|
|
2
|
+
import { AIStepMapper } from './ai-step-mapper';
|
|
3
|
+
import { TemplateEngine } from './template-engine';
|
|
4
|
+
import { PatternRegistry, PatternContext } from './patterns';
|
|
5
|
+
import { SelectorResolver } from './utils/selector-resolver';
|
|
6
|
+
import { DataResolver } from './utils/data-resolver';
|
|
7
|
+
import * as path from 'path';
|
|
8
|
+
|
|
9
|
+
export interface MappedStep {
|
|
10
|
+
code: string; // Generated Playwright code
|
|
11
|
+
comment?: string; // Optional comment
|
|
12
|
+
imports?: string[]; // Required imports
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* StepMapper - Orchestrates step-to-code conversion using pattern registry
|
|
17
|
+
* Refactored from 907 lines to < 200 lines
|
|
18
|
+
*/
|
|
19
|
+
export class StepMapper {
|
|
20
|
+
private stepCounter: number = 0;
|
|
21
|
+
private aiMapper: AIStepMapper | null = null;
|
|
22
|
+
private useAI: boolean = false;
|
|
23
|
+
private verbose: boolean = false;
|
|
24
|
+
private templateEngine: TemplateEngine;
|
|
25
|
+
private patternRegistry: PatternRegistry;
|
|
26
|
+
private selectorResolver: SelectorResolver;
|
|
27
|
+
private dataResolver: DataResolver;
|
|
28
|
+
private baseURL: string;
|
|
29
|
+
private featureName?: string;
|
|
30
|
+
private screenName?: string;
|
|
31
|
+
private featurePath?: string; // Path metadata from feature file (e.g., "/login")
|
|
32
|
+
private currentScenarioSteps?: ParsedStep[]; // All steps in current scenario for context
|
|
33
|
+
|
|
34
|
+
constructor(options: { useAI?: boolean; verbose?: boolean; baseURL?: string; featureName?: string; screenName?: string; featurePath?: string } = {}) {
|
|
35
|
+
this.useAI = options.useAI ?? false;
|
|
36
|
+
this.verbose = options.verbose ?? false;
|
|
37
|
+
this.baseURL = options.baseURL || null; // null means path-only navigation
|
|
38
|
+
this.featureName = options.featureName;
|
|
39
|
+
this.screenName = options.screenName;
|
|
40
|
+
this.featurePath = options.featurePath;
|
|
41
|
+
// Use Playwright templates as default for pattern-based generation
|
|
42
|
+
const playwrightTemplatesDir = path.join(__dirname, 'adapters', 'playwright', 'templates');
|
|
43
|
+
this.templateEngine = new TemplateEngine(playwrightTemplatesDir);
|
|
44
|
+
this.patternRegistry = new PatternRegistry();
|
|
45
|
+
this.selectorResolver = new SelectorResolver(undefined, options.screenName);
|
|
46
|
+
this.dataResolver = new DataResolver(undefined, options.screenName);
|
|
47
|
+
|
|
48
|
+
if (this.useAI) {
|
|
49
|
+
try {
|
|
50
|
+
this.aiMapper = new AIStepMapper(this.verbose);
|
|
51
|
+
if (this.verbose) {
|
|
52
|
+
console.log(` [StepMapper] AI fallback enabled (${this.patternRegistry.getPatternCount()} patterns loaded)`);
|
|
53
|
+
}
|
|
54
|
+
} catch (error) {
|
|
55
|
+
console.warn('[StepMapper] AI mapper initialization failed:', error);
|
|
56
|
+
this.useAI = false;
|
|
57
|
+
}
|
|
58
|
+
} else if (this.verbose) {
|
|
59
|
+
console.log(` [StepMapper] Dictionary mode (${this.patternRegistry.getPatternCount()} patterns loaded)`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Set feature context for data and selector resolution
|
|
65
|
+
*/
|
|
66
|
+
setFeatureContext(featureName: string, featurePath?: string): void {
|
|
67
|
+
this.featureName = featureName;
|
|
68
|
+
this.featurePath = featurePath;
|
|
69
|
+
this.selectorResolver.setFeatureContext(featureName);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Set scenario context for path variable resolution
|
|
74
|
+
*/
|
|
75
|
+
setScenarioContext(steps: ParsedStep[]): void {
|
|
76
|
+
this.currentScenarioSteps = steps;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Map a Gherkin step to Playwright code
|
|
81
|
+
* Uses pattern registry first, falls back to AI if enabled
|
|
82
|
+
*/
|
|
83
|
+
mapStep(step: ParsedStep): MappedStep | Promise<MappedStep> {
|
|
84
|
+
this.stepCounter++;
|
|
85
|
+
|
|
86
|
+
// Try pattern registry first
|
|
87
|
+
const context = this.createPatternContext();
|
|
88
|
+
const mappedStep = this.patternRegistry.generateStep(step, context);
|
|
89
|
+
|
|
90
|
+
if (mappedStep) {
|
|
91
|
+
if (this.verbose) {
|
|
92
|
+
console.log(` ✓ Pattern matched: ${step.text.substring(0, 50)}...`);
|
|
93
|
+
}
|
|
94
|
+
return mappedStep;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Fallback: Try legacy patterns for backward compatibility
|
|
98
|
+
const legacyStep = this.tryLegacyPatterns(step);
|
|
99
|
+
if (legacyStep) {
|
|
100
|
+
if (this.verbose) {
|
|
101
|
+
console.log(` ✓ Legacy pattern matched: ${step.text.substring(0, 50)}...`);
|
|
102
|
+
}
|
|
103
|
+
return legacyStep;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Fallback to AI if enabled
|
|
107
|
+
if (this.useAI && this.aiMapper) {
|
|
108
|
+
if (this.verbose) {
|
|
109
|
+
console.log(` → AI fallback for: ${step.text.substring(0, 50)}...`);
|
|
110
|
+
}
|
|
111
|
+
return this.aiMapper.mapStep(step);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// No pattern matched and no AI - return generic code with comment
|
|
115
|
+
return {
|
|
116
|
+
code: `// TODO: Implement step: ${step.text}`,
|
|
117
|
+
comment: `Unrecognized step pattern: ${step.text}`,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Create pattern context for generators
|
|
123
|
+
*/
|
|
124
|
+
private createPatternContext(): PatternContext {
|
|
125
|
+
return {
|
|
126
|
+
stepCounter: this.stepCounter,
|
|
127
|
+
extractScreenId: this.extractScreenId.bind(this),
|
|
128
|
+
templateEngine: this.templateEngine,
|
|
129
|
+
selectorResolver: this.selectorResolver,
|
|
130
|
+
dataResolver: this.dataResolver,
|
|
131
|
+
renderLocator: (resolved) => this.templateEngine.renderStep('locator', resolved),
|
|
132
|
+
baseURL: this.baseURL,
|
|
133
|
+
featureName: this.featureName,
|
|
134
|
+
screenName: this.screenName,
|
|
135
|
+
featurePath: this.featurePath, // Pass feature path to patterns
|
|
136
|
+
scenarioSteps: this.currentScenarioSteps || [], // Pass scenario steps for path variables
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Extract screen ID from selector reference
|
|
142
|
+
*/
|
|
143
|
+
private extractScreenId(selectorRef: string): string {
|
|
144
|
+
const match = selectorRef.match(/\[([\w-]+)\./);
|
|
145
|
+
return match ? match[1] : 'unknown';
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Try legacy patterns for backward compatibility
|
|
150
|
+
* These are patterns not yet migrated to the pattern registry
|
|
151
|
+
*/
|
|
152
|
+
private tryLegacyPatterns(step: ParsedStep): MappedStep | null {
|
|
153
|
+
const { text, selectorRef, dataRef, value } = step;
|
|
154
|
+
|
|
155
|
+
// Login pattern
|
|
156
|
+
if (text.includes('user is logged in as') && dataRef) {
|
|
157
|
+
return this.mapLoginStep(dataRef);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Error message assertions
|
|
161
|
+
if (text.includes('error message') && text.includes('should')) {
|
|
162
|
+
return this.mapErrorMessageAssertion();
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Generic message assertions
|
|
166
|
+
if (text.includes('message') && text.includes('should be displayed')) {
|
|
167
|
+
return this.mapGenericMessageAssertion(text);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Message with value assertions
|
|
171
|
+
if (text.includes('should see message') && value) {
|
|
172
|
+
return this.mapMessageAssertion(value, selectorRef);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// AI response assertions
|
|
176
|
+
if (text.includes('user should see') && text.includes('AI response') && selectorRef) {
|
|
177
|
+
return this.mapAIResponseAssertion(selectorRef);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Message count assertions
|
|
181
|
+
if (text.includes('messages in') && selectorRef) {
|
|
182
|
+
return this.mapMessageCountAssertion(text, selectorRef);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Message contains assertions
|
|
186
|
+
if (text.includes('should contain') && text.includes('messages') && selectorRef) {
|
|
187
|
+
return this.mapMessageCountAssertion(text, selectorRef);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// ========================================
|
|
194
|
+
// LEGACY METHODS (to be migrated to patterns)
|
|
195
|
+
// ========================================
|
|
196
|
+
|
|
197
|
+
private mapLoginStep(dataRef: string): MappedStep {
|
|
198
|
+
const varName = dataRef.replace(/[^a-zA-Z0-9]/g, '_') + '_' + this.stepCounter;
|
|
199
|
+
return {
|
|
200
|
+
code: this.templateEngine.renderStep('login', { varName, dataRef }),
|
|
201
|
+
comment: `Login as ${dataRef}`,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
private mapErrorMessageAssertion(): MappedStep {
|
|
206
|
+
return {
|
|
207
|
+
code: this.templateEngine.renderStep('error-message-assertion', {}),
|
|
208
|
+
comment: 'Assert error message is displayed',
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
private mapGenericMessageAssertion(text: string): MappedStep {
|
|
213
|
+
const messageType = text.includes('welcome') ? 'welcome' :
|
|
214
|
+
text.includes('success') ? 'success' : 'message';
|
|
215
|
+
return {
|
|
216
|
+
code: this.templateEngine.renderStep('generic-message-assertion', { messageType }),
|
|
217
|
+
comment: `Assert ${messageType} message is displayed`,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
private mapMessageAssertion(value: string, selectorRef?: string): MappedStep {
|
|
222
|
+
const varName = (selectorRef || 'message').replace(/[^a-zA-Z0-9]/g, '_') + '_' + this.stepCounter;
|
|
223
|
+
return {
|
|
224
|
+
code: this.templateEngine.renderStep('message-assertion-body', { varName, value, selectorRef }),
|
|
225
|
+
comment: `Assert message: ${value}`,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
private mapAIResponseAssertion(selectorRef: string): MappedStep {
|
|
230
|
+
const screenId = this.extractScreenId(selectorRef);
|
|
231
|
+
const varName = selectorRef.replace(/[^a-zA-Z0-9]/g, '_') + '_' + this.stepCounter;
|
|
232
|
+
return {
|
|
233
|
+
code: this.templateEngine.renderStep('ai-response-assertion-selector', { varName, selectorRef, screenId }),
|
|
234
|
+
comment: `Assert AI response in ${selectorRef}`,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
private mapMessageCountAssertion(text: string, selectorRef: string): MappedStep {
|
|
239
|
+
const match = text.match(/(\d+)\s+messages?/);
|
|
240
|
+
const expectedCount = match ? parseInt(match[1]) : 1;
|
|
241
|
+
const screenId = this.extractScreenId(selectorRef);
|
|
242
|
+
const varName = selectorRef.replace(/[^a-zA-Z0-9]/g, '_') + '_' + this.stepCounter;
|
|
243
|
+
|
|
244
|
+
return {
|
|
245
|
+
code: this.templateEngine.renderStep('message-count-assertion', {
|
|
246
|
+
varName,
|
|
247
|
+
selectorRef,
|
|
248
|
+
screenId,
|
|
249
|
+
expectedCount,
|
|
250
|
+
}),
|
|
251
|
+
comment: `Assert ${expectedCount} messages in ${selectorRef}`,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import Handlebars from 'handlebars';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
export class TemplateEngine {
|
|
6
|
+
private templates: Map<string, HandlebarsTemplateDelegate> = new Map();
|
|
7
|
+
private templatesDir: string;
|
|
8
|
+
private stepsTemplatesDir: string;
|
|
9
|
+
|
|
10
|
+
constructor(templatesDir: string) {
|
|
11
|
+
this.templatesDir = templatesDir;
|
|
12
|
+
this.stepsTemplatesDir = path.join(this.templatesDir, 'steps');
|
|
13
|
+
this.registerHelpers();
|
|
14
|
+
this.registerPartials();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
private registerHelpers(): void {
|
|
18
|
+
Handlebars.registerHelper('indent', function(text: string, spaces: number) {
|
|
19
|
+
const indentation = ' '.repeat(spaces);
|
|
20
|
+
return text.split('\n').map(line => indentation + line).join('\n');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
Handlebars.registerHelper('escapeQuotes', function(text: string) {
|
|
24
|
+
return text.replace(/'/g, "\\'");
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Comparison helpers for conditional logic
|
|
28
|
+
Handlebars.registerHelper('eq', function(a: any, b: any) {
|
|
29
|
+
return a === b;
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
Handlebars.registerHelper('or', function(...args: any[]) {
|
|
33
|
+
// Remove Handlebars options object from end
|
|
34
|
+
const values = args.slice(0, -1);
|
|
35
|
+
return values.some(v => !!v);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
Handlebars.registerHelper('and', function(...args: any[]) {
|
|
39
|
+
// Remove Handlebars options object from end
|
|
40
|
+
const values = args.slice(0, -1);
|
|
41
|
+
return values.every(v => !!v);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Comparison helpers
|
|
45
|
+
Handlebars.registerHelper('gt', function(a: any, b: any) {
|
|
46
|
+
return a > b;
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
Handlebars.registerHelper('lt', function(a: any, b: any) {
|
|
50
|
+
return a < b;
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
Handlebars.registerHelper('gte', function(a: any, b: any) {
|
|
54
|
+
return a >= b;
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
Handlebars.registerHelper('lte', function(a: any, b: any) {
|
|
58
|
+
return a <= b;
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Math helpers
|
|
62
|
+
Handlebars.registerHelper('subtract', function(a: any, b: any) {
|
|
63
|
+
return a - b;
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
Handlebars.registerHelper('add', function(a: any, b: any) {
|
|
67
|
+
return a + b;
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Check if value is defined (not null/undefined) - useful for nth: 0
|
|
71
|
+
Handlebars.registerHelper('isDefined', function(value: any) {
|
|
72
|
+
return value !== undefined && value !== null;
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private registerPartials(): void {
|
|
77
|
+
// Register locator partial for reusable selector rendering
|
|
78
|
+
const locatorPath = path.join(this.stepsTemplatesDir, 'partials', 'locator.hbs');
|
|
79
|
+
if (fs.existsSync(locatorPath)) {
|
|
80
|
+
const locatorContent = fs.readFileSync(locatorPath, 'utf-8');
|
|
81
|
+
Handlebars.registerPartial('locator', locatorContent);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private loadTemplate(templateName: string, isStepTemplate: boolean = false): HandlebarsTemplateDelegate {
|
|
86
|
+
if (this.templates.has(templateName)) {
|
|
87
|
+
return this.templates.get(templateName)!;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const baseDir = isStepTemplate ? this.stepsTemplatesDir : this.templatesDir;
|
|
91
|
+
|
|
92
|
+
// Try to find template in organized folders
|
|
93
|
+
if (isStepTemplate) {
|
|
94
|
+
const folders = ['actions', 'assertions', 'navigation', 'setup', 'partials'];
|
|
95
|
+
|
|
96
|
+
for (const folder of folders) {
|
|
97
|
+
const templatePath = path.join(baseDir, folder, `${templateName}.hbs`);
|
|
98
|
+
if (fs.existsSync(templatePath)) {
|
|
99
|
+
const templateContent = fs.readFileSync(templatePath, 'utf-8');
|
|
100
|
+
const template = Handlebars.compile(templateContent, { noEscape: true });
|
|
101
|
+
this.templates.set(templateName, template);
|
|
102
|
+
return template;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Fallback: try root steps directory
|
|
107
|
+
const templatePath = path.join(baseDir, `${templateName}.hbs`);
|
|
108
|
+
if (fs.existsSync(templatePath)) {
|
|
109
|
+
const templateContent = fs.readFileSync(templatePath, 'utf-8');
|
|
110
|
+
const template = Handlebars.compile(templateContent, { noEscape: true });
|
|
111
|
+
this.templates.set(templateName, template);
|
|
112
|
+
return template;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
throw new Error(`Template not found: ${templateName}.hbs in any subfolder`);
|
|
116
|
+
} else {
|
|
117
|
+
const templatePath = path.join(baseDir, `${templateName}.hbs`);
|
|
118
|
+
const templateContent = fs.readFileSync(templatePath, 'utf-8');
|
|
119
|
+
const template = Handlebars.compile(templateContent, { noEscape: true });
|
|
120
|
+
this.templates.set(templateName, template);
|
|
121
|
+
return template;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
render(templateName: string, data: any, isStepTemplate: boolean = false): string {
|
|
126
|
+
const template = this.loadTemplate(templateName, isStepTemplate);
|
|
127
|
+
return template(data);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
renderStep(stepTemplateName: string, data: any): string {
|
|
131
|
+
return this.render(stepTemplateName, data, true);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
renderImports(): string {
|
|
135
|
+
return this.render('imports', {});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
renderTestFile(data: {
|
|
139
|
+
imports: string;
|
|
140
|
+
featureName: string;
|
|
141
|
+
featureDescription?: string;
|
|
142
|
+
background?: string;
|
|
143
|
+
scenarios: string[];
|
|
144
|
+
}): string {
|
|
145
|
+
return this.render('test-file', data);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
renderBeforeEach(data: {
|
|
149
|
+
steps: Array<{ comment?: string; code: string }>;
|
|
150
|
+
}): string {
|
|
151
|
+
return this.render('before-each', data);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
renderScenario(data: {
|
|
155
|
+
scenarioName: string;
|
|
156
|
+
steps: Array<{ comment?: string; code: string }>;
|
|
157
|
+
}): string {
|
|
158
|
+
return this.render('scenario', data);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import yaml from 'yaml';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* DataResolver - Resolves data references to actual values
|
|
7
|
+
* at generation time (not runtime)
|
|
8
|
+
*/
|
|
9
|
+
export class DataResolver {
|
|
10
|
+
private dataCache = new Map<string, any>();
|
|
11
|
+
private testDataDir: string;
|
|
12
|
+
private screenName?: string;
|
|
13
|
+
|
|
14
|
+
constructor(testDataDir?: string, screenName?: string) {
|
|
15
|
+
this.testDataDir = testDataDir || path.join(process.cwd(), 'qa', 'test-data');
|
|
16
|
+
this.screenName = screenName;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Set screen context for data resolution
|
|
21
|
+
*/
|
|
22
|
+
setScreenContext(screenName: string): void {
|
|
23
|
+
this.screenName = screenName;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Resolve data reference to actual value
|
|
28
|
+
* @param dataRef - Format: email.valid (path.to.value without filename)
|
|
29
|
+
* @param featureName - Name of the feature file (e.g., "login" from "login.feature")
|
|
30
|
+
* @returns The resolved value
|
|
31
|
+
*/
|
|
32
|
+
resolveData(dataRef: string, featureName?: string): string {
|
|
33
|
+
// Split into parts: email.valid -> [email, valid]
|
|
34
|
+
// Use only dot (.) as separator
|
|
35
|
+
const parts = dataRef.split('.');
|
|
36
|
+
|
|
37
|
+
if (parts.length < 1) {
|
|
38
|
+
throw new Error(`Invalid data reference: ${dataRef}. Expected format: path.to.value`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// If featureName provided, use it as the file name
|
|
42
|
+
// Otherwise, use first part as filename (backward compatibility)
|
|
43
|
+
let fileName: string;
|
|
44
|
+
let valuePath: string[];
|
|
45
|
+
|
|
46
|
+
if (featureName) {
|
|
47
|
+
fileName = featureName;
|
|
48
|
+
valuePath = parts;
|
|
49
|
+
} else {
|
|
50
|
+
if (parts.length < 2) {
|
|
51
|
+
throw new Error(`Invalid data reference: ${dataRef}. Expected format: file.path.to.value or provide featureName`);
|
|
52
|
+
}
|
|
53
|
+
fileName = parts[0];
|
|
54
|
+
valuePath = parts.slice(1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Load data file
|
|
58
|
+
const data = this.loadDataFile(fileName);
|
|
59
|
+
|
|
60
|
+
// Navigate to the value
|
|
61
|
+
let current = data;
|
|
62
|
+
for (const key of valuePath) {
|
|
63
|
+
if (current && typeof current === 'object' && key in current) {
|
|
64
|
+
current = current[key];
|
|
65
|
+
} else {
|
|
66
|
+
throw new Error(
|
|
67
|
+
`Data path not found: ${dataRef}. Failed at key: ${key}`
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Return as string
|
|
73
|
+
if (typeof current === 'string') {
|
|
74
|
+
return current;
|
|
75
|
+
} else if (typeof current === 'number' || typeof current === 'boolean') {
|
|
76
|
+
return String(current);
|
|
77
|
+
} else {
|
|
78
|
+
throw new Error(
|
|
79
|
+
`Data reference ${dataRef} must resolve to a primitive value, got: ${typeof current}`
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Load data file from disk (with caching)
|
|
86
|
+
* Searches new screen-based directory structure only
|
|
87
|
+
*/
|
|
88
|
+
private loadDataFile(fileName: string): any {
|
|
89
|
+
if (this.dataCache.has(fileName)) {
|
|
90
|
+
return this.dataCache.get(fileName)!;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const filePath = this.findDataFilePath(fileName);
|
|
94
|
+
|
|
95
|
+
if (!filePath) {
|
|
96
|
+
const possiblePaths = this.getPossibleDataPaths(fileName);
|
|
97
|
+
throw new Error(
|
|
98
|
+
`Data file not found. Tried:\n${possiblePaths.join('\n')}`
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
103
|
+
const data = yaml.parse(content);
|
|
104
|
+
|
|
105
|
+
this.dataCache.set(fileName, data);
|
|
106
|
+
return data;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Find data file path (checks new screen-based structure)
|
|
111
|
+
*/
|
|
112
|
+
private findDataFilePath(fileName: string): string | null {
|
|
113
|
+
const possiblePaths = this.getPossibleDataPaths(fileName);
|
|
114
|
+
|
|
115
|
+
for (const p of possiblePaths) {
|
|
116
|
+
if (fs.existsSync(p)) {
|
|
117
|
+
return p;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Get list of possible data file paths (priority order)
|
|
126
|
+
*/
|
|
127
|
+
private getPossibleDataPaths(fileName: string): string[] {
|
|
128
|
+
const paths: string[] = [];
|
|
129
|
+
|
|
130
|
+
// New structure: qa/screens/{screenName}/test-data/{fileName}.yaml
|
|
131
|
+
if (this.screenName) {
|
|
132
|
+
const cwd = process.cwd();
|
|
133
|
+
const newPath = path.join(cwd, 'qa', 'screens', this.screenName, 'test-data', `${fileName}.yaml`);
|
|
134
|
+
const newPathYml = path.join(cwd, 'qa', 'screens', this.screenName, 'test-data', `${fileName}.yml`);
|
|
135
|
+
paths.push(newPath, newPathYml);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return paths;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Clear cache (useful for testing)
|
|
143
|
+
*/
|
|
144
|
+
clearCache(): void {
|
|
145
|
+
this.dataCache.clear();
|
|
146
|
+
}
|
|
147
|
+
}
|