@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
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The trailing scope clause — `… in [Parent] <containerType>` and its optional `with <value>` tail.
|
|
3
|
+
*
|
|
4
|
+
* Lifted out of `parseStep` because the clause failed SILENTLY (#667): the container whitelist held
|
|
5
|
+
* five types, anything else fell through, and the unmatched words stayed inline in the sentence
|
|
6
|
+
* where the first-match extractors below simply ignored them. The step compiled clean
|
|
7
|
+
* and the assertion ran against the WHOLE page instead of the named container — a test that passes
|
|
8
|
+
* for the wrong reason, findable only by diffing the generated spec against the Gherkin.
|
|
9
|
+
*
|
|
10
|
+
* So this module answers two questions, not one:
|
|
11
|
+
* - what the clause MEANS when it is recognized (`parentRef` / `parentType` / the value tail), and
|
|
12
|
+
* - what was DISCARDED when it is not (`unsupportedType`), so the compiler can say so (SG-W028)
|
|
13
|
+
* instead of quietly truncating the sentence.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Container types a step may scope into. Every one of these is something that HOLDS other elements
|
|
17
|
+
* on a page; `button`, `field`, `badge` and friends are deliberately absent — a leaf cannot be a
|
|
18
|
+
* parent, and admitting one would turn a typo into a silently wrong locator rather than a report.
|
|
19
|
+
*
|
|
20
|
+
* Ordered longest-first where one type is a prefix of another (`list-item` before `list`), because
|
|
21
|
+
* the alternation is matched left-to-right: `in [X] list-item` must not resolve as `list` with a
|
|
22
|
+
* stray `-item` left behind.
|
|
23
|
+
*
|
|
24
|
+
* `header` and `footer` are NOT here, though both hold elements. The auto-inferred fallback role
|
|
25
|
+
* for them would be the page landmarks `banner`/`contentinfo`, and a `<header>` nested inside an
|
|
26
|
+
* `<article>`/`<section>` — which is exactly how a repeating card is marked up — carries neither.
|
|
27
|
+
* That fallback would match nothing and fail for a reason unreadable from the Gherkin, so the
|
|
28
|
+
* clause is refused (SG-W028) and the author is pointed at a container type that resolves.
|
|
29
|
+
*/
|
|
30
|
+
export declare const PARENT_CONTAINER_TYPES: readonly string[];
|
|
31
|
+
export interface ParentScopeClause {
|
|
32
|
+
/** The `[Parent]` reference — a selectors.yaml key, or `{{var}}` naming the container's text. */
|
|
33
|
+
ref: string;
|
|
34
|
+
/** The container type, lowercased. */
|
|
35
|
+
type: string;
|
|
36
|
+
/** `{{var}}` name when the value tail scopes the parent BY CONTENT. */
|
|
37
|
+
valueRef?: string;
|
|
38
|
+
/** Quoted literal when the value tail scopes the parent by content without a variable. */
|
|
39
|
+
valueText?: string;
|
|
40
|
+
/** The sentence with the clause removed, so the target extractors never see the parent's tokens. */
|
|
41
|
+
remainingText: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Extract the scope clause from a step sentence.
|
|
45
|
+
*
|
|
46
|
+
* Returns `{ clause }` when a container type was recognized, `{ unsupportedType }` when the
|
|
47
|
+
* sentence carries an `in [X] <word>` clause whose `<word>` is not a container (it is dropped, and
|
|
48
|
+
* the caller reports it), or an empty object when there is no scope clause at all.
|
|
49
|
+
*/
|
|
50
|
+
export declare function extractParentScopeClause(text: string): {
|
|
51
|
+
clause?: ParentScopeClause;
|
|
52
|
+
unsupportedType?: string;
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=parent-scope-clause.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parent-scope-clause.d.ts","sourceRoot":"","sources":["../../../src/generators/gherkin-parser/parent-scope-clause.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,sBAAsB,EAAE,SAAS,MAAM,EAKnD,CAAC;AAgBF,MAAM,WAAW,iBAAiB;IAChC,iGAAiG;IACjG,GAAG,EAAE,MAAM,CAAC;IACZ,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0FAA0F;IAC1F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oGAAoG;IACpG,aAAa,EAAE,MAAM,CAAC;CACvB;AA4BD;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG;IACtD,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CA6BA"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The trailing scope clause — `… in [Parent] <containerType>` and its optional `with <value>` tail.
|
|
4
|
+
*
|
|
5
|
+
* Lifted out of `parseStep` because the clause failed SILENTLY (#667): the container whitelist held
|
|
6
|
+
* five types, anything else fell through, and the unmatched words stayed inline in the sentence
|
|
7
|
+
* where the first-match extractors below simply ignored them. The step compiled clean
|
|
8
|
+
* and the assertion ran against the WHOLE page instead of the named container — a test that passes
|
|
9
|
+
* for the wrong reason, findable only by diffing the generated spec against the Gherkin.
|
|
10
|
+
*
|
|
11
|
+
* So this module answers two questions, not one:
|
|
12
|
+
* - what the clause MEANS when it is recognized (`parentRef` / `parentType` / the value tail), and
|
|
13
|
+
* - what was DISCARDED when it is not (`unsupportedType`), so the compiler can say so (SG-W028)
|
|
14
|
+
* instead of quietly truncating the sentence.
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.PARENT_CONTAINER_TYPES = void 0;
|
|
18
|
+
exports.extractParentScopeClause = extractParentScopeClause;
|
|
19
|
+
/**
|
|
20
|
+
* Container types a step may scope into. Every one of these is something that HOLDS other elements
|
|
21
|
+
* on a page; `button`, `field`, `badge` and friends are deliberately absent — a leaf cannot be a
|
|
22
|
+
* parent, and admitting one would turn a typo into a silently wrong locator rather than a report.
|
|
23
|
+
*
|
|
24
|
+
* Ordered longest-first where one type is a prefix of another (`list-item` before `list`), because
|
|
25
|
+
* the alternation is matched left-to-right: `in [X] list-item` must not resolve as `list` with a
|
|
26
|
+
* stray `-item` left behind.
|
|
27
|
+
*
|
|
28
|
+
* `header` and `footer` are NOT here, though both hold elements. The auto-inferred fallback role
|
|
29
|
+
* for them would be the page landmarks `banner`/`contentinfo`, and a `<header>` nested inside an
|
|
30
|
+
* `<article>`/`<section>` — which is exactly how a repeating card is marked up — carries neither.
|
|
31
|
+
* That fallback would match nothing and fail for a reason unreadable from the Gherkin, so the
|
|
32
|
+
* clause is refused (SG-W028) and the author is pointed at a container type that resolves.
|
|
33
|
+
*/
|
|
34
|
+
exports.PARENT_CONTAINER_TYPES = [
|
|
35
|
+
'list-item', 'listitem', 'list',
|
|
36
|
+
'table', 'section', 'dialog', 'modal', 'drawer', 'overlay', 'form',
|
|
37
|
+
'card', 'item', 'row', 'group', 'panel', 'region', 'container',
|
|
38
|
+
'tab', 'menu',
|
|
39
|
+
];
|
|
40
|
+
const TYPES_ALT = exports.PARENT_CONTAINER_TYPES.join('|');
|
|
41
|
+
/** `in [Parent] <containerType>` — the clause proper, without any value tail. */
|
|
42
|
+
const SCOPE_CLAUSE_BASE = new RegExp(`\\s+in\\s+\\[([^\\]]+)\\]\\s+(${TYPES_ALT})\\b`, 'i');
|
|
43
|
+
/** The same, plus the optional `with {{v}}` / `with "text"` tail. */
|
|
44
|
+
const SCOPE_CLAUSE = new RegExp(`${SCOPE_CLAUSE_BASE.source}(?:\\s+with\\s+(\\{\\{[a-z0-9\\-._]+\\}\\}|"[^"]*"))?`, 'i');
|
|
45
|
+
/** The same shape with ANY word where a container type belongs — used only to report what was lost. */
|
|
46
|
+
const SCOPE_CLAUSE_ANY_TYPE = /\s+in\s+\[([^\]]+)\]\s+([\w-]+)/i;
|
|
47
|
+
/**
|
|
48
|
+
* Is the `[…]` at `clauseAt` a CONTAINER, or is it the step's own target?
|
|
49
|
+
*
|
|
50
|
+
* A scope clause narrows a target, so the target's bracket must already have appeared. Without this
|
|
51
|
+
* test, `User select {{country}} in [Country Picker] dropdown` reads its one and only target as a
|
|
52
|
+
* parent — the bracket is what the step acts ON, and the `in` is English, not grammar.
|
|
53
|
+
*/
|
|
54
|
+
function scopesATarget(text, clauseAt) {
|
|
55
|
+
return /\[[^\]]*\]/.test(text.slice(0, clauseAt));
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Does the segment before the scope clause already carry its own `with`?
|
|
59
|
+
*
|
|
60
|
+
* This is what keeps the value tail backward compatible. The documented grammar
|
|
61
|
+
* (`see [first] row in [apply list] table with {{job_name}}`) spends its single `with` on the
|
|
62
|
+
* TARGET, and re-reading that as a parent filter would silently invert the meaning of every such
|
|
63
|
+
* step already written. A SECOND `with` — `see [Tag] header with {{label}} in [Job Card] card with
|
|
64
|
+
* {{title}}` — cannot belong to the target, which already has one; only then does the tail bind to
|
|
65
|
+
* the parent. `[Ref]` contents are blanked first so a bracket like `[Filter With Tags]` is not
|
|
66
|
+
* mistaken for the keyword.
|
|
67
|
+
*/
|
|
68
|
+
function targetAlreadyHasValue(head) {
|
|
69
|
+
return /\s+with\s+/i.test(head.replace(/\[[^\]]*\]/g, ''));
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Extract the scope clause from a step sentence.
|
|
73
|
+
*
|
|
74
|
+
* Returns `{ clause }` when a container type was recognized, `{ unsupportedType }` when the
|
|
75
|
+
* sentence carries an `in [X] <word>` clause whose `<word>` is not a container (it is dropped, and
|
|
76
|
+
* the caller reports it), or an empty object when there is no scope clause at all.
|
|
77
|
+
*/
|
|
78
|
+
function extractParentScopeClause(text) {
|
|
79
|
+
const match = text.match(SCOPE_CLAUSE);
|
|
80
|
+
if (!match) {
|
|
81
|
+
const loose = text.match(SCOPE_CLAUSE_ANY_TYPE);
|
|
82
|
+
return loose && scopesATarget(text, loose.index)
|
|
83
|
+
? { unsupportedType: loose[2].toLowerCase() }
|
|
84
|
+
: {};
|
|
85
|
+
}
|
|
86
|
+
if (!scopesATarget(text, match.index))
|
|
87
|
+
return {};
|
|
88
|
+
const head = text.slice(0, match.index);
|
|
89
|
+
const tail = match[3];
|
|
90
|
+
const bindsToParent = Boolean(tail) && targetAlreadyHasValue(head);
|
|
91
|
+
// A value tail the target has already claimed stays in the sentence, exactly where it was, for the
|
|
92
|
+
// target extractors to pick up — what gets consumed is then only `in [Parent] <type>`.
|
|
93
|
+
const consumedLength = bindsToParent
|
|
94
|
+
? match[0].length
|
|
95
|
+
: match[0].match(SCOPE_CLAUSE_BASE)[0].length;
|
|
96
|
+
const clause = {
|
|
97
|
+
ref: match[1],
|
|
98
|
+
type: match[2].toLowerCase(),
|
|
99
|
+
remainingText: head + text.slice(match.index + consumedLength),
|
|
100
|
+
};
|
|
101
|
+
if (bindsToParent) {
|
|
102
|
+
if (tail.startsWith('{{'))
|
|
103
|
+
clause.valueRef = tail.slice(2, -2);
|
|
104
|
+
else
|
|
105
|
+
clause.valueText = tail.slice(1, -1);
|
|
106
|
+
}
|
|
107
|
+
return { clause };
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=parent-scope-clause.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parent-scope-clause.js","sourceRoot":"","sources":["../../../src/generators/gherkin-parser/parent-scope-clause.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,25 @@ export interface AuthGroup {
|
|
|
6
6
|
authRole?: string;
|
|
7
7
|
scenarios: string[];
|
|
8
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* One statement of a hook block (`@beforeAll` / `@afterEach` / `@afterAll`). `wrap` → the template
|
|
11
|
+
* guards the statement with try/catch and records a failure under `label` (a JSON string literal,
|
|
12
|
+
* safe to paste into code); `stopOnFailure` → a failure also ends the hook right there (action
|
|
13
|
+
* steps: later steps would run on state the failed action never produced). A plain step runs
|
|
14
|
+
* unwrapped and throws as before.
|
|
15
|
+
*/
|
|
16
|
+
export interface HookStep {
|
|
17
|
+
comment?: string;
|
|
18
|
+
code: string;
|
|
19
|
+
wrap?: boolean;
|
|
20
|
+
stopOnFailure?: boolean;
|
|
21
|
+
label?: string;
|
|
22
|
+
}
|
|
23
|
+
/** Hook block render input. `collect` → declare the failure list and end with the fail-once guard. */
|
|
24
|
+
export interface HookRenderData {
|
|
25
|
+
steps: HookStep[];
|
|
26
|
+
collect?: boolean;
|
|
27
|
+
}
|
|
9
28
|
export interface TestFileData {
|
|
10
29
|
imports: string;
|
|
11
30
|
featureName: string;
|
|
@@ -82,6 +101,7 @@ export interface RenderImportsOptions {
|
|
|
82
101
|
needsMock?: boolean;
|
|
83
102
|
urlAssertImports?: string;
|
|
84
103
|
regexEscapeImport?: boolean;
|
|
104
|
+
checkedStateImports?: string;
|
|
85
105
|
}
|
|
86
106
|
export interface TestGeneratorAdapter {
|
|
87
107
|
readonly frameworkName: string;
|
|
@@ -96,24 +116,9 @@ export interface TestGeneratorAdapter {
|
|
|
96
116
|
code: string;
|
|
97
117
|
}>;
|
|
98
118
|
}): string;
|
|
99
|
-
renderBeforeAll(data:
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
code: string;
|
|
103
|
-
}>;
|
|
104
|
-
}): string;
|
|
105
|
-
renderAfterEach(data: {
|
|
106
|
-
steps: Array<{
|
|
107
|
-
comment?: string;
|
|
108
|
-
code: string;
|
|
109
|
-
}>;
|
|
110
|
-
}): string;
|
|
111
|
-
renderAfterAll(data: {
|
|
112
|
-
steps: Array<{
|
|
113
|
-
comment?: string;
|
|
114
|
-
code: string;
|
|
115
|
-
}>;
|
|
116
|
-
}): string;
|
|
119
|
+
renderBeforeAll(data: HookRenderData): string;
|
|
120
|
+
renderAfterEach(data: HookRenderData): string;
|
|
121
|
+
renderAfterAll(data: HookRenderData): string;
|
|
117
122
|
renderStep(templateName: string, data: any): string;
|
|
118
123
|
}
|
|
119
124
|
//# sourceMappingURL=adapter-interface.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter-interface.d.ts","sourceRoot":"","sources":["../../../../src/generators/test-generator/adapters/adapter-interface.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"adapter-interface.d.ts","sourceRoot":"","sources":["../../../../src/generators/test-generator/adapters/adapter-interface.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TestGeneratorAdapter, TestFileData, ScenarioData, RenderImportsOptions } from '../adapter-interface';
|
|
1
|
+
import { TestGeneratorAdapter, TestFileData, ScenarioData, RenderImportsOptions, HookRenderData } from '../adapter-interface';
|
|
2
2
|
/**
|
|
3
3
|
* AppiumAdapter
|
|
4
4
|
* Generates WebdriverIO + Appium (Mocha) test code using Handlebars templates.
|
|
@@ -24,24 +24,9 @@ export declare class AppiumAdapter implements TestGeneratorAdapter {
|
|
|
24
24
|
code: string;
|
|
25
25
|
}>;
|
|
26
26
|
}): string;
|
|
27
|
-
renderBeforeAll(data:
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
code: string;
|
|
31
|
-
}>;
|
|
32
|
-
}): string;
|
|
33
|
-
renderAfterEach(data: {
|
|
34
|
-
steps: Array<{
|
|
35
|
-
comment?: string;
|
|
36
|
-
code: string;
|
|
37
|
-
}>;
|
|
38
|
-
}): string;
|
|
39
|
-
renderAfterAll(data: {
|
|
40
|
-
steps: Array<{
|
|
41
|
-
comment?: string;
|
|
42
|
-
code: string;
|
|
43
|
-
}>;
|
|
44
|
-
}): string;
|
|
27
|
+
renderBeforeAll(data: HookRenderData): string;
|
|
28
|
+
renderAfterEach(data: HookRenderData): string;
|
|
29
|
+
renderAfterAll(data: HookRenderData): string;
|
|
45
30
|
renderStep(templateName: string, data: any): string;
|
|
46
31
|
}
|
|
47
32
|
//# sourceMappingURL=appium-adapter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"appium-adapter.d.ts","sourceRoot":"","sources":["../../../../../src/generators/test-generator/adapters/appium/appium-adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"appium-adapter.d.ts","sourceRoot":"","sources":["../../../../../src/generators/test-generator/adapters/appium/appium-adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,YAAY,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG9H;;;;;;;;;GASG;AACH,qBAAa,aAAc,YAAW,oBAAoB;IACxD,QAAQ,CAAC,aAAa,YAAY;IAClC,QAAQ,CAAC,aAAa,cAAc;IACpC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,OAAO,CAAC,cAAc,CAAiB;;IAOvC,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM;IAI1C,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM;IAI1C,aAAa,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,MAAM;IAIrD,gBAAgB,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,KAAK,CAAC;YAAE,OAAO,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,GAAG,MAAM;IAIpF,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM;IAI7C,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM;IAI7C,cAAc,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM;IAI5C,UAAU,CAAC,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,MAAM;CAGpD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"appium-adapter.js","sourceRoot":"","sources":["../../../../../src/generators/test-generator/adapters/appium/appium-adapter.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AAExB,2DAAuD;AAEvD;;;;;;;;;GASG;AACH,MAAa,aAAa;IAMxB;QALS,kBAAa,GAAG,QAAQ,CAAC;QACzB,kBAAa,GAAG,UAAU,CAAC;QAKlC,IAAI,CAAC,YAAY,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;QACtD,IAAI,CAAC,cAAc,GAAG,IAAI,gCAAc,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC9D,CAAC;IAED,cAAc,CAAC,IAAkB;QAC/B,OAAO,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IAClD,CAAC;IAED,cAAc,CAAC,IAAkB;QAC/B,OAAO,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IAClD,CAAC;IAED,aAAa,CAAC,OAA8B;QAC1C,OAAO,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IACpD,CAAC;IAED,gBAAgB,CAAC,IAA0D;QACzE,OAAO,IAAI,CAAC,cAAc,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACpD,CAAC;IAED,eAAe,CAAC,
|
|
1
|
+
{"version":3,"file":"appium-adapter.js","sourceRoot":"","sources":["../../../../../src/generators/test-generator/adapters/appium/appium-adapter.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AAExB,2DAAuD;AAEvD;;;;;;;;;GASG;AACH,MAAa,aAAa;IAMxB;QALS,kBAAa,GAAG,QAAQ,CAAC;QACzB,kBAAa,GAAG,UAAU,CAAC;QAKlC,IAAI,CAAC,YAAY,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;QACtD,IAAI,CAAC,cAAc,GAAG,IAAI,gCAAc,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC9D,CAAC;IAED,cAAc,CAAC,IAAkB;QAC/B,OAAO,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IAClD,CAAC;IAED,cAAc,CAAC,IAAkB;QAC/B,OAAO,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IAClD,CAAC;IAED,aAAa,CAAC,OAA8B;QAC1C,OAAO,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IACpD,CAAC;IAED,gBAAgB,CAAC,IAA0D;QACzE,OAAO,IAAI,CAAC,cAAc,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACpD,CAAC;IAED,eAAe,CAAC,IAAoB;QAClC,OAAO,IAAI,CAAC,cAAc,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IACnD,CAAC;IAED,eAAe,CAAC,IAAoB;QAClC,OAAO,IAAI,CAAC,cAAc,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IACnD,CAAC;IAED,cAAc,CAAC,IAAoB;QACjC,OAAO,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IAClD,CAAC;IAED,UAAU,CAAC,YAAoB,EAAE,IAAS;QACxC,OAAO,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IAC5D,CAAC;CACF;AA1CD,sCA0CC"}
|
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
after(async () => {
|
|
2
|
+
{{#if collect}}
|
|
3
|
+
// Hook checks are collected: every failed step is recorded and the hook fails ONCE with the full list
|
|
4
|
+
const __hookFailures: string[] = [];
|
|
5
|
+
{{/if}}
|
|
2
6
|
{{#each steps}}
|
|
3
7
|
{{#if comment}}
|
|
4
8
|
// {{comment}}
|
|
5
9
|
{{/if}}
|
|
10
|
+
{{#if wrap}}
|
|
11
|
+
try {
|
|
12
|
+
{{code}}
|
|
13
|
+
} catch (e) {
|
|
14
|
+
__hookFailures.push({{label}} + ': ' + String((e as Error).message).split('\n')[0]);
|
|
15
|
+
{{#if stopOnFailure}}
|
|
16
|
+
if (__hookFailures.length) throw new Error('[sungen] hook preconditions not met:\n' + __hookFailures.join('\n'));
|
|
17
|
+
{{/if}}
|
|
18
|
+
}
|
|
19
|
+
{{else}}
|
|
6
20
|
{{code}}
|
|
21
|
+
{{/if}}
|
|
7
22
|
{{/each}}
|
|
23
|
+
{{#if collect}}
|
|
24
|
+
if (__hookFailures.length) throw new Error('[sungen] hook preconditions not met:\n' + __hookFailures.join('\n'));
|
|
25
|
+
{{/if}}
|
|
8
26
|
});
|
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
afterEach(async () => {
|
|
2
|
+
{{#if collect}}
|
|
3
|
+
// Hook checks are collected: every failed step is recorded and the hook fails ONCE with the full list
|
|
4
|
+
const __hookFailures: string[] = [];
|
|
5
|
+
{{/if}}
|
|
2
6
|
{{#each steps}}
|
|
3
7
|
{{#if comment}}
|
|
4
8
|
// {{comment}}
|
|
5
9
|
{{/if}}
|
|
10
|
+
{{#if wrap}}
|
|
11
|
+
try {
|
|
12
|
+
{{code}}
|
|
13
|
+
} catch (e) {
|
|
14
|
+
__hookFailures.push({{label}} + ': ' + String((e as Error).message).split('\n')[0]);
|
|
15
|
+
{{#if stopOnFailure}}
|
|
16
|
+
if (__hookFailures.length) throw new Error('[sungen] hook preconditions not met:\n' + __hookFailures.join('\n'));
|
|
17
|
+
{{/if}}
|
|
18
|
+
}
|
|
19
|
+
{{else}}
|
|
6
20
|
{{code}}
|
|
21
|
+
{{/if}}
|
|
7
22
|
{{/each}}
|
|
23
|
+
{{#if collect}}
|
|
24
|
+
if (__hookFailures.length) throw new Error('[sungen] hook preconditions not met:\n' + __hookFailures.join('\n'));
|
|
25
|
+
{{/if}}
|
|
8
26
|
});
|
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
before(async () => {
|
|
2
|
+
{{#if collect}}
|
|
3
|
+
// Hook checks are collected: every failed step is recorded and the hook fails ONCE with the full list
|
|
4
|
+
const __hookFailures: string[] = [];
|
|
5
|
+
{{/if}}
|
|
2
6
|
{{#each steps}}
|
|
3
7
|
{{#if comment}}
|
|
4
8
|
// {{comment}}
|
|
5
9
|
{{/if}}
|
|
10
|
+
{{#if wrap}}
|
|
11
|
+
try {
|
|
12
|
+
{{code}}
|
|
13
|
+
} catch (e) {
|
|
14
|
+
__hookFailures.push({{label}} + ': ' + String((e as Error).message).split('\n')[0]);
|
|
15
|
+
{{#if stopOnFailure}}
|
|
16
|
+
if (__hookFailures.length) throw new Error('[sungen] hook preconditions not met:\n' + __hookFailures.join('\n'));
|
|
17
|
+
{{/if}}
|
|
18
|
+
}
|
|
19
|
+
{{else}}
|
|
6
20
|
{{code}}
|
|
21
|
+
{{/if}}
|
|
7
22
|
{{/each}}
|
|
23
|
+
{{#if collect}}
|
|
24
|
+
if (__hookFailures.length) throw new Error('[sungen] hook preconditions not met:\n' + __hookFailures.join('\n'));
|
|
25
|
+
{{/if}}
|
|
8
26
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
throw new Error('[sungen] "click … at position/offset" is web-only — tap the control the position targets directly ("User tap [X] button"), or tag the scenario @manual');
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
{{!-- Tap an element by its visible text / content-desc (dynamic text match). --}}
|
|
2
|
-
{{#if nth}}await $$('//*[contains(@content-desc,"{{escapeQuotes dataValue}}") or contains(@text,"{{escapeQuotes dataValue}}")]')
|
|
2
|
+
{{#if (gte nth -1)}}await (await $$('//*[contains(@content-desc,"{{escapeQuotes dataValue}}") or contains(@text,"{{escapeQuotes dataValue}}")]')).at({{nth}}).click();{{else}}await $('//*[contains(@content-desc,"{{escapeQuotes dataValue}}") or contains(@text,"{{escapeQuotes dataValue}}")]').click();{{/if}}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
{{!-- Double-tap. Use the platform gesture (element.doubleClick is web-oriented). --}}
|
|
2
2
|
{
|
|
3
3
|
const __el = await {{> locator}};
|
|
4
|
+
// Fail loud with the REAL cause when the element never resolved. `driver.execute` does NOT do
|
|
5
|
+
// WDIO's implicit existence wait (every other action template gets that for free by going
|
|
6
|
+
// through .click()/.setValue()/expect), and the locator partial returns $(selector) even for a
|
|
7
|
+
// never-found element by design. So an undefined elementId reaches Appium, which falls through
|
|
8
|
+
// to its coordinates branch and reports "Double click offset coordinates must be provided if
|
|
9
|
+
// element is not set" — a message about offsets for what is really a not-found element (#668).
|
|
10
|
+
if (!__el.elementId) throw new Error((__el as any).error?.message || `Element not found: ${__el.selector}`);
|
|
4
11
|
if (driver.isIOS) await driver.execute('mobile: doubleTap', { elementId: __el.elementId });
|
|
5
12
|
else await driver.execute('mobile: doubleClickGesture', { elementId: __el.elementId });
|
|
6
13
|
}
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
{{!-- Hybrid app: switch into the webview context (mobile equivalent of entering an iframe).
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const __web = __ctxs.find(c => /WEBVIEW|CHROMIUM/i.test(typeof c === 'string' ? c : c.id));
|
|
5
|
-
if (__web) await driver.switchContext(typeof __web === 'string' ? __web : __web.id);
|
|
6
|
-
}
|
|
1
|
+
{{!-- Hybrid app: switch into the webview context (mobile equivalent of entering an iframe).
|
|
2
|
+
Polls for the context and throws when it never appears — see __enterWebContext (#705). --}}
|
|
3
|
+
await __enterWebContext('{{escapeQuotes frameRef}}');
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
{{!-- An HTML paginator is a web control: a native list pages by scrolling, not by a next/prev
|
|
2
|
+
button pair, so there is nothing honest to emit here. --}}
|
|
3
|
+
throw new Error("[sungen] 'go to next/prev page in table' drives an HTML paginator and is not supported on the appium adapter. Scroll the list instead, tap the pager control as a plain tap step, or tag this scenario @manual.");
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
await expect({{> locator}}).toBeDisplayed();
|
|
9
9
|
{{~else if scope~}}
|
|
10
10
|
await expect({{> locator}}).toBeDisplayed();
|
|
11
|
-
{{~else if nth~}}
|
|
11
|
+
{{~else if (gte nth -1)~}}
|
|
12
12
|
await expect({{> locator}}).toBeDisplayed();
|
|
13
13
|
{{~else~}}
|
|
14
14
|
await __assertVisible({{> appium-selector-expr}});
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
await (async () => { const e = await {{> locator}};
|
|
2
|
+
// Fail loud on a missing target — `driver.execute` skips WDIO's implicit existence wait, so an
|
|
3
|
+
// undefined elementId surfaces as an opaque coordinates/offset error instead of the not-found
|
|
4
|
+
// that actually happened (#668).
|
|
5
|
+
if (!e.elementId) throw new Error((e as any).error?.message || `Element not found: ${e.selector}`);
|
|
2
6
|
// XCUITest `mobile: touchAndHold` takes SECONDS; UiAutomator2 `mobile: longClickGesture` takes ms.
|
|
3
7
|
if (driver.isIOS) { await driver.execute('mobile: touchAndHold', { elementId: e.elementId, duration: {{durationMs}} / 1000 }); }
|
|
4
8
|
else { await driver.execute('mobile: longClickGesture', { elementId: e.elementId, duration: {{durationMs}} }); }
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
await (async () => { const e = await {{> locator}};
|
|
2
|
+
// Fail loud on a missing target — `driver.execute` skips WDIO's implicit existence wait, so an
|
|
3
|
+
// undefined elementId surfaces as an opaque coordinates/offset error instead of the not-found
|
|
4
|
+
// that actually happened (#668).
|
|
5
|
+
if (!e.elementId) throw new Error((e as any).error?.message || `Element not found: ${e.selector}`);
|
|
2
6
|
// XCUITest `mobile: pinch`: scale >1 zooms in, <1 zooms out (velocity sign must match).
|
|
3
7
|
if (driver.isIOS) { await driver.execute('mobile: pinch', { elementId: e.elementId, scale: {{#if zoomOut}}0.5{{else}}2{{/if}}, velocity: {{#if zoomOut}}-1{{else}}1{{/if}} }); }
|
|
4
8
|
else { await driver.execute('mobile: {{#if zoomOut}}pinchCloseGesture{{else}}pinchOpenGesture{{/if}}', { elementId: e.elementId, percent: 0.75 }); }
|
|
@@ -9,7 +9,15 @@
|
|
|
9
9
|
scroll-into-view, so a below-fold / nav-occluded element is scrolled into the safe band before any
|
|
10
10
|
find/tap/assert (Appium has no auto-scroll). Parent/scope/nth chains keep the plain `$()` — those
|
|
11
11
|
resolve within a container / by index where a blind scroll doesn't apply.
|
|
12
|
+
`nth` is an INDEX, gated numerically (`gte nth -1`), not on truthiness (#720): `{{#if nth}}` read
|
|
13
|
+
`nth: 0` — the index every doc page uses as its example — as "no index declared" and sent it down
|
|
14
|
+
the __ensureVisible branch, while the web adapter indexed it, so the two adapters disagreed on the
|
|
15
|
+
one value authors actually write. It renders `(await $$(expr)).at(n)`: `$$` is a
|
|
16
|
+
ChainablePromiseArray in WDIO v9, so the old `$$(expr)[n]` indexed a promise and was `undefined`
|
|
17
|
+
for EVERY n (the awaited form is what the mobile helpers elsewhere in the emitted spec already
|
|
18
|
+
use), and `.at()` carries `-1` = last match with no second branch. The resolver has already
|
|
19
|
+
normalised anything outside `>= -1` to undefined and reported it as SG-W018.
|
|
12
20
|
`plain=true` (passed by is-hidden-assertion) also forces the bare `$()`: an element asserted HIDDEN
|
|
13
21
|
is expected to be absent, so scroll-hunting for it is both pointless and harmful — the 12x down-scroll
|
|
14
22
|
would drag the screen to the bottom and strand later same-scenario steps that sit above. --}}
|
|
15
|
-
{{~#if parentLocator~}}{{
|
|
23
|
+
{{~#if parentLocator~}}{{#if (gte nth -1)}}(await {{parentLocator}}.$$({{> appium-selector-expr}})).at({{nth}}){{else}}{{parentLocator}}.$({{> appium-selector-expr}}){{/if}}{{~else~}}{{#if scope}}{{#if (gte nth -1)}}(await $('~{{escapeQuotes scope}}').$$({{> appium-selector-expr}})).at({{nth}}){{else}}$('~{{escapeQuotes scope}}').$({{> appium-selector-expr}}){{/if}}{{else}}{{#if (gte nth -1)}}(await $$({{> appium-selector-expr}})).at({{nth}}){{else}}{{#if plain}}$({{> appium-selector-expr}}){{else}}(await __ensureVisible({{> appium-selector-expr}})){{/if}}{{/if}}{{/if}}{{~/if~}}
|
|
@@ -210,6 +210,36 @@ async function __assertCheckedState(el: WebdriverIO.Element, expected: boolean,
|
|
|
210
210
|
}
|
|
211
211
|
throw new Error(`Expect ${label} to be ${want} — read [${signals.map(s => `${s.source} → ${s.value}`).join(', ')}]`);
|
|
212
212
|
}
|
|
213
|
+
|
|
214
|
+
// Entering a "frame" on a native driver means switching into the WebView CONTEXT — there is no
|
|
215
|
+
// iframe to locate. That context does not exist until the WebView runtime has created it, and the
|
|
216
|
+
// tap that kicks off the navigation returns long before that, so a ONE-SHOT getContexts() reads a
|
|
217
|
+
// list that holds only NATIVE_APP. Skipping the switch on that reading is the worst possible
|
|
218
|
+
// answer: every later step then searches the native tree, where a hybrid WebView is a SINGLE
|
|
219
|
+
// opaque leaf with no children — the target can never appear there, so no downstream wait can
|
|
220
|
+
// recover it and the run dies with a misleading "element still not displayed" (#705). Poll for the
|
|
221
|
+
// context instead, and throw when it never arrives: a step that reads "switch to X frame" must
|
|
222
|
+
// never quietly not switch.
|
|
223
|
+
async function __enterWebContext(label: string): Promise<void> {
|
|
224
|
+
const budget = Number((driver as any)?.options?.waitforTimeout) || 30000;
|
|
225
|
+
const deadline = Date.now() + budget;
|
|
226
|
+
let seen: any[] = [];
|
|
227
|
+
for (;;) {
|
|
228
|
+
seen = await driver.getContexts();
|
|
229
|
+
const web = seen.find(c => /WEBVIEW|CHROMIUM/i.test(typeof c === 'string' ? c : c.id));
|
|
230
|
+
if (web) { await driver.switchContext(typeof web === 'string' ? web : web.id); return; }
|
|
231
|
+
if (Date.now() >= deadline) break;
|
|
232
|
+
await driver.pause(500);
|
|
233
|
+
}
|
|
234
|
+
throw new Error(
|
|
235
|
+
`[sungen] "switch to ${label} frame" — no WEBVIEW/CHROMIUM context appeared within ${budget}ms ` +
|
|
236
|
+
`(contexts seen: ${JSON.stringify(seen)}). The driver is still in NATIVE_APP, where a hybrid WebView ` +
|
|
237
|
+
`is one opaque node with no children, so every later step would fail as "element not displayed" ` +
|
|
238
|
+
`while the real cause is this switch. If the transition is genuinely slower than ${budget}ms, raise ` +
|
|
239
|
+
`waitforTimeout in wdio.conf.ts; if the screen has no WebView, drop the frame step and assert the ` +
|
|
240
|
+
`native markers instead.`,
|
|
241
|
+
);
|
|
242
|
+
}
|
|
213
243
|
{{#if singleAuthRole}}
|
|
214
244
|
import * as fs from 'node:fs';
|
|
215
245
|
import * as path from 'node:path';
|
|
@@ -340,23 +370,25 @@ describe('{{featureName}}', () => {
|
|
|
340
370
|
// @auth:{{singleAuthRole}} — authenticate ONCE before any scenario; the session persists across
|
|
341
371
|
// the per-scenario relaunch below (noReset:true). Throws (blocks the spec) if login can't be done.
|
|
342
372
|
before(async () => {
|
|
343
|
-
{{#if appPackage}}
|
|
344
373
|
// Relaunch to a known launch screen first — the session may attach to the app in any state.
|
|
345
374
|
// Platform-aware id (NOT the Android literal): on iOS a @platform:mobile feature's app is the
|
|
346
375
|
// dual-id bundle id — a literal appPackage here would throw and block the whole spec.
|
|
347
|
-
// (__resolveAppId is a hoisted function declaration in this describe scope.
|
|
376
|
+
// (__resolveAppId is a hoisted function declaration in this describe scope. It is no longer
|
|
377
|
+
// gated on a `Path:`-derived package (#669): it resolves the session capability too, and throws
|
|
378
|
+
// a named error when nothing supplies an id at all.)
|
|
348
379
|
const __AUTH_APP__ = __resolveAppId();
|
|
349
380
|
try { await driver.terminateApp(__AUTH_APP__); } catch { /* not running */ }
|
|
350
381
|
await driver.activateApp(__AUTH_APP__);
|
|
351
|
-
{{/if}}
|
|
352
382
|
await __ensureAuth('{{singleAuthRole}}');
|
|
353
383
|
});
|
|
354
384
|
|
|
355
385
|
{{/if}}
|
|
356
|
-
{{#if appPackage}}
|
|
357
386
|
// Multi-app: this feature's app (from the `Path:` line). Reset to its launch screen before each
|
|
358
387
|
// scenario so one `wdio run` can host screens from different apps — each spec launches its own.
|
|
359
388
|
// The `Path:` holds the ANDROID package (or, for an @platform:ios feature, the iOS bundle id).
|
|
389
|
+
// EMPTY when the feature declared no usable `Path:` (#669) — the session capability then supplies
|
|
390
|
+
// the id (see __resolveAppId). Emitted unconditionally so that a feature without a `Path:` still
|
|
391
|
+
// gets per-scenario reset + Background instead of silently dropping to a once-per-file before().
|
|
360
392
|
const __APP_PKG_DEFAULT__ = '{{appPackage}}';
|
|
361
393
|
{{#if iosBundleId}}
|
|
362
394
|
// Per-feature iOS bundle id from the dual-id `Path: <androidPkg>/<activity> | <iosBundleId>` —
|
|
@@ -366,13 +398,26 @@ describe('{{featureName}}', () => {
|
|
|
366
398
|
{{/if}}
|
|
367
399
|
// Platform-aware app id: an @platform:mobile spec runs on BOTH OSes. On iOS prefer the feature's own
|
|
368
400
|
// bundle id (dual-id Path), then the session cap (IOS_BUNDLE_ID in wdio.conf), then the Path value;
|
|
369
|
-
// on Android (or any non-iOS session)
|
|
401
|
+
// on Android (or any non-iOS session) prefer the Path package, then the session cap.
|
|
402
|
+
// The session-capability fallback (#669) is what lets a feature with no app-package `Path:` keep a
|
|
403
|
+
// real per-scenario reset: wdio.conf sets `appium:appPackage` for the run, so the id the compiler
|
|
404
|
+
// could not read off the feature file is almost always present here. Throwing when NOTHING supplies
|
|
405
|
+
// it is deliberate — the alternative was the silent once-per-file before() this issue is about,
|
|
406
|
+
// where scenarios leak tab/scroll/login state into each other and the suite lies about why it
|
|
407
|
+
// failed. SG-W029 already named this at compile time, so this throw is never the first warning.
|
|
370
408
|
function __resolveAppId(): string {
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
409
|
+
const caps = (typeof driver !== 'undefined' ? (driver.requestedCapabilities || {}) : {}) as Record<string, string>;
|
|
410
|
+
const resolved = (typeof driver !== 'undefined' && driver.isIOS)
|
|
411
|
+
? ({{#if iosBundleId}}__IOS_BUNDLE__ || {{/if}}caps['appium:bundleId'] || caps['bundleId'] || __APP_PKG_DEFAULT__ || caps['appium:appPackage'] || caps['appPackage'])
|
|
412
|
+
: (__APP_PKG_DEFAULT__ || caps['appium:appPackage'] || caps['appPackage'] || caps['appium:bundleId'] || caps['bundleId']);
|
|
413
|
+
if (!resolved) {
|
|
414
|
+
throw new Error(
|
|
415
|
+
`[sungen] cannot resolve this app's id, so no per-scenario reset is possible (SG-W029). ` +
|
|
416
|
+
`Add an app-package \`Path:\` to the feature — \`Path: com.example.app/.MainActivity\` — ` +
|
|
417
|
+
`or set APP_PACKAGE (Android) / IOS_BUNDLE_ID (iOS) so wdio.conf puts it on the session.`,
|
|
418
|
+
);
|
|
374
419
|
}
|
|
375
|
-
return
|
|
420
|
+
return resolved;
|
|
376
421
|
}
|
|
377
422
|
// ── Reset tier ────────────────────────────────────────────────────────────────────────────────
|
|
378
423
|
// How much state each scenario starts from (`@reset:` on the Feature; default `soft`):
|
|
@@ -583,20 +628,6 @@ describe('{{featureName}}', () => {
|
|
|
583
628
|
{{/if}}
|
|
584
629
|
});
|
|
585
630
|
|
|
586
|
-
{{/if}}
|
|
587
|
-
{{#unless appPackage}}
|
|
588
|
-
{{#if backgroundSteps}}
|
|
589
|
-
before(async () => {
|
|
590
|
-
{{#each backgroundSteps}}
|
|
591
|
-
{{#if comment}}
|
|
592
|
-
// {{comment}}
|
|
593
|
-
{{/if}}
|
|
594
|
-
{{code}}
|
|
595
|
-
{{/each}}
|
|
596
|
-
});
|
|
597
|
-
|
|
598
|
-
{{/if}}
|
|
599
|
-
{{/unless}}
|
|
600
631
|
{{#if beforeAll}}
|
|
601
632
|
{{beforeAll}}
|
|
602
633
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { TestGeneratorAdapter, TestFileData, ScenarioData, StepTemplateData, LocatorExpression } from './adapter-interface';
|
|
1
|
+
export { TestGeneratorAdapter, TestFileData, ScenarioData, StepTemplateData, LocatorExpression, HookStep, HookRenderData } from './adapter-interface';
|
|
2
2
|
export { AdapterRegistry, adapterRegistry, DriverNotInstalledError } from './adapter-registry';
|
|
3
3
|
export { PlaywrightAdapter } from './playwright/playwright-adapter';
|
|
4
4
|
export { AppiumAdapter } from './appium/appium-adapter';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/generators/test-generator/adapters/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/generators/test-generator/adapters/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACtJ,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC/F,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC"}
|