@sun-asterisk/sungen 3.2.28 → 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/capabilities/discover.d.ts +29 -0
- package/dist/capabilities/discover.d.ts.map +1 -1
- package/dist/capabilities/discover.js +144 -10
- package/dist/capabilities/discover.js.map +1 -1
- package/dist/capabilities/registry.d.ts +18 -0
- package/dist/capabilities/registry.d.ts.map +1 -1
- package/dist/capabilities/registry.js +25 -0
- package/dist/capabilities/registry.js.map +1 -1
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/audit.js +9 -0
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/cli/commands/capability.js +1 -1
- package/dist/cli/commands/capability.js.map +1 -1
- 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/dashboard/templates/index.html +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/feature-parser.d.ts +1 -1
- package/dist/exporters/feature-parser.js +1 -1
- package/dist/exporters/matrix/build.d.ts.map +1 -1
- package/dist/exporters/matrix/build.js +18 -3
- package/dist/exporters/matrix/build.js.map +1 -1
- package/dist/exporters/matrix/item-labels.d.ts +35 -0
- package/dist/exporters/matrix/item-labels.d.ts.map +1 -0
- package/dist/exporters/matrix/item-labels.js +90 -0
- package/dist/exporters/matrix/item-labels.js.map +1 -0
- package/dist/exporters/matrix/render-coverage-sheet.d.ts +14 -0
- package/dist/exporters/matrix/render-coverage-sheet.d.ts.map +1 -0
- package/dist/exporters/matrix/render-coverage-sheet.js +162 -0
- package/dist/exporters/matrix/render-coverage-sheet.js.map +1 -0
- 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 +20 -0
- package/dist/exporters/matrix/render-overview-sheet.d.ts.map +1 -0
- package/dist/exporters/matrix/render-overview-sheet.js +32 -0
- package/dist/exporters/matrix/render-overview-sheet.js.map +1 -0
- package/dist/exporters/matrix/render-testcase-sheet.d.ts +30 -0
- package/dist/exporters/matrix/render-testcase-sheet.d.ts.map +1 -0
- package/dist/exporters/matrix/render-testcase-sheet.js +156 -0
- package/dist/exporters/matrix/render-testcase-sheet.js.map +1 -0
- package/dist/exporters/matrix/render-xlsx.d.ts +41 -31
- package/dist/exporters/matrix/render-xlsx.d.ts.map +1 -1
- package/dist/exporters/matrix/render-xlsx.js +72 -425
- package/dist/exporters/matrix/render-xlsx.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 +30 -0
- package/dist/exporters/matrix/testcase-summary-band.d.ts.map +1 -0
- package/dist/exporters/matrix/testcase-summary-band.js +71 -0
- package/dist/exporters/matrix/testcase-summary-band.js.map +1 -0
- package/dist/exporters/matrix/wording.d.ts.map +1 -1
- package/dist/exporters/matrix/wording.js +13 -0
- package/dist/exporters/matrix/wording.js.map +1 -1
- package/dist/exporters/matrix/xlsx-cells.d.ts +38 -0
- package/dist/exporters/matrix/xlsx-cells.d.ts.map +1 -0
- package/dist/exporters/matrix/xlsx-cells.js +52 -0
- package/dist/exporters/matrix/xlsx-cells.js.map +1 -0
- 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/exporters/xlsx-report-builder.d.ts +12 -1
- package/dist/exporters/xlsx-report-builder.d.ts.map +1 -1
- package/dist/exporters/xlsx-report-builder.js +10 -2
- package/dist/exporters/xlsx-report-builder.js.map +1 -1
- package/dist/generators/gherkin-parser/index.d.ts +10 -0
- package/dist/generators/gherkin-parser/index.d.ts.map +1 -1
- package/dist/generators/gherkin-parser/index.js +20 -12
- 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/os-support.d.ts +53 -0
- package/dist/generators/test-generator/adapters/appium/os-support.d.ts.map +1 -0
- package/dist/generators/test-generator/adapters/appium/os-support.js +200 -0
- package/dist/generators/test-generator/adapters/appium/os-support.js.map +1 -0
- 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/alert-fill-action.hbs +9 -2
- package/dist/generators/test-generator/adapters/appium/templates/steps/actions/capture-variable.hbs +24 -1
- 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/hover-action.hbs +6 -2
- package/dist/generators/test-generator/adapters/appium/templates/steps/actions/hover-element-with-text.hbs +4 -3
- 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/actions/unknown-element-action.hbs +9 -0
- package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/have-value-assertion.hbs +34 -1
- package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/label-value-assertion.hbs +14 -6
- 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/go-back-action.hbs +21 -0
- 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/gestures/set-geolocation-action.hbs +16 -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 +62 -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 +7 -2
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row.hbs +7 -2
- 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 +21 -3
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/state-with-filter-assertion.hbs +20 -2
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-empty.hbs +4 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-match-data.hbs +4 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-count.hbs +4 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-exists.hbs +12 -4
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-not-exists.hbs +14 -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-base.hbs +8 -8
- package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator-nth.hbs +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator-strategies/id.hbs +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator-strategies/testid.hbs +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator.hbs +8 -8
- 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 +165 -40
- package/dist/generators/test-generator/code-generator.js.map +1 -1
- package/dist/generators/test-generator/diagnostics.d.ts +116 -6
- package/dist/generators/test-generator/diagnostics.d.ts.map +1 -1
- package/dist/generators/test-generator/diagnostics.js +115 -5
- package/dist/generators/test-generator/diagnostics.js.map +1 -1
- package/dist/generators/test-generator/patterns/index.d.ts +57 -11
- package/dist/generators/test-generator/patterns/index.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/index.js +163 -21
- package/dist/generators/test-generator/patterns/index.js.map +1 -1
- package/dist/generators/test-generator/patterns/types.d.ts +8 -0
- package/dist/generators/test-generator/patterns/types.d.ts.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 +103 -10
- package/dist/generators/test-generator/step-mapper.d.ts.map +1 -1
- package/dist/generators/test-generator/step-mapper.js +266 -45
- 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 +53 -2
- package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
- package/dist/generators/test-generator/utils/selector-resolver.js +273 -27
- 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/audit.d.ts +3 -1
- package/dist/harness/audit.d.ts.map +1 -1
- package/dist/harness/audit.js +51 -28
- package/dist/harness/audit.js.map +1 -1
- package/dist/harness/capability-plan.d.ts +4 -0
- package/dist/harness/capability-plan.d.ts.map +1 -1
- package/dist/harness/capability-plan.js +32 -2
- package/dist/harness/capability-plan.js.map +1 -1
- package/dist/harness/catalog/drivers.yaml +1 -1
- package/dist/harness/catalog/universal-viewpoints.yaml +145 -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/parse.d.ts +6 -0
- package/dist/harness/parse.d.ts.map +1 -1
- package/dist/harness/parse.js +1 -1
- package/dist/harness/parse.js.map +1 -1
- package/dist/harness/repair.d.ts.map +1 -1
- package/dist/harness/repair.js +8 -1
- package/dist/harness/repair.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/harness/sensors.d.ts +48 -0
- package/dist/harness/sensors.d.ts.map +1 -1
- package/dist/harness/sensors.js +26 -1
- package/dist/harness/sensors.js.map +1 -1
- package/dist/harness/viewpoint-ledger.d.ts +10 -0
- package/dist/harness/viewpoint-ledger.d.ts.map +1 -1
- package/dist/harness/viewpoint-ledger.js +23 -2
- package/dist/harness/viewpoint-ledger.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/delivery.md +4 -3
- 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-delivery/SKILL.md +14 -5
- package/dist/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +62 -3
- package/dist/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +126 -11
- package/dist/orchestrator/templates/ai-src/skills/sungen-mobile-gestures/SKILL.md +16 -1
- package/dist/orchestrator/templates/ai-src/skills/sungen-selector-fix/SKILL.md +12 -0
- package/dist/orchestrator/templates/ai-src/skills/sungen-selector-keys/SKILL.md +19 -5
- package/dist/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +88 -2
- package/dist/orchestrator/templates/ai-src/skills/sungen-tc-review/SKILL.md +62 -5
- package/dist/orchestrator/templates/ai-src/skills/sungen-test-design-techniques/SKILL.md +13 -0
- package/dist/orchestrator/templates/ai-src/skills/sungen-viewpoint/SKILL.md +59 -10
- package/dist/orchestrator/templates/ai-src/skills/sungen-viewpoint/group-f-mobile-native.md +419 -0
- package/dist/orchestrator/templates/playwright.config.ts +7 -0
- package/dist/orchestrator/templates/readme.md +1 -1
- 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-pw-shape-reporter.ts +0 -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/orchestrator/templates/wdio.conf.ts +105 -1
- 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/capabilities/discover.ts +146 -10
- package/src/capabilities/registry.ts +30 -0
- package/src/cli/commands/audit.ts +9 -0
- package/src/cli/commands/capability.ts +1 -1
- 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/dashboard/templates/index.html +1 -1
- package/src/exporters/api-testcase-formatter.ts +5 -7
- package/src/exporters/feature-parser.ts +1 -1
- package/src/exporters/matrix/build.ts +17 -3
- package/src/exporters/matrix/item-labels.ts +78 -0
- package/src/exporters/matrix/render-coverage-sheet.ts +170 -0
- package/src/exporters/matrix/render-csv.ts +3 -1
- package/src/exporters/matrix/render-overview-sheet.ts +51 -0
- package/src/exporters/matrix/render-testcase-sheet.ts +178 -0
- package/src/exporters/matrix/render-xlsx.ts +67 -448
- package/src/exporters/matrix/result-totals.ts +37 -0
- package/src/exporters/matrix/testcase-summary-band.ts +74 -0
- package/src/exporters/matrix/wording.ts +13 -0
- package/src/exporters/matrix/xlsx-cells.ts +56 -0
- 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/exporters/xlsx-report-builder.ts +16 -2
- package/src/generators/gherkin-parser/index.ts +22 -11
- 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/os-support.ts +176 -0
- 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/alert-fill-action.hbs +9 -2
- package/src/generators/test-generator/adapters/appium/templates/steps/actions/capture-variable.hbs +24 -1
- 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/hover-action.hbs +6 -2
- package/src/generators/test-generator/adapters/appium/templates/steps/actions/hover-element-with-text.hbs +4 -3
- 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/actions/unknown-element-action.hbs +9 -0
- package/src/generators/test-generator/adapters/appium/templates/steps/assertions/have-value-assertion.hbs +34 -1
- package/src/generators/test-generator/adapters/appium/templates/steps/assertions/label-value-assertion.hbs +14 -6
- 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/go-back-action.hbs +21 -0
- 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/gestures/set-geolocation-action.hbs +16 -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 +62 -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 +7 -2
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row.hbs +7 -2
- 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 +21 -3
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/state-with-filter-assertion.hbs +20 -2
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-empty.hbs +4 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-match-data.hbs +4 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-count.hbs +4 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-exists.hbs +12 -4
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-not-exists.hbs +14 -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-base.hbs +8 -8
- package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator-nth.hbs +1 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator-strategies/id.hbs +1 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator-strategies/testid.hbs +1 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator.hbs +8 -8
- package/src/generators/test-generator/adapters/playwright/templates/test-file.hbs +10 -8
- package/src/generators/test-generator/code-generator.ts +181 -46
- package/src/generators/test-generator/diagnostics.ts +117 -6
- package/src/generators/test-generator/patterns/index.ts +175 -24
- package/src/generators/test-generator/patterns/types.ts +8 -0
- package/src/generators/test-generator/patterns/with-parent-scope.ts +41 -0
- package/src/generators/test-generator/step-mapper.ts +277 -43
- 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 +333 -28
- package/src/generators/test-generator/utils/selector-type-validation.ts +87 -0
- package/src/harness/audit.ts +55 -30
- package/src/harness/capability-plan.ts +33 -1
- package/src/harness/catalog/drivers.yaml +1 -1
- package/src/harness/catalog/universal-viewpoints.yaml +145 -0
- package/src/harness/data-driven-lint.ts +192 -32
- package/src/harness/parse.ts +7 -1
- package/src/harness/repair.ts +8 -1
- package/src/harness/script-check.ts +186 -21
- package/src/harness/sensors.ts +75 -1
- package/src/harness/viewpoint-ledger.ts +26 -5
- 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/delivery.md +4 -3
- 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-delivery/SKILL.md +14 -5
- package/src/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +62 -3
- package/src/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +126 -11
- package/src/orchestrator/templates/ai-src/skills/sungen-mobile-gestures/SKILL.md +16 -1
- package/src/orchestrator/templates/ai-src/skills/sungen-selector-fix/SKILL.md +12 -0
- package/src/orchestrator/templates/ai-src/skills/sungen-selector-keys/SKILL.md +19 -5
- package/src/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +88 -2
- package/src/orchestrator/templates/ai-src/skills/sungen-tc-review/SKILL.md +62 -5
- package/src/orchestrator/templates/ai-src/skills/sungen-test-design-techniques/SKILL.md +13 -0
- package/src/orchestrator/templates/ai-src/skills/sungen-viewpoint/SKILL.md +59 -10
- package/src/orchestrator/templates/ai-src/skills/sungen-viewpoint/group-f-mobile-native.md +419 -0
- package/src/orchestrator/templates/playwright.config.ts +7 -0
- package/src/orchestrator/templates/readme.md +1 -1
- package/src/orchestrator/templates/specs-checked-state.ts +324 -0
- package/src/orchestrator/templates/specs-pw-shape-reporter.ts +0 -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/orchestrator/templates/wdio.conf.ts +105 -1
- package/src/utils/selector-types.ts +54 -5
|
@@ -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
|
});
|
package/dist/generators/test-generator/adapters/appium/templates/steps/actions/alert-fill-action.hbs
CHANGED
|
@@ -1,2 +1,9 @@
|
|
|
1
|
-
{{!-- Filling a native prompt
|
|
2
|
-
|
|
1
|
+
{{!-- Filling a native prompt has no Appium implementation here. This file used to be comment-ONLY,
|
|
2
|
+
which made it the one member of the web-only set that failed SILENTLY: the comment is stripped,
|
|
3
|
+
so the step emitted nothing, ran, and did nothing — a scenario could fill a prompt and pass
|
|
4
|
+
having never touched it. Every other web-only step on this adapter refuses by name, and now so
|
|
5
|
+
does this one. `alert-fill` also declares `platforms: ['web']`, so the refusal normally arrives
|
|
6
|
+
at COMPILE time (SG-W020); this body is the second line of defence for any future pattern that
|
|
7
|
+
reaches the template without declaring its platforms.
|
|
8
|
+
Requested value: '{{fillValue}}' --}}
|
|
9
|
+
throw new Error("[sungen] filling a native prompt is not supported on the appium adapter. Accept or dismiss the alert instead, drive the app's own text field as a normal element, or tag this scenario @manual:M10.");
|
package/dist/generators/test-generator/adapters/appium/templates/steps/actions/capture-variable.hbs
CHANGED
|
@@ -6,5 +6,28 @@
|
|
|
6
6
|
const __sources = driver.isIOS
|
|
7
7
|
? {{#if (eq capture 'inputValue')}}[await __el.getAttribute('value'), await __el.getAttribute('label')]{{else}}[await __el.getAttribute('label'), await __el.getAttribute('value')]{{/if}}
|
|
8
8
|
: [await __el.getText(), await __el.getAttribute('content-desc')];
|
|
9
|
-
|
|
9
|
+
let __captured = String(__sources.find(s => s && String(s).trim() !== '') ?? '').trim();
|
|
10
|
+
{{#if (eq capture 'inputValue')}}
|
|
11
|
+
{{!-- iOS placeholder guard. Some WebDriverAgent versions echo an empty UITextField's
|
|
12
|
+
placeholder back as its @value (the XCUITest driver documents @value as
|
|
13
|
+
"a complex attribute whose calculation algorithm depends on the actual element type"
|
|
14
|
+
and promises nothing for an empty field). Unguarded, an empty field captures its
|
|
15
|
+
PLACEHOLDER into testData under the author's variable name — and because a capture
|
|
16
|
+
feeds later steps, that corruption propagates silently instead of failing loudly.
|
|
17
|
+
Unlike the assertion path there is no expected value to gate on, so this check is
|
|
18
|
+
unconditional on iOS: one extra round-trip buys a captured value that is not a lie. --}}
|
|
19
|
+
if (driver.isIOS && __captured !== '') {
|
|
20
|
+
let __placeholder = null;
|
|
21
|
+
try { __placeholder = await __el.getAttribute('placeholderValue'); } catch { /* attribute unsupported on this node */ }
|
|
22
|
+
if (__placeholder && String(__placeholder).trim() === __captured) {
|
|
23
|
+
{{!-- Leave a breadcrumb. Unlike the assertion path — which throws at the field in
|
|
24
|
+
question — a discarded capture succeeds silently and the empty string travels to
|
|
25
|
+
whatever step later consumes it, possibly in another file. That downstream failure
|
|
26
|
+
carries nothing linking it back here, so say it out loud now. --}}
|
|
27
|
+
console.warn(` ! [sungen] {{escapeQuotes varName}} read back as its own placeholder ("${__captured}") — captured empty instead`);
|
|
28
|
+
__captured = '';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
{{/if}}
|
|
32
|
+
testData.set('{{escapeQuotes varName}}', __captured);
|
|
10
33
|
}
|
|
@@ -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}}');
|
package/dist/generators/test-generator/adapters/appium/templates/steps/actions/hover-action.hbs
CHANGED
|
@@ -1,2 +1,6 @@
|
|
|
1
|
-
{{!-- No hover on touch
|
|
2
|
-
|
|
1
|
+
{{!-- No hover on a touch screen. This template used to hold only this comment, so the step compiled
|
|
2
|
+
to an empty line: the scenario claimed to exercise a hover, exercised nothing, and passed.
|
|
3
|
+
`hover-element` now declares platforms: ['web'], so a mobile project is refused at SG-W020
|
|
4
|
+
before reaching here — this throw is the second source agreeing with the first, the treatment
|
|
5
|
+
alert-fill-action already has. --}}
|
|
6
|
+
throw new Error("[sungen] hover is not available on the appium adapter — a touch screen has no hover state. Content a hover reveals is normally already visible on mobile; if the interaction is genuinely required, use `User tap [X]`, otherwise tag the scenario @manual:M10.");
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
{{!-- No hover on touch
|
|
2
|
-
is
|
|
3
|
-
|
|
1
|
+
{{!-- No hover on a touch screen; mirrors hover-action.hbs. Text-filtering the target changes which
|
|
2
|
+
element is picked, not whether hovering it means anything. Braces are avoided in the message
|
|
3
|
+
below on purpose: handlebars would interpolate a literal mustache away to an empty string. --}}
|
|
4
|
+
throw new Error("[sungen] hover is not available on the appium adapter — a touch screen has no hover state. To act on the item matching a value, tap it instead (`User tap [X] item with` your data ref); if the hover itself is the thing under test, tag the scenario @manual:M10.");
|
|
@@ -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.");
|
|
@@ -1,2 +1,11 @@
|
|
|
1
|
+
{{#if (eq action "hover")}}
|
|
2
|
+
{{!-- This template is reached by a MIXED pattern that serves click, double-click AND hover, so it
|
|
3
|
+
cannot be declared web-only without deleting tap from mobile. It also ignored `action` and
|
|
4
|
+
always clicked — which turned `hover [Target X] with {{ref}}` into a TAP on mobile. That is
|
|
5
|
+
worse than the silent no-op the pure hover patterns had: a tap has side effects a hover never
|
|
6
|
+
had, so the scenario changed app state while claiming to hover. Refuse instead. --}}
|
|
7
|
+
throw new Error("[sungen] hover is not available on the appium adapter — a touch screen has no hover state, and this step would otherwise have tapped the element instead. Use `User tap` if acting on it is what you meant, or tag the scenario @manual:M10.");
|
|
8
|
+
{{else}}
|
|
1
9
|
{{!-- Fallback for an unrecognized action: tap an element by text / content-desc. --}}
|
|
2
10
|
await $('//*[contains(@content-desc,"{{escapeQuotes dataValue}}") or contains(@text,"{{escapeQuotes dataValue}}")]').click();
|
|
11
|
+
{{/if}}
|
|
@@ -1 +1,34 @@
|
|
|
1
|
-
|
|
1
|
+
{{!-- Input-value assertion (mobile). The web template asserts toHaveValue(), which
|
|
2
|
+
expect-webdriverio implements as toHaveElementProperty('value') → GET
|
|
3
|
+
element/:id/property/value. That is a DOM command: UiAutomator2 does not implement
|
|
4
|
+
getElementProperty and answers 404 for every call, so the assertion used to fail
|
|
5
|
+
whatever the field held. Read the native value instead, exactly as
|
|
6
|
+
actions/capture-variable.hbs does for `capture: 'inputValue'`:
|
|
7
|
+
· iOS — @value first, then @label (this is the input's OWN value, not its label)
|
|
8
|
+
· Android — getText() (GET element/:id/text), then @content-desc
|
|
9
|
+
`probeNative` is deliberately ignored: it drives a DOM tagName probe for ambiguous
|
|
10
|
+
dropdown/select/combobox targets on web, and a native tree has no tagName to probe. --}}
|
|
11
|
+
{
|
|
12
|
+
const __el = await {{> locator}};
|
|
13
|
+
await __el.waitForDisplayed();
|
|
14
|
+
const __expected = String('{{escapeQuotes dataValue}}').trim();
|
|
15
|
+
const __sources = driver.isIOS
|
|
16
|
+
? [await __el.getAttribute('value'), await __el.getAttribute('label')]
|
|
17
|
+
: [await __el.getText(), await __el.getAttribute('content-desc')];
|
|
18
|
+
let __actual = String(__sources.find(s => s && String(s).trim() !== '') ?? '').trim();
|
|
19
|
+
{{!-- iOS only, and only when we EXPECT empty: some WebDriverAgent versions echo an empty
|
|
20
|
+
UITextField's placeholder back as its @value. The XCUITest driver documents @value as
|
|
21
|
+
"a complex attribute whose calculation algorithm depends on the actual element type"
|
|
22
|
+
and promises nothing for an empty field, so the behaviour varies by WDA version.
|
|
23
|
+
@placeholderValue is a supported XCUITest attribute; an exact match means the field is
|
|
24
|
+
empty and we simply read its placeholder. Gated on __expected === '' so a non-empty
|
|
25
|
+
assertion pays no extra round-trip and its behaviour is bit-for-bit unchanged. --}}
|
|
26
|
+
if (driver.isIOS && __expected === '' && __actual !== '') {
|
|
27
|
+
let __placeholder = null;
|
|
28
|
+
try { __placeholder = await __el.getAttribute('placeholderValue'); } catch { /* attribute unsupported on this node */ }
|
|
29
|
+
if (__placeholder && String(__placeholder).trim() === __actual) __actual = '';
|
|
30
|
+
}
|
|
31
|
+
if (__actual !== __expected) {
|
|
32
|
+
throw new Error(`[sungen] Expected value "${__expected}" but element reads "${__actual}"`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -1,12 +1,20 @@
|
|
|
1
|
-
{{!-- Label-value assertion (mobile): locate a visible
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
{{!-- Label-value assertion (mobile), NO selectors.yaml entry: locate a visible node carrying
|
|
2
|
+
the value anywhere on screen. The web variant matches "label: value" as one string —
|
|
3
|
+
native trees keep label and value as separate nodes, so only the value is matched here.
|
|
4
|
+
Declare an entry for the ref to assert a specific element instead (#666).
|
|
5
|
+
|
|
6
|
+
Android publishes text into @text (native/RN) or @content-desc (Flutter Semantics), and
|
|
7
|
+
which one is populated is a property of the toolkit, not of the widget. This used to be
|
|
8
|
+
`UiSelector().text(...)`, which cannot read @content-desc at all and so missed on every
|
|
9
|
+
Flutter screen; UiSelector has no OR, hence the xpath. iOS scatters it across
|
|
10
|
+
label/value, which the predicate already ORs.
|
|
11
|
+
|
|
12
|
+
The expected value must stay a standalone quoted literal so the runtime-data transform
|
|
13
|
+
can swap it for testData.get(...). --}}
|
|
6
14
|
{
|
|
7
15
|
const __expected = String('{{escapeQuotes dataValue}}').trim();
|
|
8
16
|
const __sel = driver.isIOS
|
|
9
17
|
? `-ios predicate string:label == "${__expected}" OR value == "${__expected}"`
|
|
10
|
-
:
|
|
18
|
+
: `//*[@text="${__expected}" or @content-desc="${__expected}"]`;
|
|
11
19
|
await expect($(__sel)).toBeDisplayed();
|
|
12
20
|
}
|
|
@@ -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}});
|
package/dist/generators/test-generator/adapters/appium/templates/steps/gestures/go-back-action.hbs
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{{!-- The OS/hardware back gesture. NOT the in-app Back button, and the difference is the whole
|
|
2
|
+
point: Android's system back does NOT run the screen's own handler unless the app wires it
|
|
3
|
+
(onBackPressed / BackHandler), so a defect on this path is invisible to a `tap [Back]`
|
|
4
|
+
scenario. That is exactly why `viewpoint-ledger.ts` treats the in-app control as a wrong
|
|
5
|
+
substitution for the "OS/hardware back gesture" theme (#626) — and why this template has to
|
|
6
|
+
exist for that theme to have any answer other than @manual.
|
|
7
|
+
|
|
8
|
+
Android: KEYCODE_BACK through the execute alias rather than `driver.pressKeyCode(4)`, for the
|
|
9
|
+
same reason `location-services-action` uses `mobile: isGpsEnabled` — WDIO v9 dropped the
|
|
10
|
+
legacy JSONWP wrappers, while a driver extension call cannot be removed from under us.
|
|
11
|
+
|
|
12
|
+
iOS: there IS no hardware back. `driver.back()` is WebDriverAgent's NAVIGATION back (it drives
|
|
13
|
+
the nav-bar back affordance), not the user's edge swipe-back gesture. Both OSes are therefore
|
|
14
|
+
implemented — the matrix reads ✅/✅ and the semantic difference is stated here and in the
|
|
15
|
+
matrix note, rather than dressed up as a refusal it is not. --}}
|
|
16
|
+
if (driver.isIOS) {
|
|
17
|
+
// WDA navigation-back — NOT the user's swipe-back gesture; iOS exposes no hardware back key.
|
|
18
|
+
await driver.back();
|
|
19
|
+
} else {
|
|
20
|
+
await driver.execute('mobile: pressKey', { keycode: 4 }); // KEYCODE_BACK — the real hardware back
|
|
21
|
+
}
|
|
@@ -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 }); }
|
|
@@ -1,2 +1,18 @@
|
|
|
1
|
+
{{#if missing}}
|
|
2
|
+
{{!-- No coordinates in the step and no data reference to read. Refuse by name: this used to default
|
|
3
|
+
to latitude 0 / longitude 0, which is Null Island — a real place, so the test passed there. --}}
|
|
4
|
+
throw new Error("[sungen] cannot set location: no coordinates and no data reference in \"{{escapeQuotes missing}}\". Write the numbers inline (`User set location to 10.7769, 106.7009`), or point at a test-data key holding \"<latitude> <longitude>\".");
|
|
5
|
+
{{else}}
|
|
6
|
+
{{#if dataRef}}
|
|
7
|
+
{{!-- Coordinates read from test-data AT RUN TIME, so one compiled spec serves every environment. --}}
|
|
8
|
+
await (async () => {
|
|
9
|
+
const __raw = String(testData.get('{{dataRef}}'));
|
|
10
|
+
const __nums = __raw.match(/-?\d+(?:\.\d+)?/g) || [];
|
|
11
|
+
if (__nums.length < 2) throw new Error(`[sungen] test-data '{{dataRef}}' = "${__raw}" — setting a location needs two numbers, "<latitude> <longitude>"; found ${__nums.length}.`);
|
|
12
|
+
await driver.setGeoLocation({ latitude: Number(__nums[0]), longitude: Number(__nums[1]), altitude: 0 });
|
|
13
|
+
})();
|
|
14
|
+
{{else}}
|
|
1
15
|
{{!-- Mock the device GPS location. --}}
|
|
2
16
|
await driver.setGeoLocation({ latitude: {{latitude}}, longitude: {{longitude}}, altitude: 0 });
|
|
17
|
+
{{/if}}
|
|
18
|
+
{{/if}}
|
|
@@ -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~}}
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
{{#if platform}}
|
|
2
2
|
// sungen:platform={{platform}}
|
|
3
3
|
{{/if}}
|
|
4
|
+
{{#if screenshotOnFailure}}
|
|
5
|
+
// @screenshot:on-failure — used to be web-only and silently dropped on mobile.
|
|
6
|
+
// wdio.conf.ts's afterTest hook already captures screenshot + page source + device log for EVERY
|
|
7
|
+
// mobile failure, so the tag is not what turns evidence on. What it declares is that this feature's
|
|
8
|
+
// evidence is ESSENTIAL: it survives SUNGEN_MOBILE_EVIDENCE=off, which otherwise suppresses capture
|
|
9
|
+
// for the run. Set at module load, so it covers every scenario in this spec.
|
|
10
|
+
(globalThis as Record<string, unknown>).__sungenForceEvidence = true;
|
|
11
|
+
{{/if}}
|
|
4
12
|
{{#if runtimeData}}
|
|
5
13
|
|
|
6
14
|
const testData = TestDataLoader.load('{{screenName}}', '{{featureFileName}}');
|
|
@@ -202,6 +210,36 @@ async function __assertCheckedState(el: WebdriverIO.Element, expected: boolean,
|
|
|
202
210
|
}
|
|
203
211
|
throw new Error(`Expect ${label} to be ${want} — read [${signals.map(s => `${s.source} → ${s.value}`).join(', ')}]`);
|
|
204
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
|
+
}
|
|
205
243
|
{{#if singleAuthRole}}
|
|
206
244
|
import * as fs from 'node:fs';
|
|
207
245
|
import * as path from 'node:path';
|
|
@@ -332,23 +370,25 @@ describe('{{featureName}}', () => {
|
|
|
332
370
|
// @auth:{{singleAuthRole}} — authenticate ONCE before any scenario; the session persists across
|
|
333
371
|
// the per-scenario relaunch below (noReset:true). Throws (blocks the spec) if login can't be done.
|
|
334
372
|
before(async () => {
|
|
335
|
-
{{#if appPackage}}
|
|
336
373
|
// Relaunch to a known launch screen first — the session may attach to the app in any state.
|
|
337
374
|
// Platform-aware id (NOT the Android literal): on iOS a @platform:mobile feature's app is the
|
|
338
375
|
// dual-id bundle id — a literal appPackage here would throw and block the whole spec.
|
|
339
|
-
// (__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.)
|
|
340
379
|
const __AUTH_APP__ = __resolveAppId();
|
|
341
380
|
try { await driver.terminateApp(__AUTH_APP__); } catch { /* not running */ }
|
|
342
381
|
await driver.activateApp(__AUTH_APP__);
|
|
343
|
-
{{/if}}
|
|
344
382
|
await __ensureAuth('{{singleAuthRole}}');
|
|
345
383
|
});
|
|
346
384
|
|
|
347
385
|
{{/if}}
|
|
348
|
-
{{#if appPackage}}
|
|
349
386
|
// Multi-app: this feature's app (from the `Path:` line). Reset to its launch screen before each
|
|
350
387
|
// scenario so one `wdio run` can host screens from different apps — each spec launches its own.
|
|
351
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().
|
|
352
392
|
const __APP_PKG_DEFAULT__ = '{{appPackage}}';
|
|
353
393
|
{{#if iosBundleId}}
|
|
354
394
|
// Per-feature iOS bundle id from the dual-id `Path: <androidPkg>/<activity> | <iosBundleId>` —
|
|
@@ -358,13 +398,26 @@ describe('{{featureName}}', () => {
|
|
|
358
398
|
{{/if}}
|
|
359
399
|
// Platform-aware app id: an @platform:mobile spec runs on BOTH OSes. On iOS prefer the feature's own
|
|
360
400
|
// bundle id (dual-id Path), then the session cap (IOS_BUNDLE_ID in wdio.conf), then the Path value;
|
|
361
|
-
// 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.
|
|
362
408
|
function __resolveAppId(): string {
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
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
|
+
);
|
|
366
419
|
}
|
|
367
|
-
return
|
|
420
|
+
return resolved;
|
|
368
421
|
}
|
|
369
422
|
// ── Reset tier ────────────────────────────────────────────────────────────────────────────────
|
|
370
423
|
// How much state each scenario starts from (`@reset:` on the Feature; default `soft`):
|
|
@@ -575,20 +628,6 @@ describe('{{featureName}}', () => {
|
|
|
575
628
|
{{/if}}
|
|
576
629
|
});
|
|
577
630
|
|
|
578
|
-
{{/if}}
|
|
579
|
-
{{#unless appPackage}}
|
|
580
|
-
{{#if backgroundSteps}}
|
|
581
|
-
before(async () => {
|
|
582
|
-
{{#each backgroundSteps}}
|
|
583
|
-
{{#if comment}}
|
|
584
|
-
// {{comment}}
|
|
585
|
-
{{/if}}
|
|
586
|
-
{{code}}
|
|
587
|
-
{{/each}}
|
|
588
|
-
});
|
|
589
|
-
|
|
590
|
-
{{/if}}
|
|
591
|
-
{{/unless}}
|
|
592
631
|
{{#if beforeAll}}
|
|
593
632
|
{{beforeAll}}
|
|
594
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"}
|
|
@@ -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
|
* PlaywrightAdapter
|
|
4
4
|
* Generates Playwright TypeScript test code using Handlebars templates
|
|
@@ -18,24 +18,9 @@ export declare class PlaywrightAdapter implements TestGeneratorAdapter {
|
|
|
18
18
|
code: string;
|
|
19
19
|
}>;
|
|
20
20
|
}): string;
|
|
21
|
-
renderBeforeAll(data:
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
code: string;
|
|
25
|
-
}>;
|
|
26
|
-
}): string;
|
|
27
|
-
renderAfterEach(data: {
|
|
28
|
-
steps: Array<{
|
|
29
|
-
comment?: string;
|
|
30
|
-
code: string;
|
|
31
|
-
}>;
|
|
32
|
-
}): string;
|
|
33
|
-
renderAfterAll(data: {
|
|
34
|
-
steps: Array<{
|
|
35
|
-
comment?: string;
|
|
36
|
-
code: string;
|
|
37
|
-
}>;
|
|
38
|
-
}): string;
|
|
21
|
+
renderBeforeAll(data: HookRenderData): string;
|
|
22
|
+
renderAfterEach(data: HookRenderData): string;
|
|
23
|
+
renderAfterAll(data: HookRenderData): string;
|
|
39
24
|
renderStep(templateName: string, data: any): string;
|
|
40
25
|
}
|
|
41
26
|
//# sourceMappingURL=playwright-adapter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"playwright-adapter.d.ts","sourceRoot":"","sources":["../../../../../src/generators/test-generator/adapters/playwright/playwright-adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"playwright-adapter.d.ts","sourceRoot":"","sources":["../../../../../src/generators/test-generator/adapters/playwright/playwright-adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,YAAY,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG9H;;;GAGG;AACH,qBAAa,iBAAkB,YAAW,oBAAoB;IAC5D,QAAQ,CAAC,aAAa,gBAAgB;IACtC,QAAQ,CAAC,aAAa,cAAc;IACpC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,OAAO,CAAC,cAAc,CAAiB;;IAQvC,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":"playwright-adapter.js","sourceRoot":"","sources":["../../../../../src/generators/test-generator/adapters/playwright/playwright-adapter.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AAExB,2DAAuD;AAEvD;;;GAGG;AACH,MAAa,iBAAiB;IAM5B;QALS,kBAAa,GAAG,YAAY,CAAC;QAC7B,kBAAa,GAAG,UAAU,CAAC;QAKlC,2CAA2C;QAC3C,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":"playwright-adapter.js","sourceRoot":"","sources":["../../../../../src/generators/test-generator/adapters/playwright/playwright-adapter.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AAExB,2DAAuD;AAEvD;;;GAGG;AACH,MAAa,iBAAiB;IAM5B;QALS,kBAAa,GAAG,YAAY,CAAC;QAC7B,kBAAa,GAAG,UAAU,CAAC;QAKlC,2CAA2C;QAC3C,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;AA3CD,8CA2CC"}
|
|
@@ -1,8 +1,26 @@
|
|
|
1
|
-
test.afterAll(async (
|
|
1
|
+
test.afterAll(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
|
+
expect(__hookFailures, 'Hook preconditions not met').toEqual([]);
|
|
17
|
+
{{/if}}
|
|
18
|
+
}
|
|
19
|
+
{{else}}
|
|
6
20
|
{{code}}
|
|
21
|
+
{{/if}}
|
|
7
22
|
{{/each}}
|
|
23
|
+
{{#if collect}}
|
|
24
|
+
expect(__hookFailures, 'Hook preconditions not met').toEqual([]);
|
|
25
|
+
{{/if}}
|
|
8
26
|
});
|
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
test.afterEach(async ({ page }) => {
|
|
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
|
+
expect(__hookFailures, 'Hook preconditions not met').toEqual([]);
|
|
17
|
+
{{/if}}
|
|
18
|
+
}
|
|
19
|
+
{{else}}
|
|
6
20
|
{{code}}
|
|
21
|
+
{{/if}}
|
|
7
22
|
{{/each}}
|
|
23
|
+
{{#if collect}}
|
|
24
|
+
expect(__hookFailures, 'Hook preconditions not met').toEqual([]);
|
|
25
|
+
{{/if}}
|
|
8
26
|
});
|
|
@@ -1,8 +1,26 @@
|
|
|
1
|
-
test.beforeAll(async (
|
|
1
|
+
test.beforeAll(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
|
+
expect(__hookFailures, 'Hook preconditions not met').toEqual([]);
|
|
17
|
+
{{/if}}
|
|
18
|
+
}
|
|
19
|
+
{{else}}
|
|
6
20
|
{{code}}
|
|
21
|
+
{{/if}}
|
|
7
22
|
{{/each}}
|
|
23
|
+
{{#if collect}}
|
|
24
|
+
expect(__hookFailures, 'Hook preconditions not met').toEqual([]);
|
|
25
|
+
{{/if}}
|
|
8
26
|
});
|
|
@@ -18,6 +18,9 @@ import { {{urlAssertImports}} } from '{{basePath}}/url-assert';
|
|
|
18
18
|
{{#if regexEscapeImport}}
|
|
19
19
|
import { escapeRegExp } from '{{basePath}}/regex-escape';
|
|
20
20
|
{{/if}}
|
|
21
|
+
{{#if checkedStateImports}}
|
|
22
|
+
import { {{checkedStateImports}} } from '{{basePath}}/checked-state';
|
|
23
|
+
{{/if}}
|
|
21
24
|
|
|
22
25
|
// This file is auto-generated from Gherkin feature files
|
|
23
26
|
// DO NOT EDIT MANUALLY - changes will be overwritten
|
package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/check-action.hbs
CHANGED
|
@@ -1 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
{{!-- Playwright's .check() accepts ONLY native checkbox/radio and role=checkbox|radio|switch —
|
|
2
|
+
a `<button aria-pressed>` toggle threw "Not a checkbox or radio button" (#675). The branch
|
|
3
|
+
cannot be decided here: a testid/CSS selector carries no role, so the element is inspected at
|
|
4
|
+
run time by setCheckedState (specs/checked-state.ts), which also keeps the step IDEMPOTENT —
|
|
5
|
+
the reason `check` exists rather than `click`. --}}
|
|
6
|
+
await setCheckedState({{> locator}}, true, '{{escapeQuotes selectorRef}}'{{> checked-opts cls=checkedClass attr=checkedAttribute}});
|