@sun-asterisk/sungen 1.0.19 → 1.0.21
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 +3 -3
- package/dist/cli/commands/add.d.ts +3 -0
- package/dist/cli/commands/add.d.ts.map +1 -0
- package/dist/cli/commands/add.js +27 -0
- package/dist/cli/commands/add.js.map +1 -0
- package/dist/cli/commands/cache-clear.d.ts +3 -0
- package/dist/cli/commands/cache-clear.d.ts.map +1 -0
- package/dist/cli/commands/cache-clear.js +24 -0
- package/dist/cli/commands/cache-clear.js.map +1 -0
- package/dist/cli/commands/full.d.ts +3 -0
- package/dist/cli/commands/full.d.ts.map +1 -0
- package/dist/cli/commands/full.js +37 -0
- package/dist/cli/commands/full.js.map +1 -0
- package/dist/cli/commands/generate.d.ts +3 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +53 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/commands/init.d.ts +3 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +20 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/live-scan.d.ts +3 -0
- package/dist/cli/commands/live-scan.d.ts.map +1 -0
- package/dist/cli/commands/{live-scan-command.js → live-scan.js} +22 -16
- package/dist/cli/commands/live-scan.js.map +1 -0
- package/dist/cli/commands/makeauth.d.ts +3 -0
- package/dist/cli/commands/makeauth.d.ts.map +1 -0
- package/dist/cli/commands/makeauth.js +76 -0
- package/dist/cli/commands/makeauth.js.map +1 -0
- package/dist/cli/commands/map.d.ts +3 -0
- package/dist/cli/commands/map.d.ts.map +1 -0
- package/dist/cli/commands/map.js +93 -0
- package/dist/cli/commands/map.js.map +1 -0
- package/dist/cli/commands/validate.d.ts +3 -0
- package/dist/cli/commands/validate.d.ts.map +1 -0
- package/dist/cli/commands/validate.js +43 -0
- package/dist/cli/commands/validate.js.map +1 -0
- package/dist/cli/index.js +29 -442
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/types.d.ts +9 -0
- package/dist/cli/types.d.ts.map +1 -0
- package/dist/cli/types.js +7 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/cli/utils.d.ts +6 -0
- package/dist/cli/utils.d.ts.map +1 -0
- package/dist/cli/utils.js +101 -0
- package/dist/cli/utils.js.map +1 -0
- package/dist/core/live-scanner/matrix-reader.d.ts.map +1 -1
- package/dist/core/live-scanner/matrix-reader.js +2 -40
- package/dist/core/live-scanner/matrix-reader.js.map +1 -1
- package/dist/core/live-scanner/scanner.d.ts.map +1 -1
- package/dist/core/live-scanner/scanner.js +22 -4
- package/dist/core/live-scanner/scanner.js.map +1 -1
- package/dist/core/live-scanner/step-replayer.d.ts +1 -1
- package/dist/core/live-scanner/step-replayer.d.ts.map +1 -1
- package/dist/core/live-scanner/step-replayer.js +107 -6
- package/dist/core/live-scanner/step-replayer.js.map +1 -1
- package/dist/core/live-scanner/types.d.ts +1 -0
- package/dist/core/live-scanner/types.d.ts.map +1 -1
- package/dist/core/validator/selector-validator.d.ts.map +1 -1
- package/dist/core/validator/selector-validator.js +2 -1
- package/dist/core/validator/selector-validator.js.map +1 -1
- package/dist/generators/scaffold-generator/index.d.ts +2 -1
- package/dist/generators/scaffold-generator/index.d.ts.map +1 -1
- package/dist/generators/scaffold-generator/index.js +21 -1
- package/dist/generators/scaffold-generator/index.js.map +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/click-select-action.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/wait-for-role-with-data.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/wait-for-role.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/checked-assertion.hbs +2 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/column-cell-assertion.hbs +3 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/contain-text-assertion.hbs +2 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/count-assertion.hbs +2 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-assertion.hbs +2 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-filter-assertion.hbs +2 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-role-variable-assertion.hbs +4 -3
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-variable-assertion.hbs +2 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/empty-assertion.hbs +2 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/enabled-assertion.hbs +2 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/focused-assertion.hbs +2 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/have-text-assertion.hbs +2 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-dialog-heading-assertion.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-filter-assertion.hbs +2 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-role-variable-assertion.hbs +4 -3
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-variable-assertion.hbs +2 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/is-hidden-assertion.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/list-item-count-assertion.hbs +2 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/not-checked-assertion.hbs +2 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/page-assertion.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-assertion.hbs +2 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-dialog-heading-assertion.hbs +2 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-locator-variable-assertion.hbs +2 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-role-variable-assertion.hbs +4 -3
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-value-assertion.hbs +2 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-variable-assertion.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/navigation/navigation.hbs +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/navigation/wait-for-element-with-text.hbs +1 -1
- package/dist/generators/test-generator/patterns/assertion-patterns.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/assertion-patterns.js +95 -58
- package/dist/generators/test-generator/patterns/assertion-patterns.js.map +1 -1
- package/dist/generators/test-generator/patterns/form-patterns.d.ts +0 -2
- package/dist/generators/test-generator/patterns/form-patterns.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/form-patterns.js +34 -47
- package/dist/generators/test-generator/patterns/form-patterns.js.map +1 -1
- package/dist/generators/test-generator/patterns/index.d.ts +3 -1
- package/dist/generators/test-generator/patterns/index.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/index.js +20 -3
- package/dist/generators/test-generator/patterns/index.js.map +1 -1
- package/dist/generators/test-generator/patterns/interaction-patterns.d.ts +0 -1
- package/dist/generators/test-generator/patterns/interaction-patterns.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/interaction-patterns.js +44 -85
- package/dist/generators/test-generator/patterns/interaction-patterns.js.map +1 -1
- package/dist/generators/test-generator/patterns/legacy-patterns.d.ts +7 -0
- package/dist/generators/test-generator/patterns/legacy-patterns.d.ts.map +1 -0
- package/dist/generators/test-generator/patterns/legacy-patterns.js +98 -0
- package/dist/generators/test-generator/patterns/legacy-patterns.js.map +1 -0
- package/dist/generators/test-generator/patterns/navigation-patterns.d.ts +0 -2
- package/dist/generators/test-generator/patterns/navigation-patterns.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/navigation-patterns.js +14 -42
- package/dist/generators/test-generator/patterns/navigation-patterns.js.map +1 -1
- package/dist/generators/test-generator/patterns/setup-patterns.d.ts +0 -1
- package/dist/generators/test-generator/patterns/setup-patterns.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/setup-patterns.js +23 -35
- package/dist/generators/test-generator/patterns/setup-patterns.js.map +1 -1
- package/dist/generators/test-generator/patterns/types.d.ts +18 -3
- package/dist/generators/test-generator/patterns/types.d.ts.map +1 -1
- package/dist/generators/test-generator/step-mapper.d.ts +0 -15
- package/dist/generators/test-generator/step-mapper.d.ts.map +1 -1
- package/dist/generators/test-generator/step-mapper.js +4 -106
- package/dist/generators/test-generator/step-mapper.js.map +1 -1
- package/dist/{executor/test-generator.d.ts → generators/test-generator/types.d.ts} +4 -25
- package/dist/generators/test-generator/types.d.ts.map +1 -0
- package/dist/generators/test-generator/types.js +106 -0
- package/dist/generators/test-generator/types.js.map +1 -0
- package/dist/generators/test-generator/utils/data-resolver.d.ts.map +1 -1
- package/dist/generators/test-generator/utils/data-resolver.js +8 -17
- package/dist/generators/test-generator/utils/data-resolver.js.map +1 -1
- package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
- package/dist/generators/test-generator/utils/selector-resolver.js +10 -18
- package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -1
- package/dist/orchestrator/cache-manager.d.ts +1 -23
- package/dist/orchestrator/cache-manager.d.ts.map +1 -1
- package/dist/orchestrator/cache-manager.js +1 -87
- package/dist/orchestrator/cache-manager.js.map +1 -1
- package/dist/orchestrator/pipeline.d.ts +11 -28
- package/dist/orchestrator/pipeline.d.ts.map +1 -1
- package/dist/orchestrator/pipeline.js +52 -371
- package/dist/orchestrator/pipeline.js.map +1 -1
- package/dist/orchestrator/reporter.d.ts +1 -1
- package/dist/orchestrator/reporter.d.ts.map +1 -1
- package/dist/orchestrator/screen-manager.js +1 -1
- package/dist/orchestrator/screen-manager.js.map +1 -1
- package/dist/utils/feature-finder.d.ts +9 -0
- package/dist/utils/feature-finder.d.ts.map +1 -0
- package/dist/utils/feature-finder.js +67 -0
- package/dist/utils/feature-finder.js.map +1 -0
- package/dist/utils/screen-paths.d.ts +10 -0
- package/dist/utils/screen-paths.d.ts.map +1 -0
- package/dist/utils/screen-paths.js +73 -0
- package/dist/utils/screen-paths.js.map +1 -0
- package/dist/utils/selector-loader.d.ts +6 -0
- package/dist/utils/selector-loader.d.ts.map +1 -0
- package/dist/utils/selector-loader.js +20 -0
- package/dist/utils/selector-loader.js.map +1 -0
- package/dist/utils/selector-types.d.ts +7 -0
- package/dist/utils/selector-types.d.ts.map +1 -0
- package/dist/utils/selector-types.js +19 -0
- package/dist/utils/selector-types.js.map +1 -0
- package/dist/utils/test-data-loader.d.ts +6 -0
- package/dist/utils/test-data-loader.d.ts.map +1 -0
- package/dist/utils/test-data-loader.js +20 -0
- package/dist/utils/test-data-loader.js.map +1 -0
- package/dist/utils/yaml-io.d.ts +14 -0
- package/dist/utils/yaml-io.d.ts.map +1 -0
- package/dist/utils/yaml-io.js +72 -0
- package/dist/utils/yaml-io.js.map +1 -0
- package/package.json +1 -1
- package/src/cli/commands/add.ts +25 -0
- package/src/cli/commands/cache-clear.ts +22 -0
- package/src/cli/commands/full.ts +35 -0
- package/src/cli/commands/generate.ts +55 -0
- package/src/cli/commands/init.ts +17 -0
- package/src/cli/commands/{live-scan-command.ts → live-scan.ts} +21 -18
- package/src/cli/commands/makeauth.ts +77 -0
- package/src/cli/commands/map.ts +97 -0
- package/src/cli/commands/validate.ts +43 -0
- package/src/cli/index.ts +32 -473
- package/src/cli/types.ts +9 -0
- package/src/cli/utils.ts +106 -0
- package/src/core/live-scanner/matrix-reader.ts +2 -8
- package/src/core/live-scanner/scanner.ts +27 -4
- package/src/core/live-scanner/step-replayer.ts +92 -6
- package/src/core/live-scanner/types.ts +1 -0
- package/src/core/validator/selector-validator.ts +3 -2
- package/src/generators/scaffold-generator/index.ts +23 -2
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/click-select-action.hbs +2 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/wait-for-role-with-data.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/wait-for-role.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/checked-assertion.hbs +2 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/column-cell-assertion.hbs +3 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/contain-text-assertion.hbs +2 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/count-assertion.hbs +2 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-assertion.hbs +2 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-filter-assertion.hbs +2 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-role-variable-assertion.hbs +4 -3
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-variable-assertion.hbs +2 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/empty-assertion.hbs +2 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/enabled-assertion.hbs +2 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/focused-assertion.hbs +2 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/have-text-assertion.hbs +2 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-dialog-heading-assertion.hbs +2 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-filter-assertion.hbs +2 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-role-variable-assertion.hbs +4 -3
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-variable-assertion.hbs +2 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/is-hidden-assertion.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/list-item-count-assertion.hbs +2 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/not-checked-assertion.hbs +2 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/page-assertion.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-assertion.hbs +2 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-dialog-heading-assertion.hbs +2 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-locator-variable-assertion.hbs +2 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-role-variable-assertion.hbs +4 -3
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-value-assertion.hbs +2 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-variable-assertion.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/navigation/navigation.hbs +1 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/navigation/wait-for-element-with-text.hbs +1 -1
- package/src/generators/test-generator/patterns/assertion-patterns.ts +102 -62
- package/src/generators/test-generator/patterns/form-patterns.ts +38 -60
- package/src/generators/test-generator/patterns/index.ts +22 -4
- package/src/generators/test-generator/patterns/interaction-patterns.ts +47 -107
- package/src/generators/test-generator/patterns/legacy-patterns.ts +104 -0
- package/src/generators/test-generator/patterns/navigation-patterns.ts +27 -69
- package/src/generators/test-generator/patterns/setup-patterns.ts +23 -41
- package/src/generators/test-generator/patterns/types.ts +26 -9
- package/src/generators/test-generator/step-mapper.ts +4 -124
- package/src/generators/test-generator/types.ts +131 -0
- package/src/generators/test-generator/utils/data-resolver.ts +8 -13
- package/src/generators/test-generator/utils/selector-resolver.ts +15 -17
- package/src/orchestrator/cache-manager.ts +1 -107
- package/src/orchestrator/pipeline.ts +58 -433
- package/src/orchestrator/reporter.ts +1 -1
- package/src/orchestrator/screen-manager.ts +1 -1
- package/src/utils/feature-finder.ts +33 -0
- package/src/utils/screen-paths.ts +37 -0
- package/src/utils/selector-loader.ts +23 -0
- package/src/utils/selector-types.ts +17 -0
- package/src/utils/test-data-loader.ts +23 -0
- package/src/utils/yaml-io.ts +33 -0
- package/dist/cli/commands/auto-tag-command.d.ts +0 -8
- package/dist/cli/commands/auto-tag-command.d.ts.map +0 -1
- package/dist/cli/commands/auto-tag-command.js +0 -104
- package/dist/cli/commands/auto-tag-command.js.map +0 -1
- package/dist/cli/commands/live-scan-command.d.ts +0 -9
- package/dist/cli/commands/live-scan-command.d.ts.map +0 -1
- package/dist/cli/commands/live-scan-command.js.map +0 -1
- package/dist/executor/playwright/playwright-generator.d.ts +0 -33
- package/dist/executor/playwright/playwright-generator.d.ts.map +0 -1
- package/dist/executor/playwright/playwright-generator.js +0 -136
- package/dist/executor/playwright/playwright-generator.js.map +0 -1
- package/dist/executor/test-generator.d.ts.map +0 -1
- package/dist/executor/test-generator.js +0 -30
- package/dist/executor/test-generator.js.map +0 -1
- package/dist/generators/cli.d.ts +0 -7
- package/dist/generators/cli.d.ts.map +0 -1
- package/dist/generators/cli.js +0 -570
- package/dist/generators/cli.js.map +0 -1
- package/dist/input/cli-adapter.d.ts +0 -75
- package/dist/input/cli-adapter.d.ts.map +0 -1
- package/dist/input/cli-adapter.js +0 -218
- package/dist/input/cli-adapter.js.map +0 -1
- package/dist/input/config-adapter.d.ts +0 -25
- package/dist/input/config-adapter.d.ts.map +0 -1
- package/dist/input/config-adapter.js +0 -70
- package/dist/input/config-adapter.js.map +0 -1
- package/dist/input/input-adapter.d.ts +0 -28
- package/dist/input/input-adapter.d.ts.map +0 -1
- package/dist/input/input-adapter.js +0 -17
- package/dist/input/input-adapter.js.map +0 -1
- package/dist/input/vscode-adapter.d.ts +0 -62
- package/dist/input/vscode-adapter.d.ts.map +0 -1
- package/dist/input/vscode-adapter.js +0 -64
- package/dist/input/vscode-adapter.js.map +0 -1
- package/dist/tools/auto-tagger.d.ts +0 -107
- package/dist/tools/auto-tagger.d.ts.map +0 -1
- package/dist/tools/auto-tagger.js +0 -502
- package/dist/tools/auto-tagger.js.map +0 -1
- package/src/cli/commands/auto-tag-command.ts +0 -80
- package/src/executor/playwright/playwright-generator.ts +0 -125
- package/src/executor/test-generator.ts +0 -90
- package/src/generators/cli.ts +0 -640
- package/src/input/cli-adapter.ts +0 -233
- package/src/input/config-adapter.ts +0 -71
- package/src/input/input-adapter.ts +0 -32
- package/src/input/vscode-adapter.ts +0 -90
- package/src/tools/auto-tagger.ts +0 -572
package/src/cli/index.ts
CHANGED
|
@@ -4,482 +4,41 @@
|
|
|
4
4
|
* Command-line interface for generating E2E tests from Gherkin features
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
for (const fileResult of result.results) {
|
|
18
|
-
if (fileResult.valid) {
|
|
19
|
-
if (verbose) {
|
|
20
|
-
console.log(`✓ ${fileResult.file}`);
|
|
21
|
-
console.log(` ✓ Gherkin syntax valid`);
|
|
22
|
-
if (fileResult.warnings.length === 0) {
|
|
23
|
-
console.log(` ✓ All checks passed`);
|
|
24
|
-
}
|
|
25
|
-
} else {
|
|
26
|
-
console.log(`✓ ${fileResult.file}`);
|
|
27
|
-
}
|
|
28
|
-
} else {
|
|
29
|
-
console.log(`✗ ${fileResult.file}`);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Print warnings
|
|
33
|
-
for (const warning of fileResult.warnings) {
|
|
34
|
-
const lineInfo = warning.line ? `:${warning.line}` : '';
|
|
35
|
-
console.log(` ⊘ ${warning.message}${lineInfo}`);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Print errors
|
|
39
|
-
for (const error of fileResult.errors) {
|
|
40
|
-
const lineInfo = error.line ? `:${error.line}` : '';
|
|
41
|
-
console.log(` ✗ ${error.message}${lineInfo}`);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (!fileResult.valid || (verbose && fileResult.warnings.length > 0)) {
|
|
45
|
-
console.log('');
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Print summary
|
|
50
|
-
console.log('\nSummary:');
|
|
51
|
-
console.log(` Files: ${result.summary.totalFiles} total, ${result.summary.passedFiles} passed, ${result.summary.failedFiles} failed`);
|
|
52
|
-
console.log(` Errors: ${result.summary.totalErrors}`);
|
|
53
|
-
console.log(` Warnings: ${result.summary.totalWarnings}`);
|
|
54
|
-
|
|
55
|
-
// Print error breakdown if there are errors
|
|
56
|
-
if (result.summary.totalErrors > 0) {
|
|
57
|
-
const errorsByType = new Map<string, number>();
|
|
58
|
-
const errorsByFile = new Map<string, string[]>();
|
|
59
|
-
|
|
60
|
-
for (const fileResult of result.results) {
|
|
61
|
-
for (const error of fileResult.errors) {
|
|
62
|
-
// Count by type
|
|
63
|
-
errorsByType.set(error.code, (errorsByType.get(error.code) || 0) + 1);
|
|
64
|
-
|
|
65
|
-
// Group missing elements by file
|
|
66
|
-
if (error.code === 'MISSING_SELECTOR' || error.code === 'MISSING_DATA_REF') {
|
|
67
|
-
if (!errorsByFile.has(fileResult.file)) {
|
|
68
|
-
errorsByFile.set(fileResult.file, []);
|
|
69
|
-
}
|
|
70
|
-
if (error.element) {
|
|
71
|
-
errorsByFile.get(fileResult.file)!.push(error.element);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
console.log('\nError Breakdown:');
|
|
78
|
-
for (const [code, count] of errorsByType.entries()) {
|
|
79
|
-
const description = getErrorDescription(code);
|
|
80
|
-
console.log(` ${code}: ${count} ${description}`);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Show suggested fixes
|
|
84
|
-
if (errorsByType.has('MISSING_SELECTOR_FILE') || errorsByType.has('MISSING_DATA_FILE')) {
|
|
85
|
-
console.log('\n💡 Suggested Fix:');
|
|
86
|
-
console.log(' Run: sungen map --screen <name>');
|
|
87
|
-
console.log(' This will generate missing selector and test-data files');
|
|
88
|
-
} else if (errorsByType.has('MISSING_SELECTOR') || errorsByType.has('MISSING_DATA_REF')) {
|
|
89
|
-
console.log('\n💡 Suggested Fix:');
|
|
90
|
-
if (errorsByType.has('MISSING_SELECTOR')) {
|
|
91
|
-
console.log(' Missing selectors - Add them to the selector YAML files');
|
|
92
|
-
}
|
|
93
|
-
if (errorsByType.has('MISSING_DATA_REF')) {
|
|
94
|
-
console.log(' Missing data refs - Add them to the test-data YAML files');
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (result.valid) {
|
|
100
|
-
console.log('\n✅ Validation passed');
|
|
101
|
-
} else {
|
|
102
|
-
console.log('\n❌ Validation failed');
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Get human-readable description for error code
|
|
108
|
-
*/
|
|
109
|
-
function getErrorDescription(code: string): string {
|
|
110
|
-
switch (code) {
|
|
111
|
-
case 'GHERKIN_SYNTAX_ERROR': return 'Gherkin syntax errors';
|
|
112
|
-
case 'MISSING_PATH_METADATA': return 'missing Path: metadata';
|
|
113
|
-
case 'MISSING_SELECTOR_FILE': return 'missing selector files';
|
|
114
|
-
case 'MISSING_SELECTOR': return 'missing selector definitions';
|
|
115
|
-
case 'MISSING_DATA_FILE': return 'missing test-data files';
|
|
116
|
-
case 'MISSING_DATA_REF': return 'missing data references';
|
|
117
|
-
case 'INVALID_YAML_SYNTAX': return 'invalid YAML syntax';
|
|
118
|
-
case 'INVALID_SELECTOR_TYPE': return 'invalid selector types';
|
|
119
|
-
case 'INVALID_DATA_VALUE': return 'invalid data values';
|
|
120
|
-
case 'EMPTY_FEATURE': return 'empty feature files';
|
|
121
|
-
default: return 'errors';
|
|
122
|
-
}
|
|
123
|
-
}
|
|
7
|
+
import { Command } from 'commander';
|
|
8
|
+
import { registerInitCommand } from './commands/init';
|
|
9
|
+
import { registerAddCommand } from './commands/add';
|
|
10
|
+
import { registerLiveScanCommand } from './commands/live-scan';
|
|
11
|
+
import { registerMapCommand } from './commands/map';
|
|
12
|
+
import { registerGenerateCommand } from './commands/generate';
|
|
13
|
+
import { registerFullCommand } from './commands/full';
|
|
14
|
+
import { registerValidateCommand } from './commands/validate';
|
|
15
|
+
import { registerCacheClearCommand } from './commands/cache-clear';
|
|
16
|
+
import { registerMakeauthCommand } from './commands/makeauth';
|
|
124
17
|
|
|
125
18
|
async function main() {
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
process.exit(1);
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
const mapCmd = adapter.addMapCommand(program);
|
|
153
|
-
mapCmd.action(async (options) => {
|
|
154
|
-
try {
|
|
155
|
-
const cliOptions = {
|
|
156
|
-
...program.opts(),
|
|
157
|
-
...options
|
|
158
|
-
};
|
|
159
|
-
const config = new ConfigLoader().load(cliOptions);
|
|
160
|
-
const { ScaffoldGenerator } = require('../generators/scaffold-generator');
|
|
161
|
-
const path = require('path');
|
|
162
|
-
|
|
163
|
-
const generator = new ScaffoldGenerator();
|
|
164
|
-
|
|
165
|
-
if (options.screen) {
|
|
166
|
-
// Process screen folder: qa/screens/<screen>/features/
|
|
167
|
-
const screensDir = options.output || 'qa/screens';
|
|
168
|
-
const forceOverwrite = cliOptions.force || false;
|
|
169
|
-
|
|
170
|
-
// Run live-scan first if --scan-live flag is set
|
|
171
|
-
if (options.scanLive) {
|
|
172
|
-
const { LiveScanner } = require('../core/live-scanner');
|
|
173
|
-
console.log('🔍 Running live-scan before mapping...\n');
|
|
174
|
-
|
|
175
|
-
const scanner = new LiveScanner({
|
|
176
|
-
screenName: options.screen,
|
|
177
|
-
screensDir,
|
|
178
|
-
headed: options.headed,
|
|
179
|
-
authDir: options.authDir,
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
await scanner.scan();
|
|
183
|
-
console.log('');
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
if (forceOverwrite) {
|
|
187
|
-
console.log(`Mapping screen: ${options.screen} (force: selectors will be overwritten)\n`);
|
|
188
|
-
} else {
|
|
189
|
-
console.log(`Mapping screen: ${options.screen}\n`);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
const results = generator.processScreen(options.screen, screensDir, forceOverwrite);
|
|
193
|
-
|
|
194
|
-
for (const result of results) {
|
|
195
|
-
console.log(`✓ Mapped ${result.featureFile}.feature`);
|
|
196
|
-
|
|
197
|
-
// Show selector status
|
|
198
|
-
if (result.selectorsSkipped) {
|
|
199
|
-
console.log(` ⊘ ${path.basename(result.selectorsPath)} (skipped - already exists)`);
|
|
200
|
-
} else {
|
|
201
|
-
console.log(` → ${path.basename(result.selectorsPath)} (${result.elementCount} elements)`);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Show test data status
|
|
205
|
-
if (result.testDataMerged) {
|
|
206
|
-
console.log(` ↻ ${path.basename(result.testDataPath)} (smart-merged — ${result.dataRefCount} variables)\n`);
|
|
207
|
-
} else {
|
|
208
|
-
console.log(` → ${path.basename(result.testDataPath)} (${result.dataRefCount} variables)\n`);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
console.log(`Next step: sungen generate --screen ${options.screen}`);
|
|
213
|
-
console.log(' This will create the test specs based on the mapped selectors and test data.');
|
|
214
|
-
} else if (options.file) {
|
|
215
|
-
// Process single feature file
|
|
216
|
-
// Derive output from feature file location: features/ -> selectors/screens/
|
|
217
|
-
const deriveOutputDir = (featureFilePath: string): string => {
|
|
218
|
-
const featureDir = path.dirname(featureFilePath);
|
|
219
|
-
if (featureDir.includes('features')) {
|
|
220
|
-
return featureDir.replace(/features\/?$/, 'selectors/screens');
|
|
221
|
-
}
|
|
222
|
-
return path.join(featureDir, '..', 'selectors', 'screens');
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
const outputDir = options.output || deriveOutputDir(options.file);
|
|
226
|
-
const forceOverwrite = cliOptions.force || false;
|
|
227
|
-
console.log(`Mapping from file: ${options.file}\n`);
|
|
228
|
-
const result = generator.processFeatureFile(options.file, outputDir, forceOverwrite);
|
|
229
|
-
console.log(`✓ Generated: ${result.outputPath} (${result.elementCount} elements)`);
|
|
230
|
-
} else {
|
|
231
|
-
console.error('❌ Error: Please specify --screen <name> or --file <path>');
|
|
232
|
-
process.exit(1);
|
|
233
|
-
}
|
|
234
|
-
} catch (error) {
|
|
235
|
-
console.error('❌ Mapping failed:', error);
|
|
236
|
-
process.exit(1);
|
|
237
|
-
}
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
const genCmd = adapter.addGenerateCommand(program);
|
|
241
|
-
genCmd.action(async (options) => {
|
|
242
|
-
try {
|
|
243
|
-
// Run validation first (unless --skip-validation is set)
|
|
244
|
-
if (!options.skipValidation) {
|
|
245
|
-
const { ScreenValidator } = require('../core/validator');
|
|
246
|
-
const validator = new ScreenValidator();
|
|
247
|
-
|
|
248
|
-
let validationResult: ValidationResult;
|
|
249
|
-
if (options.screen) {
|
|
250
|
-
console.log(`🔍 Validating screen: ${options.screen}...\n`);
|
|
251
|
-
validationResult = validator.validateScreen(options.screen);
|
|
252
|
-
} else {
|
|
253
|
-
console.log('🔍 Validating all screens...\n');
|
|
254
|
-
validationResult = validator.validateAll();
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// Show validation errors if any
|
|
258
|
-
if (!validationResult.valid) {
|
|
259
|
-
printValidationResult(validationResult, false);
|
|
260
|
-
console.error('\n❌ Validation failed. Fix errors before generating tests.');
|
|
261
|
-
console.error(' Tip: Use --skip-validation to bypass validation (not recommended)');
|
|
262
|
-
process.exit(1);
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
// Show brief success message
|
|
266
|
-
console.log(`✅ Validation passed (${validationResult.summary.totalFiles} files)\n`);
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
const cliOptions = {
|
|
270
|
-
...program.opts(),
|
|
271
|
-
...options
|
|
272
|
-
};
|
|
273
|
-
const config = new ConfigLoader().load(cliOptions);
|
|
274
|
-
const pipeline = new Pipeline(config);
|
|
275
|
-
|
|
276
|
-
await pipeline.runTestGeneration(options.screen);
|
|
277
|
-
} catch (error) {
|
|
278
|
-
console.error('❌ Test generation failed:', error);
|
|
279
|
-
process.exit(1);
|
|
280
|
-
}
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
const fullCmd = adapter.addFullCommand(program);
|
|
284
|
-
fullCmd.action(async (options) => {
|
|
285
|
-
try {
|
|
286
|
-
const cliOptions = {
|
|
287
|
-
...program.opts(),
|
|
288
|
-
...options
|
|
289
|
-
};
|
|
290
|
-
const config = new ConfigLoader().load(cliOptions);
|
|
291
|
-
const pipeline = new Pipeline(config);
|
|
292
|
-
|
|
293
|
-
const screens = options.screen ? [options.screen] : undefined;
|
|
294
|
-
await pipeline.runFull(screens);
|
|
295
|
-
} catch (error) {
|
|
296
|
-
console.error('❌ Full pipeline failed:', error);
|
|
297
|
-
process.exit(1);
|
|
298
|
-
}
|
|
299
|
-
});
|
|
300
|
-
|
|
301
|
-
const initCmd = adapter.addInitCommand(program);
|
|
302
|
-
initCmd.action(async (projectName?: string) => {
|
|
303
|
-
try {
|
|
304
|
-
const { ProjectInitializer } = require('../orchestrator/project-initializer');
|
|
305
|
-
const initializer = new ProjectInitializer();
|
|
306
|
-
await initializer.initialize(projectName);
|
|
307
|
-
} catch (error) {
|
|
308
|
-
console.error('❌ Init failed:', error);
|
|
309
|
-
process.exit(1);
|
|
310
|
-
}
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
const cacheCmd = adapter.addCacheCommand(program);
|
|
314
|
-
cacheCmd.action(async (options) => {
|
|
315
|
-
try {
|
|
316
|
-
const config = new ConfigLoader().load(adapter.extractOptions(cacheCmd));
|
|
317
|
-
const cacheManager = new CacheManager(config);
|
|
318
|
-
|
|
319
|
-
console.log('🗑️ Clearing cache...');
|
|
320
|
-
await cacheManager.clear();
|
|
321
|
-
console.log('✅ Cache cleared successfully');
|
|
322
|
-
} catch (error) {
|
|
323
|
-
console.error('❌ Cache clear failed:', error);
|
|
324
|
-
process.exit(1);
|
|
325
|
-
}
|
|
326
|
-
});
|
|
327
|
-
|
|
328
|
-
const autoTagCmd = adapter.addAutoTagCommand(program);
|
|
329
|
-
autoTagCmd.action(async (options) => {
|
|
330
|
-
try {
|
|
331
|
-
const cliOptions = {
|
|
332
|
-
...program.opts(),
|
|
333
|
-
...options
|
|
334
|
-
};
|
|
335
|
-
const config = new ConfigLoader().load(cliOptions);
|
|
336
|
-
const { createAutoTagCommand } = require('./commands/auto-tag-command');
|
|
337
|
-
|
|
338
|
-
await createAutoTagCommand(config).parseAsync(['node', 'sungen', ...process.argv.slice(3)]);
|
|
339
|
-
} catch (error) {
|
|
340
|
-
console.error('❌ Auto-tagging failed:', error);
|
|
341
|
-
process.exit(1);
|
|
342
|
-
}
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
const liveScanCmd = adapter.addLiveScanCommand(program);
|
|
346
|
-
liveScanCmd.action(async (options) => {
|
|
347
|
-
try {
|
|
348
|
-
const cliOptions = {
|
|
349
|
-
...program.opts(),
|
|
350
|
-
...options
|
|
351
|
-
};
|
|
352
|
-
const config = new ConfigLoader().load(cliOptions);
|
|
353
|
-
const { createLiveScanCommand } = require('./commands/live-scan-command');
|
|
354
|
-
|
|
355
|
-
await createLiveScanCommand(config).parseAsync(['node', 'sungen', ...process.argv.slice(3)]);
|
|
356
|
-
} catch (error) {
|
|
357
|
-
console.error('❌ Live scan failed:', error);
|
|
358
|
-
process.exit(1);
|
|
359
|
-
}
|
|
360
|
-
});
|
|
361
|
-
|
|
362
|
-
const addScreenCmd = adapter.addAddScreenCommand(program);
|
|
363
|
-
addScreenCmd.action(async (options) => {
|
|
364
|
-
try {
|
|
365
|
-
const { ScreenManager } = require('../orchestrator/screen-manager');
|
|
366
|
-
const manager = new ScreenManager();
|
|
367
|
-
|
|
368
|
-
await manager.addScreen({
|
|
369
|
-
name: options.screen,
|
|
370
|
-
path: options.path,
|
|
371
|
-
description: options.description
|
|
372
|
-
});
|
|
373
|
-
} catch (error) {
|
|
374
|
-
console.error('❌ Add screen failed:', error);
|
|
375
|
-
process.exit(1);
|
|
376
|
-
}
|
|
377
|
-
});
|
|
378
|
-
|
|
379
|
-
const validateCmd = adapter.addValidateCommand(program);
|
|
380
|
-
validateCmd.action(async (options) => {
|
|
381
|
-
try {
|
|
382
|
-
const { ScreenValidator } = require('../core/validator');
|
|
383
|
-
|
|
384
|
-
const validator = new ScreenValidator({
|
|
385
|
-
verbose: options.verbose,
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
let result: ValidationResult;
|
|
389
|
-
if (options.screen) {
|
|
390
|
-
console.log(`Validating screen: ${options.screen}\n`);
|
|
391
|
-
result = validator.validateScreen(options.screen);
|
|
392
|
-
} else {
|
|
393
|
-
console.log('Validating all screens...\n');
|
|
394
|
-
result = validator.validateAll();
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
// Output results
|
|
398
|
-
if (options.json) {
|
|
399
|
-
console.log(JSON.stringify(result, null, 2));
|
|
400
|
-
} else {
|
|
401
|
-
printValidationResult(result, options.verbose);
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
// Exit with error code if validation failed
|
|
405
|
-
if (!result.valid) {
|
|
406
|
-
process.exit(1);
|
|
407
|
-
}
|
|
408
|
-
} catch (error) {
|
|
409
|
-
console.error('❌ Validation failed:', error);
|
|
410
|
-
process.exit(1);
|
|
411
|
-
}
|
|
412
|
-
});
|
|
413
|
-
|
|
414
|
-
const makeAuthCmd = adapter.addMakeAuthCommand(program);
|
|
415
|
-
makeAuthCmd.action(async (name: string, options: any) => {
|
|
416
|
-
try {
|
|
417
|
-
const { AuthMaker } = require('../tools/auth-maker');
|
|
418
|
-
|
|
419
|
-
// Only pass baseURL if explicitly provided via --url
|
|
420
|
-
// Otherwise let AuthMaker detect from playwright.config.ts
|
|
421
|
-
const authMaker = new AuthMaker({
|
|
422
|
-
baseURL: options.url,
|
|
423
|
-
loginPath: options.path || '/login',
|
|
424
|
-
outputDir: options.output || 'specs/.auth',
|
|
425
|
-
timeout: options.timeout ? parseInt(options.timeout, 300) : undefined,
|
|
426
|
-
navigationTimeout: options.navTimeout ? parseInt(options.navTimeout, 300) : undefined,
|
|
427
|
-
stabilityWait: options.stabilityWait ? parseInt(options.stabilityWait, 300) : undefined,
|
|
428
|
-
});
|
|
429
|
-
|
|
430
|
-
// Handle --list flag
|
|
431
|
-
if (options.list) {
|
|
432
|
-
const authStates = authMaker.listAuth();
|
|
433
|
-
if (authStates.length === 0) {
|
|
434
|
-
console.log('No auth states found.');
|
|
435
|
-
} else {
|
|
436
|
-
console.log('Available auth states:');
|
|
437
|
-
for (const state of authStates) {
|
|
438
|
-
console.log(` - ${state}`);
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
return;
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
// Handle --verify flag
|
|
445
|
-
if (options.verify) {
|
|
446
|
-
const isValid = await authMaker.verifyAuth(name);
|
|
447
|
-
process.exit(isValid ? 0 : 1);
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
// Handle --export flag
|
|
451
|
-
if (options.export) {
|
|
452
|
-
const base64 = authMaker.exportAuth(name);
|
|
453
|
-
if (base64) {
|
|
454
|
-
console.log('');
|
|
455
|
-
console.log('Base64 Auth State (for CI):');
|
|
456
|
-
console.log('========================================');
|
|
457
|
-
console.log(base64);
|
|
458
|
-
console.log('========================================');
|
|
459
|
-
console.log('');
|
|
460
|
-
console.log('Save this to CI secret: AUTH_STATE_' + name.toUpperCase());
|
|
461
|
-
}
|
|
462
|
-
return;
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
// Default: create new auth state
|
|
466
|
-
await authMaker.makeAuth({
|
|
467
|
-
name,
|
|
468
|
-
baseURL: options.url,
|
|
469
|
-
loginPath: options.path,
|
|
470
|
-
outputDir: options.output,
|
|
471
|
-
timeout: options.timeout ? parseInt(options.timeout, 10) : undefined,
|
|
472
|
-
navigationTimeout: options.navTimeout ? parseInt(options.navTimeout, 10) : undefined,
|
|
473
|
-
stabilityWait: options.stabilityWait ? parseInt(options.stabilityWait, 10) : undefined,
|
|
474
|
-
headless: options.headless,
|
|
475
|
-
});
|
|
476
|
-
} catch (error) {
|
|
477
|
-
console.error('❌ Auth generation failed:', error);
|
|
478
|
-
process.exit(1);
|
|
479
|
-
}
|
|
480
|
-
});
|
|
19
|
+
const program = new Command();
|
|
20
|
+
|
|
21
|
+
program
|
|
22
|
+
.name('sungen')
|
|
23
|
+
.description('AI-Native E2E Test Generator - Generate Playwright tests from Gherkin features')
|
|
24
|
+
.version('1.0.21');
|
|
25
|
+
|
|
26
|
+
// Global options
|
|
27
|
+
program
|
|
28
|
+
.option('-c, --config <path>', 'Path to custom config file')
|
|
29
|
+
.option('-v, --verbose', 'Enable verbose logging');
|
|
30
|
+
|
|
31
|
+
// Register all commands
|
|
32
|
+
registerInitCommand(program);
|
|
33
|
+
registerAddCommand(program);
|
|
34
|
+
registerLiveScanCommand(program);
|
|
35
|
+
registerMapCommand(program);
|
|
36
|
+
registerGenerateCommand(program);
|
|
37
|
+
registerFullCommand(program);
|
|
38
|
+
registerValidateCommand(program);
|
|
39
|
+
registerCacheClearCommand(program);
|
|
40
|
+
registerMakeauthCommand(program);
|
|
481
41
|
|
|
482
|
-
// Parse arguments
|
|
483
42
|
await program.parseAsync(process.argv);
|
|
484
43
|
}
|
|
485
44
|
|
package/src/cli/types.ts
ADDED
package/src/cli/utils.ts
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { ValidationResult } from '../core/validator';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Get human-readable description for error code
|
|
5
|
+
*/
|
|
6
|
+
function getErrorDescription(code: string): string {
|
|
7
|
+
switch (code) {
|
|
8
|
+
case 'GHERKIN_SYNTAX_ERROR': return 'Gherkin syntax errors';
|
|
9
|
+
case 'MISSING_PATH_METADATA': return 'missing Path: metadata';
|
|
10
|
+
case 'MISSING_SELECTOR_FILE': return 'missing selector files';
|
|
11
|
+
case 'MISSING_SELECTOR': return 'missing selector definitions';
|
|
12
|
+
case 'MISSING_DATA_FILE': return 'missing test-data files';
|
|
13
|
+
case 'MISSING_DATA_REF': return 'missing data references';
|
|
14
|
+
case 'INVALID_YAML_SYNTAX': return 'invalid YAML syntax';
|
|
15
|
+
case 'INVALID_SELECTOR_TYPE': return 'invalid selector types';
|
|
16
|
+
case 'INVALID_DATA_VALUE': return 'invalid data values';
|
|
17
|
+
case 'EMPTY_FEATURE': return 'empty feature files';
|
|
18
|
+
default: return 'errors';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Print validation result to console
|
|
24
|
+
*/
|
|
25
|
+
export function printValidationResult(result: ValidationResult, verbose: boolean = false): void {
|
|
26
|
+
for (const fileResult of result.results) {
|
|
27
|
+
if (fileResult.valid) {
|
|
28
|
+
if (verbose) {
|
|
29
|
+
console.log(`✓ ${fileResult.file}`);
|
|
30
|
+
console.log(` ✓ Gherkin syntax valid`);
|
|
31
|
+
if (fileResult.warnings.length === 0) {
|
|
32
|
+
console.log(` ✓ All checks passed`);
|
|
33
|
+
}
|
|
34
|
+
} else {
|
|
35
|
+
console.log(`✓ ${fileResult.file}`);
|
|
36
|
+
}
|
|
37
|
+
} else {
|
|
38
|
+
console.log(`✗ ${fileResult.file}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
for (const warning of fileResult.warnings) {
|
|
42
|
+
const lineInfo = warning.line ? `:${warning.line}` : '';
|
|
43
|
+
console.log(` ⊘ ${warning.message}${lineInfo}`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
for (const error of fileResult.errors) {
|
|
47
|
+
const lineInfo = error.line ? `:${error.line}` : '';
|
|
48
|
+
console.log(` ✗ ${error.message}${lineInfo}`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (!fileResult.valid || (verbose && fileResult.warnings.length > 0)) {
|
|
52
|
+
console.log('');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
console.log('\nSummary:');
|
|
57
|
+
console.log(` Files: ${result.summary.totalFiles} total, ${result.summary.passedFiles} passed, ${result.summary.failedFiles} failed`);
|
|
58
|
+
console.log(` Errors: ${result.summary.totalErrors}`);
|
|
59
|
+
console.log(` Warnings: ${result.summary.totalWarnings}`);
|
|
60
|
+
|
|
61
|
+
if (result.summary.totalErrors > 0) {
|
|
62
|
+
const errorsByType = new Map<string, number>();
|
|
63
|
+
const errorsByFile = new Map<string, string[]>();
|
|
64
|
+
|
|
65
|
+
for (const fileResult of result.results) {
|
|
66
|
+
for (const error of fileResult.errors) {
|
|
67
|
+
errorsByType.set(error.code, (errorsByType.get(error.code) || 0) + 1);
|
|
68
|
+
|
|
69
|
+
if (error.code === 'MISSING_SELECTOR' || error.code === 'MISSING_DATA_REF') {
|
|
70
|
+
if (!errorsByFile.has(fileResult.file)) {
|
|
71
|
+
errorsByFile.set(fileResult.file, []);
|
|
72
|
+
}
|
|
73
|
+
if (error.element) {
|
|
74
|
+
errorsByFile.get(fileResult.file)!.push(error.element);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
console.log('\nError Breakdown:');
|
|
81
|
+
for (const [code, count] of errorsByType.entries()) {
|
|
82
|
+
const description = getErrorDescription(code);
|
|
83
|
+
console.log(` ${code}: ${count} ${description}`);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (errorsByType.has('MISSING_SELECTOR_FILE') || errorsByType.has('MISSING_DATA_FILE')) {
|
|
87
|
+
console.log('\n💡 Suggested Fix:');
|
|
88
|
+
console.log(' Run: sungen map --screen <name>');
|
|
89
|
+
console.log(' This will generate missing selector and test-data files');
|
|
90
|
+
} else if (errorsByType.has('MISSING_SELECTOR') || errorsByType.has('MISSING_DATA_REF')) {
|
|
91
|
+
console.log('\n💡 Suggested Fix:');
|
|
92
|
+
if (errorsByType.has('MISSING_SELECTOR')) {
|
|
93
|
+
console.log(' Missing selectors - Add them to the selector YAML files');
|
|
94
|
+
}
|
|
95
|
+
if (errorsByType.has('MISSING_DATA_REF')) {
|
|
96
|
+
console.log(' Missing data refs - Add them to the test-data YAML files');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (result.valid) {
|
|
102
|
+
console.log('\n✅ Validation passed');
|
|
103
|
+
} else {
|
|
104
|
+
console.log('\n❌ Validation failed');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
* Merges elements across scenarios (first match wins).
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import
|
|
8
|
-
import * as yaml from 'yaml';
|
|
7
|
+
import { readYamlIfExists } from '../../utils/yaml-io';
|
|
9
8
|
import { LiveElement, LiveScanResult } from './types';
|
|
10
9
|
|
|
11
10
|
/**
|
|
@@ -13,12 +12,7 @@ import { LiveElement, LiveScanResult } from './types';
|
|
|
13
12
|
* Returns null if file doesn't exist.
|
|
14
13
|
*/
|
|
15
14
|
export function readMatrix(filePath: string): LiveScanResult | null {
|
|
16
|
-
|
|
17
|
-
return null;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const content = fs.readFileSync(filePath, 'utf-8');
|
|
21
|
-
const parsed = yaml.parse(content);
|
|
15
|
+
const parsed = readYamlIfExists<any>(filePath);
|
|
22
16
|
|
|
23
17
|
if (!parsed || !parsed.scenarios) {
|
|
24
18
|
return null;
|