@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
package/src/generators/test-generator/adapters/playwright/templates/steps/actions/check-action.hbs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
await {{> locator}}.check();
|
package/src/generators/test-generator/adapters/playwright/templates/steps/actions/clear-action.hbs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
await {{> locator}}.clear();
|
package/src/generators/test-generator/adapters/playwright/templates/steps/actions/click-action.hbs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
await {{> locator}}.click();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
await {{> locator}}.dblclick();
|
package/src/generators/test-generator/adapters/playwright/templates/steps/actions/fill-action.hbs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
await {{> locator}}.fill('{{fillValue}}');
|
package/src/generators/test-generator/adapters/playwright/templates/steps/actions/hover-action.hbs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
await {{> locator}}.hover();
|
package/src/generators/test-generator/adapters/playwright/templates/steps/actions/press-action.hbs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
await {{> locator}}.press('{{key}}');
|
package/src/generators/test-generator/adapters/playwright/templates/steps/actions/select-action.hbs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
await {{> locator}}.selectOption('{{selectValue}}');
|
package/src/generators/test-generator/adapters/playwright/templates/steps/actions/uncheck-action.hbs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
await {{> locator}}.uncheck();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
await expect({{> locator}}).toBeChecked();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
await expect({{> locator}}).toContainText('{{expectedText}}');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
await expect({{> locator}}).toHaveCount({{expectedCount}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
await expect({{> locator}}).toBeFocused();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
await expect({{> locator}}).toHaveText('{{expectedText}}');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
await expect({{> locator}}).not.toBeChecked();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
await expect({{> locator}}).not.toBeVisible();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
await expect({{> locator}}).toBeVisible();
|
package/src/generators/test-generator/adapters/playwright/templates/steps/navigation/navigation.hbs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
await page.goto('{{#if baseURL}}{{baseURL}}{{/if}}{{path}}');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
await {{> locator}}.waitFor({ state: '{{state}}' });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
await page.waitForTimeout({{duration}});
|
package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator.hbs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{{#if (eq strategy 'testid')}}page.getByTestId('{{value}}'){{else if (eq strategy 'role')}}page.getByRole('{{role}}', { name: '{{escapeQuotes name}}' }){{else if (eq strategy 'placeholder')}}page.getByPlaceholder('{{escapeQuotes value}}'){{else if (eq strategy 'label')}}page.getByLabel('{{escapeQuotes value}}'){{else if (eq strategy 'text')}}page.getByText('{{escapeQuotes value}}'){{else if (eq strategy 'id')}}page.locator('{{selector}}'){{else}}page.locator('{{escapeQuotes selector}}'){{/if}}{{#if (and (isDefined nth) (gt nth 0))}}.nth({{subtract nth 1}}){{/if}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Application should be running (no action needed)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{{imports}}
|
|
2
|
+
|
|
3
|
+
{{#if featureDescription}}
|
|
4
|
+
/**
|
|
5
|
+
* Feature: {{featureName}}
|
|
6
|
+
* {{featureDescription}}
|
|
7
|
+
*/
|
|
8
|
+
{{/if}}
|
|
9
|
+
|
|
10
|
+
test.describe('{{featureName}}', () => {
|
|
11
|
+
{{#if background}}
|
|
12
|
+
{{background}}
|
|
13
|
+
|
|
14
|
+
{{/if}}
|
|
15
|
+
{{#each scenarios}}
|
|
16
|
+
{{this}}
|
|
17
|
+
|
|
18
|
+
{{/each}}
|
|
19
|
+
});
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI-Based Step Mapper
|
|
3
|
+
* Fallback for dictionary when Gherkin patterns are ambiguous or unknown
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
7
|
+
import { ParsedStep } from '../gherkin-parser';
|
|
8
|
+
import { MappedStep } from './step-mapper';
|
|
9
|
+
|
|
10
|
+
export class AIStepMapper {
|
|
11
|
+
private client: Anthropic;
|
|
12
|
+
private verbose: boolean;
|
|
13
|
+
|
|
14
|
+
constructor(verbose: boolean = false) {
|
|
15
|
+
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
16
|
+
if (!apiKey) {
|
|
17
|
+
throw new Error('ANTHROPIC_API_KEY environment variable is required for AI step mapping');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
this.client = new Anthropic({ apiKey });
|
|
21
|
+
this.verbose = verbose;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Map a Gherkin step to Playwright code using AI
|
|
26
|
+
* Provides rich context to help AI understand the intent
|
|
27
|
+
*/
|
|
28
|
+
async mapStep(step: ParsedStep): Promise<MappedStep> {
|
|
29
|
+
if (this.verbose) {
|
|
30
|
+
console.log(` [AI] Mapping step: "${step.text}"`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const prompt = this.buildPrompt(step);
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
const message = await this.client.messages.create({
|
|
37
|
+
model: 'claude-3-5-haiku-20241022', // Fast & cheap for code generation
|
|
38
|
+
max_tokens: 500,
|
|
39
|
+
temperature: 0, // Deterministic for code generation
|
|
40
|
+
messages: [{
|
|
41
|
+
role: 'user',
|
|
42
|
+
content: prompt
|
|
43
|
+
}]
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const content = message.content[0];
|
|
47
|
+
if (content.type !== 'text') {
|
|
48
|
+
throw new Error('Unexpected response type from AI');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const code = this.extractCode(content.text);
|
|
52
|
+
|
|
53
|
+
if (this.verbose) {
|
|
54
|
+
console.log(` [AI] Generated code (${code.split('\n').length} lines)`);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
code,
|
|
59
|
+
comment: `AI-generated from: ${step.text}`
|
|
60
|
+
};
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error(`[AI] Failed to map step: ${error}`);
|
|
63
|
+
|
|
64
|
+
// Fallback to TODO comment
|
|
65
|
+
return {
|
|
66
|
+
code: `// TODO: AI mapping failed - implement manually: ${step.text}`,
|
|
67
|
+
comment: `AI mapping error: ${error instanceof Error ? error.message : 'Unknown error'}`
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Build context-rich prompt for AI
|
|
74
|
+
* Includes examples, patterns, and clear instructions
|
|
75
|
+
*/
|
|
76
|
+
private buildPrompt(step: ParsedStep): string {
|
|
77
|
+
const { keyword, text, selectorRef, dataRef, value } = step;
|
|
78
|
+
|
|
79
|
+
return `You are an expert Playwright test code generator.
|
|
80
|
+
|
|
81
|
+
**Task**: Convert this Gherkin step into Playwright TypeScript code.
|
|
82
|
+
|
|
83
|
+
**Gherkin Step**:
|
|
84
|
+
${keyword} ${text}
|
|
85
|
+
|
|
86
|
+
**Parsed Information**:
|
|
87
|
+
- Element ID: ${selectorRef || 'N/A'}
|
|
88
|
+
- Data Reference: ${dataRef || 'N/A'}
|
|
89
|
+
- Value: ${value || 'N/A'}
|
|
90
|
+
|
|
91
|
+
**Context**:
|
|
92
|
+
- We use a custom selector helper: \`pw.fill(elementId, value, screenId)\`
|
|
93
|
+
- Element IDs are in format: [screen.element-name]
|
|
94
|
+
- Screen ID is extracted from element ID (e.g., "chat" from "[chat.input]")
|
|
95
|
+
- For assertions, use: \`await pw.getElement(elementId, screenId)\` then \`expect(element)...\`
|
|
96
|
+
|
|
97
|
+
**Common Patterns & Examples**:
|
|
98
|
+
|
|
99
|
+
1. **Fill/Input Actions**:
|
|
100
|
+
- "user fills/inputs/enters [element] with value"
|
|
101
|
+
- "user types value in/into [element]"
|
|
102
|
+
→ \`await pw.fill('[element]', 'value', 'screen');\`
|
|
103
|
+
|
|
104
|
+
2. **Click Actions**:
|
|
105
|
+
- "user clicks/taps/presses [element]"
|
|
106
|
+
- "user clicks on [element]"
|
|
107
|
+
→ \`await pw.click('[element]', 'screen');\`
|
|
108
|
+
|
|
109
|
+
3. **Keyboard Actions**:
|
|
110
|
+
- "user presses Enter in [element]"
|
|
111
|
+
- "user hits Tab key in [element]"
|
|
112
|
+
→ \`const el = await pw.getElement('[element]', 'screen');\n await el.press('Enter');\`
|
|
113
|
+
|
|
114
|
+
4. **Visibility Assertions**:
|
|
115
|
+
- "user should see [element]"
|
|
116
|
+
- "[element] is/should be visible"
|
|
117
|
+
- "[element] appears/shows"
|
|
118
|
+
→ \`const el = await pw.getElement('[element]', 'screen');\n await expect(el).toBeVisible();\`
|
|
119
|
+
|
|
120
|
+
5. **State Assertions**:
|
|
121
|
+
- "[element] should be disabled/enabled"
|
|
122
|
+
- "[element] is checked/unchecked"
|
|
123
|
+
→ \`const el = await pw.getElement('[element]', 'screen');\n await expect(el).toBeDisabled();\`
|
|
124
|
+
|
|
125
|
+
6. **Text Content Assertions**:
|
|
126
|
+
- "[element] should contain text \\"value\\""
|
|
127
|
+
- "[element] has/displays text \\"value\\""
|
|
128
|
+
→ \`const el = await pw.getElement('[element]', 'screen');\n await expect(el).toContainText('value');\`
|
|
129
|
+
|
|
130
|
+
7. **Collection State**:
|
|
131
|
+
- "[element] should be empty"
|
|
132
|
+
- "[element] has no items"
|
|
133
|
+
→ \`const el = await pw.getElement('[element]', 'screen');\n const items = await el.locator('> *').all();\n expect(items.length).toBe(0);\`
|
|
134
|
+
|
|
135
|
+
8. **Scroll State**:
|
|
136
|
+
- "[element] should be scrolled to bottom"
|
|
137
|
+
→ \`const el = await pw.getElement('[element]', 'screen');\n const scrollHeight = await el.evaluate(el => el.scrollHeight);\n const scrollTop = await el.evaluate(el => el.scrollTop);\n const clientHeight = await el.evaluate(el => el.clientHeight);\n expect(scrollTop + clientHeight).toBeGreaterThanOrEqual(scrollHeight - 10);\`
|
|
138
|
+
|
|
139
|
+
**Important Rules**:
|
|
140
|
+
1. Extract screen ID from element ID: "[chat.input]" → screen="chat"
|
|
141
|
+
2. Use proper TypeScript syntax with await
|
|
142
|
+
3. Use descriptive variable names (element, el, container, etc.)
|
|
143
|
+
4. Add helpful comments for complex assertions
|
|
144
|
+
5. NEVER use page.evaluate() unless absolutely necessary
|
|
145
|
+
6. NEVER generate partial or incomplete statements
|
|
146
|
+
7. Each step should generate COMPLETE, SELF-CONTAINED code
|
|
147
|
+
8. If you can't map the step, return a comment: // TODO: Implement step
|
|
148
|
+
|
|
149
|
+
**Output Format**:
|
|
150
|
+
Return ONLY complete Playwright TypeScript statements, no explanations, no markdown blocks.
|
|
151
|
+
Each statement must be syntactically complete and can be inserted directly into a test function.
|
|
152
|
+
|
|
153
|
+
**Example Output**:
|
|
154
|
+
const chat_input_123 = await pw.getElement('[chat.input]', 'chat');
|
|
155
|
+
await expect(chat_input_123).toBeVisible();
|
|
156
|
+
|
|
157
|
+
Now generate code for the given step.`;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Extract clean code from AI response
|
|
162
|
+
* Remove markdown code blocks, explanations, etc.
|
|
163
|
+
*/
|
|
164
|
+
private extractCode(response: string): string {
|
|
165
|
+
let code = response.trim();
|
|
166
|
+
|
|
167
|
+
// Remove markdown code blocks
|
|
168
|
+
code = code.replace(/```(?:typescript|ts|javascript|js)?\n?/g, '');
|
|
169
|
+
code = code.replace(/```\n?/g, '');
|
|
170
|
+
|
|
171
|
+
// Remove leading/trailing whitespace
|
|
172
|
+
code = code.trim();
|
|
173
|
+
|
|
174
|
+
// If response contains explanations, try to extract only code
|
|
175
|
+
const lines = code.split('\n');
|
|
176
|
+
const codeLines = lines.filter(line => {
|
|
177
|
+
const trimmed = line.trim();
|
|
178
|
+
|
|
179
|
+
// Skip lines that are clearly explanations (start with text, not code)
|
|
180
|
+
// But keep all valid TypeScript/JavaScript syntax
|
|
181
|
+
if (trimmed === '') return true; // Keep empty lines
|
|
182
|
+
if (trimmed.startsWith('//')) return true; // Keep comments
|
|
183
|
+
|
|
184
|
+
// Exclude lines that look like natural language explanations
|
|
185
|
+
// (start with capital letter and contain spaces, no semicolons/operators)
|
|
186
|
+
if (/^[A-Z][a-z]+ [\w\s]+$/.test(trimmed) && !trimmed.includes(';')) {
|
|
187
|
+
return false; // This looks like an explanation
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Keep lines that contain code-like patterns
|
|
191
|
+
const codePatterns = [
|
|
192
|
+
'await ', 'const ', 'let ', 'var ', 'return ', 'expect(', 'if ', 'else',
|
|
193
|
+
'for ', 'while ', 'function ', '=>', 'pw.', 'page.',
|
|
194
|
+
')', '}', '];', '});', '})', 'import ', 'export ',
|
|
195
|
+
'.', '(', '[', '=', '+', '-', '*', '/', '%', '&&', '||'
|
|
196
|
+
];
|
|
197
|
+
|
|
198
|
+
return codePatterns.some(pattern => trimmed.includes(pattern));
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// If we filtered too much, return original
|
|
202
|
+
if (codeLines.length === 0) {
|
|
203
|
+
return code;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
let finalCode = codeLines.join('\n');
|
|
207
|
+
|
|
208
|
+
// Safety check: Remove incomplete page.evaluate statements
|
|
209
|
+
// If we find "page.evaluate(" without proper closing, remove it
|
|
210
|
+
const evaluatePattern = /await\s+page\.evaluate\(\(\)\s*=>\s*\{\s*$/gm;
|
|
211
|
+
if (evaluatePattern.test(finalCode)) {
|
|
212
|
+
// Has unclosed page.evaluate at end - this is incomplete, return TODO
|
|
213
|
+
return '// TODO: Implement step (AI generated incomplete code)';
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Safety check: If code ends with an opening brace/paren, it's incomplete
|
|
217
|
+
const endsIncomplete = /[\({]\s*$/.test(finalCode);
|
|
218
|
+
if (endsIncomplete) {
|
|
219
|
+
return '// TODO: Implement step (AI generated incomplete code)';
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return finalCode;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { ParsedFeature, ParsedScenario, ParsedStep } from '../gherkin-parser';
|
|
4
|
+
import { StepMapper } from './step-mapper';
|
|
5
|
+
import { TestGeneratorAdapter, adapterRegistry } from './adapters';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Result of test generation for a single feature file
|
|
9
|
+
*/
|
|
10
|
+
export interface GeneratedTest {
|
|
11
|
+
featureName: string;
|
|
12
|
+
filePath: string;
|
|
13
|
+
code: string;
|
|
14
|
+
sourceFile?: string; // Source feature file path
|
|
15
|
+
stepCount?: number; // Total steps in generated test
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class CodeGenerator {
|
|
19
|
+
private stepMapper: StepMapper;
|
|
20
|
+
private adapter: TestGeneratorAdapter;
|
|
21
|
+
private screenName?: string;
|
|
22
|
+
|
|
23
|
+
constructor(options: { useAI?: boolean; verbose?: boolean; framework?: string; baseURL?: string; screenName?: string } = {}) {
|
|
24
|
+
this.screenName = options.screenName;
|
|
25
|
+
this.stepMapper = new StepMapper(options);
|
|
26
|
+
|
|
27
|
+
// Get adapter from registry (default: playwright)
|
|
28
|
+
const frameworkName = options.framework || 'playwright';
|
|
29
|
+
this.adapter = adapterRegistry.getAdapter(frameworkName);
|
|
30
|
+
|
|
31
|
+
if (options.verbose) {
|
|
32
|
+
console.log(`[CodeGenerator] Using ${this.adapter.frameworkName} adapter`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Generate test file from parsed feature
|
|
38
|
+
*/
|
|
39
|
+
async generateTest(
|
|
40
|
+
feature: ParsedFeature,
|
|
41
|
+
outputDir: string
|
|
42
|
+
): Promise<GeneratedTest> {
|
|
43
|
+
// Use source file name if available, otherwise derive from feature name
|
|
44
|
+
let fileName: string;
|
|
45
|
+
if (feature.sourceFile) {
|
|
46
|
+
// Extract filename and replace .feature with .spec.ts
|
|
47
|
+
const baseName = path.basename(feature.sourceFile, path.extname(feature.sourceFile));
|
|
48
|
+
fileName = `${baseName}.spec.ts`;
|
|
49
|
+
} else {
|
|
50
|
+
// Fallback to converting feature name
|
|
51
|
+
fileName = this.featureNameToFileName(feature.name);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Extract screen name from source file path if available
|
|
55
|
+
// qa/screens/{screenName}/features/{featureName}.feature -> screenName
|
|
56
|
+
let screenSubdir = '';
|
|
57
|
+
if (feature.sourceFile) {
|
|
58
|
+
const sourceDir = path.dirname(feature.sourceFile);
|
|
59
|
+
const parts = sourceDir.split(path.sep);
|
|
60
|
+
const screensIndex = parts.indexOf('screens');
|
|
61
|
+
if (screensIndex >= 0 && screensIndex < parts.length - 2) {
|
|
62
|
+
screenSubdir = parts[screensIndex + 1]; // screen name after 'screens'
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Build output path with screen subdirectory
|
|
67
|
+
const filePath = screenSubdir
|
|
68
|
+
? path.join(outputDir, screenSubdir, fileName)
|
|
69
|
+
: path.join(outputDir, fileName);
|
|
70
|
+
|
|
71
|
+
// Generate imports using adapter
|
|
72
|
+
const imports = this.adapter.renderImports();
|
|
73
|
+
|
|
74
|
+
// Generate test code (async now to support AI mapping)
|
|
75
|
+
const testCode = await this.generateTestCode(feature);
|
|
76
|
+
|
|
77
|
+
// Combine
|
|
78
|
+
const code = `${imports}\n\n${testCode}`;
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
featureName: feature.name,
|
|
82
|
+
filePath,
|
|
83
|
+
code,
|
|
84
|
+
sourceFile: feature.sourceFile,
|
|
85
|
+
stepCount: this.countSteps(feature),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Count total steps in feature (excluding background)
|
|
91
|
+
*/
|
|
92
|
+
private countSteps(feature: ParsedFeature): number {
|
|
93
|
+
let total = 0;
|
|
94
|
+
for (const scenario of feature.scenarios) {
|
|
95
|
+
total += scenario.steps.length;
|
|
96
|
+
}
|
|
97
|
+
return total;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Write generated test to file
|
|
102
|
+
*/
|
|
103
|
+
writeTest(generatedTest: GeneratedTest): void {
|
|
104
|
+
const dir = path.dirname(generatedTest.filePath);
|
|
105
|
+
if (!fs.existsSync(dir)) {
|
|
106
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
fs.writeFileSync(generatedTest.filePath, generatedTest.code, 'utf-8');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
private async generateTestCode(feature: ParsedFeature): Promise<string> {
|
|
113
|
+
// Extract feature name from source file if available, otherwise derive from feature name
|
|
114
|
+
let featureName: string;
|
|
115
|
+
if (feature.sourceFile) {
|
|
116
|
+
// Extract filename without extension: "/path/to/login.feature" -> "login"
|
|
117
|
+
featureName = path.basename(feature.sourceFile, path.extname(feature.sourceFile));
|
|
118
|
+
} else {
|
|
119
|
+
// Fallback: derive from feature name (e.g., "User Authentication - Login" -> "login")
|
|
120
|
+
featureName = this.featureNameToFileName(feature.name).replace('.spec.ts', '');
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Set feature context for data resolution and navigation
|
|
124
|
+
this.stepMapper.setFeatureContext(featureName, feature.path);
|
|
125
|
+
|
|
126
|
+
// Generate background if exists
|
|
127
|
+
let background: string | undefined;
|
|
128
|
+
if (feature.background) {
|
|
129
|
+
background = await this.generateBeforeEach(feature.background);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Generate all scenarios
|
|
133
|
+
const scenarios: string[] = [];
|
|
134
|
+
for (const scenario of feature.scenarios) {
|
|
135
|
+
scenarios.push(await this.generateScenario(scenario, !!feature.background));
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Use adapter to render the complete test file structure
|
|
139
|
+
return this.adapter.renderTestFile({
|
|
140
|
+
imports: '', // Not used in template as it's rendered separately
|
|
141
|
+
featureName: feature.name,
|
|
142
|
+
featureDescription: feature.description,
|
|
143
|
+
background,
|
|
144
|
+
scenarios,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
private async generateBeforeEach(background: ParsedScenario): Promise<string> {
|
|
149
|
+
// Map all steps
|
|
150
|
+
const steps: Array<{ comment?: string; code: string }> = [];
|
|
151
|
+
for (const step of background.steps) {
|
|
152
|
+
const mapped = await Promise.resolve(this.stepMapper.mapStep(step));
|
|
153
|
+
steps.push({
|
|
154
|
+
comment: mapped.comment,
|
|
155
|
+
code: this.indentCode(mapped.code, 4),
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Use adapter to render beforeEach
|
|
160
|
+
return this.adapter.renderBeforeEach({
|
|
161
|
+
steps,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
private async generateScenario(scenario: ParsedScenario, hasBackground: boolean): Promise<string> {
|
|
166
|
+
// Set scenario context for path variable resolution
|
|
167
|
+
this.stepMapper.setScenarioContext(scenario.steps);
|
|
168
|
+
|
|
169
|
+
// Map all steps
|
|
170
|
+
const steps: Array<{ comment?: string; code: string }> = [];
|
|
171
|
+
for (const step of scenario.steps) {
|
|
172
|
+
const mapped = await Promise.resolve(this.stepMapper.mapStep(step));
|
|
173
|
+
steps.push({
|
|
174
|
+
comment: mapped.comment,
|
|
175
|
+
code: this.indentCode(mapped.code, 4),
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Use adapter to render scenario
|
|
180
|
+
return this.adapter.renderScenario({
|
|
181
|
+
scenarioName: scenario.name,
|
|
182
|
+
steps,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Indent code lines with specified number of spaces
|
|
188
|
+
*/
|
|
189
|
+
private indentCode(code: string, spaces: number): string {
|
|
190
|
+
const indentation = ' '.repeat(spaces);
|
|
191
|
+
return code.split('\n').map(line => indentation + line).join('\n');
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Convert feature name to file name
|
|
196
|
+
* Example: "User Login" → "user-login.spec.ts"
|
|
197
|
+
*/
|
|
198
|
+
private featureNameToFileName(featureName: string): string {
|
|
199
|
+
return (
|
|
200
|
+
featureName
|
|
201
|
+
.toLowerCase()
|
|
202
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
203
|
+
.replace(/^-|-$/g, '') + '.spec.ts'
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Generate tests for all features in a directory
|
|
209
|
+
*/
|
|
210
|
+
async generateAllTests(
|
|
211
|
+
featuresDir: string,
|
|
212
|
+
outputDir: string,
|
|
213
|
+
featureFiles: string[]
|
|
214
|
+
): Promise<GeneratedTest[]> {
|
|
215
|
+
const { GherkinParser } = require('../gherkin-parser');
|
|
216
|
+
const parser = new GherkinParser();
|
|
217
|
+
|
|
218
|
+
const results: GeneratedTest[] = [];
|
|
219
|
+
|
|
220
|
+
for (const featureFile of featureFiles) {
|
|
221
|
+
try {
|
|
222
|
+
const feature = parser.parseFeatureFile(featureFile);
|
|
223
|
+
const generatedTest = await this.generateTest(feature, outputDir);
|
|
224
|
+
this.writeTest(generatedTest);
|
|
225
|
+
results.push(generatedTest);
|
|
226
|
+
|
|
227
|
+
console.log(`✓ Generated: ${path.basename(generatedTest.filePath)}`);
|
|
228
|
+
} catch (error) {
|
|
229
|
+
console.error(`✗ Failed to generate test for ${featureFile}:`, error);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return results;
|
|
234
|
+
}
|
|
235
|
+
}
|