@sun-asterisk/sungen 3.2.29 → 3.2.30
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/delivery.d.ts.map +1 -1
- package/dist/cli/commands/delivery.js +2 -1
- 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 +6 -2
- package/dist/cli/commands/generate.js.map +1 -1
- package/dist/cli/commands/inspect.js +1 -1
- package/dist/cli/commands/inspect.js.map +1 -1
- package/dist/cli/commands/results-merge.d.ts.map +1 -1
- package/dist/cli/commands/results-merge.js +9 -2
- package/dist/cli/commands/results-merge.js.map +1 -1
- package/dist/cli/commands/results-sanitize.d.ts +24 -0
- package/dist/cli/commands/results-sanitize.d.ts.map +1 -0
- package/dist/cli/commands/results-sanitize.js +126 -0
- package/dist/cli/commands/results-sanitize.js.map +1 -0
- package/dist/cli/commands/script-check.d.ts.map +1 -1
- package/dist/cli/commands/script-check.js +3 -1
- package/dist/cli/commands/script-check.js.map +1 -1
- 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/exporters/api-testcase-formatter.d.ts +3 -6
- package/dist/exporters/api-testcase-formatter.d.ts.map +1 -1
- package/dist/exporters/api-testcase-formatter.js +7 -10
- package/dist/exporters/api-testcase-formatter.js.map +1 -1
- package/dist/exporters/matrix/build.d.ts.map +1 -1
- package/dist/exporters/matrix/build.js +4 -2
- package/dist/exporters/matrix/build.js.map +1 -1
- package/dist/exporters/matrix/render-coverage-sheet.d.ts.map +1 -1
- package/dist/exporters/matrix/render-coverage-sheet.js +3 -1
- package/dist/exporters/matrix/render-coverage-sheet.js.map +1 -1
- package/dist/exporters/matrix/render-csv.d.ts.map +1 -1
- package/dist/exporters/matrix/render-csv.js +3 -1
- package/dist/exporters/matrix/render-csv.js.map +1 -1
- package/dist/exporters/matrix/render-overview-sheet.d.ts.map +1 -1
- package/dist/exporters/matrix/render-overview-sheet.js +5 -9
- package/dist/exporters/matrix/render-overview-sheet.js.map +1 -1
- package/dist/exporters/matrix/result-totals.d.ts +23 -0
- package/dist/exporters/matrix/result-totals.d.ts.map +1 -0
- package/dist/exporters/matrix/result-totals.js +21 -0
- package/dist/exporters/matrix/result-totals.js.map +1 -0
- package/dist/exporters/matrix/testcase-summary-band.d.ts.map +1 -1
- package/dist/exporters/matrix/testcase-summary-band.js +2 -6
- package/dist/exporters/matrix/testcase-summary-band.js.map +1 -1
- package/dist/exporters/qa-env-secret-denylist.js +2 -2
- package/dist/exporters/qa-env-secret-denylist.js.map +1 -1
- package/dist/exporters/report-path-sanitizer.d.ts +38 -0
- package/dist/exporters/report-path-sanitizer.d.ts.map +1 -0
- package/dist/exporters/report-path-sanitizer.js +137 -0
- package/dist/exporters/report-path-sanitizer.js.map +1 -0
- package/dist/exporters/result-variants.d.ts.map +1 -1
- package/dist/exporters/result-variants.js +2 -1
- package/dist/exporters/result-variants.js.map +1 -1
- package/dist/exporters/sensitive-key.d.ts +31 -0
- package/dist/exporters/sensitive-key.d.ts.map +1 -0
- package/dist/exporters/sensitive-key.js +50 -0
- package/dist/exporters/sensitive-key.js.map +1 -0
- package/dist/exporters/test-data-resolver.d.ts +4 -1
- package/dist/exporters/test-data-resolver.d.ts.map +1 -1
- package/dist/exporters/test-data-resolver.js +12 -2
- package/dist/exporters/test-data-resolver.js.map +1 -1
- package/dist/generators/gherkin-parser/index.d.ts +3 -0
- package/dist/generators/gherkin-parser/index.d.ts.map +1 -1
- package/dist/generators/gherkin-parser/index.js +17 -9
- package/dist/generators/gherkin-parser/index.js.map +1 -1
- package/dist/generators/gherkin-parser/parent-scope-clause.d.ts +54 -0
- package/dist/generators/gherkin-parser/parent-scope-clause.d.ts.map +1 -0
- package/dist/generators/gherkin-parser/parent-scope-clause.js +109 -0
- package/dist/generators/gherkin-parser/parent-scope-clause.js.map +1 -0
- package/dist/generators/test-generator/adapters/adapter-interface.d.ts +23 -18
- package/dist/generators/test-generator/adapters/adapter-interface.d.ts.map +1 -1
- package/dist/generators/test-generator/adapters/appium/appium-adapter.d.ts +4 -19
- package/dist/generators/test-generator/adapters/appium/appium-adapter.d.ts.map +1 -1
- package/dist/generators/test-generator/adapters/appium/appium-adapter.js.map +1 -1
- package/dist/generators/test-generator/adapters/appium/templates/after-all.hbs +18 -0
- package/dist/generators/test-generator/adapters/appium/templates/after-each.hbs +18 -0
- package/dist/generators/test-generator/adapters/appium/templates/before-all.hbs +18 -0
- package/dist/generators/test-generator/adapters/appium/templates/steps/actions/click-at-position-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/appium/templates/steps/actions/click-element-with-text.hbs +1 -1
- package/dist/generators/test-generator/adapters/appium/templates/steps/actions/double-click-action.hbs +7 -0
- package/dist/generators/test-generator/adapters/appium/templates/steps/actions/frame-enter-action.hbs +3 -6
- package/dist/generators/test-generator/adapters/appium/templates/steps/actions/table-paginate-action.hbs +3 -0
- package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/visible-assertion.hbs +1 -1
- package/dist/generators/test-generator/adapters/appium/templates/steps/gestures/long-press-action.hbs +4 -0
- package/dist/generators/test-generator/adapters/appium/templates/steps/gestures/pinch-zoom-action.hbs +4 -0
- package/dist/generators/test-generator/adapters/appium/templates/steps/partials/locator.hbs +9 -1
- package/dist/generators/test-generator/adapters/appium/templates/test-file.hbs +54 -23
- package/dist/generators/test-generator/adapters/index.d.ts +1 -1
- package/dist/generators/test-generator/adapters/index.d.ts.map +1 -1
- package/dist/generators/test-generator/adapters/playwright/playwright-adapter.d.ts +4 -19
- package/dist/generators/test-generator/adapters/playwright/playwright-adapter.d.ts.map +1 -1
- package/dist/generators/test-generator/adapters/playwright/playwright-adapter.js.map +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/after-all.hbs +19 -1
- package/dist/generators/test-generator/adapters/playwright/templates/after-each.hbs +18 -0
- package/dist/generators/test-generator/adapters/playwright/templates/before-all.hbs +19 -1
- package/dist/generators/test-generator/adapters/playwright/templates/imports.hbs +3 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/check-action.hbs +6 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/click-at-position-action.hbs +23 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/expand-action.hbs +8 -8
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/fill-editor-action.hbs +7 -2
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row-nth.hbs +3 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row.hbs +3 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/table-paginate-action.hbs +5 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/uncheck-action.hbs +3 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/unknown-element-action.hbs +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/wait-for-page.hbs +18 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/all-contain-assertion.hbs +32 -4
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/all-contain-element.hbs +5 -2
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/checked-assertion.hbs +5 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/column-cell-assertion.hbs +13 -2
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/contain-text-assertion.hbs +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-role-variable-assertion.hbs +2 -2
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-variable-assertion.hbs +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/have-text-assertion.hbs +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-role-variable-assertion.hbs +2 -2
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-variable-assertion.hbs +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/not-checked-assertion.hbs +2 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/selected-assertion.hbs +14 -3
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/state-with-filter-assertion.hbs +13 -2
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-role-variable-assertion.hbs +3 -3
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-value-assertion.hbs +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-variable-assertion.hbs +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/checked-opts.hbs +8 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator-nth.hbs +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/test-file.hbs +10 -8
- package/dist/generators/test-generator/code-generator.d.ts +37 -0
- package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
- package/dist/generators/test-generator/code-generator.js +160 -39
- package/dist/generators/test-generator/code-generator.js.map +1 -1
- package/dist/generators/test-generator/diagnostics.d.ts +79 -5
- package/dist/generators/test-generator/diagnostics.d.ts.map +1 -1
- package/dist/generators/test-generator/diagnostics.js +78 -4
- package/dist/generators/test-generator/diagnostics.js.map +1 -1
- package/dist/generators/test-generator/patterns/index.d.ts +24 -5
- package/dist/generators/test-generator/patterns/index.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/index.js +92 -14
- package/dist/generators/test-generator/patterns/index.js.map +1 -1
- package/dist/generators/test-generator/patterns/with-parent-scope.d.ts +18 -0
- package/dist/generators/test-generator/patterns/with-parent-scope.d.ts.map +1 -0
- package/dist/generators/test-generator/patterns/with-parent-scope.js +40 -0
- package/dist/generators/test-generator/patterns/with-parent-scope.js.map +1 -0
- package/dist/generators/test-generator/step-mapper.d.ts +63 -9
- package/dist/generators/test-generator/step-mapper.d.ts.map +1 -1
- package/dist/generators/test-generator/step-mapper.js +166 -28
- package/dist/generators/test-generator/step-mapper.js.map +1 -1
- package/dist/generators/test-generator/template-engine.d.ts +4 -19
- package/dist/generators/test-generator/template-engine.d.ts.map +1 -1
- package/dist/generators/test-generator/template-engine.js +17 -12
- package/dist/generators/test-generator/template-engine.js.map +1 -1
- package/dist/generators/test-generator/utils/data-resolver.d.ts +7 -0
- package/dist/generators/test-generator/utils/data-resolver.d.ts.map +1 -1
- package/dist/generators/test-generator/utils/data-resolver.js +19 -2
- package/dist/generators/test-generator/utils/data-resolver.js.map +1 -1
- package/dist/generators/test-generator/utils/dialog-scope-identity.d.ts +41 -0
- package/dist/generators/test-generator/utils/dialog-scope-identity.d.ts.map +1 -0
- package/dist/generators/test-generator/utils/dialog-scope-identity.js +61 -0
- package/dist/generators/test-generator/utils/dialog-scope-identity.js.map +1 -0
- package/dist/generators/test-generator/utils/escape-js-string.d.ts +17 -0
- package/dist/generators/test-generator/utils/escape-js-string.d.ts.map +1 -0
- package/dist/generators/test-generator/utils/escape-js-string.js +29 -0
- package/dist/generators/test-generator/utils/escape-js-string.js.map +1 -0
- package/dist/generators/test-generator/utils/nearest-match.d.ts +24 -0
- package/dist/generators/test-generator/utils/nearest-match.d.ts.map +1 -0
- package/dist/generators/test-generator/utils/nearest-match.js +56 -0
- package/dist/generators/test-generator/utils/nearest-match.js.map +1 -0
- package/dist/generators/test-generator/utils/selector-entry-fields.d.ts +58 -0
- package/dist/generators/test-generator/utils/selector-entry-fields.d.ts.map +1 -0
- package/dist/generators/test-generator/utils/selector-entry-fields.js +119 -0
- package/dist/generators/test-generator/utils/selector-entry-fields.js.map +1 -0
- package/dist/generators/test-generator/utils/selector-entry-walk.d.ts +25 -0
- package/dist/generators/test-generator/utils/selector-entry-walk.d.ts.map +1 -0
- package/dist/generators/test-generator/utils/selector-entry-walk.js +54 -0
- package/dist/generators/test-generator/utils/selector-entry-walk.js.map +1 -0
- package/dist/generators/test-generator/utils/selector-nth-validation.d.ts +59 -0
- package/dist/generators/test-generator/utils/selector-nth-validation.d.ts.map +1 -0
- package/dist/generators/test-generator/utils/selector-nth-validation.js +91 -0
- package/dist/generators/test-generator/utils/selector-nth-validation.js.map +1 -0
- package/dist/generators/test-generator/utils/selector-resolver.d.ts +30 -1
- package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
- package/dist/generators/test-generator/utils/selector-resolver.js +195 -15
- package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -1
- package/dist/generators/test-generator/utils/selector-type-validation.d.ts +51 -0
- package/dist/generators/test-generator/utils/selector-type-validation.d.ts.map +1 -0
- package/dist/generators/test-generator/utils/selector-type-validation.js +77 -0
- package/dist/generators/test-generator/utils/selector-type-validation.js.map +1 -0
- package/dist/harness/data-driven-lint.d.ts.map +1 -1
- package/dist/harness/data-driven-lint.js +217 -33
- package/dist/harness/data-driven-lint.js.map +1 -1
- package/dist/harness/script-check.d.ts +2 -2
- package/dist/harness/script-check.d.ts.map +1 -1
- package/dist/harness/script-check.js +186 -25
- package/dist/harness/script-check.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/orchestrator/project-initializer.d.ts +6 -0
- package/dist/orchestrator/project-initializer.d.ts.map +1 -1
- package/dist/orchestrator/project-initializer.js +16 -0
- package/dist/orchestrator/project-initializer.js.map +1 -1
- package/dist/orchestrator/report-sanitize-reporter-install.d.ts +24 -0
- package/dist/orchestrator/report-sanitize-reporter-install.d.ts.map +1 -0
- package/dist/orchestrator/report-sanitize-reporter-install.js +161 -0
- package/dist/orchestrator/report-sanitize-reporter-install.js.map +1 -0
- package/dist/orchestrator/templates/ai-src/commands/run-test.md +9 -1
- package/dist/orchestrator/templates/ai-src/skills/sungen-api-coverage-model/SKILL.md +10 -0
- package/dist/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +14 -2
- package/dist/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +108 -8
- package/dist/orchestrator/templates/ai-src/skills/sungen-selector-fix/SKILL.md +1 -0
- package/dist/orchestrator/templates/ai-src/skills/sungen-selector-keys/SKILL.md +9 -2
- package/dist/orchestrator/templates/ai-src/skills/sungen-tc-review/SKILL.md +4 -4
- package/dist/orchestrator/templates/playwright.config.ts +7 -0
- package/dist/orchestrator/templates/specs-checked-state.d.ts +83 -0
- package/dist/orchestrator/templates/specs-checked-state.d.ts.map +1 -0
- package/dist/orchestrator/templates/specs-checked-state.js +261 -0
- package/dist/orchestrator/templates/specs-checked-state.js.map +1 -0
- package/dist/orchestrator/templates/specs-checked-state.ts +324 -0
- package/dist/orchestrator/templates/specs-report-path-sanitize-reporter.d.ts +36 -0
- package/dist/orchestrator/templates/specs-report-path-sanitize-reporter.d.ts.map +1 -0
- package/dist/orchestrator/templates/specs-report-path-sanitize-reporter.js +155 -0
- package/dist/orchestrator/templates/specs-report-path-sanitize-reporter.js.map +1 -0
- package/dist/orchestrator/templates/specs-report-path-sanitize-reporter.ts +142 -0
- package/dist/orchestrator/templates/specs-url-assert.d.ts +50 -25
- package/dist/orchestrator/templates/specs-url-assert.d.ts.map +1 -1
- package/dist/orchestrator/templates/specs-url-assert.js +65 -24
- package/dist/orchestrator/templates/specs-url-assert.js.map +1 -1
- package/dist/orchestrator/templates/specs-url-assert.ts +101 -28
- package/dist/utils/selector-types.d.ts +43 -1
- package/dist/utils/selector-types.d.ts.map +1 -1
- package/dist/utils/selector-types.js +51 -7
- package/dist/utils/selector-types.js.map +1 -1
- package/package.json +3 -3
- package/src/cli/commands/delivery.ts +2 -1
- package/src/cli/commands/generate.ts +5 -2
- package/src/cli/commands/inspect.ts +1 -1
- package/src/cli/commands/results-merge.ts +9 -2
- package/src/cli/commands/results-sanitize.ts +98 -0
- package/src/cli/commands/script-check.ts +3 -1
- package/src/cli/commands/update.ts +3 -0
- package/src/exporters/api-testcase-formatter.ts +5 -7
- package/src/exporters/matrix/build.ts +4 -2
- package/src/exporters/matrix/render-coverage-sheet.ts +3 -1
- package/src/exporters/matrix/render-csv.ts +3 -1
- package/src/exporters/matrix/render-overview-sheet.ts +5 -10
- package/src/exporters/matrix/result-totals.ts +37 -0
- package/src/exporters/matrix/testcase-summary-band.ts +2 -7
- package/src/exporters/qa-env-secret-denylist.ts +1 -1
- package/src/exporters/report-path-sanitizer.ts +144 -0
- package/src/exporters/result-variants.ts +2 -1
- package/src/exporters/sensitive-key.ts +48 -0
- package/src/exporters/test-data-resolver.ts +12 -2
- package/src/generators/gherkin-parser/index.ts +21 -10
- package/src/generators/gherkin-parser/parent-scope-clause.ts +130 -0
- package/src/generators/test-generator/adapters/adapter-interface.ts +25 -3
- package/src/generators/test-generator/adapters/appium/appium-adapter.ts +4 -4
- package/src/generators/test-generator/adapters/appium/templates/after-all.hbs +18 -0
- package/src/generators/test-generator/adapters/appium/templates/after-each.hbs +18 -0
- package/src/generators/test-generator/adapters/appium/templates/before-all.hbs +18 -0
- package/src/generators/test-generator/adapters/appium/templates/steps/actions/click-at-position-action.hbs +1 -0
- package/src/generators/test-generator/adapters/appium/templates/steps/actions/click-element-with-text.hbs +1 -1
- package/src/generators/test-generator/adapters/appium/templates/steps/actions/double-click-action.hbs +7 -0
- package/src/generators/test-generator/adapters/appium/templates/steps/actions/frame-enter-action.hbs +3 -6
- package/src/generators/test-generator/adapters/appium/templates/steps/actions/table-paginate-action.hbs +3 -0
- package/src/generators/test-generator/adapters/appium/templates/steps/assertions/visible-assertion.hbs +1 -1
- package/src/generators/test-generator/adapters/appium/templates/steps/gestures/long-press-action.hbs +4 -0
- package/src/generators/test-generator/adapters/appium/templates/steps/gestures/pinch-zoom-action.hbs +4 -0
- package/src/generators/test-generator/adapters/appium/templates/steps/partials/locator.hbs +9 -1
- package/src/generators/test-generator/adapters/appium/templates/test-file.hbs +54 -23
- package/src/generators/test-generator/adapters/index.ts +1 -1
- package/src/generators/test-generator/adapters/playwright/playwright-adapter.ts +4 -4
- package/src/generators/test-generator/adapters/playwright/templates/after-all.hbs +19 -1
- package/src/generators/test-generator/adapters/playwright/templates/after-each.hbs +18 -0
- package/src/generators/test-generator/adapters/playwright/templates/before-all.hbs +19 -1
- package/src/generators/test-generator/adapters/playwright/templates/imports.hbs +3 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/check-action.hbs +6 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/click-at-position-action.hbs +23 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/expand-action.hbs +8 -8
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/fill-editor-action.hbs +7 -2
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row-nth.hbs +3 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row.hbs +3 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/table-paginate-action.hbs +5 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/uncheck-action.hbs +3 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/unknown-element-action.hbs +1 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/wait-for-page.hbs +18 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/all-contain-assertion.hbs +32 -4
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/all-contain-element.hbs +5 -2
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/checked-assertion.hbs +5 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/column-cell-assertion.hbs +13 -2
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/contain-text-assertion.hbs +1 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-role-variable-assertion.hbs +2 -2
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-variable-assertion.hbs +1 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/have-text-assertion.hbs +1 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-role-variable-assertion.hbs +2 -2
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-variable-assertion.hbs +1 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/not-checked-assertion.hbs +2 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/selected-assertion.hbs +14 -3
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/state-with-filter-assertion.hbs +13 -2
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-role-variable-assertion.hbs +3 -3
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-value-assertion.hbs +1 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-variable-assertion.hbs +1 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/partials/checked-opts.hbs +8 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator-nth.hbs +1 -1
- package/src/generators/test-generator/adapters/playwright/templates/test-file.hbs +10 -8
- package/src/generators/test-generator/code-generator.ts +176 -45
- package/src/generators/test-generator/diagnostics.ts +79 -5
- package/src/generators/test-generator/patterns/index.ts +97 -16
- package/src/generators/test-generator/patterns/with-parent-scope.ts +41 -0
- package/src/generators/test-generator/step-mapper.ts +170 -26
- package/src/generators/test-generator/template-engine.ts +21 -21
- package/src/generators/test-generator/utils/data-resolver.ts +23 -2
- package/src/generators/test-generator/utils/dialog-scope-identity.ts +71 -0
- package/src/generators/test-generator/utils/escape-js-string.ts +24 -0
- package/src/generators/test-generator/utils/nearest-match.ts +55 -0
- package/src/generators/test-generator/utils/selector-entry-fields.ts +131 -0
- package/src/generators/test-generator/utils/selector-entry-walk.ts +58 -0
- package/src/generators/test-generator/utils/selector-nth-validation.ts +99 -0
- package/src/generators/test-generator/utils/selector-resolver.ts +245 -16
- package/src/generators/test-generator/utils/selector-type-validation.ts +87 -0
- package/src/harness/data-driven-lint.ts +192 -32
- package/src/harness/script-check.ts +186 -21
- package/src/index.ts +7 -0
- package/src/orchestrator/project-initializer.ts +17 -0
- package/src/orchestrator/report-sanitize-reporter-install.ts +109 -0
- package/src/orchestrator/templates/ai-src/commands/run-test.md +9 -1
- package/src/orchestrator/templates/ai-src/skills/sungen-api-coverage-model/SKILL.md +10 -0
- package/src/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +14 -2
- package/src/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +108 -8
- package/src/orchestrator/templates/ai-src/skills/sungen-selector-fix/SKILL.md +1 -0
- package/src/orchestrator/templates/ai-src/skills/sungen-selector-keys/SKILL.md +9 -2
- package/src/orchestrator/templates/ai-src/skills/sungen-tc-review/SKILL.md +4 -4
- package/src/orchestrator/templates/playwright.config.ts +7 -0
- package/src/orchestrator/templates/specs-checked-state.ts +324 -0
- package/src/orchestrator/templates/specs-report-path-sanitize-reporter.ts +142 -0
- package/src/orchestrator/templates/specs-url-assert.ts +101 -28
- package/src/utils/selector-types.ts +54 -5
|
@@ -10,6 +10,13 @@
|
|
|
10
10
|
* SG-W002 — step parsed a {{dataRef}} value but the generated code never uses it
|
|
11
11
|
* SG-W003 — `name` filter defaulted from the Gherkin reference on a name-from-content
|
|
12
12
|
* role (status/alert/…) — such a filter can never match; opt out with `name: null`
|
|
13
|
+
* SG-W004 — a selectors.yaml entry declares a field no consumer reads, so writing it has no
|
|
14
|
+
* effect on the generated test. Reserved for this in the original diagnostics spec
|
|
15
|
+
* (`exact: true` with no construct it applies to) and implemented for the wider class
|
|
16
|
+
* by #712, where `pagination:` and `contenteditable:` were public, documented,
|
|
17
|
+
* plumbed — and read by nothing. The field partition lives in
|
|
18
|
+
* utils/selector-entry-fields.ts; a field added there without a named consumer is
|
|
19
|
+
* the bug this code exists to catch.
|
|
13
20
|
* SG-W005 — qa/app.yaml problem (unknown key, unknown preset, unparseable)
|
|
14
21
|
* SG-W006 — qa/app.<env>.yaml found (per-environment profiles are unsupported by design)
|
|
15
22
|
* SG-W007 — browser-alert handler step written AFTER an action step: the listener
|
|
@@ -59,6 +66,23 @@
|
|
|
59
66
|
* but the generated code is a BARE VISIBILITY check: the clause was swallowed by the
|
|
60
67
|
* catch-all and the test would pass whatever the element says. Four separate defects
|
|
61
68
|
* have arrived this way, so the step compiles to a runtime throw instead.
|
|
69
|
+
* SG-W017 — a step needs a selector-entry field the entry does not declare, so there is nothing
|
|
70
|
+
* honest to compile. Today: a table paginate step whose table declares no
|
|
71
|
+
* `pagination.next`/`.prev` (#712). The mirror of SG-W004 — that one reports a field
|
|
72
|
+
* written that nothing reads, this one a field a consumer needs that nobody wrote.
|
|
73
|
+
* Compiles the step to a loud runtime throw rather than guessing a locator, which is
|
|
74
|
+
* the #690 failure (a locator no page has, failing far from the cause).
|
|
75
|
+
* SG-W018 — a selectors.yaml entry declares an `nth:` the compiler cannot use (#720). `nth:` was
|
|
76
|
+
* the one entry field whose VALUE nothing checked: the key is known (SG-W004 quiet) and
|
|
77
|
+
* the `type:` is valid (SG-E027 quiet), so `nth: -1`, `nth: 'last'`, `nth: 1.5` and
|
|
78
|
+
* `nth: -2` all compiled clean — the web side dropped the filter entirely (identical to
|
|
79
|
+
* deleting the line, then a strict-mode violation naming the DOM) while the mobile side
|
|
80
|
+
* emitted `$$('~x')[-1]` / `[last]`, undefined-indexing and a bare identifier that even
|
|
81
|
+
* the SG-E022 parse check reads as valid JavaScript. The contract is an integer `>= -1`
|
|
82
|
+
* (`0..N` a zero-based index, `-1` the last match); anything else is normalised away
|
|
83
|
+
* before it reaches a template, and reported here so "ignored" is stated rather than
|
|
84
|
+
* discovered. A warning, on SG-W004's reasoning — the value is inert once dropped and
|
|
85
|
+
* `--strict` already turns the channel non-zero
|
|
62
86
|
* SG-E020 — the step matched a pattern whose template the ACTIVE adapter does not ship. Before
|
|
63
87
|
* the platform SPI this was an unhandled `Template not found` that killed the WHOLE
|
|
64
88
|
* feature file and named neither the step nor the adapter. The step now compiles to a
|
|
@@ -111,6 +135,13 @@
|
|
|
111
135
|
* RUN time, so the compiler cannot know — the matrix, not this code, is the net that
|
|
112
136
|
* covers that case. Reported as an E-code and compiled to a loud throw, because the
|
|
113
137
|
* feature has declared the one OS where the step is known not to work.
|
|
138
|
+
* SG-E026 — a click step names a POSITION (`at position "top-left"`, `at offset x=…, y=…`) that
|
|
139
|
+
* would not be honoured: the keyword is misspelt, a value is outside the grammar (not a
|
|
140
|
+
* number, negative, above 100%, a missing axis, an unknown preset), or another click form
|
|
141
|
+
* claimed the step first (`try to click`, a `with {{v}}` text filter, `… and accept [OK]
|
|
142
|
+
* alert`). Each of those would compile to a click on the element's CENTRE and pass — for a
|
|
143
|
+
* backdrop-dismiss overlay that is the one outcome that proves nothing — so the step
|
|
144
|
+
* compiles to a loud throw instead
|
|
114
145
|
* SG-W026 — a mobile ACTIVE-NAVIGATION step that emitted NO executable code, so a promised screen
|
|
115
146
|
* change never happens. `When User open [Settings] page` compiles to the one-line
|
|
116
147
|
* `navigation` template — a comment noting the app was already launched by the wdio
|
|
@@ -137,6 +168,15 @@
|
|
|
137
168
|
* Reported rather than resolved by precedence — two tests genuinely sharing one title
|
|
138
169
|
* cannot be told apart by a name-keyed lookup, so the only honest fix is a rename. Silently
|
|
139
170
|
* picking a winner would be the same silent-discard shape as SG-W021
|
|
171
|
+
* SG-E027 — a selectors.yaml entry declares a `type:` that is not a selector type at all. YAML is
|
|
172
|
+
* untyped at run time, so `type: 'testId'` (capital I), `'xpth'`, `'rol'` or any other
|
|
173
|
+
* misspelling used to compile clean and resolve through the strategy switch's
|
|
174
|
+
* `default:` branch as `getByPlaceholder('<the value>')` — a locator that cannot
|
|
175
|
+
* match, failing much later as a timeout naming placeholder text the author never
|
|
176
|
+
* wrote. Checked where the selector FILE is loaded rather than in the switch: `page`
|
|
177
|
+
* legitimately reaches that `default:` on every page assertion, and the load point can
|
|
178
|
+
* name the entry key and the nearest valid spelling. Reported once per entry, and
|
|
179
|
+
* every step naming that entry compiles to a `throw`
|
|
140
180
|
* SG-E022 — the generated spec is not parseable JS/TS, so NOTHING in the file runs — Playwright
|
|
141
181
|
* reports one SyntaxError and every scenario in the unit is lost. A compiler self-check
|
|
142
182
|
* (@babel/parser) on the emitted code, added after a field report where the runtime-data
|
|
@@ -145,16 +185,50 @@
|
|
|
145
185
|
* compiler, not the Gherkin: it should be impossible, and it is reported so a broken
|
|
146
186
|
* build names itself at generate time instead of one step further downstream
|
|
147
187
|
*
|
|
188
|
+
* SG-W028 — a step's trailing scope clause was DROPPED, so the step runs against more of the page
|
|
189
|
+
* than its sentence names. Two causes, one code: the `<word>` after `in [X]` is not a
|
|
190
|
+
* container type (a typo, or a leaf element used as a parent), or the by-content form
|
|
191
|
+
* `in [X] <type> with {{v}}` was written for the mobile adapter, which chains a parent
|
|
192
|
+
* element and has no content filter. Before this, both compiled clean and silently
|
|
193
|
+
* widened the assertion to the whole screen — the failure mode that only a diff of the
|
|
194
|
+
* generated spec against the Gherkin could reveal (#667)
|
|
195
|
+
* SG-W029 — a mobile (appium) feature compiled with NO usable app-package `Path:` — either the line
|
|
196
|
+
* is missing outright, or it holds a web-style route (`Path: /applied-jobs`) that the
|
|
197
|
+
* package guard rejects. Both used to be silent, and both cost the same two things: the
|
|
198
|
+
* per-scenario `beforeEach` was not emitted at all, so Background dropped to Mocha's
|
|
199
|
+
* `before()` (once per FILE, every scenario sharing one continuous app session — a tab
|
|
200
|
+
* switch or a scroll in one scenario stranding elements off-screen for every later one),
|
|
201
|
+
* and the `@reset:` tier ladder went with it, leaving the tag inert. The spec now always
|
|
202
|
+
* emits the reset machinery and resolves the app id from the session capability that
|
|
203
|
+
* wdio.conf sets, throwing a named error when nothing supplies one — so this is a
|
|
204
|
+
* warning about an under-declared feature file, not a broken build (#669)
|
|
205
|
+
* SG-W030 — a selectors.yaml `expanded.class`/`expanded.attribute` carries a character outside the
|
|
206
|
+
* accepted class/attribute-name set (whitespace, a quote, a backslash, `$`, `{`, `}`).
|
|
207
|
+
* The value is pasted into the generated spec (string literal, regex, classList argument),
|
|
208
|
+
* and selectors.yaml is often generated from the page under test, so it is refused and the
|
|
209
|
+
* field dropped — the step falls back to driving/asserting `aria-expanded`. Reported once
|
|
210
|
+
* per entry and field. A WARNING rather than a refusal because the fallback still tests
|
|
211
|
+
* something; the checked/selected signal has no fallback and is refused outright instead
|
|
212
|
+
*
|
|
213
|
+
* SG-E031 — a selectors.yaml `checked:`/`selected:` declaration the compiler refuses: the two
|
|
214
|
+
* spellings disagree, a class token or attribute name carries whitespace/a quote/a
|
|
215
|
+
* backslash, or one entry declares both a class and an attribute. Each is silent at run
|
|
216
|
+
* time — the matcher would never match and the step would time out blaming the
|
|
217
|
+
* component — so the declaration is refused rather than compiled. Unlike the expanded
|
|
218
|
+
* signal (SG-W030) it is not dropped-and-warned: with no signal the step is back on the
|
|
219
|
+
* failure the declaration exists to fix. Recorded here AND thrown, so a pattern that
|
|
220
|
+
* resolves selectors inside a `catch` cannot swallow it silently
|
|
148
221
|
* Diagnostics never change the EXIT CODE by themselves; `sungen generate --strict` turns any
|
|
149
222
|
* collected diagnostic into a non-zero exit. They are not all inert, though: SG-W001, SG-W011,
|
|
150
|
-
* SG-E020, SG-E021, SG-W020, SG-E023
|
|
151
|
-
* `throw
|
|
152
|
-
*
|
|
153
|
-
*
|
|
223
|
+
* SG-E020, SG-E021, SG-W020, SG-E023, SG-E024, SG-E025, SG-E026 and SG-E027 additionally compile
|
|
224
|
+
* the offending step to a runtime `throw` — a step that reads as a check and silently checks
|
|
225
|
+
* nothing is worse than one that fails loudly — and SG-E031 refuses the file outright. (SG-E022 is
|
|
226
|
+
* the one exception to the "blame the Gherkin" rule and throws nothing: the file is still written
|
|
227
|
+
* so the user keeps the artifact to inspect.)
|
|
154
228
|
* Generation always COMPLETES — the rest of the scenario and the rest of the file still compile.
|
|
155
229
|
*/
|
|
156
230
|
|
|
157
|
-
export type DiagnosticCode = 'SG-W001' | 'SG-W002' | 'SG-W003' | 'SG-W005' | 'SG-W006' | 'SG-W007' | 'SG-W008' | 'SG-W009' | 'SG-W010' | 'SG-W011' | 'SG-W012' | 'SG-W013' | 'SG-W014' | 'SG-W015' | 'SG-W016' | 'SG-E020' | 'SG-E021' | 'SG-W020' | 'SG-W021' | 'SG-W022' | 'SG-W023' | 'SG-W024' | 'SG-W026' | 'SG-E025' | 'SG-E022' | 'SG-E023' | 'SG-E024';
|
|
231
|
+
export type DiagnosticCode = 'SG-W001' | 'SG-W002' | 'SG-W003' | 'SG-W004' | 'SG-W005' | 'SG-W006' | 'SG-W007' | 'SG-W008' | 'SG-W009' | 'SG-W010' | 'SG-W011' | 'SG-W012' | 'SG-W013' | 'SG-W014' | 'SG-W015' | 'SG-W016' | 'SG-W017' | 'SG-W018' | 'SG-E020' | 'SG-E021' | 'SG-W020' | 'SG-W021' | 'SG-W022' | 'SG-W023' | 'SG-W024' | 'SG-W026' | 'SG-E025' | 'SG-E026' | 'SG-E022' | 'SG-E023' | 'SG-E024' | 'SG-E027' | 'SG-W028' | 'SG-W029' | 'SG-W030' | 'SG-E031';
|
|
158
232
|
|
|
159
233
|
export interface Diagnostic {
|
|
160
234
|
code: DiagnosticCode;
|
|
@@ -6,6 +6,8 @@ import { discoverAndRegisterCapabilities } from '../../../capabilities/discover'
|
|
|
6
6
|
import { maskRefsForMatching } from '../utils/mask-refs-for-matching';
|
|
7
7
|
import { unsupportedStepCode } from './unsupported-step-code';
|
|
8
8
|
import { osSupportOfTemplate } from '../adapters/appium/os-support';
|
|
9
|
+
import { withParentScope } from './with-parent-scope';
|
|
10
|
+
import { escapeSingleQuoted } from '../utils/escape-js-string';
|
|
9
11
|
|
|
10
12
|
// Both helpers moved out of this file so the Gherkin parser (state-clause extraction) and the
|
|
11
13
|
// step-mapper (SG-W001 no-pattern fallback) can use them without importing the pattern registry.
|
|
@@ -135,6 +137,10 @@ export class PatternRegistry {
|
|
|
135
137
|
// Matching mirrors findPattern exactly: refs masked FIRST (so `[Tap Water]` is not a
|
|
136
138
|
// verb), then `tap` → `click` normalisation for the mobile vocabulary.
|
|
137
139
|
const matchStep: ParsedStep = { ...step, text: normalizeVerbs(maskRefsForMatching(step.text)) };
|
|
140
|
+
// The step's parent scope, resolved ONCE for the whole search. Not per candidate pattern: a
|
|
141
|
+
// resolver may decline and hand the step to the next one, and re-resolving here would report
|
|
142
|
+
// the mobile by-content refusal (SG-W028) once per attempt instead of once per step.
|
|
143
|
+
const parentScope = PatternRegistry.resolveParentLocator(step, context);
|
|
138
144
|
for (const pattern of this.patterns) {
|
|
139
145
|
if (!this.matchesPattern(matchStep, pattern.matcher)) continue;
|
|
140
146
|
|
|
@@ -144,10 +150,20 @@ export class PatternRegistry {
|
|
|
144
150
|
const platformMiss = PatternRegistry.platformMiss(pattern, context, step);
|
|
145
151
|
if (platformMiss) return platformMiss;
|
|
146
152
|
|
|
153
|
+
// Shared by BOTH code paths below. The injection used to live inside the resolver branch, so
|
|
154
|
+
// a `generator` pattern discarded a perfectly parsed scope: `see [Tag] header with {{label}}
|
|
155
|
+
// in [Job Card] section` routes to `see-with-variable` (a generator) and asserted against the
|
|
156
|
+
// whole page (#667). Scope that is parsed and then dropped widens the step just as silently
|
|
157
|
+
// as scope that never parsed at all.
|
|
158
|
+
// `table-*` patterns opt out by name — they resolve the container from the step text
|
|
159
|
+
// themselves and would otherwise scope it twice.
|
|
160
|
+
const parentLocator = pattern.name.startsWith('table-') ? undefined : parentScope;
|
|
161
|
+
const scoped = parentLocator ? withParentScope(context, parentLocator) : context;
|
|
162
|
+
|
|
147
163
|
try {
|
|
148
164
|
// Prefer resolver (framework-agnostic) over generator (legacy)
|
|
149
165
|
if (pattern.resolver) {
|
|
150
|
-
const resolved = pattern.resolver(step,
|
|
166
|
+
const resolved = pattern.resolver(step, scoped);
|
|
151
167
|
if (!resolved) continue; // resolver declined — fall through
|
|
152
168
|
|
|
153
169
|
// iOS gate — AFTER the resolver, because it needs the template the step actually reached.
|
|
@@ -167,17 +183,16 @@ export class PatternRegistry {
|
|
|
167
183
|
if (resolverStateMiss) return resolverStateMiss;
|
|
168
184
|
|
|
169
185
|
// Auto-inject parent scoping if step has parentRef
|
|
170
|
-
|
|
171
|
-
if (step.parentRef && step.parentType && !pattern.name.startsWith('table-')) {
|
|
172
|
-
resolved.data.parentLocator = PatternRegistry.resolveParentLocator(
|
|
173
|
-
step.parentRef, step.parentType, context
|
|
174
|
-
);
|
|
175
|
-
}
|
|
186
|
+
if (parentLocator) resolved.data.parentLocator = parentLocator;
|
|
176
187
|
|
|
177
188
|
const code = context.templateEngine.renderStep(resolved.templateName, resolved.data);
|
|
189
|
+
// The compiler's post-map guards need to know WHICH form won and what it resolved to (e.g.
|
|
190
|
+
// a refusal a resolver recorded in its data) — without re-matching.
|
|
178
191
|
return {
|
|
179
192
|
code,
|
|
180
193
|
comment: resolved.comment,
|
|
194
|
+
pattern: pattern.name,
|
|
195
|
+
templateData: resolved.data,
|
|
181
196
|
};
|
|
182
197
|
}
|
|
183
198
|
|
|
@@ -185,7 +200,9 @@ export class PatternRegistry {
|
|
|
185
200
|
// A legacy generator has no decline path, so this pattern owns the step already.
|
|
186
201
|
const generatorStateMiss = PatternRegistry.stateMiss(pattern, context, step);
|
|
187
202
|
if (generatorStateMiss) return generatorStateMiss;
|
|
188
|
-
|
|
203
|
+
// A generator returning nothing still falls through to the no-pattern path.
|
|
204
|
+
const generated = pattern.generator(step, scoped);
|
|
205
|
+
return generated ? { ...generated, pattern: pattern.name } : null;
|
|
189
206
|
}
|
|
190
207
|
|
|
191
208
|
return null;
|
|
@@ -347,14 +364,23 @@ export class PatternRegistry {
|
|
|
347
364
|
}
|
|
348
365
|
|
|
349
366
|
/**
|
|
350
|
-
* Resolve
|
|
351
|
-
*
|
|
367
|
+
* Resolve a step's `in [Parent] <type> [with <value>]` scope to a locator string, or `undefined`
|
|
368
|
+
* when the step carries no scope.
|
|
352
369
|
*
|
|
353
|
-
*
|
|
354
|
-
*
|
|
355
|
-
*
|
|
370
|
+
* Tries YAML lookup first, falls back to auto-inferring a role from the container type with the
|
|
371
|
+
* reference as the accessible name. A reference written as `{{var}}` is resolved through
|
|
372
|
+
* test-data before it reaches that name — containers are routinely labelled with the text under
|
|
373
|
+
* test, and a literal `{{var}}` in the name matches nothing.
|
|
356
374
|
*/
|
|
357
|
-
private static resolveParentLocator(
|
|
375
|
+
private static resolveParentLocator(step: ParsedStep, context: PatternContext): string | undefined {
|
|
376
|
+
const { parentRef, parentType } = step;
|
|
377
|
+
if (!parentRef || !parentType) return undefined;
|
|
378
|
+
|
|
379
|
+
const base = PatternRegistry.parentContainerLocator(parentRef, parentType, context);
|
|
380
|
+
return PatternRegistry.filterParentByValue(base, step, context);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
private static parentContainerLocator(
|
|
358
384
|
parentRef: string, parentType: string, context: PatternContext
|
|
359
385
|
): string {
|
|
360
386
|
// Try resolving from selectors YAML
|
|
@@ -370,13 +396,68 @@ export class PatternRegistry {
|
|
|
370
396
|
const roleMap: Record<string, string> = {
|
|
371
397
|
table: 'table',
|
|
372
398
|
list: 'list',
|
|
399
|
+
'list-item': 'listitem',
|
|
400
|
+
listitem: 'listitem',
|
|
401
|
+
item: 'listitem',
|
|
402
|
+
row: 'row',
|
|
373
403
|
section: 'region',
|
|
404
|
+
container: 'region',
|
|
405
|
+
panel: 'region',
|
|
406
|
+
card: 'region',
|
|
407
|
+
group: 'group',
|
|
374
408
|
dialog: 'dialog',
|
|
409
|
+
modal: 'dialog',
|
|
410
|
+
drawer: 'dialog',
|
|
411
|
+
overlay: 'dialog',
|
|
375
412
|
form: 'form',
|
|
413
|
+
tab: 'tabpanel',
|
|
414
|
+
menu: 'menu',
|
|
376
415
|
};
|
|
377
416
|
const role = roleMap[parentType] || parentType;
|
|
378
|
-
const
|
|
379
|
-
return `page.getByRole('${role}', { name: '${
|
|
417
|
+
const name = escapeSingleQuoted(PatternRegistry.resolveInlineData(parentRef, context));
|
|
418
|
+
return `page.getByRole('${role}', { name: '${name}' })`;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Narrow the container to the ONE whose content matches the step's parent value — the
|
|
423
|
+
* `with {{job_title}}` tail of `see [Tag] header with {{label}} in [Job Card] card with
|
|
424
|
+
* {{job_title}}`. Without it a list of identical cards leaves the assertion matching whichever
|
|
425
|
+
* one Playwright reaches first.
|
|
426
|
+
*
|
|
427
|
+
* Web-only, and refused rather than approximated elsewhere: the Appium partial chains a parent
|
|
428
|
+
* with `$()`, which has no content filter, so emitting one would be invalid code and pretending
|
|
429
|
+
* the scope applied would be the very silence this whole fix exists to end (SG-W028).
|
|
430
|
+
*/
|
|
431
|
+
private static filterParentByValue(
|
|
432
|
+
base: string, step: ParsedStep, context: PatternContext
|
|
433
|
+
): string {
|
|
434
|
+
const raw = step.parentValueRef
|
|
435
|
+
? PatternRegistry.resolveInlineData(`{{${step.parentValueRef}}}`, context)
|
|
436
|
+
: step.parentValueText;
|
|
437
|
+
if (raw === undefined) return base;
|
|
438
|
+
|
|
439
|
+
if (context.platform === 'mobile') {
|
|
440
|
+
context.diagnostics?.add('SG-W028',
|
|
441
|
+
`scoping a container BY CONTENT ("in [${step.parentRef}] ${step.parentType} with …") is web-only — the mobile adapter chains a parent element, which has no content filter, so this step would search every ${step.parentType} on the screen. Give the container an accessibility id that identifies it and scope by that instead, or assert on the element the value belongs to`,
|
|
442
|
+
{ feature: context.featureName, step: step.text });
|
|
443
|
+
return base;
|
|
444
|
+
}
|
|
445
|
+
return `${base}.filter({ hasText: '${escapeSingleQuoted(raw)}' })`;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Resolve a `{{var}}` written where literal text is expected, leaving anything else untouched.
|
|
450
|
+
* An unknown variable stays as written rather than throwing — the locator is then wrong in a way
|
|
451
|
+
* the author can read, which beats losing the whole step.
|
|
452
|
+
*/
|
|
453
|
+
private static resolveInlineData(text: string, context: PatternContext): string {
|
|
454
|
+
const match = text.match(/^\{\{([a-z0-9\-._]+)\}\}$/i);
|
|
455
|
+
if (!match) return text;
|
|
456
|
+
try {
|
|
457
|
+
return context.dataResolver.resolveData(match[1], context.featureName);
|
|
458
|
+
} catch {
|
|
459
|
+
return text;
|
|
460
|
+
}
|
|
380
461
|
}
|
|
381
462
|
|
|
382
463
|
/**
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { PatternContext } from './types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Return a `PatternContext` in which every selector the pattern resolves comes back already scoped
|
|
5
|
+
* to `parentLocator`.
|
|
6
|
+
*
|
|
7
|
+
* Why a wrapped context rather than one assignment. A `resolver` pattern hands its template data
|
|
8
|
+
* back to the registry, which can stamp `parentLocator` on it; a `generator` pattern renders its own
|
|
9
|
+
* code and never exposes that object, so the registry had no seam and the scope was simply lost
|
|
10
|
+
* (#667). The seam both kinds share is where they ASK for a selector — `selectorResolver` and
|
|
11
|
+
* `renderLocator` — so the scope is attached there instead, and every locator partial (Playwright
|
|
12
|
+
* and Appium alike) already knows what to do with a `parentLocator` field.
|
|
13
|
+
*
|
|
14
|
+
* Only the target's own scope is stamped; anything a pattern resolves that ALREADY carries a
|
|
15
|
+
* `parentLocator` is left alone, so a pattern that builds its own container chain (table rows) keeps
|
|
16
|
+
* winning over the generic one.
|
|
17
|
+
*/
|
|
18
|
+
export function withParentScope(context: PatternContext, parentLocator: string): PatternContext {
|
|
19
|
+
const scope = <T>(resolved: T): T =>
|
|
20
|
+
resolved && typeof resolved === 'object' && !(resolved as any).parentLocator
|
|
21
|
+
? { ...(resolved as any), parentLocator }
|
|
22
|
+
: resolved;
|
|
23
|
+
|
|
24
|
+
// A Proxy rather than a copy: SelectorResolver carries more than the one method patterns call,
|
|
25
|
+
// and a hand-written stand-in would silently drop whatever it forgot.
|
|
26
|
+
const selectorResolver = new Proxy(context.selectorResolver, {
|
|
27
|
+
get(target, prop, receiver) {
|
|
28
|
+
if (prop === 'resolveSelector') {
|
|
29
|
+
return (...args: unknown[]) => scope((target as any).resolveSelector(...args));
|
|
30
|
+
}
|
|
31
|
+
const value = Reflect.get(target, prop, receiver);
|
|
32
|
+
return typeof value === 'function' ? value.bind(target) : value;
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
...context,
|
|
38
|
+
selectorResolver,
|
|
39
|
+
renderLocator: (resolved: any) => context.renderLocator(scope(resolved)),
|
|
40
|
+
};
|
|
41
|
+
}
|