@sun-asterisk/sungen 1.0.23 → 2.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/README.md +198 -74
- package/dist/cli/commands/add.d.ts.map +1 -1
- package/dist/cli/commands/add.js +5 -3
- package/dist/cli/commands/add.js.map +1 -1
- package/dist/cli/commands/generate.d.ts.map +1 -1
- package/dist/cli/commands/generate.js +110 -35
- package/dist/cli/commands/generate.js.map +1 -1
- package/dist/cli/index.d.ts +2 -2
- package/dist/cli/index.js +5 -16
- package/dist/cli/index.js.map +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/frame-enter-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/frame-exit-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/keyboard-global-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/scroll-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/label-value-assertion.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-filter.hbs +3 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-index.hbs +3 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-column-exists.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-empty.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-count.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-exists.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-not-exists.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-value-assertion.hbs +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator-base.hbs +11 -2
- package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator.hbs +11 -2
- package/dist/generators/test-generator/code-generator.d.ts +0 -1
- package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
- package/dist/generators/test-generator/code-generator.js +0 -47
- package/dist/generators/test-generator/code-generator.js.map +1 -1
- package/dist/generators/test-generator/patterns/assertion-patterns.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/assertion-patterns.js +33 -8
- package/dist/generators/test-generator/patterns/assertion-patterns.js.map +1 -1
- package/dist/generators/test-generator/patterns/index.d.ts +4 -1
- package/dist/generators/test-generator/patterns/index.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/index.js +17 -5
- package/dist/generators/test-generator/patterns/index.js.map +1 -1
- package/dist/generators/test-generator/patterns/interaction-patterns.js +1 -1
- package/dist/generators/test-generator/patterns/interaction-patterns.js.map +1 -1
- package/dist/generators/test-generator/patterns/keyboard-patterns.d.ts +7 -0
- package/dist/generators/test-generator/patterns/keyboard-patterns.d.ts.map +1 -0
- package/dist/generators/test-generator/patterns/keyboard-patterns.js +47 -0
- package/dist/generators/test-generator/patterns/keyboard-patterns.js.map +1 -0
- package/dist/generators/test-generator/patterns/scope-patterns.d.ts +7 -0
- package/dist/generators/test-generator/patterns/scope-patterns.d.ts.map +1 -0
- package/dist/generators/test-generator/patterns/scope-patterns.js +36 -0
- package/dist/generators/test-generator/patterns/scope-patterns.js.map +1 -0
- package/dist/generators/test-generator/patterns/scroll-patterns.d.ts +7 -0
- package/dist/generators/test-generator/patterns/scroll-patterns.d.ts.map +1 -0
- package/dist/generators/test-generator/patterns/scroll-patterns.js +25 -0
- package/dist/generators/test-generator/patterns/scroll-patterns.js.map +1 -0
- package/dist/generators/test-generator/patterns/table-patterns.d.ts +7 -0
- package/dist/generators/test-generator/patterns/table-patterns.d.ts.map +1 -0
- package/dist/generators/test-generator/patterns/table-patterns.js +192 -0
- package/dist/generators/test-generator/patterns/table-patterns.js.map +1 -0
- package/dist/generators/test-generator/step-mapper.d.ts +1 -3
- package/dist/generators/test-generator/step-mapper.d.ts.map +1 -1
- package/dist/generators/test-generator/step-mapper.js +36 -34
- package/dist/generators/test-generator/step-mapper.js.map +1 -1
- package/dist/generators/test-generator/template-engine.d.ts.map +1 -1
- package/dist/generators/test-generator/template-engine.js +4 -1
- package/dist/generators/test-generator/template-engine.js.map +1 -1
- package/dist/generators/test-generator/types.d.ts +7 -24
- package/dist/generators/test-generator/types.d.ts.map +1 -1
- package/dist/generators/test-generator/types.js +2 -101
- package/dist/generators/test-generator/types.js.map +1 -1
- package/dist/generators/test-generator/utils/selector-resolver.d.ts +14 -0
- package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
- package/dist/generators/test-generator/utils/selector-resolver.js +37 -11
- package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -1
- package/dist/orchestrator/project-initializer.d.ts +8 -0
- package/dist/orchestrator/project-initializer.d.ts.map +1 -1
- package/dist/orchestrator/project-initializer.js +343 -32
- package/dist/orchestrator/project-initializer.js.map +1 -1
- package/dist/orchestrator/screen-manager.d.ts +1 -32
- package/dist/orchestrator/screen-manager.d.ts.map +1 -1
- package/dist/orchestrator/screen-manager.js +55 -216
- package/dist/orchestrator/screen-manager.js.map +1 -1
- package/dist/utils/selector-types.d.ts +1 -1
- package/dist/utils/selector-types.d.ts.map +1 -1
- package/dist/utils/selector-types.js +3 -0
- package/dist/utils/selector-types.js.map +1 -1
- package/package.json +2 -2
- package/src/cli/commands/add.ts +5 -3
- package/src/cli/commands/generate.ts +90 -38
- package/src/cli/index.ts +5 -16
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/frame-enter-action.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/frame-exit-action.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/keyboard-global-action.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/scroll-action.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row.hbs +2 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/label-value-assertion.hbs +2 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-filter.hbs +3 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-index.hbs +3 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-column-exists.hbs +2 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-empty.hbs +2 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-count.hbs +2 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-exists.hbs +2 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-not-exists.hbs +2 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-value-assertion.hbs +1 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator-base.hbs +11 -2
- package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator.hbs +11 -2
- package/src/generators/test-generator/code-generator.ts +0 -59
- package/src/generators/test-generator/patterns/assertion-patterns.ts +39 -8
- package/src/generators/test-generator/patterns/index.ts +12 -3
- package/src/generators/test-generator/patterns/interaction-patterns.ts +1 -1
- package/src/generators/test-generator/patterns/keyboard-patterns.ts +51 -0
- package/src/generators/test-generator/patterns/scope-patterns.ts +40 -0
- package/src/generators/test-generator/patterns/scroll-patterns.ts +27 -0
- package/src/generators/test-generator/patterns/table-patterns.ts +232 -0
- package/src/generators/test-generator/step-mapper.ts +39 -34
- package/src/generators/test-generator/template-engine.ts +3 -1
- package/src/generators/test-generator/types.ts +7 -112
- package/src/generators/test-generator/utils/selector-resolver.ts +70 -25
- package/src/orchestrator/project-initializer.ts +345 -32
- package/src/orchestrator/screen-manager.ts +61 -233
- package/src/utils/selector-types.ts +3 -0
- package/dist/cli/commands/cache-clear.d.ts +0 -3
- package/dist/cli/commands/cache-clear.d.ts.map +0 -1
- package/dist/cli/commands/cache-clear.js +0 -24
- package/dist/cli/commands/cache-clear.js.map +0 -1
- package/dist/cli/commands/full.d.ts +0 -3
- package/dist/cli/commands/full.d.ts.map +0 -1
- package/dist/cli/commands/full.js +0 -37
- package/dist/cli/commands/full.js.map +0 -1
- package/dist/cli/commands/live-scan.d.ts +0 -3
- package/dist/cli/commands/live-scan.d.ts.map +0 -1
- package/dist/cli/commands/live-scan.js +0 -78
- package/dist/cli/commands/live-scan.js.map +0 -1
- package/dist/cli/commands/map.d.ts +0 -3
- package/dist/cli/commands/map.d.ts.map +0 -1
- package/dist/cli/commands/map.js +0 -93
- package/dist/cli/commands/map.js.map +0 -1
- package/dist/cli/commands/validate.d.ts +0 -3
- package/dist/cli/commands/validate.d.ts.map +0 -1
- package/dist/cli/commands/validate.js +0 -43
- package/dist/cli/commands/validate.js.map +0 -1
- package/dist/cli/utils.d.ts +0 -6
- package/dist/cli/utils.d.ts.map +0 -1
- package/dist/cli/utils.js +0 -101
- package/dist/cli/utils.js.map +0 -1
- package/dist/config/config-loader.d.ts +0 -51
- package/dist/config/config-loader.d.ts.map +0 -1
- package/dist/config/config-loader.js +0 -216
- package/dist/config/config-loader.js.map +0 -1
- package/dist/config/config-schema.d.ts +0 -121
- package/dist/config/config-schema.d.ts.map +0 -1
- package/dist/config/config-schema.js +0 -7
- package/dist/config/config-schema.js.map +0 -1
- package/dist/core/live-scanner/config-reader.d.ts +0 -10
- package/dist/core/live-scanner/config-reader.d.ts.map +0 -1
- package/dist/core/live-scanner/config-reader.js +0 -87
- package/dist/core/live-scanner/config-reader.js.map +0 -1
- package/dist/core/live-scanner/element-finder.d.ts +0 -20
- package/dist/core/live-scanner/element-finder.d.ts.map +0 -1
- package/dist/core/live-scanner/element-finder.js +0 -486
- package/dist/core/live-scanner/element-finder.js.map +0 -1
- package/dist/core/live-scanner/index.d.ts +0 -8
- package/dist/core/live-scanner/index.d.ts.map +0 -1
- package/dist/core/live-scanner/index.js +0 -33
- package/dist/core/live-scanner/index.js.map +0 -1
- package/dist/core/live-scanner/matrix-reader.d.ts +0 -17
- package/dist/core/live-scanner/matrix-reader.d.ts.map +0 -1
- package/dist/core/live-scanner/matrix-reader.js +0 -60
- package/dist/core/live-scanner/matrix-reader.js.map +0 -1
- package/dist/core/live-scanner/matrix-writer.d.ts +0 -7
- package/dist/core/live-scanner/matrix-writer.d.ts.map +0 -1
- package/dist/core/live-scanner/matrix-writer.js +0 -103
- package/dist/core/live-scanner/matrix-writer.js.map +0 -1
- package/dist/core/live-scanner/role-fallback.d.ts +0 -15
- package/dist/core/live-scanner/role-fallback.d.ts.map +0 -1
- package/dist/core/live-scanner/role-fallback.js +0 -45
- package/dist/core/live-scanner/role-fallback.js.map +0 -1
- package/dist/core/live-scanner/scanner.d.ts +0 -13
- package/dist/core/live-scanner/scanner.d.ts.map +0 -1
- package/dist/core/live-scanner/scanner.js +0 -243
- package/dist/core/live-scanner/scanner.js.map +0 -1
- package/dist/core/live-scanner/step-replayer.d.ts +0 -26
- package/dist/core/live-scanner/step-replayer.d.ts.map +0 -1
- package/dist/core/live-scanner/step-replayer.js +0 -286
- package/dist/core/live-scanner/step-replayer.js.map +0 -1
- package/dist/core/live-scanner/types.d.ts +0 -52
- package/dist/core/live-scanner/types.d.ts.map +0 -1
- package/dist/core/live-scanner/types.js +0 -14
- package/dist/core/live-scanner/types.js.map +0 -1
- package/dist/core/selector-base/annotation-handler.d.ts +0 -45
- package/dist/core/selector-base/annotation-handler.d.ts.map +0 -1
- package/dist/core/selector-base/annotation-handler.js +0 -102
- package/dist/core/selector-base/annotation-handler.js.map +0 -1
- package/dist/core/selector-base/base-generator.d.ts +0 -49
- package/dist/core/selector-base/base-generator.d.ts.map +0 -1
- package/dist/core/selector-base/base-generator.js +0 -214
- package/dist/core/selector-base/base-generator.js.map +0 -1
- package/dist/core/selector-base/gherkin-parser.d.ts +0 -24
- package/dist/core/selector-base/gherkin-parser.d.ts.map +0 -1
- package/dist/core/selector-base/gherkin-parser.js +0 -42
- package/dist/core/selector-base/gherkin-parser.js.map +0 -1
- package/dist/core/selector-mapper/priority-mapper.d.ts +0 -74
- package/dist/core/selector-mapper/priority-mapper.d.ts.map +0 -1
- package/dist/core/selector-mapper/priority-mapper.js +0 -477
- package/dist/core/selector-mapper/priority-mapper.js.map +0 -1
- package/dist/core/ui-scanner/heuristics/base-heuristic.d.ts +0 -91
- package/dist/core/ui-scanner/heuristics/base-heuristic.d.ts.map +0 -1
- package/dist/core/ui-scanner/heuristics/base-heuristic.js +0 -175
- package/dist/core/ui-scanner/heuristics/base-heuristic.js.map +0 -1
- package/dist/core/ui-scanner/react-scanner.d.ts +0 -32
- package/dist/core/ui-scanner/react-scanner.d.ts.map +0 -1
- package/dist/core/ui-scanner/react-scanner.js +0 -163
- package/dist/core/ui-scanner/react-scanner.js.map +0 -1
- package/dist/core/ui-scanner/scanner-interface.d.ts +0 -94
- package/dist/core/ui-scanner/scanner-interface.d.ts.map +0 -1
- package/dist/core/ui-scanner/scanner-interface.js +0 -33
- package/dist/core/ui-scanner/scanner-interface.js.map +0 -1
- package/dist/core/ui-scanner/strict-scanner.d.ts +0 -81
- package/dist/core/ui-scanner/strict-scanner.d.ts.map +0 -1
- package/dist/core/ui-scanner/strict-scanner.js +0 -511
- package/dist/core/ui-scanner/strict-scanner.js.map +0 -1
- package/dist/core/validator/data-validator.d.ts +0 -38
- package/dist/core/validator/data-validator.d.ts.map +0 -1
- package/dist/core/validator/data-validator.js +0 -212
- package/dist/core/validator/data-validator.js.map +0 -1
- package/dist/core/validator/feature-validator.d.ts +0 -27
- package/dist/core/validator/feature-validator.d.ts.map +0 -1
- package/dist/core/validator/feature-validator.js +0 -182
- package/dist/core/validator/feature-validator.js.map +0 -1
- package/dist/core/validator/index.d.ts +0 -46
- package/dist/core/validator/index.d.ts.map +0 -1
- package/dist/core/validator/index.js +0 -17
- package/dist/core/validator/index.js.map +0 -1
- package/dist/core/validator/screen-validator.d.ts +0 -35
- package/dist/core/validator/screen-validator.d.ts.map +0 -1
- package/dist/core/validator/screen-validator.js +0 -195
- package/dist/core/validator/screen-validator.js.map +0 -1
- package/dist/core/validator/selector-validator.d.ts +0 -36
- package/dist/core/validator/selector-validator.d.ts.map +0 -1
- package/dist/core/validator/selector-validator.js +0 -210
- package/dist/core/validator/selector-validator.js.map +0 -1
- package/dist/external/ai-provider.d.ts +0 -60
- package/dist/external/ai-provider.d.ts.map +0 -1
- package/dist/external/ai-provider.js +0 -30
- package/dist/external/ai-provider.js.map +0 -1
- package/dist/external/anthropic-provider.d.ts +0 -29
- package/dist/external/anthropic-provider.d.ts.map +0 -1
- package/dist/external/anthropic-provider.js +0 -85
- package/dist/external/anthropic-provider.js.map +0 -1
- package/dist/generators/cache/cache-manager.d.ts +0 -66
- package/dist/generators/cache/cache-manager.d.ts.map +0 -1
- package/dist/generators/cache/cache-manager.js +0 -286
- package/dist/generators/cache/cache-manager.js.map +0 -1
- package/dist/generators/dsl-writer/index.d.ts +0 -33
- package/dist/generators/dsl-writer/index.d.ts.map +0 -1
- package/dist/generators/dsl-writer/index.js +0 -226
- package/dist/generators/dsl-writer/index.js.map +0 -1
- package/dist/generators/scaffold-generator/index.d.ts +0 -162
- package/dist/generators/scaffold-generator/index.d.ts.map +0 -1
- package/dist/generators/scaffold-generator/index.js +0 -868
- package/dist/generators/scaffold-generator/index.js.map +0 -1
- package/dist/generators/selector-mapper/ai-mapper.d.ts +0 -56
- package/dist/generators/selector-mapper/ai-mapper.d.ts.map +0 -1
- package/dist/generators/selector-mapper/ai-mapper.js +0 -457
- package/dist/generators/selector-mapper/ai-mapper.js.map +0 -1
- package/dist/generators/selector-mapper/hybrid-mapper.d.ts +0 -67
- package/dist/generators/selector-mapper/hybrid-mapper.d.ts.map +0 -1
- package/dist/generators/selector-mapper/hybrid-mapper.js +0 -349
- package/dist/generators/selector-mapper/hybrid-mapper.js.map +0 -1
- package/dist/generators/selector-mapper/index.d.ts +0 -8
- package/dist/generators/selector-mapper/index.d.ts.map +0 -1
- package/dist/generators/selector-mapper/index.js +0 -12
- package/dist/generators/selector-mapper/index.js.map +0 -1
- package/dist/generators/selector-mapper/intelligent-mapper.d.ts +0 -125
- package/dist/generators/selector-mapper/intelligent-mapper.d.ts.map +0 -1
- package/dist/generators/selector-mapper/intelligent-mapper.js +0 -391
- package/dist/generators/selector-mapper/intelligent-mapper.js.map +0 -1
- package/dist/generators/test-generator/ai-step-mapper.d.ts +0 -27
- package/dist/generators/test-generator/ai-step-mapper.d.ts.map +0 -1
- package/dist/generators/test-generator/ai-step-mapper.js +0 -204
- package/dist/generators/test-generator/ai-step-mapper.js.map +0 -1
- package/dist/generators/test-generator/auth-setup-generator.d.ts +0 -18
- package/dist/generators/test-generator/auth-setup-generator.d.ts.map +0 -1
- package/dist/generators/test-generator/auth-setup-generator.js +0 -82
- package/dist/generators/test-generator/auth-setup-generator.js.map +0 -1
- package/dist/generators/test-generator/patterns/legacy-patterns.d.ts +0 -7
- package/dist/generators/test-generator/patterns/legacy-patterns.d.ts.map +0 -1
- package/dist/generators/test-generator/patterns/legacy-patterns.js +0 -98
- package/dist/generators/test-generator/patterns/legacy-patterns.js.map +0 -1
- package/dist/generators/test-generator/templates/auth-setup.ts.hbs +0 -36
- package/dist/generators/ui-model-builder/deep-scanner.d.ts +0 -121
- package/dist/generators/ui-model-builder/deep-scanner.d.ts.map +0 -1
- package/dist/generators/ui-model-builder/deep-scanner.js +0 -1113
- package/dist/generators/ui-model-builder/deep-scanner.js.map +0 -1
- package/dist/generators/ui-model-builder/enhanced-deep-scanner.d.ts +0 -110
- package/dist/generators/ui-model-builder/enhanced-deep-scanner.d.ts.map +0 -1
- package/dist/generators/ui-model-builder/enhanced-deep-scanner.js +0 -608
- package/dist/generators/ui-model-builder/enhanced-deep-scanner.js.map +0 -1
- package/dist/generators/ui-model-builder/react-scanner.d.ts +0 -107
- package/dist/generators/ui-model-builder/react-scanner.d.ts.map +0 -1
- package/dist/generators/ui-model-builder/react-scanner.js +0 -797
- package/dist/generators/ui-model-builder/react-scanner.js.map +0 -1
- package/dist/orchestrator/cache-manager.d.ts +0 -15
- package/dist/orchestrator/cache-manager.d.ts.map +0 -1
- package/dist/orchestrator/cache-manager.js +0 -62
- package/dist/orchestrator/cache-manager.js.map +0 -1
- package/dist/orchestrator/pipeline.d.ts +0 -56
- package/dist/orchestrator/pipeline.d.ts.map +0 -1
- package/dist/orchestrator/pipeline.js +0 -298
- package/dist/orchestrator/pipeline.js.map +0 -1
- package/dist/orchestrator/reporter.d.ts +0 -15
- package/dist/orchestrator/reporter.d.ts.map +0 -1
- package/dist/orchestrator/reporter.js +0 -30
- package/dist/orchestrator/reporter.js.map +0 -1
- package/src/cli/commands/cache-clear.ts +0 -22
- package/src/cli/commands/full.ts +0 -35
- package/src/cli/commands/live-scan.ts +0 -82
- package/src/cli/commands/map.ts +0 -97
- package/src/cli/commands/validate.ts +0 -43
- package/src/cli/utils.ts +0 -106
- package/src/config/ai-providers.yaml +0 -56
- package/src/config/config-loader.ts +0 -248
- package/src/config/config-schema.ts +0 -148
- package/src/config/default.config.yaml +0 -107
- package/src/config/framework.config.yaml +0 -52
- package/src/config/routes.yaml +0 -31
- package/src/core/live-scanner/config-reader.ts +0 -57
- package/src/core/live-scanner/element-finder.ts +0 -541
- package/src/core/live-scanner/index.ts +0 -7
- package/src/core/live-scanner/matrix-reader.ts +0 -65
- package/src/core/live-scanner/matrix-writer.ts +0 -77
- package/src/core/live-scanner/role-fallback.ts +0 -43
- package/src/core/live-scanner/scanner.ts +0 -254
- package/src/core/live-scanner/step-replayer.ts +0 -306
- package/src/core/live-scanner/types.ts +0 -58
- package/src/core/selector-base/annotation-handler.ts +0 -127
- package/src/core/selector-base/base-generator.ts +0 -234
- package/src/core/selector-base/gherkin-parser.ts +0 -57
- package/src/core/selector-mapper/priority-mapper.ts +0 -607
- package/src/core/ui-scanner/heuristics/base-heuristic.ts +0 -216
- package/src/core/ui-scanner/react-scanner.ts +0 -156
- package/src/core/ui-scanner/scanner-interface.ts +0 -133
- package/src/core/ui-scanner/strict-scanner.ts +0 -629
- package/src/core/validator/data-validator.ts +0 -202
- package/src/core/validator/feature-validator.ts +0 -176
- package/src/core/validator/index.ts +0 -57
- package/src/core/validator/screen-validator.ts +0 -209
- package/src/core/validator/selector-validator.ts +0 -209
- package/src/external/ai-provider.ts +0 -90
- package/src/external/anthropic-provider.ts +0 -114
- package/src/generators/README.md +0 -410
- package/src/generators/cache/cache-manager.ts +0 -322
- package/src/generators/dsl-writer/index.ts +0 -253
- package/src/generators/scaffold-generator/index.ts +0 -1019
- package/src/generators/selector-mapper/ai-mapper.ts +0 -528
- package/src/generators/selector-mapper/hybrid-mapper.ts +0 -427
- package/src/generators/selector-mapper/index.ts +0 -10
- package/src/generators/selector-mapper/intelligent-mapper.ts +0 -530
- package/src/generators/test-generator/ai-step-mapper.ts +0 -224
- package/src/generators/test-generator/auth-setup-generator.ts +0 -59
- package/src/generators/test-generator/patterns/legacy-patterns.ts +0 -104
- package/src/generators/test-generator/templates/auth-setup.ts.hbs +0 -36
- package/src/generators/ui-model-builder/deep-scanner.ts +0 -1244
- package/src/generators/ui-model-builder/enhanced-deep-scanner.ts +0 -731
- package/src/generators/ui-model-builder/react-scanner.ts +0 -959
- package/src/orchestrator/cache-manager.ts +0 -32
- package/src/orchestrator/pipeline.ts +0 -354
- package/src/orchestrator/reporter.ts +0 -36
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Data Validator
|
|
3
|
-
* Validates test-data YAML files and checks referenced data paths exist
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import * as fs from 'fs';
|
|
7
|
-
import * as path from 'path';
|
|
8
|
-
import yaml from 'yaml';
|
|
9
|
-
import { ValidationIssue } from './index';
|
|
10
|
-
|
|
11
|
-
type DataFile = Record<string, unknown>;
|
|
12
|
-
|
|
13
|
-
export class DataValidator {
|
|
14
|
-
private screenName: string;
|
|
15
|
-
private baseDir: string;
|
|
16
|
-
private dataCache = new Map<string, DataFile>();
|
|
17
|
-
|
|
18
|
-
constructor(screenName: string, baseDir?: string) {
|
|
19
|
-
this.screenName = screenName;
|
|
20
|
-
this.baseDir = baseDir || process.cwd();
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Validate test-data file for a feature
|
|
25
|
-
*/
|
|
26
|
-
validateFile(featureName: string): { errors: ValidationIssue[]; warnings: ValidationIssue[] } {
|
|
27
|
-
const errors: ValidationIssue[] = [];
|
|
28
|
-
const warnings: ValidationIssue[] = [];
|
|
29
|
-
|
|
30
|
-
const filePath = this.findDataPath(featureName);
|
|
31
|
-
|
|
32
|
-
if (!filePath) {
|
|
33
|
-
// Data file is optional - only warn if there are data refs
|
|
34
|
-
return { errors, warnings };
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Load and parse YAML
|
|
38
|
-
let content: string;
|
|
39
|
-
let data: DataFile;
|
|
40
|
-
|
|
41
|
-
try {
|
|
42
|
-
content = fs.readFileSync(filePath, 'utf-8');
|
|
43
|
-
} catch (error) {
|
|
44
|
-
errors.push({
|
|
45
|
-
type: 'error',
|
|
46
|
-
code: 'INVALID_YAML_SYNTAX',
|
|
47
|
-
message: `Cannot read file: ${(error as Error).message}`,
|
|
48
|
-
file: filePath,
|
|
49
|
-
});
|
|
50
|
-
return { errors, warnings };
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
try {
|
|
54
|
-
data = yaml.parse(content) as DataFile;
|
|
55
|
-
} catch (error) {
|
|
56
|
-
errors.push({
|
|
57
|
-
type: 'error',
|
|
58
|
-
code: 'INVALID_YAML_SYNTAX',
|
|
59
|
-
message: `YAML parse error: ${(error as Error).message}`,
|
|
60
|
-
file: filePath,
|
|
61
|
-
});
|
|
62
|
-
return { errors, warnings };
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (data && typeof data !== 'object') {
|
|
66
|
-
errors.push({
|
|
67
|
-
type: 'error',
|
|
68
|
-
code: 'INVALID_YAML_SYNTAX',
|
|
69
|
-
message: 'Test data file must be a valid YAML object',
|
|
70
|
-
file: filePath,
|
|
71
|
-
});
|
|
72
|
-
return { errors, warnings };
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Cache for later ref validation
|
|
76
|
-
this.dataCache.set(featureName, data || {});
|
|
77
|
-
|
|
78
|
-
return { errors, warnings };
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Check if data references exist and resolve to primitives
|
|
83
|
-
*/
|
|
84
|
-
validateRefs(
|
|
85
|
-
featureName: string,
|
|
86
|
-
refs: Array<{ ref: string; line: number }>,
|
|
87
|
-
featureFile: string
|
|
88
|
-
): ValidationIssue[] {
|
|
89
|
-
const errors: ValidationIssue[] = [];
|
|
90
|
-
|
|
91
|
-
if (refs.length === 0) {
|
|
92
|
-
return errors;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Load data if not cached
|
|
96
|
-
if (!this.dataCache.has(featureName)) {
|
|
97
|
-
const filePath = this.findDataPath(featureName);
|
|
98
|
-
if (!filePath) {
|
|
99
|
-
// Data file doesn't exist but we have refs - error
|
|
100
|
-
for (const { ref, line } of refs) {
|
|
101
|
-
errors.push({
|
|
102
|
-
type: 'error',
|
|
103
|
-
code: 'MISSING_DATA_FILE',
|
|
104
|
-
message: `Test data file not found for feature "${featureName}" (needed for {{${ref}}})`,
|
|
105
|
-
file: featureFile,
|
|
106
|
-
line,
|
|
107
|
-
element: ref,
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
return errors;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
try {
|
|
114
|
-
const content = fs.readFileSync(filePath, 'utf-8');
|
|
115
|
-
const data = yaml.parse(content) as DataFile;
|
|
116
|
-
this.dataCache.set(featureName, data || {});
|
|
117
|
-
} catch {
|
|
118
|
-
// Error already reported in validateFile
|
|
119
|
-
return errors;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const data = this.dataCache.get(featureName);
|
|
124
|
-
if (!data) {
|
|
125
|
-
return errors;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Check each ref
|
|
129
|
-
for (const { ref, line } of refs) {
|
|
130
|
-
const result = this.resolvePath(data, ref);
|
|
131
|
-
|
|
132
|
-
if (!result.found) {
|
|
133
|
-
errors.push({
|
|
134
|
-
type: 'error',
|
|
135
|
-
code: 'MISSING_DATA_REF',
|
|
136
|
-
message: `Data {{${ref}}} not found in test-data/${featureName}.yaml (failed at: ${result.failedAt})`,
|
|
137
|
-
file: featureFile,
|
|
138
|
-
line,
|
|
139
|
-
element: ref,
|
|
140
|
-
});
|
|
141
|
-
} else if (!this.isPrimitive(result.value)) {
|
|
142
|
-
errors.push({
|
|
143
|
-
type: 'error',
|
|
144
|
-
code: 'INVALID_DATA_VALUE',
|
|
145
|
-
message: `Data {{${ref}}} must resolve to a primitive value, got: ${typeof result.value}`,
|
|
146
|
-
file: featureFile,
|
|
147
|
-
line,
|
|
148
|
-
element: ref,
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
return errors;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Resolve dotted path in data object
|
|
158
|
-
*/
|
|
159
|
-
private resolvePath(data: DataFile, ref: string): { found: boolean; value?: unknown; failedAt?: string } {
|
|
160
|
-
const parts = ref.split('.');
|
|
161
|
-
let current: unknown = data;
|
|
162
|
-
|
|
163
|
-
for (const key of parts) {
|
|
164
|
-
if (current && typeof current === 'object' && key in (current as Record<string, unknown>)) {
|
|
165
|
-
current = (current as Record<string, unknown>)[key];
|
|
166
|
-
} else {
|
|
167
|
-
return { found: false, failedAt: key };
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
return { found: true, value: current };
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* Check if value is a primitive (string, number, boolean)
|
|
176
|
-
*/
|
|
177
|
-
private isPrimitive(value: unknown): boolean {
|
|
178
|
-
return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean';
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Find test-data file path
|
|
183
|
-
*/
|
|
184
|
-
private findDataPath(featureName: string): string | null {
|
|
185
|
-
const possiblePaths = [
|
|
186
|
-
// New structure
|
|
187
|
-
path.join(this.baseDir, 'qa', 'screens', this.screenName, 'test-data', `${featureName}.yaml`),
|
|
188
|
-
path.join(this.baseDir, 'qa', 'screens', this.screenName, 'test-data', `${featureName}.yml`),
|
|
189
|
-
// Legacy structure
|
|
190
|
-
path.join(this.baseDir, 'qa', 'test-data', `${featureName}.yaml`),
|
|
191
|
-
path.join(this.baseDir, 'qa', 'test-data', `${featureName}.yml`),
|
|
192
|
-
];
|
|
193
|
-
|
|
194
|
-
for (const p of possiblePaths) {
|
|
195
|
-
if (fs.existsSync(p)) {
|
|
196
|
-
return p;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
return null;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Feature Validator
|
|
3
|
-
* Validates Gherkin feature files and extracts selector/data references
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import * as fs from 'fs';
|
|
7
|
-
import * as Gherkin from '@cucumber/gherkin';
|
|
8
|
-
import * as Messages from '@cucumber/messages';
|
|
9
|
-
import { ValidationIssue, ExtractedRefs } from './index';
|
|
10
|
-
|
|
11
|
-
export interface FeatureValidationResult {
|
|
12
|
-
valid: boolean;
|
|
13
|
-
errors: ValidationIssue[];
|
|
14
|
-
warnings: ValidationIssue[];
|
|
15
|
-
path?: string; // Extracted Path metadata
|
|
16
|
-
refs: ExtractedRefs;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export class FeatureValidator {
|
|
20
|
-
private builder: Gherkin.AstBuilder;
|
|
21
|
-
private matcher: Gherkin.GherkinClassicTokenMatcher;
|
|
22
|
-
// @ts-ignore - Parser typing issue with @cucumber/gherkin
|
|
23
|
-
private parser: Gherkin.Parser;
|
|
24
|
-
|
|
25
|
-
constructor() {
|
|
26
|
-
const uuidFn = Messages.IdGenerator.uuid();
|
|
27
|
-
this.builder = new Gherkin.AstBuilder(uuidFn);
|
|
28
|
-
this.matcher = new Gherkin.GherkinClassicTokenMatcher();
|
|
29
|
-
// @ts-ignore - Parser typing issue with @cucumber/gherkin
|
|
30
|
-
this.parser = new Gherkin.Parser(this.builder, this.matcher);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Validate a feature file
|
|
35
|
-
*/
|
|
36
|
-
validate(filePath: string): FeatureValidationResult {
|
|
37
|
-
const errors: ValidationIssue[] = [];
|
|
38
|
-
const warnings: ValidationIssue[] = [];
|
|
39
|
-
const refs: ExtractedRefs = { selectors: [], dataRefs: [] };
|
|
40
|
-
let path: string | undefined;
|
|
41
|
-
|
|
42
|
-
// Check file exists
|
|
43
|
-
if (!fs.existsSync(filePath)) {
|
|
44
|
-
errors.push({
|
|
45
|
-
type: 'error',
|
|
46
|
-
code: 'GHERKIN_SYNTAX_ERROR',
|
|
47
|
-
message: `Feature file not found: ${filePath}`,
|
|
48
|
-
file: filePath,
|
|
49
|
-
});
|
|
50
|
-
return { valid: false, errors, warnings, refs };
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Read and parse content
|
|
54
|
-
let content: string;
|
|
55
|
-
try {
|
|
56
|
-
content = fs.readFileSync(filePath, 'utf-8');
|
|
57
|
-
} catch (error) {
|
|
58
|
-
errors.push({
|
|
59
|
-
type: 'error',
|
|
60
|
-
code: 'GHERKIN_SYNTAX_ERROR',
|
|
61
|
-
message: `Cannot read file: ${(error as Error).message}`,
|
|
62
|
-
file: filePath,
|
|
63
|
-
});
|
|
64
|
-
return { valid: false, errors, warnings, refs };
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Parse Gherkin
|
|
68
|
-
let gherkinDocument: Messages.GherkinDocument;
|
|
69
|
-
try {
|
|
70
|
-
gherkinDocument = this.parser.parse(content);
|
|
71
|
-
} catch (error) {
|
|
72
|
-
const errMsg = (error as Error).message;
|
|
73
|
-
// Try to extract line number from error message
|
|
74
|
-
const lineMatch = errMsg.match(/\((\d+):\d+\)/);
|
|
75
|
-
const line = lineMatch ? parseInt(lineMatch[1], 10) : undefined;
|
|
76
|
-
|
|
77
|
-
errors.push({
|
|
78
|
-
type: 'error',
|
|
79
|
-
code: 'GHERKIN_SYNTAX_ERROR',
|
|
80
|
-
message: `Gherkin parse error: ${errMsg}`,
|
|
81
|
-
file: filePath,
|
|
82
|
-
line,
|
|
83
|
-
});
|
|
84
|
-
return { valid: false, errors, warnings, refs };
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Check feature exists
|
|
88
|
-
if (!gherkinDocument.feature) {
|
|
89
|
-
errors.push({
|
|
90
|
-
type: 'error',
|
|
91
|
-
code: 'EMPTY_FEATURE',
|
|
92
|
-
message: 'No feature found in file',
|
|
93
|
-
file: filePath,
|
|
94
|
-
});
|
|
95
|
-
return { valid: false, errors, warnings, refs };
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const feature = gherkinDocument.feature;
|
|
99
|
-
|
|
100
|
-
// Extract Path metadata
|
|
101
|
-
const description = feature.description || '';
|
|
102
|
-
const pathMatch = description.match(/^\s*Path:\s*(.+)$/m);
|
|
103
|
-
if (pathMatch) {
|
|
104
|
-
path = pathMatch[1].trim();
|
|
105
|
-
} else {
|
|
106
|
-
warnings.push({
|
|
107
|
-
type: 'warning',
|
|
108
|
-
code: 'MISSING_PATH_METADATA',
|
|
109
|
-
message: 'Missing Path: metadata in feature description',
|
|
110
|
-
file: filePath,
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Extract refs from background
|
|
115
|
-
const background = feature.children.find(child => child.background)?.background;
|
|
116
|
-
if (background) {
|
|
117
|
-
this.extractRefsFromSteps(background.steps, filePath, refs);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// Extract refs from scenarios
|
|
121
|
-
for (const child of feature.children) {
|
|
122
|
-
if (child.scenario) {
|
|
123
|
-
this.extractRefsFromSteps(child.scenario.steps, filePath, refs);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return {
|
|
128
|
-
valid: errors.length === 0,
|
|
129
|
-
errors,
|
|
130
|
-
warnings,
|
|
131
|
-
path,
|
|
132
|
-
refs,
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Extract selector and data references from steps
|
|
138
|
-
*/
|
|
139
|
-
private extractRefsFromSteps(
|
|
140
|
-
steps: readonly Messages.Step[],
|
|
141
|
-
filePath: string,
|
|
142
|
-
refs: ExtractedRefs
|
|
143
|
-
): void {
|
|
144
|
-
for (const step of steps) {
|
|
145
|
-
const text = step.text;
|
|
146
|
-
const line = step.location?.line;
|
|
147
|
-
|
|
148
|
-
// Extract selector references: [Element Name]
|
|
149
|
-
const selectorMatches = text.matchAll(/\[([^\]]+)\]/g);
|
|
150
|
-
for (const match of selectorMatches) {
|
|
151
|
-
refs.selectors.push({
|
|
152
|
-
ref: match[1],
|
|
153
|
-
line: line || 0,
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// Extract data references: {{variable}} or {{path.to.value}}
|
|
158
|
-
const dataMatches = text.matchAll(/\{\{([a-zA-Z0-9\-\.\_]+)\}\}/g);
|
|
159
|
-
for (const match of dataMatches) {
|
|
160
|
-
refs.dataRefs.push({
|
|
161
|
-
ref: match[1],
|
|
162
|
-
line: line || 0,
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// Legacy format: <variable>
|
|
167
|
-
const legacyDataMatches = text.matchAll(/<([^>]+)>/g);
|
|
168
|
-
for (const match of legacyDataMatches) {
|
|
169
|
-
refs.dataRefs.push({
|
|
170
|
-
ref: match[1],
|
|
171
|
-
line: line || 0,
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Validator Core - Types and Exports
|
|
3
|
-
* Validates Gherkin features and selector/test-data mappings
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export interface ValidationIssue {
|
|
7
|
-
type: 'error' | 'warning';
|
|
8
|
-
code: ValidationCode;
|
|
9
|
-
message: string;
|
|
10
|
-
file: string;
|
|
11
|
-
line?: number;
|
|
12
|
-
element?: string; // The [element] or {{variable}} that caused the issue
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface ValidationSummary {
|
|
16
|
-
totalFiles: number;
|
|
17
|
-
passedFiles: number;
|
|
18
|
-
failedFiles: number;
|
|
19
|
-
totalErrors: number;
|
|
20
|
-
totalWarnings: number;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface FileValidationResult {
|
|
24
|
-
file: string;
|
|
25
|
-
valid: boolean;
|
|
26
|
-
errors: ValidationIssue[];
|
|
27
|
-
warnings: ValidationIssue[];
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface ValidationResult {
|
|
31
|
-
valid: boolean;
|
|
32
|
-
summary: ValidationSummary;
|
|
33
|
-
results: FileValidationResult[];
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export type ValidationCode =
|
|
37
|
-
| 'GHERKIN_SYNTAX_ERROR'
|
|
38
|
-
| 'MISSING_PATH_METADATA'
|
|
39
|
-
| 'MISSING_SELECTOR_FILE'
|
|
40
|
-
| 'MISSING_SELECTOR'
|
|
41
|
-
| 'MISSING_DATA_FILE'
|
|
42
|
-
| 'MISSING_DATA_REF'
|
|
43
|
-
| 'INVALID_YAML_SYNTAX'
|
|
44
|
-
| 'INVALID_SELECTOR_TYPE'
|
|
45
|
-
| 'INVALID_DATA_VALUE'
|
|
46
|
-
| 'EMPTY_FEATURE';
|
|
47
|
-
|
|
48
|
-
export interface ExtractedRefs {
|
|
49
|
-
selectors: Array<{ ref: string; line: number }>;
|
|
50
|
-
dataRefs: Array<{ ref: string; line: number }>;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Re-exports
|
|
54
|
-
export { FeatureValidator } from './feature-validator';
|
|
55
|
-
export { SelectorValidator } from './selector-validator';
|
|
56
|
-
export { DataValidator } from './data-validator';
|
|
57
|
-
export { ScreenValidator } from './screen-validator';
|
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Screen Validator
|
|
3
|
-
* Orchestrates validation for a screen (all features in qa/screens/<name>/)
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import * as fs from 'fs';
|
|
7
|
-
import * as path from 'path';
|
|
8
|
-
import {
|
|
9
|
-
ValidationResult,
|
|
10
|
-
FileValidationResult,
|
|
11
|
-
ValidationSummary,
|
|
12
|
-
ValidationIssue,
|
|
13
|
-
} from './index';
|
|
14
|
-
import { FeatureValidator } from './feature-validator';
|
|
15
|
-
import { SelectorValidator } from './selector-validator';
|
|
16
|
-
import { DataValidator } from './data-validator';
|
|
17
|
-
|
|
18
|
-
export interface ScreenValidatorOptions {
|
|
19
|
-
verbose?: boolean;
|
|
20
|
-
baseDir?: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export class ScreenValidator {
|
|
24
|
-
private baseDir: string;
|
|
25
|
-
private verbose: boolean;
|
|
26
|
-
|
|
27
|
-
constructor(options: ScreenValidatorOptions = {}) {
|
|
28
|
-
this.baseDir = options.baseDir || process.cwd();
|
|
29
|
-
this.verbose = options.verbose || false;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Validate a specific screen
|
|
34
|
-
*/
|
|
35
|
-
validateScreen(screenName: string): ValidationResult {
|
|
36
|
-
const results: FileValidationResult[] = [];
|
|
37
|
-
|
|
38
|
-
const screenDir = path.join(this.baseDir, 'qa', 'screens', screenName);
|
|
39
|
-
const featuresDir = path.join(screenDir, 'features');
|
|
40
|
-
|
|
41
|
-
// Check if screen exists
|
|
42
|
-
if (!fs.existsSync(screenDir)) {
|
|
43
|
-
return this.createErrorResult(`Screen "${screenName}" not found at ${screenDir}`);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (!fs.existsSync(featuresDir)) {
|
|
47
|
-
return this.createErrorResult(`Features directory not found at ${featuresDir}`);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Find all feature files
|
|
51
|
-
const featureFiles = this.discoverFeatureFiles(featuresDir);
|
|
52
|
-
|
|
53
|
-
if (featureFiles.length === 0) {
|
|
54
|
-
return this.createErrorResult(`No .feature files found in ${featuresDir}`);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Initialize validators
|
|
58
|
-
const featureValidator = new FeatureValidator();
|
|
59
|
-
const selectorValidator = new SelectorValidator(screenName, this.baseDir);
|
|
60
|
-
const dataValidator = new DataValidator(screenName, this.baseDir);
|
|
61
|
-
|
|
62
|
-
// Validate each feature file
|
|
63
|
-
for (const featureFile of featureFiles) {
|
|
64
|
-
const featureName = path.basename(featureFile, '.feature');
|
|
65
|
-
const relativeFile = path.relative(this.baseDir, featureFile);
|
|
66
|
-
|
|
67
|
-
const fileResult: FileValidationResult = {
|
|
68
|
-
file: relativeFile,
|
|
69
|
-
valid: true,
|
|
70
|
-
errors: [],
|
|
71
|
-
warnings: [],
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
// 1. Validate Gherkin syntax and extract refs
|
|
75
|
-
const featureResult = featureValidator.validate(featureFile);
|
|
76
|
-
fileResult.errors.push(...featureResult.errors);
|
|
77
|
-
fileResult.warnings.push(...featureResult.warnings);
|
|
78
|
-
|
|
79
|
-
// 2. Validate selector file
|
|
80
|
-
const selectorFileResult = selectorValidator.validateFile(featureName);
|
|
81
|
-
fileResult.errors.push(...selectorFileResult.errors);
|
|
82
|
-
fileResult.warnings.push(...selectorFileResult.warnings);
|
|
83
|
-
|
|
84
|
-
// 3. Validate selector refs exist
|
|
85
|
-
if (featureResult.refs.selectors.length > 0) {
|
|
86
|
-
const selectorRefErrors = selectorValidator.validateRefs(
|
|
87
|
-
featureName,
|
|
88
|
-
featureResult.refs.selectors,
|
|
89
|
-
relativeFile
|
|
90
|
-
);
|
|
91
|
-
fileResult.errors.push(...selectorRefErrors);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// 4. Validate data file
|
|
95
|
-
const dataFileResult = dataValidator.validateFile(featureName);
|
|
96
|
-
fileResult.errors.push(...dataFileResult.errors);
|
|
97
|
-
fileResult.warnings.push(...dataFileResult.warnings);
|
|
98
|
-
|
|
99
|
-
// 5. Validate data refs exist
|
|
100
|
-
if (featureResult.refs.dataRefs.length > 0) {
|
|
101
|
-
const dataRefErrors = dataValidator.validateRefs(
|
|
102
|
-
featureName,
|
|
103
|
-
featureResult.refs.dataRefs,
|
|
104
|
-
relativeFile
|
|
105
|
-
);
|
|
106
|
-
fileResult.errors.push(...dataRefErrors);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Update validity
|
|
110
|
-
fileResult.valid = fileResult.errors.length === 0;
|
|
111
|
-
results.push(fileResult);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return this.buildResult(results);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Validate all screens
|
|
119
|
-
*/
|
|
120
|
-
validateAll(): ValidationResult {
|
|
121
|
-
const screensDir = path.join(this.baseDir, 'qa', 'screens');
|
|
122
|
-
|
|
123
|
-
if (!fs.existsSync(screensDir)) {
|
|
124
|
-
return this.createErrorResult(`Screens directory not found at ${screensDir}`);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const screens = fs.readdirSync(screensDir, { withFileTypes: true })
|
|
128
|
-
.filter(entry => entry.isDirectory())
|
|
129
|
-
.map(entry => entry.name);
|
|
130
|
-
|
|
131
|
-
if (screens.length === 0) {
|
|
132
|
-
return this.createErrorResult(`No screens found in ${screensDir}`);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const allResults: FileValidationResult[] = [];
|
|
136
|
-
|
|
137
|
-
for (const screenName of screens) {
|
|
138
|
-
const screenResult = this.validateScreen(screenName);
|
|
139
|
-
allResults.push(...screenResult.results);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
return this.buildResult(allResults);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Discover .feature files in a directory
|
|
147
|
-
*/
|
|
148
|
-
private discoverFeatureFiles(dir: string): string[] {
|
|
149
|
-
const files: string[] = [];
|
|
150
|
-
|
|
151
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
152
|
-
for (const entry of entries) {
|
|
153
|
-
const fullPath = path.join(dir, entry.name);
|
|
154
|
-
if (entry.isDirectory()) {
|
|
155
|
-
files.push(...this.discoverFeatureFiles(fullPath));
|
|
156
|
-
} else if (entry.isFile() && entry.name.endsWith('.feature')) {
|
|
157
|
-
files.push(fullPath);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
return files;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Build final validation result
|
|
166
|
-
*/
|
|
167
|
-
private buildResult(results: FileValidationResult[]): ValidationResult {
|
|
168
|
-
const summary: ValidationSummary = {
|
|
169
|
-
totalFiles: results.length,
|
|
170
|
-
passedFiles: results.filter(r => r.valid).length,
|
|
171
|
-
failedFiles: results.filter(r => !r.valid).length,
|
|
172
|
-
totalErrors: results.reduce((sum, r) => sum + r.errors.length, 0),
|
|
173
|
-
totalWarnings: results.reduce((sum, r) => sum + r.warnings.length, 0),
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
return {
|
|
177
|
-
valid: summary.failedFiles === 0,
|
|
178
|
-
summary,
|
|
179
|
-
results,
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Create error result for invalid setup
|
|
185
|
-
*/
|
|
186
|
-
private createErrorResult(message: string): ValidationResult {
|
|
187
|
-
return {
|
|
188
|
-
valid: false,
|
|
189
|
-
summary: {
|
|
190
|
-
totalFiles: 0,
|
|
191
|
-
passedFiles: 0,
|
|
192
|
-
failedFiles: 0,
|
|
193
|
-
totalErrors: 1,
|
|
194
|
-
totalWarnings: 0,
|
|
195
|
-
},
|
|
196
|
-
results: [{
|
|
197
|
-
file: '',
|
|
198
|
-
valid: false,
|
|
199
|
-
errors: [{
|
|
200
|
-
type: 'error',
|
|
201
|
-
code: 'GHERKIN_SYNTAX_ERROR',
|
|
202
|
-
message,
|
|
203
|
-
file: '',
|
|
204
|
-
}],
|
|
205
|
-
warnings: [],
|
|
206
|
-
}],
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
|
-
}
|