@sun-asterisk/sungen 3.2.32 → 3.2.34-beta.1
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/dist/cli/commands/audit.d.ts +5 -0
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/audit.js +64 -11
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/cli/commands/capability.d.ts.map +1 -1
- package/dist/cli/commands/capability.js +40 -18
- package/dist/cli/commands/capability.js.map +1 -1
- package/dist/cli/commands/changed.d.ts.map +1 -1
- package/dist/cli/commands/changed.js +2 -3
- package/dist/cli/commands/changed.js.map +1 -1
- package/dist/cli/commands/dashboard.d.ts.map +1 -1
- package/dist/cli/commands/dashboard.js +2 -28
- package/dist/cli/commands/dashboard.js.map +1 -1
- package/dist/cli/commands/defect.d.ts +7 -0
- package/dist/cli/commands/defect.d.ts.map +1 -0
- package/dist/cli/commands/defect.js +68 -0
- package/dist/cli/commands/defect.js.map +1 -0
- package/dist/cli/commands/delivery.d.ts.map +1 -1
- package/dist/cli/commands/delivery.js +113 -59
- package/dist/cli/commands/delivery.js.map +1 -1
- package/dist/cli/commands/generate.d.ts.map +1 -1
- package/dist/cli/commands/generate.js +14 -7
- package/dist/cli/commands/generate.js.map +1 -1
- package/dist/cli/commands/results-merge.d.ts +9 -0
- package/dist/cli/commands/results-merge.d.ts.map +1 -1
- package/dist/cli/commands/results-merge.js +9 -12
- package/dist/cli/commands/results-merge.js.map +1 -1
- package/dist/cli/commands/results-sanitize.d.ts.map +1 -1
- package/dist/cli/commands/results-sanitize.js +2 -13
- package/dist/cli/commands/results-sanitize.js.map +1 -1
- package/dist/cli/commands/select.d.ts +12 -0
- package/dist/cli/commands/select.d.ts.map +1 -0
- package/dist/cli/commands/select.js +122 -0
- package/dist/cli/commands/select.js.map +1 -0
- package/dist/cli/commands/triage.d.ts +7 -0
- package/dist/cli/commands/triage.d.ts.map +1 -0
- package/dist/cli/commands/triage.js +98 -0
- package/dist/cli/commands/triage.js.map +1 -0
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +3 -0
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/commands/viewpoint.d.ts +7 -0
- package/dist/cli/commands/viewpoint.d.ts.map +1 -0
- package/dist/cli/commands/viewpoint.js +70 -0
- package/dist/cli/commands/viewpoint.js.map +1 -0
- package/dist/cli/index.js +13 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/dashboard/snapshot-builder.d.ts.map +1 -1
- package/dist/dashboard/snapshot-builder.js +6 -10
- package/dist/dashboard/snapshot-builder.js.map +1 -1
- package/dist/dashboard/templates/index.html +1 -1
- package/dist/dashboard/types.d.ts +1 -0
- package/dist/dashboard/types.d.ts.map +1 -1
- package/dist/exporters/csv-exporter.d.ts +4 -0
- package/dist/exporters/csv-exporter.d.ts.map +1 -1
- package/dist/exporters/csv-exporter.js +12 -11
- package/dist/exporters/csv-exporter.js.map +1 -1
- package/dist/exporters/feature-parser.d.ts +29 -0
- package/dist/exporters/feature-parser.d.ts.map +1 -1
- package/dist/exporters/feature-parser.js +44 -1
- package/dist/exporters/feature-parser.js.map +1 -1
- package/dist/exporters/json-exporter.d.ts.map +1 -1
- package/dist/exporters/json-exporter.js +7 -0
- package/dist/exporters/json-exporter.js.map +1 -1
- package/dist/exporters/locale-variants.d.ts +7 -1
- package/dist/exporters/locale-variants.d.ts.map +1 -1
- package/dist/exporters/locale-variants.js +23 -16
- package/dist/exporters/locale-variants.js.map +1 -1
- package/dist/exporters/manual-hybrid-oracle.d.ts +54 -0
- package/dist/exporters/manual-hybrid-oracle.d.ts.map +1 -0
- package/dist/exporters/manual-hybrid-oracle.js +114 -0
- package/dist/exporters/manual-hybrid-oracle.js.map +1 -0
- package/dist/exporters/matrix/build.d.ts.map +1 -1
- package/dist/exporters/matrix/build.js +68 -19
- package/dist/exporters/matrix/build.js.map +1 -1
- package/dist/exporters/matrix/carry-manual-results.d.ts +89 -0
- package/dist/exporters/matrix/carry-manual-results.d.ts.map +1 -0
- package/dist/exporters/matrix/carry-manual-results.js +302 -0
- package/dist/exporters/matrix/carry-manual-results.js.map +1 -0
- package/dist/exporters/matrix/export.d.ts +9 -1
- package/dist/exporters/matrix/export.d.ts.map +1 -1
- package/dist/exporters/matrix/export.js +21 -3
- package/dist/exporters/matrix/export.js.map +1 -1
- package/dist/exporters/matrix/gates.js +6 -0
- package/dist/exporters/matrix/gates.js.map +1 -1
- package/dist/exporters/matrix/render-csv.js +1 -1
- package/dist/exporters/matrix/render-csv.js.map +1 -1
- package/dist/exporters/matrix/render-testcase-sheet.d.ts.map +1 -1
- package/dist/exporters/matrix/render-testcase-sheet.js +10 -4
- package/dist/exporters/matrix/render-testcase-sheet.js.map +1 -1
- package/dist/exporters/matrix/render-xlsx.d.ts.map +1 -1
- package/dist/exporters/matrix/render-xlsx.js +3 -0
- package/dist/exporters/matrix/render-xlsx.js.map +1 -1
- package/dist/exporters/matrix/types.d.ts +13 -1
- package/dist/exporters/matrix/types.d.ts.map +1 -1
- package/dist/exporters/matrix/types.js.map +1 -1
- package/dist/exporters/matrix/wording.d.ts +8 -1
- package/dist/exporters/matrix/wording.d.ts.map +1 -1
- package/dist/exporters/matrix/wording.js +37 -2
- package/dist/exporters/matrix/wording.js.map +1 -1
- package/dist/exporters/playwright-report-parser.d.ts.map +1 -1
- package/dist/exporters/playwright-report-parser.js +1 -0
- package/dist/exporters/playwright-report-parser.js.map +1 -1
- package/dist/exporters/run-environment.d.ts +32 -0
- package/dist/exporters/run-environment.d.ts.map +1 -0
- package/dist/exporters/run-environment.js +125 -0
- package/dist/exporters/run-environment.js.map +1 -0
- package/dist/exporters/scenario-merger.d.ts +18 -0
- package/dist/exporters/scenario-merger.d.ts.map +1 -1
- package/dist/exporters/scenario-merger.js +49 -3
- package/dist/exporters/scenario-merger.js.map +1 -1
- package/dist/exporters/test-data-resolver.d.ts +0 -4
- package/dist/exporters/test-data-resolver.d.ts.map +1 -1
- package/dist/exporters/test-data-resolver.js +0 -7
- package/dist/exporters/test-data-resolver.js.map +1 -1
- package/dist/exporters/types.d.ts +5 -0
- package/dist/exporters/types.d.ts.map +1 -1
- package/dist/exporters/xlsx-exporter.d.ts +2 -0
- package/dist/exporters/xlsx-exporter.d.ts.map +1 -1
- package/dist/exporters/xlsx-exporter.js +7 -2
- package/dist/exporters/xlsx-exporter.js.map +1 -1
- package/dist/generators/gherkin-parser/index.d.ts +11 -4
- package/dist/generators/gherkin-parser/index.d.ts.map +1 -1
- package/dist/generators/gherkin-parser/index.js +49 -19
- package/dist/generators/gherkin-parser/index.js.map +1 -1
- package/dist/generators/test-generator/adapters/adapter-interface.d.ts +4 -0
- package/dist/generators/test-generator/adapters/adapter-interface.d.ts.map +1 -1
- package/dist/generators/test-generator/adapters/appium/templates/steps/actions/reinstall-app-action.hbs +2 -2
- package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/label-value-assertion.hbs +8 -2
- package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/visible-with-role-variable-assertion.hbs +7 -3
- package/dist/generators/test-generator/adapters/appium/templates/test-file.hbs +68 -4
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/click-select-action.hbs +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/select-action.hbs +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/label-value-assertion.hbs +7 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-role-variable-assertion.hbs +8 -4
- package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/pick-option.hbs +13 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/url-assertion.hbs +5 -1
- package/dist/generators/test-generator/adapters/playwright/templates/test-file.hbs +16 -0
- package/dist/generators/test-generator/code-generator.d.ts +2 -1
- package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
- package/dist/generators/test-generator/code-generator.js +90 -5
- package/dist/generators/test-generator/code-generator.js.map +1 -1
- package/dist/generators/test-generator/diagnostics.d.ts +36 -5
- package/dist/generators/test-generator/diagnostics.d.ts.map +1 -1
- package/dist/generators/test-generator/diagnostics.js +35 -4
- package/dist/generators/test-generator/diagnostics.js.map +1 -1
- package/dist/generators/test-generator/patterns/index.d.ts +12 -2
- package/dist/generators/test-generator/patterns/index.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/index.js +15 -9
- package/dist/generators/test-generator/patterns/index.js.map +1 -1
- package/dist/generators/test-generator/patterns/types.d.ts +15 -0
- package/dist/generators/test-generator/patterns/types.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/with-parent-scope.d.ts +5 -0
- package/dist/generators/test-generator/patterns/with-parent-scope.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/with-parent-scope.js +6 -0
- package/dist/generators/test-generator/patterns/with-parent-scope.js.map +1 -1
- package/dist/generators/test-generator/step-mapper.d.ts +46 -0
- package/dist/generators/test-generator/step-mapper.d.ts.map +1 -1
- package/dist/generators/test-generator/step-mapper.js +84 -9
- package/dist/generators/test-generator/step-mapper.js.map +1 -1
- package/dist/generators/test-generator/utils/data-resolver.d.ts +25 -0
- package/dist/generators/test-generator/utils/data-resolver.d.ts.map +1 -1
- package/dist/generators/test-generator/utils/data-resolver.js +39 -8
- package/dist/generators/test-generator/utils/data-resolver.js.map +1 -1
- package/dist/generators/test-generator/utils/selector-entry-fields.d.ts.map +1 -1
- package/dist/generators/test-generator/utils/selector-entry-fields.js +1 -0
- package/dist/generators/test-generator/utils/selector-entry-fields.js.map +1 -1
- package/dist/generators/test-generator/utils/selector-resolver.d.ts +37 -4
- package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
- package/dist/generators/test-generator/utils/selector-resolver.js +212 -79
- package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -1
- package/dist/harness/audit.d.ts +3 -0
- package/dist/harness/audit.d.ts.map +1 -1
- package/dist/harness/audit.js +60 -19
- package/dist/harness/audit.js.map +1 -1
- package/dist/harness/capability.d.ts +7 -1
- package/dist/harness/capability.d.ts.map +1 -1
- package/dist/harness/capability.js +15 -12
- package/dist/harness/capability.js.map +1 -1
- package/dist/harness/catalog/universal-viewpoints.yaml +5 -5
- package/dist/harness/config-file.d.ts +17 -0
- package/dist/harness/config-file.d.ts.map +1 -0
- package/dist/harness/config-file.js +100 -0
- package/dist/harness/config-file.js.map +1 -0
- package/dist/harness/counted-assertions.d.ts +2 -0
- package/dist/harness/counted-assertions.d.ts.map +1 -0
- package/dist/harness/counted-assertions.js +38 -0
- package/dist/harness/counted-assertions.js.map +1 -0
- package/dist/harness/data-driven-lint.d.ts.map +1 -1
- package/dist/harness/data-driven-lint.js +69 -27
- package/dist/harness/data-driven-lint.js.map +1 -1
- package/dist/harness/defect-draft.d.ts +14 -0
- package/dist/harness/defect-draft.d.ts.map +1 -0
- package/dist/harness/defect-draft.js +143 -0
- package/dist/harness/defect-draft.js.map +1 -0
- package/dist/harness/defects.d.ts +24 -0
- package/dist/harness/defects.d.ts.map +1 -0
- package/dist/harness/defects.js +118 -0
- package/dist/harness/defects.js.map +1 -0
- package/dist/harness/depth-lint.d.ts.map +1 -1
- package/dist/harness/depth-lint.js +2 -1
- package/dist/harness/depth-lint.js.map +1 -1
- package/dist/harness/flow-check.d.ts.map +1 -1
- package/dist/harness/flow-check.js +6 -2
- package/dist/harness/flow-check.js.map +1 -1
- package/dist/harness/keyword-match.d.ts +59 -0
- package/dist/harness/keyword-match.d.ts.map +1 -0
- package/dist/harness/keyword-match.js +86 -0
- package/dist/harness/keyword-match.js.map +1 -0
- package/dist/harness/manifest.d.ts.map +1 -1
- package/dist/harness/manifest.js +2 -2
- package/dist/harness/manifest.js.map +1 -1
- package/dist/harness/next-step.d.ts +2 -4
- package/dist/harness/next-step.d.ts.map +1 -1
- package/dist/harness/next-step.js +50 -5
- package/dist/harness/next-step.js.map +1 -1
- package/dist/harness/parse.d.ts +45 -0
- package/dist/harness/parse.d.ts.map +1 -1
- package/dist/harness/parse.js +142 -24
- package/dist/harness/parse.js.map +1 -1
- package/dist/harness/perf.d.ts +7 -1
- package/dist/harness/perf.d.ts.map +1 -1
- package/dist/harness/perf.js +13 -10
- package/dist/harness/perf.js.map +1 -1
- package/dist/harness/quality-gates.d.ts +9 -2
- package/dist/harness/quality-gates.d.ts.map +1 -1
- package/dist/harness/quality-gates.js +22 -8
- package/dist/harness/quality-gates.js.map +1 -1
- package/dist/harness/query-catalog.js +0 -0
- package/dist/harness/query-catalog.js.map +1 -1
- package/dist/harness/read-text.d.ts +21 -0
- package/dist/harness/read-text.d.ts.map +1 -1
- package/dist/harness/read-text.js +32 -1
- package/dist/harness/read-text.js.map +1 -1
- package/dist/harness/script-check.d.ts.map +1 -1
- package/dist/harness/script-check.js +7 -1
- package/dist/harness/script-check.js.map +1 -1
- package/dist/harness/secret-scan.d.ts +27 -1
- package/dist/harness/secret-scan.d.ts.map +1 -1
- package/dist/harness/secret-scan.js +57 -4
- package/dist/harness/secret-scan.js.map +1 -1
- package/dist/harness/select-by-ids.d.ts +31 -0
- package/dist/harness/select-by-ids.d.ts.map +1 -0
- package/dist/harness/select-by-ids.js +106 -0
- package/dist/harness/select-by-ids.js.map +1 -0
- package/dist/harness/sensors.d.ts +20 -1
- package/dist/harness/sensors.d.ts.map +1 -1
- package/dist/harness/sensors.js +133 -39
- package/dist/harness/sensors.js.map +1 -1
- package/dist/harness/spec-branches.d.ts +0 -18
- package/dist/harness/spec-branches.d.ts.map +1 -1
- package/dist/harness/spec-branches.js +24 -3
- package/dist/harness/spec-branches.js.map +1 -1
- package/dist/harness/spec-coverage.d.ts.map +1 -1
- package/dist/harness/spec-coverage.js +14 -4
- package/dist/harness/spec-coverage.js.map +1 -1
- package/dist/harness/triage-signals.d.ts +20 -0
- package/dist/harness/triage-signals.d.ts.map +1 -0
- package/dist/harness/triage-signals.js +30 -0
- package/dist/harness/triage-signals.js.map +1 -0
- package/dist/harness/triage-unit.d.ts +23 -0
- package/dist/harness/triage-unit.d.ts.map +1 -0
- package/dist/harness/triage-unit.js +142 -0
- package/dist/harness/triage-unit.js.map +1 -0
- package/dist/harness/triage.d.ts +28 -0
- package/dist/harness/triage.d.ts.map +1 -0
- package/dist/harness/triage.js +99 -0
- package/dist/harness/triage.js.map +1 -0
- package/dist/harness/ui-inventory.d.ts +40 -0
- package/dist/harness/ui-inventory.d.ts.map +1 -0
- package/dist/harness/ui-inventory.js +191 -0
- package/dist/harness/ui-inventory.js.map +1 -0
- package/dist/harness/viewpoint-baseline.d.ts.map +1 -1
- package/dist/harness/viewpoint-baseline.js +7 -1
- package/dist/harness/viewpoint-baseline.js.map +1 -1
- package/dist/harness/viewpoint-draft-header.d.ts +7 -0
- package/dist/harness/viewpoint-draft-header.d.ts.map +1 -0
- package/dist/harness/viewpoint-draft-header.js +100 -0
- package/dist/harness/viewpoint-draft-header.js.map +1 -0
- package/dist/harness/viewpoint-ledger.d.ts +13 -3
- package/dist/harness/viewpoint-ledger.d.ts.map +1 -1
- package/dist/harness/viewpoint-ledger.js +106 -19
- package/dist/harness/viewpoint-ledger.js.map +1 -1
- package/dist/harness/viewpoint-mode.d.ts +9 -0
- package/dist/harness/viewpoint-mode.d.ts.map +1 -0
- package/dist/harness/viewpoint-mode.js +52 -0
- package/dist/harness/viewpoint-mode.js.map +1 -0
- package/dist/harness/viewpoint-priority.d.ts +19 -0
- package/dist/harness/viewpoint-priority.d.ts.map +1 -0
- package/dist/harness/viewpoint-priority.js +36 -0
- package/dist/harness/viewpoint-priority.js.map +1 -0
- package/dist/harness/viewpoint-review-open.d.ts +6 -0
- package/dist/harness/viewpoint-review-open.d.ts.map +1 -0
- package/dist/harness/viewpoint-review-open.js +90 -0
- package/dist/harness/viewpoint-review-open.js.map +1 -0
- package/dist/harness/viewpoint-scan-refs.d.ts +50 -0
- package/dist/harness/viewpoint-scan-refs.d.ts.map +1 -0
- package/dist/harness/viewpoint-scan-refs.js +200 -0
- package/dist/harness/viewpoint-scan-refs.js.map +1 -0
- package/dist/harness/viewpoint-scan.d.ts +41 -0
- package/dist/harness/viewpoint-scan.d.ts.map +1 -0
- package/dist/harness/viewpoint-scan.js +118 -0
- package/dist/harness/viewpoint-scan.js.map +1 -0
- package/dist/harness/write-atomic.d.ts +2 -0
- package/dist/harness/write-atomic.d.ts.map +1 -0
- package/dist/harness/write-atomic.js +62 -0
- package/dist/harness/write-atomic.js.map +1 -0
- package/dist/orchestrator/ai-skills/writer.d.ts.map +1 -1
- package/dist/orchestrator/ai-skills/writer.js +15 -7
- package/dist/orchestrator/ai-skills/writer.js.map +1 -1
- package/dist/orchestrator/assets-drift.d.ts.map +1 -1
- package/dist/orchestrator/assets-drift.js +11 -6
- package/dist/orchestrator/assets-drift.js.map +1 -1
- package/dist/orchestrator/flow-manager.d.ts +0 -1
- package/dist/orchestrator/flow-manager.d.ts.map +1 -1
- package/dist/orchestrator/flow-manager.js +3 -52
- package/dist/orchestrator/flow-manager.js.map +1 -1
- package/dist/orchestrator/project-deps-sync.d.ts.map +1 -1
- package/dist/orchestrator/project-deps-sync.js +22 -1
- package/dist/orchestrator/project-deps-sync.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 +49 -7
- package/dist/orchestrator/project-initializer.js.map +1 -1
- package/dist/orchestrator/screen-manager.d.ts.map +1 -1
- package/dist/orchestrator/screen-manager.js +8 -62
- package/dist/orchestrator/screen-manager.js.map +1 -1
- package/dist/orchestrator/security-overrides-catalog.d.ts +39 -0
- package/dist/orchestrator/security-overrides-catalog.d.ts.map +1 -0
- package/dist/orchestrator/security-overrides-catalog.js +63 -0
- package/dist/orchestrator/security-overrides-catalog.js.map +1 -0
- package/dist/orchestrator/security-overrides.d.ts +51 -0
- package/dist/orchestrator/security-overrides.d.ts.map +1 -0
- package/dist/orchestrator/security-overrides.js +165 -0
- package/dist/orchestrator/security-overrides.js.map +1 -0
- package/dist/orchestrator/templates/ai-src/agents/discovery.md +11 -3
- package/dist/orchestrator/templates/ai-src/agents/reviewer.md +8 -0
- package/dist/orchestrator/templates/ai-src/commands/create-test.md +32 -24
- package/dist/orchestrator/templates/ai-src/commands/review.md +2 -2
- package/dist/orchestrator/templates/ai-src/commands/run-test.md +78 -15
- package/dist/orchestrator/templates/ai-src/skills/sungen-capture/mode-local.md +2 -2
- package/dist/orchestrator/templates/ai-src/skills/sungen-delivery/SKILL.md +14 -0
- package/dist/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +25 -1
- package/dist/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +26 -8
- package/dist/orchestrator/templates/ai-src/skills/sungen-harness-audit/SKILL.md +5 -1
- package/dist/orchestrator/templates/ai-src/skills/sungen-selector-fix/SKILL.md +58 -14
- package/dist/orchestrator/templates/ai-src/skills/sungen-selector-keys/SKILL.md +13 -1
- package/dist/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +42 -2
- package/dist/orchestrator/templates/ai-src/skills/sungen-tc-review/SKILL.md +7 -0
- package/dist/orchestrator/templates/ai-src/skills/sungen-viewpoint/SKILL.md +18 -0
- package/dist/orchestrator/templates/ai-src/skills/sungen-viewpoint/review-checklist.md +63 -0
- package/dist/orchestrator/templates/ai-src/skills/sungen-viewpoint/viewpoint-template.md +158 -0
- package/dist/orchestrator/templates/playwright.config.ts +4 -2
- package/dist/orchestrator/templates/specs-locale-fixture.ts +21 -9
- package/dist/orchestrator/templates/specs-pw-shape-reporter.ts +0 -0
- package/dist/orchestrator/templates/specs-url-assert.d.ts +17 -1
- package/dist/orchestrator/templates/specs-url-assert.d.ts.map +1 -1
- package/dist/orchestrator/templates/specs-url-assert.js +38 -4
- package/dist/orchestrator/templates/specs-url-assert.js.map +1 -1
- package/dist/orchestrator/templates/specs-url-assert.ts +47 -4
- package/dist/orchestrator/templates/wdio.conf.ts +24 -1
- package/dist/orchestrator/trace-mode-install.d.ts +14 -0
- package/dist/orchestrator/trace-mode-install.d.ts.map +1 -0
- package/dist/orchestrator/trace-mode-install.js +132 -0
- package/dist/orchestrator/trace-mode-install.js.map +1 -0
- package/dist/orchestrator/viewpoint-pattern-catalog.d.ts +23 -0
- package/dist/orchestrator/viewpoint-pattern-catalog.d.ts.map +1 -0
- package/dist/orchestrator/viewpoint-pattern-catalog.js +48 -0
- package/dist/orchestrator/viewpoint-pattern-catalog.js.map +1 -0
- package/dist/orchestrator/viewpoint-scaffold.d.ts +3 -0
- package/dist/orchestrator/viewpoint-scaffold.d.ts.map +1 -0
- package/dist/orchestrator/viewpoint-scaffold.js +70 -0
- package/dist/orchestrator/viewpoint-scaffold.js.map +1 -0
- package/package.json +3 -3
- package/src/cli/commands/audit.ts +59 -12
- package/src/cli/commands/capability.ts +54 -19
- package/src/cli/commands/changed.ts +2 -4
- package/src/cli/commands/dashboard.ts +1 -26
- package/src/cli/commands/defect.ts +49 -0
- package/src/cli/commands/delivery.ts +106 -56
- package/src/cli/commands/generate.ts +15 -7
- package/src/cli/commands/results-merge.ts +9 -9
- package/src/cli/commands/results-sanitize.ts +2 -9
- package/src/cli/commands/select.ts +88 -0
- package/src/cli/commands/triage.ts +57 -0
- package/src/cli/commands/update.ts +3 -0
- package/src/cli/commands/viewpoint.ts +58 -0
- package/src/cli/index.ts +13 -2
- package/src/dashboard/snapshot-builder.ts +6 -8
- package/src/dashboard/templates/index.html +1 -1
- package/src/dashboard/types.ts +1 -0
- package/src/exporters/csv-exporter.ts +12 -11
- package/src/exporters/feature-parser.ts +44 -2
- package/src/exporters/json-exporter.ts +6 -1
- package/src/exporters/locale-variants.ts +23 -17
- package/src/exporters/manual-hybrid-oracle.ts +112 -0
- package/src/exporters/matrix/build.ts +71 -19
- package/src/exporters/matrix/carry-manual-results.ts +292 -0
- package/src/exporters/matrix/export.ts +24 -4
- package/src/exporters/matrix/gates.ts +6 -0
- package/src/exporters/matrix/render-csv.ts +1 -1
- package/src/exporters/matrix/render-testcase-sheet.ts +10 -4
- package/src/exporters/matrix/render-xlsx.ts +3 -0
- package/src/exporters/matrix/types.ts +13 -1
- package/src/exporters/matrix/wording.ts +36 -2
- package/src/exporters/playwright-report-parser.ts +1 -0
- package/src/exporters/run-environment.ts +89 -0
- package/src/exporters/scenario-merger.ts +51 -5
- package/src/exporters/test-data-resolver.ts +0 -6
- package/src/exporters/types.ts +5 -0
- package/src/exporters/xlsx-exporter.ts +7 -2
- package/src/generators/gherkin-parser/index.ts +50 -18
- package/src/generators/test-generator/adapters/adapter-interface.ts +6 -2
- package/src/generators/test-generator/adapters/appium/templates/steps/actions/reinstall-app-action.hbs +2 -2
- package/src/generators/test-generator/adapters/appium/templates/steps/assertions/label-value-assertion.hbs +8 -2
- package/src/generators/test-generator/adapters/appium/templates/steps/assertions/visible-with-role-variable-assertion.hbs +7 -3
- package/src/generators/test-generator/adapters/appium/templates/test-file.hbs +68 -4
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/click-select-action.hbs +1 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/select-action.hbs +1 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/label-value-assertion.hbs +7 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-role-variable-assertion.hbs +8 -4
- package/src/generators/test-generator/adapters/playwright/templates/steps/partials/pick-option.hbs +13 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/partials/url-assertion.hbs +5 -1
- package/src/generators/test-generator/adapters/playwright/templates/test-file.hbs +16 -0
- package/src/generators/test-generator/code-generator.ts +77 -5
- package/src/generators/test-generator/diagnostics.ts +36 -5
- package/src/generators/test-generator/patterns/index.ts +15 -8
- package/src/generators/test-generator/patterns/types.ts +15 -0
- package/src/generators/test-generator/patterns/with-parent-scope.ts +6 -0
- package/src/generators/test-generator/step-mapper.ts +90 -8
- package/src/generators/test-generator/utils/data-resolver.ts +41 -12
- package/src/generators/test-generator/utils/selector-entry-fields.ts +1 -0
- package/src/generators/test-generator/utils/selector-resolver.ts +238 -82
- package/src/harness/audit.ts +69 -24
- package/src/harness/capability.ts +23 -12
- package/src/harness/catalog/universal-viewpoints.yaml +5 -5
- package/src/harness/config-file.ts +66 -0
- package/src/harness/counted-assertions.ts +33 -0
- package/src/harness/data-driven-lint.ts +82 -24
- package/src/harness/defect-draft.ts +115 -0
- package/src/harness/defects.ts +94 -0
- package/src/harness/depth-lint.ts +2 -1
- package/src/harness/flow-check.ts +6 -2
- package/src/harness/keyword-match.ts +85 -0
- package/src/harness/manifest.ts +2 -2
- package/src/harness/next-step.ts +47 -5
- package/src/harness/parse.ts +151 -27
- package/src/harness/perf.ts +15 -7
- package/src/harness/quality-gates.ts +22 -8
- package/src/harness/query-catalog.ts +0 -0
- package/src/harness/read-text.ts +32 -1
- package/src/harness/script-check.ts +7 -1
- package/src/harness/secret-scan.ts +60 -4
- package/src/harness/select-by-ids.ts +83 -0
- package/src/harness/sensors.ts +141 -40
- package/src/harness/spec-branches.ts +6 -3
- package/src/harness/spec-coverage.ts +14 -4
- package/src/harness/triage-signals.ts +46 -0
- package/src/harness/triage-unit.ts +113 -0
- package/src/harness/triage.ts +127 -0
- package/src/harness/ui-inventory.ts +164 -0
- package/src/harness/viewpoint-baseline.ts +7 -1
- package/src/harness/viewpoint-draft-header.ts +55 -0
- package/src/harness/viewpoint-ledger.ts +113 -25
- package/src/harness/viewpoint-mode.ts +49 -0
- package/src/harness/viewpoint-priority.ts +38 -0
- package/src/harness/viewpoint-review-open.ts +51 -0
- package/src/harness/viewpoint-scan-refs.ts +154 -0
- package/src/harness/viewpoint-scan.ts +111 -0
- package/src/harness/write-atomic.ts +22 -0
- package/src/orchestrator/ai-skills/writer.ts +18 -3
- package/src/orchestrator/assets-drift.ts +10 -5
- package/src/orchestrator/flow-manager.ts +3 -53
- package/src/orchestrator/project-deps-sync.ts +23 -1
- package/src/orchestrator/project-initializer.ts +54 -6
- package/src/orchestrator/screen-manager.ts +7 -61
- package/src/orchestrator/security-overrides-catalog.ts +69 -0
- package/src/orchestrator/security-overrides.ts +149 -0
- package/src/orchestrator/templates/ai-src/agents/discovery.md +11 -3
- package/src/orchestrator/templates/ai-src/agents/reviewer.md +8 -0
- package/src/orchestrator/templates/ai-src/commands/create-test.md +32 -24
- package/src/orchestrator/templates/ai-src/commands/review.md +2 -2
- package/src/orchestrator/templates/ai-src/commands/run-test.md +78 -15
- package/src/orchestrator/templates/ai-src/skills/sungen-capture/mode-local.md +2 -2
- package/src/orchestrator/templates/ai-src/skills/sungen-delivery/SKILL.md +14 -0
- package/src/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +25 -1
- package/src/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +26 -8
- package/src/orchestrator/templates/ai-src/skills/sungen-harness-audit/SKILL.md +5 -1
- package/src/orchestrator/templates/ai-src/skills/sungen-selector-fix/SKILL.md +58 -14
- package/src/orchestrator/templates/ai-src/skills/sungen-selector-keys/SKILL.md +13 -1
- package/src/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +42 -2
- package/src/orchestrator/templates/ai-src/skills/sungen-tc-review/SKILL.md +7 -0
- package/src/orchestrator/templates/ai-src/skills/sungen-viewpoint/SKILL.md +18 -0
- package/src/orchestrator/templates/ai-src/skills/sungen-viewpoint/review-checklist.md +63 -0
- package/src/orchestrator/templates/ai-src/skills/sungen-viewpoint/viewpoint-template.md +158 -0
- package/src/orchestrator/templates/playwright.config.ts +4 -2
- package/src/orchestrator/templates/specs-locale-fixture.ts +21 -9
- package/src/orchestrator/templates/specs-pw-shape-reporter.ts +0 -0
- package/src/orchestrator/templates/specs-url-assert.ts +47 -4
- package/src/orchestrator/templates/wdio.conf.ts +24 -1
- package/src/orchestrator/trace-mode-install.ts +94 -0
- package/src/orchestrator/viewpoint-pattern-catalog.ts +61 -0
- package/src/orchestrator/viewpoint-scaffold.ts +36 -0
package/src/cli/index.ts
CHANGED
|
@@ -24,6 +24,7 @@ import { registerIngestCommand } from './commands/ingest';
|
|
|
24
24
|
import { registerEvalCommand } from './commands/eval';
|
|
25
25
|
import { registerManifestCommand } from './commands/manifest';
|
|
26
26
|
import { registerChangedCommand } from './commands/changed';
|
|
27
|
+
import { registerSelectCommand } from './commands/select';
|
|
27
28
|
import { registerLedgerCommand } from './commands/ledger';
|
|
28
29
|
import { registerFeedbackCommand } from './commands/feedback';
|
|
29
30
|
import { registerQaFeedbackCommand } from './commands/qa-feedback';
|
|
@@ -36,8 +37,11 @@ import { registerCapabilityCommand } from './commands/capability';
|
|
|
36
37
|
import { registerFlowCheckCommand } from './commands/flow-check';
|
|
37
38
|
import { registerContextCommand } from './commands/context';
|
|
38
39
|
import { registerRepairCommand } from './commands/repair';
|
|
40
|
+
import { registerTriageCommand } from './commands/triage';
|
|
41
|
+
import { registerDefectCommand } from './commands/defect';
|
|
39
42
|
import { registerResultsCommand } from './commands/results-merge';
|
|
40
43
|
import { registerLoginCommand } from './commands/login';
|
|
44
|
+
import { registerViewpointCommand } from './commands/viewpoint';
|
|
41
45
|
import { capabilityRegistry } from '../capabilities/registry';
|
|
42
46
|
import { discoverAndRegisterCapabilities } from '../capabilities/discover';
|
|
43
47
|
import { warnAssetsDrift } from '../orchestrator/assets-drift';
|
|
@@ -75,6 +79,7 @@ registerSetupMobileEnvCommand(program);
|
|
|
75
79
|
registerGateCommand(program);
|
|
76
80
|
registerManifestCommand(program);
|
|
77
81
|
registerChangedCommand(program);
|
|
82
|
+
registerSelectCommand(program);
|
|
78
83
|
registerLedgerCommand(program);
|
|
79
84
|
registerFeedbackCommand(program);
|
|
80
85
|
registerQaFeedbackCommand(program);
|
|
@@ -87,10 +92,13 @@ registerSetupMobileEnvCommand(program);
|
|
|
87
92
|
registerFlowCheckCommand(program);
|
|
88
93
|
registerContextCommand(program);
|
|
89
94
|
registerRepairCommand(program);
|
|
95
|
+
registerTriageCommand(program);
|
|
96
|
+
registerDefectCommand(program);
|
|
90
97
|
registerResultsCommand(program);
|
|
91
98
|
registerIngestCommand(program);
|
|
92
99
|
registerEvalCommand(program);
|
|
93
100
|
registerLoginCommand(program);
|
|
101
|
+
registerViewpointCommand(program);
|
|
94
102
|
|
|
95
103
|
// Capability-contributed CLI commands (Capability SPI): drivers own their authoring commands
|
|
96
104
|
// (e.g. @sungen/driver-api → `sungen api import`). Discover, then register each.
|
|
@@ -123,12 +131,15 @@ registerSetupMobileEnvCommand(program);
|
|
|
123
131
|
const opts = actionCommand.opts() as Record<string, unknown>;
|
|
124
132
|
const unit = [opts.screen, opts.flow, opts.area].find((v) => typeof v === 'string' && v)
|
|
125
133
|
?? (typeof actionCommand.args?.[0] === 'string' ? actionCommand.args[0] : undefined);
|
|
126
|
-
|
|
134
|
+
// `--grep` is machine output too: callers capture it with `$(…)`, and a footer on stdout
|
|
135
|
+
// became part of the regex — the last alternative of `changed --grep` silently matched
|
|
136
|
+
// nothing, so `--change-only` skipped its last scenario (#836).
|
|
137
|
+
handBack = { unit: unit as string | undefined, json: opts.json === true || opts.grep === true };
|
|
127
138
|
});
|
|
128
139
|
process.on('exit', (code) => {
|
|
129
140
|
if (!handBack || code === 1) return;
|
|
130
141
|
const line = `\nNext: sungen next${handBack.unit ? ` ${handBack.unit}` : ''}`;
|
|
131
|
-
// stderr under --json so the hand-back never lands in the
|
|
142
|
+
// stderr under --json / --grep so the hand-back never lands in the captured payload.
|
|
132
143
|
if (handBack.json) process.stderr.write(`${line}\n`);
|
|
133
144
|
else process.stdout.write(`${line}\n`);
|
|
134
145
|
});
|
|
@@ -29,6 +29,7 @@ import { resolvePlatformAppId } from '../exporters/mobile-app-id';
|
|
|
29
29
|
import { discoverLocaleVariants, LocaleVariant } from '../exporters/locale-variants';
|
|
30
30
|
import { getPackageVersion } from '../exporters/package-info';
|
|
31
31
|
import { ApiCatalogEntry, EnvironmentInfo } from '../exporters/types';
|
|
32
|
+
import { readCapabilities } from '../harness/capability';
|
|
32
33
|
import {
|
|
33
34
|
AggregateSummary,
|
|
34
35
|
DashboardSnapshot,
|
|
@@ -98,14 +99,11 @@ export function buildDashboardSnapshot(options: BuildSnapshotOptions): Dashboard
|
|
|
98
99
|
* Mirrors `isMobileProject` in src/cli/commands/delivery.ts.
|
|
99
100
|
*/
|
|
100
101
|
function isMobileProject(cwd: string): boolean {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
} catch {
|
|
107
|
-
return false;
|
|
108
|
-
}
|
|
102
|
+
// Reads through `readCapabilities` rather than re-parsing the file: the third copy of this parse
|
|
103
|
+
// was the third place a malformed capabilities.yaml quietly read as "web". The shared reader
|
|
104
|
+
// reports the breakage once per process; here it still degrades to web, which is the safe
|
|
105
|
+
// direction (per-OS delivery is skipped, nothing is deleted).
|
|
106
|
+
return readCapabilities(cwd).platform === 'mobile';
|
|
109
107
|
}
|
|
110
108
|
|
|
111
109
|
function buildOneScreen(
|
|
@@ -121,7 +121,7 @@ use chrome, FireFox or Internet Explorer 11`)}var a=e(`safe-buffer`),o=e(`random
|
|
|
121
121
|
(Test evidence, DefectID, Actual result)`]));let f=[`Accessing`,`GUI`,`Function`],p=new Map;for(let e of o){let t=p.get(e.category2)||[];t.push(e),p.set(e.category2,t)}let m=new Set,h=(e,t)=>{d.push(UN([``,e,``,``,``,``,``,``,``,``,``,``,``,``,``,``]));for(let e of t)d.push(UN(LN(e)))};for(let e of f){let t=p.get(e);!t||t.length===0||(m.add(e),h(e,t))}for(let[e,t]of p.entries())m.has(e)||h(e,t);return``+d.join(`
|
|
122
122
|
`)+`
|
|
123
123
|
`}async function MN(e,t){let n=IN(e,t.screens),r=VN();for(let t of n)for(let n of ON(t)){let t=DN(FN(n),{sungenVersion:e.environment.sungenVersion});n.apiDetail&&n.apiDetail.length>0&&EN(t,n.apiDetail);let i=await KN(await t.xlsx.writeBuffer()),a=new Blob([i.buffer],{type:`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`}),o=URL.createObjectURL(a);GN(`${n.basename}-testcases_${r}.xlsx`,o),setTimeout(()=>URL.revokeObjectURL(o),1e3)}}function NN(e){let t={total:e.length,passed:0,failed:0,pending:0,na:0,notCompiled:0,passRate:0};for(let n of e)n.status===`Passed`?t.passed++:n.status===`Failed`?t.failed++:n.status===`Pending`?t.pending++:n.status===`N/A`&&t.na++,n.type===`Not compiled`&&t.notCompiled++;let n=t.passed+t.failed;return t.passRate=n>0?t.passed/n:0,t}function PN(e){return{tcId:e.tcId,category1:e.category1,category2:e.category2,precondition:e.precondition,testData:e.testData,steps:RN(e.steps),expectedResults:RN(e.expectedResults),priority:e.priority,testcaseType:e.type,testResult:e.status,executedDate:e.executedDate??``,testExecutor:e.testExecutor??``,testEnvironment:e.testEnvironment??``,note:zN(e)}}function FN(e){let t=e.specLink??``,n=(n,r)=>{let i=NN(r);return{sheetName:n,summary:{screen:e.basename,total:i.total,passed:i.passed,failed:i.failed,pending:i.pending,na:i.na},rows:r.map(PN),specLink:t}},r=[];if(e.locales&&e.locales.length>=2){let t=[];for(let i of e.locales){let e=i.scenarios.filter(e=>e.type!==`Manual`);r.push(n(`${i.displayCode} Auto`,e)),i.locale===``&&(t=i.scenarios.filter(e=>e.type===`Manual`))}t.length===0&&e.locales[0]&&(t=e.locales[0].scenarios.filter(e=>e.type===`Manual`)),r.push(n(`Manual`,t))}else{let t=e.scenarios.filter(e=>e.type!==`Manual`),i=e.scenarios.filter(e=>e.type===`Manual`);r.push(n(`Auto`,t)),r.push(n(`Manual`,i))}return r}function IN(e,t){if(!t||t.length===0)return e.screens;let n=new Set(t);return e.screens.filter(e=>n.has(e.name))}function LN(e){return[e.tcId,``,``,``,e.category1,e.precondition,e.testData,RN(e.steps),RN(e.expectedResults),e.priority,e.type,e.status,e.executedDate??``,e.testExecutor??``,e.testEnvironment??``,zN(e)]}function RN(e){return!e||e.length===0?``:e.length===1?e[0]:e.map((e,t)=>`${t+1}. ${e}`).join(`
|
|
124
|
-
`)}function zN(e){if(e.type===`Not compiled`)return`Scenario not compiled — re-run \`sungen generate --screen ${e.category4}\``;if(e.status!==`Failed`)return``;let t=[];if(e.errorMessage){let n=e.errorMessage.replace(/^Error:\s*/i,``),r=n.length>200?n.substring(0,197)+`…`:n;t.push(`• Error: ${r}`)}return e.tracePath&&t.push(`• Trace: ${e.tracePath}`),t.join(`
|
|
124
|
+
`)}function zN(e){if(e.type===`Not compiled`)return`Scenario not compiled — re-run \`sungen generate --screen ${e.category4}\``;if(e.type===`Manual`&&e.manualReason&&!e.executedDate)return`Manual: ${e.manualReason}`;if(e.status!==`Failed`)return``;let t=[];if(e.errorMessage){let n=e.errorMessage.replace(/^Error:\s*/i,``),r=n.length>200?n.substring(0,197)+`…`:n;t.push(`• Error: ${r}`)}return e.tracePath&&t.push(`• Trace: ${e.tracePath}`),t.join(`
|
|
125
125
|
`)}function BN(){let e=new Date(Date.now()+kN);return`${String(e.getUTCDate()).padStart(2,`0`)}/${String(e.getUTCMonth()+1).padStart(2,`0`)}/${e.getUTCFullYear()}`}function VN(){let e=new Date(Date.now()+kN);return`${e.getUTCFullYear()}-${String(e.getUTCMonth()+1).padStart(2,`0`)}-${String(e.getUTCDate()).padStart(2,`0`)}_${String(e.getUTCHours()).padStart(2,`0`)}-${String(e.getUTCMinutes()).padStart(2,`0`)}-${String(e.getUTCSeconds()).padStart(2,`0`)}`}function HN(e){if(e==null)return``;let t=String(e);return/[",\n\r]/.test(t)?`"`+t.replace(/"/g,`""`)+`"`:t}function UN(e){return e.map(HN).join(`,`)}function WN(e,t,n){let r=new Blob([t],{type:n}),i=URL.createObjectURL(r);GN(e,i),setTimeout(()=>URL.revokeObjectURL(i),1e3)}function GN(e,t){let n=document.createElement(`a`);n.href=t,n.download=e,document.body.appendChild(n),n.click(),n.remove()}async function KN(e){let t=await aN.default.loadAsync(e),n=Object.keys(t.files).filter(e=>/^xl\/drawings\/drawing\d+\.xml$/.test(e));for(let e of n){let n=t.file(e);if(!n)continue;let r=(await n.async(`string`)).replace(/<a:picLocks([^/]*)\/>/g,(e,t)=>{let n=e=>RegExp(`\\b${e}=`).test(t);return`<a:picLocks${t}${[`noMove`,`noResize`,`noSelect`].filter(e=>!n(e)).map(e=>` ${e}="1"`).join(``)}/>`});t.file(e,r)}return t.generateAsync({type:`uint8array`,compression:`DEFLATE`})}function qN({snapshot:e}){let{t}=O(),[n,r]=(0,y.useState)(`all`),[i,a]=(0,y.useState)(()=>new Set),o=e.screens,s=n===`all`?o:o.filter(e=>i.has(e.name)),c=s.reduce((e,t)=>e+t.summary.total,0),l=e=>e.reduce((e,t)=>e+Math.max(1,t.features?.length??1),0),u=l(s),d=l(o),f=e=>{let t=new Set(i);t.has(e)?t.delete(e):t.add(e),a(t)},p=()=>a(new Set(o.map(e=>e.name))),m=()=>a(new Set),h=i.size===o.length&&o.length>0;return(0,M.jsxs)(`div`,{className:`space-y-6 max-w-3xl`,children:[(0,M.jsxs)(`div`,{className:`bg-white dark:bg-night-800 rounded-xl border border-ink-100 dark:border-night-700 p-6 shadow-sm space-y-5`,children:[(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`h2`,{className:`text-lg font-semibold mb-1`,children:t(`export.title`)}),(0,M.jsx)(`p`,{className:`text-xs text-ink-500 dark:text-night-500`,children:t(`export.subtitle`)})]}),(0,M.jsxs)(`div`,{className:`space-y-3`,children:[(0,M.jsx)(YN,{children:t(`export.scope`)}),(0,M.jsxs)(`div`,{className:`flex flex-wrap gap-3`,children:[(0,M.jsx)(JN,{checked:n===`all`,onChange:()=>r(`all`),label:t(`export.allScreens`),hint:t(`export.allScreens.hint`,{screens:o.length,files:d,tcs:e.summary.total})}),(0,M.jsx)(JN,{checked:n===`selected`,onChange:()=>r(`selected`),label:t(`export.selectedScreens`),hint:t(`export.selectedScreens.hint`)})]})]}),n===`selected`&&(0,M.jsxs)(`div`,{className:`space-y-2`,children:[(0,M.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-2`,children:[(0,M.jsx)(YN,{children:t(`export.screens`)}),(0,M.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,M.jsx)(`span`,{className:`text-xs text-ink-500 dark:text-night-500 tabular-nums`,children:t(`export.selectedCount`,{selected:i.size,total:o.length})}),(0,M.jsx)(`button`,{type:`button`,onClick:p,disabled:h,className:`text-xs px-2 py-1 rounded-md border border-ink-100 dark:border-night-700 hover:bg-ink-100 dark:hover:bg-night-700 disabled:opacity-40 disabled:cursor-not-allowed`,children:t(`export.selectAll`)}),(0,M.jsx)(`button`,{type:`button`,onClick:m,disabled:i.size===0,className:`text-xs px-2 py-1 rounded-md border border-ink-100 dark:border-night-700 hover:bg-ink-100 dark:hover:bg-night-700 disabled:opacity-40 disabled:cursor-not-allowed`,children:t(`export.deselectAll`)})]})]}),(0,M.jsx)(`div`,{className:`grid grid-cols-2 sm:grid-cols-3 gap-2`,children:o.map(e=>{let n=i.has(e.name),r=e.features?.length??0;return(0,M.jsxs)(`label`,{className:`flex items-center gap-2 px-3 py-2 rounded-lg border cursor-pointer ${n?`bg-brand-50 dark:bg-brand-700/20 border-brand-500`:`bg-white dark:bg-night-900 border-ink-100 dark:border-night-700`}`,children:[(0,M.jsx)(`input`,{type:`checkbox`,checked:n,onChange:()=>f(e.name),className:`accent-brand-600`}),(0,M.jsx)(`span`,{className:`text-sm font-medium`,children:e.name}),r>1&&(0,M.jsx)(`span`,{className:`text-[10px] uppercase tracking-wider px-1.5 py-0.5 rounded-md bg-brand-100 dark:bg-brand-700/30 text-brand-700 dark:text-brand-100`,children:t(`export.featuresBadge`,{n:r})}),(0,M.jsx)(`span`,{className:`text-xs text-ink-500 dark:text-night-500 ml-auto`,children:e.summary.total})]},e.name)})})]}),(0,M.jsxs)(`div`,{className:`border-t border-ink-100 dark:border-night-700 pt-5 flex flex-wrap items-center gap-3`,children:[(0,M.jsxs)(`button`,{type:`button`,onClick:()=>{AN(e,{screens:n===`all`?void 0:Array.from(i)})},disabled:s.length===0,className:`px-4 py-2 rounded-lg bg-white dark:bg-night-900 border border-ink-100 dark:border-night-700 text-sm font-medium hover:bg-ink-100 dark:hover:bg-night-700 disabled:opacity-40 disabled:cursor-not-allowed inline-flex items-center gap-2`,children:[(0,M.jsx)(XN,{}),t(`export.downloadCsv`)]}),(0,M.jsxs)(`button`,{type:`button`,onClick:()=>{MN(e,{screens:n===`all`?void 0:Array.from(i)})},disabled:s.length===0,className:`px-4 py-2 rounded-lg bg-brand-600 text-white text-sm font-medium hover:bg-brand-700 disabled:opacity-40 disabled:cursor-not-allowed inline-flex items-center gap-2`,children:[(0,M.jsx)(XN,{}),t(`export.downloadXlsx`)]}),(0,M.jsx)(`span`,{className:`text-sm text-ink-500 dark:text-night-500 ml-auto`,children:t(`export.summary`,{screens:s.length,files:u,tcs:c})})]})]}),(0,M.jsx)(ZN,{})]})}function JN({checked:e,onChange:t,label:n,hint:r}){return(0,M.jsxs)(`button`,{type:`button`,onClick:t,className:`flex-1 min-w-[180px] text-left px-4 py-3 rounded-lg border transition-colors ${e?`bg-brand-50 dark:bg-brand-700/20 border-brand-500 ring-1 ring-brand-500`:`bg-white dark:bg-night-900 border-ink-100 dark:border-night-700 hover:border-ink-300 dark:hover:border-night-600`}`,children:[(0,M.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,M.jsx)(`span`,{className:`w-3 h-3 rounded-full border-2 ${e?`border-brand-600 bg-brand-600`:`border-ink-300 dark:border-night-500`}`}),(0,M.jsx)(`span`,{className:`text-sm font-medium`,children:n})]}),(0,M.jsx)(`div`,{className:`text-xs text-ink-500 dark:text-night-500 mt-1 ml-5`,children:r})]})}function YN({children:e}){return(0,M.jsx)(`div`,{className:`text-xs font-semibold uppercase tracking-wider text-ink-500 dark:text-night-500`,children:e})}function XN(){return(0,M.jsxs)(`svg`,{width:`16`,height:`16`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,M.jsx)(`path`,{d:`M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4`}),(0,M.jsx)(`polyline`,{points:`7 10 12 15 17 10`}),(0,M.jsx)(`line`,{x1:`12`,y1:`15`,x2:`12`,y2:`3`})]})}function ZN(){let{t:e}=O();return(0,M.jsxs)(`div`,{className:`bg-brand-50 dark:bg-brand-700/15 border border-brand-100 dark:border-brand-700/40 rounded-xl p-4 text-sm text-ink-700 dark:text-night-300`,children:[(0,M.jsx)(`div`,{className:`font-semibold mb-1`,children:e(`export.tip.title`)}),(0,M.jsx)(`code`,{className:`font-mono text-xs`,children:`sungen delivery [name…]`}),(0,M.jsxs)(`span`,{className:`text-ink-500 dark:text-night-500`,children:[e(`export.tip.body`),(0,M.jsx)(`span`,{className:`font-mono`,children:`qa/deliverables/`})]})]})}function QN(){let e=(0,y.useMemo)(sM,[]),[t,n]=(0,y.useState)(`overview`),[r,i]=(0,y.useState)(`all`),[a,o]=(0,y.useState)(null),s=(0,y.useRef)(0),{theme:c,toggle:l}=tM(),{t:u}=O();if(!e)return(0,M.jsx)(`div`,{className:`min-h-screen flex items-center justify-center p-6`,children:(0,M.jsx)(F,{title:u(`empty.title`),body:u(`empty.body`),hint:u(`empty.hint`)})});let{current:d,history:f}=e,p=f.length>0,m=d.screens.filter(e=>!rM(e)).length,h=d.screens.filter(e=>rM(e)).length,g=m>0&&h>0,_=g?r:`all`,v=(0,y.useMemo)(()=>oM(d,_),[d,_]),b=(0,y.useMemo)(()=>({...e,current:v}),[e,v]);return(0,M.jsxs)(`div`,{className:`min-h-screen flex`,children:[(0,M.jsx)(P,{active:t,onChange:n,hasHistory:p}),(0,M.jsxs)(`div`,{className:`flex-1 flex flex-col min-w-0`,children:[(0,M.jsx)(eP,{current:d,theme:c,onToggleTheme:l}),g&&(0,M.jsx)($N,{value:r,onChange:i,allCount:m+h,webCount:m,mobileCount:h}),(0,M.jsxs)(`main`,{className:`flex-1 p-6 overflow-x-hidden`,children:[t===`overview`&&(0,M.jsx)(dM,{payload:b,theme:c,onSelectScreen:e=>{s.current+=1,o({name:e,nonce:s.current}),n(`suites`)}}),t===`suites`&&(0,M.jsx)(MM,{snapshot:v,focusScreen:a}),t===`trends`&&(0,M.jsx)(WM,{payload:e,theme:c}),t===`compare`&&(0,M.jsx)(XM,{payload:e}),t===`export`&&(0,M.jsx)(qN,{snapshot:v})]})]})]})}function $N({value:e,onChange:t,allCount:n,webCount:r,mobileCount:i}){return(0,M.jsx)(`div`,{className:`bg-white dark:bg-night-800 border-b border-ink-100 dark:border-night-700 px-6 pt-3 flex gap-1`,children:[{key:`all`,label:`All`,count:n},{key:`web`,label:`🌐 Web`,count:r},{key:`mobile`,label:`📱 Mobile`,count:i}].map(n=>(0,M.jsxs)(`button`,{onClick:()=>t(n.key),className:`px-4 py-2 text-sm font-medium border-b-2 -mb-px transition-colors ${e===n.key?`border-brand-500 text-brand-600 dark:text-brand-500`:`border-transparent text-ink-500 dark:text-night-500 hover:text-ink-700 dark:hover:text-night-300`}`,children:[n.label,(0,M.jsx)(`span`,{className:`ml-1.5 text-xs text-ink-400 dark:text-night-500`,children:n.count})]},n.key))})}function eP({current:e,theme:t,onToggleTheme:n}){let{t:r}=O();return(0,M.jsxs)(`header`,{className:`bg-white dark:bg-night-800 border-b border-ink-100 dark:border-night-700 px-6 py-4 flex flex-wrap items-center gap-4`,children:[(0,M.jsxs)(`div`,{children:[(0,M.jsx)(`div`,{className:`text-xs uppercase tracking-wider text-ink-500 dark:text-night-500`,children:r(`header.run`)}),(0,M.jsx)(`div`,{className:`text-sm font-mono font-medium`,children:qj(e.runId)})]}),(0,M.jsx)(nP,{}),(0,M.jsx)(tP,{label:r(`header.environment`),value:e.environment.baseURL||`—`}),(0,M.jsx)(tP,{label:r(`header.project`),value:e.environment.projectName||`—`}),e.environment.gitBranch&&(0,M.jsx)(tP,{label:r(`header.branch`),value:e.environment.gitBranch,mono:!0}),(0,M.jsxs)(`div`,{className:`ml-auto flex items-center gap-2`,children:[(0,M.jsxs)(`div`,{className:`text-xs text-ink-500 dark:text-night-500 mr-1`,children:[`sungen v`,e.environment.sungenVersion]}),(0,M.jsx)(z,{}),(0,M.jsx)(I,{theme:t,onToggle:n})]})]})}function tP({label:e,value:t,mono:n}){return(0,M.jsxs)(`div`,{className:`min-w-0`,children:[(0,M.jsx)(`div`,{className:`text-xs uppercase tracking-wider text-ink-500 dark:text-night-500`,children:e}),(0,M.jsx)(`div`,{className:`text-sm truncate max-w-[260px] ${n?`font-mono`:``}`,title:t,children:t})]})}function nP(){return(0,M.jsx)(`div`,{className:`hidden sm:block w-px h-8 bg-ink-100 dark:bg-night-700`})}function rP(){let{locale:e,setLocale:t}=k();return(0,M.jsx)(A,{value:(0,y.useMemo)(()=>({locale:e,setLocale:t,t:(t,n)=>E(e,t,n)}),[e]),children:(0,M.jsx)(QN,{})})}(0,v.createRoot)(document.getElementById(`root`)).render((0,M.jsx)(y.StrictMode,{children:(0,M.jsx)(rP,{})}));</script>
|
|
126
126
|
<style rel="stylesheet" crossorigin>*,:before,:after{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border:0 solid #e5e7eb}:before,:after{--tw-content:""}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Helvetica Neue,sans-serif;line-height:1.5}body{line-height:inherit;margin:0}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-feature-settings:normal;font-variation-settings:normal;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-feature-settings:inherit;font-variation-settings:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button{-webkit-appearance:button;background-color:#0000;background-image:none}input:where([type=button]){-webkit-appearance:button;background-color:#0000;background-image:none}input:where([type=reset]){-webkit-appearance:button;background-color:#0000;background-image:none}input:where([type=submit]){-webkit-appearance:button;background-color:#0000;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{margin:0;padding:0;list-style:none}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder{opacity:1;color:#9ca3af}textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}html,body,#root{height:100%}body{font-feature-settings:"cv11", "ss01"}body,.stat-card,.nav-link{transition:background-color .15s,border-color .15s,color .15s}.stat-card{--tw-border-opacity:1;border-width:1px;border-color:rgb(241 245 249/var(--tw-border-opacity,1));--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1));--tw-shadow:0 1px 2px 0 #0000000d;--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000), var(--tw-ring-shadow,0 0 #0000), var(--tw-shadow);border-radius:.75rem;flex-direction:column;gap:.25rem;padding:1.25rem;display:flex}.stat-card:is(.dark *){--tw-border-opacity:1;border-color:rgb(31 42 68/var(--tw-border-opacity,1));--tw-bg-opacity:1;background-color:rgb(17 26 44/var(--tw-bg-opacity,1))}.stat-label{text-transform:uppercase;letter-spacing:.05em;--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity,1));font-size:.75rem;font-weight:500;line-height:1rem}.stat-label:is(.dark *){--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.stat-value{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction);font-size:1.875rem;font-weight:600;line-height:2.25rem}.pill{border-radius:.375rem;align-items:center;padding:.125rem .5rem;font-size:.75rem;font-weight:500;line-height:1rem;display:inline-flex}.nav-link{cursor:pointer;--tw-text-opacity:1;color:rgb(51 65 85/var(--tw-text-opacity,1));border-radius:.5rem;padding:.5rem .75rem;font-size:.875rem;font-weight:500;line-height:1.25rem}.nav-link:hover{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity,1))}.nav-link:is(.dark *){--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity,1))}.nav-link:hover:is(.dark *){--tw-bg-opacity:1;background-color:rgb(31 42 68/var(--tw-bg-opacity,1))}.nav-link-active{--tw-bg-opacity:1;background-color:rgb(239 246 255/var(--tw-bg-opacity,1));--tw-text-opacity:1;color:rgb(29 78 216/var(--tw-text-opacity,1))}.nav-link-active:hover{--tw-bg-opacity:1;background-color:rgb(239 246 255/var(--tw-bg-opacity,1))}.nav-link-active:is(.dark *){--tw-text-opacity:1;color:rgb(219 234 254/var(--tw-text-opacity,1));background-color:#1d4ed833}.nav-link-active:hover:is(.dark *){background-color:#1d4ed84d}.dark .scrollbar-thin::-webkit-scrollbar-thumb{background:#1f2a44}.dark .scrollbar-thin::-webkit-scrollbar-thumb:hover{background:#2a3654}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{top:0;bottom:0;left:0;right:0}.bottom-0{bottom:0}.left-0{left:0}.left-3{left:.75rem}.right-0{right:0}.top-0{top:0}.top-1\/2{top:50%}.top-full{top:100%}.z-40{z-index:40}.z-50{z-index:50}.col-span-3{grid-column:span 3/span 3}.col-span-6{grid-column:span 6/span 6}.-mx-2{margin-left:-.5rem;margin-right:-.5rem}.mx-auto{margin-left:auto;margin-right:auto}.-mb-px{margin-bottom:-1px}.-mt-1{margin-top:-.25rem}.mb-1{margin-bottom:.25rem}.mb-1\.5{margin-bottom:.375rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.ml-1{margin-left:.25rem}.ml-1\.5{margin-left:.375rem}.ml-5{margin-left:1.25rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-1\.5{height:.375rem}.h-12{height:3rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-3{height:.75rem}.h-5{height:1.25rem}.h-56{height:14rem}.h-6{height:1.5rem}.h-72{height:18rem}.h-8{height:2rem}.h-9{height:2.25rem}.min-h-\[400px\]{min-height:400px}.min-h-screen{min-height:100vh}.w-1{width:.25rem}.w-1\.5{width:.375rem}.w-12{width:3rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-3{width:.75rem}.w-5{width:1.25rem}.w-56{width:14rem}.w-8{width:2rem}.w-full{width:100%}.w-px{width:1px}.min-w-0{min-width:0}.min-w-\[160px\]{min-width:160px}.min-w-\[180px\]{min-width:180px}.min-w-\[200px\]{min-width:200px}.max-w-3xl{max-width:48rem}.max-w-\[260px\]{max-width:260px}.max-w-md{max-width:28rem}.flex-1{flex:1}.shrink-0{flex-shrink:0}.-translate-y-1\/2{--tw-translate-y:-50%;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate:180deg;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-90{--tw-rotate:90deg;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.scroll-mt-4{scroll-margin-top:1rem}.list-decimal{list-style-type:decimal}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.items-baseline{align-items:baseline}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-ink-100>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(241 245 249/var(--tw-divide-opacity,1))}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.overflow-x-hidden{overflow-x:hidden}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.whitespace-pre-wrap{white-space:pre-wrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-sm{border-radius:.125rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-b-2{border-bottom-width:2px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-bad-500\/40{border-color:#dc262666}.border-brand-100{--tw-border-opacity:1;border-color:rgb(219 234 254/var(--tw-border-opacity,1))}.border-brand-500{--tw-border-opacity:1;border-color:rgb(59 130 246/var(--tw-border-opacity,1))}.border-brand-500\/40{border-color:#3b82f666}.border-brand-600{--tw-border-opacity:1;border-color:rgb(37 99 235/var(--tw-border-opacity,1))}.border-emerald-300\/60{border-color:#6ee7b799}.border-ink-100{--tw-border-opacity:1;border-color:rgb(241 245 249/var(--tw-border-opacity,1))}.border-ink-300{--tw-border-opacity:1;border-color:rgb(203 213 225/var(--tw-border-opacity,1))}.border-ok-500\/40{border-color:#16a34a66}.border-purple-500\/40{border-color:#a855f766}.border-transparent{border-color:#0000}.border-warn-500\/40{border-color:#d9770666}.bg-amber-100{--tw-bg-opacity:1;background-color:rgb(254 243 199/var(--tw-bg-opacity,1))}.bg-bad-100{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity,1))}.bg-bad-100\/30{background-color:#fee2e24d}.bg-bad-500{--tw-bg-opacity:1;background-color:rgb(220 38 38/var(--tw-bg-opacity,1))}.bg-brand-100{--tw-bg-opacity:1;background-color:rgb(219 234 254/var(--tw-bg-opacity,1))}.bg-brand-50{--tw-bg-opacity:1;background-color:rgb(239 246 255/var(--tw-bg-opacity,1))}.bg-brand-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.bg-brand-600{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity,1))}.bg-emerald-100{--tw-bg-opacity:1;background-color:rgb(209 250 229/var(--tw-bg-opacity,1))}.bg-emerald-500{--tw-bg-opacity:1;background-color:rgb(16 185 129/var(--tw-bg-opacity,1))}.bg-ink-100{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity,1))}.bg-ink-100\/50{background-color:#f1f5f980}.bg-ink-300{--tw-bg-opacity:1;background-color:rgb(203 213 225/var(--tw-bg-opacity,1))}.bg-ink-500{--tw-bg-opacity:1;background-color:rgb(100 116 139/var(--tw-bg-opacity,1))}.bg-ink-900\/50{background-color:#0f172a80}.bg-ok-100{--tw-bg-opacity:1;background-color:rgb(220 252 231/var(--tw-bg-opacity,1))}.bg-ok-100\/30{background-color:#dcfce74d}.bg-ok-500{--tw-bg-opacity:1;background-color:rgb(22 163 74/var(--tw-bg-opacity,1))}.bg-purple-100{--tw-bg-opacity:1;background-color:rgb(243 232 255/var(--tw-bg-opacity,1))}.bg-purple-500{--tw-bg-opacity:1;background-color:rgb(168 85 247/var(--tw-bg-opacity,1))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity,1))}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.bg-sky-100{--tw-bg-opacity:1;background-color:rgb(224 242 254/var(--tw-bg-opacity,1))}.bg-sky-500{--tw-bg-opacity:1;background-color:rgb(14 165 233/var(--tw-bg-opacity,1))}.bg-warn-100{--tw-bg-opacity:1;background-color:rgb(254 243 199/var(--tw-bg-opacity,1))}.bg-warn-500{--tw-bg-opacity:1;background-color:rgb(217 119 6/var(--tw-bg-opacity,1))}.bg-warn-500\/10{background-color:#d977061a}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.bg-white\/60{background-color:#fff9}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.pl-12{padding-left:3rem}.pl-20{padding-left:5rem}.pl-5{padding-left:1.25rem}.pl-9{padding-left:2.25rem}.pr-3{padding-right:.75rem}.pr-4{padding-right:1rem}.pr-5{padding-right:1.25rem}.pt-3{padding-top:.75rem}.pt-4{padding-top:1rem}.pt-5{padding-top:1.25rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace}.font-sans{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.text-2xl{font-size:1.5rem;line-height:2rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)}.leading-none{line-height:1}.leading-tight{line-height:1.25}.tracking-wide{letter-spacing:.025em}.tracking-wider{letter-spacing:.05em}.text-amber-700{--tw-text-opacity:1;color:rgb(180 83 9/var(--tw-text-opacity,1))}.text-bad-500{--tw-text-opacity:1;color:rgb(220 38 38/var(--tw-text-opacity,1))}.text-brand-600{--tw-text-opacity:1;color:rgb(37 99 235/var(--tw-text-opacity,1))}.text-brand-700{--tw-text-opacity:1;color:rgb(29 78 216/var(--tw-text-opacity,1))}.text-emerald-700{--tw-text-opacity:1;color:rgb(4 120 87/var(--tw-text-opacity,1))}.text-ink-300{--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity,1))}.text-ink-500{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity,1))}.text-ink-700{--tw-text-opacity:1;color:rgb(51 65 85/var(--tw-text-opacity,1))}.text-ink-900{--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity,1))}.text-ok-500{--tw-text-opacity:1;color:rgb(22 163 74/var(--tw-text-opacity,1))}.text-purple-700{--tw-text-opacity:1;color:rgb(126 34 206/var(--tw-text-opacity,1))}.text-red-700{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity,1))}.text-sky-700{--tw-text-opacity:1;color:rgb(3 105 161/var(--tw-text-opacity,1))}.text-warn-500{--tw-text-opacity:1;color:rgb(217 119 6/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-white\/80{color:#fffc}.line-through{text-decoration-line:line-through}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.accent-brand-600{accent-color:#2563eb}.opacity-35{opacity:.35}.opacity-40{opacity:.4}.opacity-50{opacity:.5}.opacity-70{opacity:.7}.shadow-2xl{--tw-shadow:0 25px 50px -12px #00000040;--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000), var(--tw-ring-shadow,0 0 #0000), var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000), var(--tw-ring-shadow,0 0 #0000), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 2px 0 #0000000d;--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000), var(--tw-ring-shadow,0 0 #0000), var(--tw-shadow)}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow,0 0 #0000)}.ring-brand-500{--tw-ring-opacity:1;--tw-ring-color:rgb(59 130 246/var(--tw-ring-opacity,1))}.invert{--tw-invert:invert(100%);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.\!filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)!important}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-transform{transition-property:transform;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-700{transition-duration:.7s}.placeholder\:text-ink-500::placeholder{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity,1))}.hover\:border-ink-300:hover{--tw-border-opacity:1;border-color:rgb(203 213 225/var(--tw-border-opacity,1))}.hover\:bg-brand-700:hover{--tw-bg-opacity:1;background-color:rgb(29 78 216/var(--tw-bg-opacity,1))}.hover\:bg-ink-100:hover{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity,1))}.hover\:bg-ink-100\/40:hover{background-color:#f1f5f966}.hover\:bg-ink-100\/50:hover{background-color:#f1f5f980}.hover\:bg-ink-100\/60:hover{background-color:#f1f5f999}.hover\:bg-ink-300\/60:hover{background-color:#cbd5e199}.hover\:text-ink-700:hover{--tw-text-opacity:1;color:rgb(51 65 85/var(--tw-text-opacity,1))}.focus\:border-transparent:focus{border-color:#0000}.focus\:outline-none:focus{outline-offset:2px;outline:2px solid #0000}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow,0 0 #0000)}.focus\:ring-brand-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(59 130 246/var(--tw-ring-opacity,1))}.focus-visible\:outline:focus-visible{outline-style:solid}.focus-visible\:outline-2:focus-visible{outline-width:2px}.focus-visible\:outline-brand-500:focus-visible{outline-color:#3b82f6}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-40:disabled{opacity:.4}.dark\:divide-night-700:is(.dark *)>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(31 42 68/var(--tw-divide-opacity,1))}.dark\:border-amber-500\/40:is(.dark *){border-color:#f59e0b66}.dark\:border-brand-500\/40:is(.dark *){border-color:#3b82f666}.dark\:border-brand-700\/40:is(.dark *){border-color:#1d4ed866}.dark\:border-emerald-500\/40:is(.dark *){border-color:#10b98166}.dark\:border-emerald-700:is(.dark *){--tw-border-opacity:1;border-color:rgb(4 120 87/var(--tw-border-opacity,1))}.dark\:border-night-500:is(.dark *){--tw-border-opacity:1;border-color:rgb(148 163 184/var(--tw-border-opacity,1))}.dark\:border-night-600:is(.dark *){--tw-border-opacity:1;border-color:rgb(42 54 84/var(--tw-border-opacity,1))}.dark\:border-night-700:is(.dark *){--tw-border-opacity:1;border-color:rgb(31 42 68/var(--tw-border-opacity,1))}.dark\:border-purple-500\/40:is(.dark *){border-color:#a855f766}.dark\:border-red-500\/40:is(.dark *){border-color:#ef444466}.dark\:bg-amber-500\/15:is(.dark *){background-color:#f59e0b26}.dark\:bg-black\/70:is(.dark *){background-color:#000000b3}.dark\:bg-brand-500:is(.dark *){--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity,1))}.dark\:bg-brand-700\/15:is(.dark *){background-color:#1d4ed826}.dark\:bg-brand-700\/20:is(.dark *){background-color:#1d4ed833}.dark\:bg-brand-700\/25:is(.dark *){background-color:#1d4ed840}.dark\:bg-brand-700\/30:is(.dark *){background-color:#1d4ed84d}.dark\:bg-emerald-400:is(.dark *){--tw-bg-opacity:1;background-color:rgb(52 211 153/var(--tw-bg-opacity,1))}.dark\:bg-emerald-500\/15:is(.dark *){background-color:#10b98126}.dark\:bg-emerald-500\/5:is(.dark *){background-color:#10b9810d}.dark\:bg-emerald-900\/40:is(.dark *){background-color:#064e3b66}.dark\:bg-night-500:is(.dark *){--tw-bg-opacity:1;background-color:rgb(148 163 184/var(--tw-bg-opacity,1))}.dark\:bg-night-700:is(.dark *){--tw-bg-opacity:1;background-color:rgb(31 42 68/var(--tw-bg-opacity,1))}.dark\:bg-night-700\/50:is(.dark *){background-color:#1f2a4480}.dark\:bg-night-800:is(.dark *){--tw-bg-opacity:1;background-color:rgb(17 26 44/var(--tw-bg-opacity,1))}.dark\:bg-night-900:is(.dark *){--tw-bg-opacity:1;background-color:rgb(11 18 32/var(--tw-bg-opacity,1))}.dark\:bg-night-900\/20:is(.dark *){background-color:#0b122033}.dark\:bg-night-900\/30:is(.dark *){background-color:#0b12204d}.dark\:bg-night-900\/40:is(.dark *){background-color:#0b122066}.dark\:bg-purple-500\/15:is(.dark *){background-color:#a855f726}.dark\:bg-red-400:is(.dark *){--tw-bg-opacity:1;background-color:rgb(248 113 113/var(--tw-bg-opacity,1))}.dark\:bg-red-500\/15:is(.dark *){background-color:#ef444426}.dark\:bg-red-500\/5:is(.dark *){background-color:#ef44440d}.dark\:bg-sky-500\/15:is(.dark *){background-color:#0ea5e926}.dark\:bg-sky-900\/40:is(.dark *){background-color:#0c4a6e66}.dark\:text-amber-300:is(.dark *){--tw-text-opacity:1;color:rgb(252 211 77/var(--tw-text-opacity,1))}.dark\:text-brand-100:is(.dark *){--tw-text-opacity:1;color:rgb(219 234 254/var(--tw-text-opacity,1))}.dark\:text-brand-500:is(.dark *){--tw-text-opacity:1;color:rgb(59 130 246/var(--tw-text-opacity,1))}.dark\:text-emerald-300:is(.dark *){--tw-text-opacity:1;color:rgb(110 231 183/var(--tw-text-opacity,1))}.dark\:text-night-100:is(.dark *){--tw-text-opacity:1;color:rgb(226 232 240/var(--tw-text-opacity,1))}.dark\:text-night-300:is(.dark *){--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity,1))}.dark\:text-night-500:is(.dark *){--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.dark\:text-purple-300:is(.dark *){--tw-text-opacity:1;color:rgb(216 180 254/var(--tw-text-opacity,1))}.dark\:text-red-300:is(.dark *){--tw-text-opacity:1;color:rgb(252 165 165/var(--tw-text-opacity,1))}.dark\:text-sky-300:is(.dark *){--tw-text-opacity:1;color:rgb(125 211 252/var(--tw-text-opacity,1))}.dark\:placeholder\:text-night-500:is(.dark *)::-moz-placeholder{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.dark\:placeholder\:text-night-500:is(.dark *)::placeholder{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.dark\:hover\:border-night-600:hover:is(.dark *){--tw-border-opacity:1;border-color:rgb(42 54 84/var(--tw-border-opacity,1))}.dark\:hover\:bg-night-600:hover:is(.dark *){--tw-bg-opacity:1;background-color:rgb(42 54 84/var(--tw-bg-opacity,1))}.dark\:hover\:bg-night-700:hover:is(.dark *){--tw-bg-opacity:1;background-color:rgb(31 42 68/var(--tw-bg-opacity,1))}.dark\:hover\:bg-night-700\/30:hover:is(.dark *){background-color:#1f2a444d}.dark\:hover\:bg-night-700\/40:hover:is(.dark *){background-color:#1f2a4466}.dark\:hover\:text-night-300:hover:is(.dark *){--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity,1))}@media (min-width:640px){.sm\:col-span-2{grid-column:span 2/span 2}.sm\:col-span-7{grid-column:span 7/span 7}.sm\:block{display:block}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}@media (min-width:768px){.md\:inline-flex{display:inline-flex}}@media (min-width:1024px){.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}}@media (min-width:1280px){.xl\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}
|
|
127
127
|
/*$vite$:1*/</style>
|
package/src/dashboard/types.ts
CHANGED
|
@@ -144,6 +144,7 @@ export interface ScenarioSnapshot {
|
|
|
144
144
|
duration?: number; // ms
|
|
145
145
|
errorMessage?: string;
|
|
146
146
|
tracePath?: string;
|
|
147
|
+
manualReason?: string; // `# MANUAL: …` reason → Note column of a Pending manual row
|
|
147
148
|
executedDate?: string; // dd/mm/yyyy
|
|
148
149
|
testEnvironment?: string;
|
|
149
150
|
testExecutor?: string;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import * as fs from 'fs';
|
|
7
7
|
import * as path from 'path';
|
|
8
8
|
import { getPackageVersion } from './package-info';
|
|
9
|
-
import { MergedScenario } from './scenario-merger';
|
|
9
|
+
import { MergedScenario, extractManualReason } from './scenario-merger';
|
|
10
10
|
import {
|
|
11
11
|
extractAuthRole,
|
|
12
12
|
extractPriority,
|
|
@@ -27,10 +27,15 @@ import { collectSecretValues, formatApiCallSummaryLines, formatApiExpected, form
|
|
|
27
27
|
import { SelectorKeyMap, substituteSelectorKeysInStep } from './selector-key-resolver';
|
|
28
28
|
import { formatVariantRow, resolveResultVariants } from './result-variants';
|
|
29
29
|
import { collectQaEnvSecretDenylist, warnIfRedactionIncomplete } from './qa-env-secret-denylist';
|
|
30
|
+
import { formatEnv } from './run-environment';
|
|
30
31
|
|
|
31
32
|
export interface BuildCsvInput {
|
|
32
33
|
screen: string;
|
|
33
34
|
featureName: string;
|
|
35
|
+
/** The exact command that regenerates this unit (`sungen generate --flow checkout`). `screen`
|
|
36
|
+
* is the deliverable label — the FEATURE basename, `flow/<x>` for a flow — so a note built from
|
|
37
|
+
* it named a command that fails (#880). */
|
|
38
|
+
generateCommand?: string;
|
|
34
39
|
/** URL path for the screen/flow entry point — concatenated onto baseURL
|
|
35
40
|
* when building the Test Environment column so QA can see the exact URL
|
|
36
41
|
* the test targets. */
|
|
@@ -206,7 +211,12 @@ export function buildTestCaseRows(input: BuildCsvInput): TestCaseRow[] {
|
|
|
206
211
|
// No execution record AND no compiled test → Manual if @manual, else genuinely not compiled.
|
|
207
212
|
testResult = testcaseType === 'Manual' ? 'Pending' : 'N/A';
|
|
208
213
|
if (testcaseType !== 'Manual') {
|
|
209
|
-
note =
|
|
214
|
+
note = `Scenario not compiled — re-run \`${input.generateCommand ?? `sungen generate --screen ${input.screen}`}\``;
|
|
215
|
+
} else {
|
|
216
|
+
// Why the case is manual — the `# MANUAL: …` comment — so the tester reading the
|
|
217
|
+
// deliverable knows what blocks automation (#810). Empty when no reason is written.
|
|
218
|
+
const reason = extractManualReason(m.feature.comments ?? []);
|
|
219
|
+
if (reason) note = redactSecrets(`Manual: ${reason}`, qaEnvSecrets.values);
|
|
210
220
|
}
|
|
211
221
|
} else {
|
|
212
222
|
// Compiled but no execution record → Pending
|
|
@@ -290,15 +300,6 @@ export function buildSummary(screen: string, rows: TestCaseRow[], outputFile: st
|
|
|
290
300
|
* the baseURL so the deliverable shows the exact URL each test targets
|
|
291
301
|
* (e.g. `https://staging.example.com/kudos (chromium)`).
|
|
292
302
|
*/
|
|
293
|
-
function formatEnv(baseURL: string, featurePath: string | undefined, projectName: string): string {
|
|
294
|
-
const base = (baseURL || '').replace(/\/+$/, '');
|
|
295
|
-
const p = (featurePath || '').replace(/^\/+/, '');
|
|
296
|
-
// Join with '/' only when there is a baseURL (web). For mobile baseURL is empty
|
|
297
|
-
// and `p` is an app id (e.g. com.kngroup.media.converter) — emit it bare, no '/'.
|
|
298
|
-
const url = base && p ? `${base}/${p}` : (p || base);
|
|
299
|
-
return `${url} (${projectName})`;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
303
|
function csvCell(v: string | number | undefined | null): string {
|
|
303
304
|
if (v === null || v === undefined) return '';
|
|
304
305
|
const s = String(v);
|
|
@@ -3,9 +3,39 @@
|
|
|
3
3
|
* Reuses the existing GherkinParser.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { GherkinParser, ParsedFeature, ParsedScenario } from '../generators/gherkin-parser';
|
|
6
|
+
import { GherkinParser, ParsedDataTable, ParsedFeature, ParsedScenario } from '../generators/gherkin-parser';
|
|
7
7
|
import { FeatureMetadata, OrderedStep, ScenarioMetadata } from './types';
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Fold a step's data table into the text the exporters carry (#771). The table
|
|
11
|
+
* IS the step's content — `tab order:` names every stop, `table match data:`
|
|
12
|
+
* every expected row — so without it a delivered case says "See tab order:."
|
|
13
|
+
* and a table edit leaves the scenario fingerprint unchanged.
|
|
14
|
+
*
|
|
15
|
+
* Folded once, here, so every consumer (matrix + legacy cells, fingerprint,
|
|
16
|
+
* oracle shape) sees the same thing. A step with no table keeps its text
|
|
17
|
+
* byte-identical: no existing fingerprint moves on upgrade.
|
|
18
|
+
*
|
|
19
|
+
* `tab order:` | Ref | [A] | [B] | → `tab order: [A] → [B]` (order is the meaning;
|
|
20
|
+
* `Ref` is a keyword header, not a column name)
|
|
21
|
+
* any other | Name | Age | … → `…: Name: Alice, Age: 30; Name: Bob, Age: 25`
|
|
22
|
+
* (one column too: `Title: x; Title: y` — its header names what x is)
|
|
23
|
+
*
|
|
24
|
+
* A blank cell renders as `(empty)` — the matrix's data-fidelity word. Left blank it would
|
|
25
|
+
* read `Age: ;`, indistinguishable from the truncation this fixes, and in `table match
|
|
26
|
+
* data:` a blank cell is itself an assertion (the cell is empty).
|
|
27
|
+
*/
|
|
28
|
+
export function withDataTable(text: string, table: ParsedDataTable | undefined): string {
|
|
29
|
+
if (!table || table.rows.length === 0) return text;
|
|
30
|
+
const base = text.replace(/\s*:\s*$/, '');
|
|
31
|
+
const cell = (v: string | undefined): string => (v === undefined || v.trim() === '' ? '(empty)' : v);
|
|
32
|
+
// Only `tab order` is a sequence of refs — the one shape matrix/wording.ts reads as `→`.
|
|
33
|
+
const body = /\btab order$/i.test(base)
|
|
34
|
+
? table.rows.map((r) => cell(r.cells[0])).join(' → ')
|
|
35
|
+
: table.rows.map((r) => table.headers.map((h, i) => `${h}: ${cell(r.cells[i])}`).join(', ')).join('; ');
|
|
36
|
+
return `${base}: ${body}`;
|
|
37
|
+
}
|
|
38
|
+
|
|
9
39
|
/**
|
|
10
40
|
* Variables referenced in a scenario: find all {{var_name}} in step text.
|
|
11
41
|
*/
|
|
@@ -60,7 +90,7 @@ function classifySteps(scenario: ParsedScenario): OrderedStep[] {
|
|
|
60
90
|
else if (keyword === 'Then') currentBucket = 'then';
|
|
61
91
|
// And / But → inherit currentBucket
|
|
62
92
|
|
|
63
|
-
ordered.push({ text: step.text, bucket: currentBucket });
|
|
93
|
+
ordered.push({ text: withDataTable(step.text, step.dataTable), bucket: currentBucket });
|
|
64
94
|
}
|
|
65
95
|
|
|
66
96
|
return ordered;
|
|
@@ -87,6 +117,7 @@ export function parseFeatureMetadata(featureFilePath: string): FeatureMetadata {
|
|
|
87
117
|
referencedVars: extractReferencedVars(sc, extractTestcaseType([...parsed.tags, ...sc.tags]) === 'Manual'),
|
|
88
118
|
orderedSteps: classifySteps(sc),
|
|
89
119
|
comments: sc.comments,
|
|
120
|
+
hookType: sc.hookType,
|
|
90
121
|
}));
|
|
91
122
|
|
|
92
123
|
return {
|
|
@@ -106,6 +137,17 @@ export function isStepsBaseScenario(sc: ScenarioMetadata): boolean {
|
|
|
106
137
|
return !!sc.stepsName;
|
|
107
138
|
}
|
|
108
139
|
|
|
140
|
+
/**
|
|
141
|
+
* A hook (`@beforeAll` / `@afterEach` / `@afterAll`) — setup or teardown around the tests, compiled
|
|
142
|
+
* to `test.beforeAll()` etc. Read from the scenario's OWN tag (the parser's `hookType`), never from
|
|
143
|
+
* the feature+scenario tag union. It is not a test case: counted as one, it blocked the matrix at
|
|
144
|
+
* Gate A (a hook carries no VP id, as the gherkin skill tells authors) and showed in the legacy
|
|
145
|
+
* workbook and the dashboard as a "Not compiled" row (#880).
|
|
146
|
+
*/
|
|
147
|
+
export function isHookScenario(sc: ScenarioMetadata): boolean {
|
|
148
|
+
return !!sc.hookType;
|
|
149
|
+
}
|
|
150
|
+
|
|
109
151
|
/**
|
|
110
152
|
* Return true if this is the default scaffold sample scenario (not real).
|
|
111
153
|
*/
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* richer ScenarioSnapshot / ScreenSnapshot shape used by the dashboard UI.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { MergedScenario } from './scenario-merger';
|
|
8
|
+
import { MergedScenario, extractManualReason } from './scenario-merger';
|
|
9
9
|
import {
|
|
10
10
|
extractAuthRole,
|
|
11
11
|
extractPriority,
|
|
@@ -192,6 +192,7 @@ export function buildScreenSnapshot(input: BuildScreenSnapshotInput): ScreenSnap
|
|
|
192
192
|
let testEnvironment: string | undefined;
|
|
193
193
|
let testExecutor: string | undefined;
|
|
194
194
|
let type: ScenarioSnapshot['type'];
|
|
195
|
+
let manualReason: string | undefined;
|
|
195
196
|
|
|
196
197
|
if (result) {
|
|
197
198
|
// A result exists → the scenario compiled AND ran; authoritative over the `!m.spec`
|
|
@@ -224,6 +225,9 @@ export function buildScreenSnapshot(input: BuildScreenSnapshotInput): ScreenSnap
|
|
|
224
225
|
// No result AND no compiled test → Manual if @manual, else genuinely not compiled.
|
|
225
226
|
type = baseType === 'Manual' ? 'Manual' : 'Not compiled';
|
|
226
227
|
status = baseType === 'Manual' ? 'Pending' : 'N/A';
|
|
228
|
+
// Same Note source as csv-exporter: the `# MANUAL: …` reason (#810).
|
|
229
|
+
const reason = baseType === 'Manual' ? extractManualReason(m.feature.comments ?? []) : '';
|
|
230
|
+
if (reason) manualReason = redactSecrets(reason, qaEnvSecrets.values);
|
|
227
231
|
} else {
|
|
228
232
|
// Compiled but no execution record → Pending.
|
|
229
233
|
type = baseType;
|
|
@@ -249,6 +253,7 @@ export function buildScreenSnapshot(input: BuildScreenSnapshotInput): ScreenSnap
|
|
|
249
253
|
executedDate,
|
|
250
254
|
errorMessage,
|
|
251
255
|
tracePath,
|
|
256
|
+
manualReason,
|
|
252
257
|
testEnvironment,
|
|
253
258
|
testExecutor,
|
|
254
259
|
});
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
*/
|
|
35
35
|
import * as fs from 'fs';
|
|
36
36
|
import * as path from 'path';
|
|
37
|
-
import {
|
|
37
|
+
import { readYamlConfig, warnUnreadableConfig } from '../harness/config-file';
|
|
38
38
|
|
|
39
39
|
export interface LocaleVariant {
|
|
40
40
|
/** Result-file suffix as found on disk ('' = base). */
|
|
@@ -65,23 +65,29 @@ export interface LocaleConfig {
|
|
|
65
65
|
|
|
66
66
|
export const DEFAULT_BASE_LOCALE = 'en';
|
|
67
67
|
|
|
68
|
-
/**
|
|
68
|
+
/**
|
|
69
|
+
* Read the i18n declaration from qa/capabilities.yaml (absent → no locales, base 'en').
|
|
70
|
+
*
|
|
71
|
+
* An unreadable file previously took the same path as an absent one — the `existsSync` check sat
|
|
72
|
+
* INSIDE the try, so a parse error fell through to the same "undeclared" return. Every declared
|
|
73
|
+
* locale then dropped out of the deliverable with no line anywhere saying why.
|
|
74
|
+
*/
|
|
69
75
|
export function readLocaleConfig(cwd: string): LocaleConfig {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
return { baseLocale
|
|
76
|
+
const p = path.join(cwd, 'qa', 'capabilities.yaml');
|
|
77
|
+
const read = readYamlConfig<{ locales?: unknown; base_locale?: unknown } | null>(p);
|
|
78
|
+
if (read.state === 'absent') return { baseLocale: DEFAULT_BASE_LOCALE, locales: [] };
|
|
79
|
+
if (read.state === 'unreadable') {
|
|
80
|
+
warnUnreadableConfig(p, read.error, 'no locale variants are discovered — the deliverable covers the base locale only');
|
|
81
|
+
return { baseLocale: DEFAULT_BASE_LOCALE, locales: [] };
|
|
82
|
+
}
|
|
83
|
+
const parsed = read.value;
|
|
84
|
+
const locales = Array.isArray(parsed?.locales)
|
|
85
|
+
? parsed!.locales!.filter((l): l is string => typeof l === 'string' && l.length > 0)
|
|
86
|
+
: [];
|
|
87
|
+
const baseLocale = typeof parsed?.base_locale === 'string' && parsed.base_locale
|
|
88
|
+
? parsed.base_locale
|
|
89
|
+
: DEFAULT_BASE_LOCALE;
|
|
90
|
+
return { baseLocale, locales };
|
|
85
91
|
}
|
|
86
92
|
|
|
87
93
|
const OS_SUFFIX = /^(android|ios)(\.|$)/;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The @manual "presence placeholder" hybrid (#810) — one predicate for every stage.
|
|
3
|
+
*
|
|
4
|
+
* Shape: a @manual scenario keeps complete Gherkin, but its only assertions are bare presence
|
|
5
|
+
* checks (`Then User see [Job List] table`), while the REAL oracle ("the newer row appears above
|
|
6
|
+
* the older one") sits in an unlabelled `# Tester verifies:` comment. Both gates only asked "is
|
|
7
|
+
* there a Then?", and the exporter only captures numbered comment lines — so the deliverable said
|
|
8
|
+
* "See [Job List] table" and a tester ticking it Passed recorded a check nobody made.
|
|
9
|
+
*
|
|
10
|
+
* The compile gate (SG-W008), the audit gate (MANUAL-STEPS-INSUFFICIENT) and both exporters read
|
|
11
|
+
* the comment block through THIS module, so the three can never disagree about what the oracle is.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
export interface KeywordStep {
|
|
15
|
+
/** Gherkin keyword as written: Given / When / Then / And / But (surrounding space allowed). */
|
|
16
|
+
keyword: string;
|
|
17
|
+
/** Step text without the keyword. */
|
|
18
|
+
text: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const NUMBERED = /^\d+[.)]\s*/;
|
|
22
|
+
const DIVIDER = /^[-=*_]{2,}/;
|
|
23
|
+
const HEADER = /^tester verifies\b\s*:?\s*(.*)$/i;
|
|
24
|
+
const LABELLED_ORACLE = /^\d+[.)]\s*[A-Za-z /]*?(observ|oracle|expect|result|then|assert)[A-Za-z /]*:/i;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The prose a `Tester verifies:` header carries when it is NOT written as numbered lines — the
|
|
28
|
+
* text on the header line itself plus the lines after it, up to the first numbered item or divider.
|
|
29
|
+
* Returns null when the block is empty (a bare header followed by numbered items is the structured
|
|
30
|
+
* shape, not this one) or when there is no header at all. Only the FIRST header's block is read —
|
|
31
|
+
* a second `Tester verifies:` ends it.
|
|
32
|
+
*/
|
|
33
|
+
export function extractUnlabeledOracle(comments: string[]): string | null {
|
|
34
|
+
const parts: string[] = [];
|
|
35
|
+
let inBlock = false;
|
|
36
|
+
for (const raw of comments) {
|
|
37
|
+
const line = raw.trim();
|
|
38
|
+
if (!inBlock) {
|
|
39
|
+
const m = line.match(HEADER);
|
|
40
|
+
if (!m) continue;
|
|
41
|
+
inBlock = true;
|
|
42
|
+
if (m[1].trim()) parts.push(m[1].trim());
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (!line) continue;
|
|
46
|
+
if (NUMBERED.test(line) || DIVIDER.test(line) || HEADER.test(line)) break;
|
|
47
|
+
parts.push(line);
|
|
48
|
+
}
|
|
49
|
+
const text = parts.join(' ').replace(/\s+/g, ' ').trim();
|
|
50
|
+
return text ? text : null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** True when the comments state an oracle — a labelled numbered line, or unlabelled header prose. */
|
|
54
|
+
export function hasCommentOracle(comments: string[]): boolean {
|
|
55
|
+
return comments.some((c) => LABELLED_ORACLE.test(c.trim())) || extractUnlabeledOracle(comments) !== null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* A bare presence assertion: the element exists, nothing about its content, order, count or state.
|
|
60
|
+
* `User see [Job List] table` / `User is on [Home] page` / `User see [Save] button is visible`.
|
|
61
|
+
* Anything after the element type (`match data:`, `with {{v}}`, `row 2`, `is sorted …`) is a real check.
|
|
62
|
+
*/
|
|
63
|
+
export function isPresenceOnlyAssertion(text: string): boolean {
|
|
64
|
+
return /^User (?:see|is on) \[[^\]]+\](?: [a-z]+)?(?: (?:is|are) (?:visible|displayed|shown))?\s*$/i.test(text.trim());
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* True when no assertion checks anything beyond presence — including when there is no assertion
|
|
69
|
+
* at all (a documentation-style manual). Only then may unlabelled comment prose stand in as the
|
|
70
|
+
* oracle: a Then that already asserts content/order/count IS the oracle, and replacing it with the
|
|
71
|
+
* prose would drop the real check from the deliverable.
|
|
72
|
+
*/
|
|
73
|
+
export function onlyPresenceAssertions(assertionTexts: string[]): boolean {
|
|
74
|
+
return assertionTexts.every(isPresenceOnlyAssertion);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** The scenario's assertion steps — a Then, plus every And/But whose preceding explicit keyword is Then. */
|
|
78
|
+
export function assertionSteps(steps: KeywordStep[]): KeywordStep[] {
|
|
79
|
+
let bucket = '';
|
|
80
|
+
const out: KeywordStep[] = [];
|
|
81
|
+
for (const s of steps) {
|
|
82
|
+
const kw = s.keyword.trim();
|
|
83
|
+
if (kw === 'Given' || kw === 'When' || kw === 'Then') bucket = kw;
|
|
84
|
+
if (bucket === 'Then') out.push(s);
|
|
85
|
+
}
|
|
86
|
+
return out;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* The banned hybrid: ≥1 assertion, every assertion a bare presence placeholder, and an oracle in
|
|
91
|
+
* the comments. A @manual whose Gherkin already asserts something real is fine — its comments are
|
|
92
|
+
* an elaboration, not the only statement of what the case checks.
|
|
93
|
+
*/
|
|
94
|
+
export function isPresencePlaceholderHybrid(steps: KeywordStep[], comments: string[]): boolean {
|
|
95
|
+
const asserts = assertionSteps(steps);
|
|
96
|
+
return asserts.length > 0 && onlyPresenceAssertions(asserts.map((s) => s.text)) && hasCommentOracle(comments);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** Split raw scenario-block lines into keyword steps (for the text-based audit gate). */
|
|
100
|
+
export function keywordStepsOf(block: string): KeywordStep[] {
|
|
101
|
+
const out: KeywordStep[] = [];
|
|
102
|
+
for (const line of block.split('\n')) {
|
|
103
|
+
const m = line.match(/^\s*(Given|When|Then|And|But)\s+(.+?)\s*$/);
|
|
104
|
+
if (m) out.push({ keyword: m[1], text: m[2] });
|
|
105
|
+
}
|
|
106
|
+
return out;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Comment lines of a raw scenario block, with the leading `# ` stripped. */
|
|
110
|
+
export function commentLinesOf(block: string): string[] {
|
|
111
|
+
return block.split('\n').filter((l) => /^\s*#/.test(l)).map((l) => l.replace(/^\s*#\s?/, ''));
|
|
112
|
+
}
|