@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.
Files changed (486) hide show
  1. package/dist/capabilities/discover.d.ts +29 -0
  2. package/dist/capabilities/discover.d.ts.map +1 -1
  3. package/dist/capabilities/discover.js +144 -10
  4. package/dist/capabilities/discover.js.map +1 -1
  5. package/dist/capabilities/registry.d.ts +18 -0
  6. package/dist/capabilities/registry.d.ts.map +1 -1
  7. package/dist/capabilities/registry.js +25 -0
  8. package/dist/capabilities/registry.js.map +1 -1
  9. package/dist/cli/commands/audit.d.ts.map +1 -1
  10. package/dist/cli/commands/audit.js +9 -0
  11. package/dist/cli/commands/audit.js.map +1 -1
  12. package/dist/cli/commands/capability.js +1 -1
  13. package/dist/cli/commands/capability.js.map +1 -1
  14. package/dist/cli/commands/delivery.d.ts.map +1 -1
  15. package/dist/cli/commands/delivery.js +2 -1
  16. package/dist/cli/commands/delivery.js.map +1 -1
  17. package/dist/cli/commands/generate.d.ts.map +1 -1
  18. package/dist/cli/commands/generate.js +6 -2
  19. package/dist/cli/commands/generate.js.map +1 -1
  20. package/dist/cli/commands/inspect.js +1 -1
  21. package/dist/cli/commands/inspect.js.map +1 -1
  22. package/dist/cli/commands/results-merge.d.ts.map +1 -1
  23. package/dist/cli/commands/results-merge.js +9 -2
  24. package/dist/cli/commands/results-merge.js.map +1 -1
  25. package/dist/cli/commands/results-sanitize.d.ts +24 -0
  26. package/dist/cli/commands/results-sanitize.d.ts.map +1 -0
  27. package/dist/cli/commands/results-sanitize.js +126 -0
  28. package/dist/cli/commands/results-sanitize.js.map +1 -0
  29. package/dist/cli/commands/script-check.d.ts.map +1 -1
  30. package/dist/cli/commands/script-check.js +3 -1
  31. package/dist/cli/commands/script-check.js.map +1 -1
  32. package/dist/cli/commands/update.d.ts.map +1 -1
  33. package/dist/cli/commands/update.js +3 -0
  34. package/dist/cli/commands/update.js.map +1 -1
  35. package/dist/dashboard/templates/index.html +1 -1
  36. package/dist/exporters/api-testcase-formatter.d.ts +3 -6
  37. package/dist/exporters/api-testcase-formatter.d.ts.map +1 -1
  38. package/dist/exporters/api-testcase-formatter.js +7 -10
  39. package/dist/exporters/api-testcase-formatter.js.map +1 -1
  40. package/dist/exporters/feature-parser.d.ts +1 -1
  41. package/dist/exporters/feature-parser.js +1 -1
  42. package/dist/exporters/matrix/build.d.ts.map +1 -1
  43. package/dist/exporters/matrix/build.js +18 -3
  44. package/dist/exporters/matrix/build.js.map +1 -1
  45. package/dist/exporters/matrix/item-labels.d.ts +35 -0
  46. package/dist/exporters/matrix/item-labels.d.ts.map +1 -0
  47. package/dist/exporters/matrix/item-labels.js +90 -0
  48. package/dist/exporters/matrix/item-labels.js.map +1 -0
  49. package/dist/exporters/matrix/render-coverage-sheet.d.ts +14 -0
  50. package/dist/exporters/matrix/render-coverage-sheet.d.ts.map +1 -0
  51. package/dist/exporters/matrix/render-coverage-sheet.js +162 -0
  52. package/dist/exporters/matrix/render-coverage-sheet.js.map +1 -0
  53. package/dist/exporters/matrix/render-csv.d.ts.map +1 -1
  54. package/dist/exporters/matrix/render-csv.js +3 -1
  55. package/dist/exporters/matrix/render-csv.js.map +1 -1
  56. package/dist/exporters/matrix/render-overview-sheet.d.ts +20 -0
  57. package/dist/exporters/matrix/render-overview-sheet.d.ts.map +1 -0
  58. package/dist/exporters/matrix/render-overview-sheet.js +32 -0
  59. package/dist/exporters/matrix/render-overview-sheet.js.map +1 -0
  60. package/dist/exporters/matrix/render-testcase-sheet.d.ts +30 -0
  61. package/dist/exporters/matrix/render-testcase-sheet.d.ts.map +1 -0
  62. package/dist/exporters/matrix/render-testcase-sheet.js +156 -0
  63. package/dist/exporters/matrix/render-testcase-sheet.js.map +1 -0
  64. package/dist/exporters/matrix/render-xlsx.d.ts +41 -31
  65. package/dist/exporters/matrix/render-xlsx.d.ts.map +1 -1
  66. package/dist/exporters/matrix/render-xlsx.js +72 -425
  67. package/dist/exporters/matrix/render-xlsx.js.map +1 -1
  68. package/dist/exporters/matrix/result-totals.d.ts +23 -0
  69. package/dist/exporters/matrix/result-totals.d.ts.map +1 -0
  70. package/dist/exporters/matrix/result-totals.js +21 -0
  71. package/dist/exporters/matrix/result-totals.js.map +1 -0
  72. package/dist/exporters/matrix/testcase-summary-band.d.ts +30 -0
  73. package/dist/exporters/matrix/testcase-summary-band.d.ts.map +1 -0
  74. package/dist/exporters/matrix/testcase-summary-band.js +71 -0
  75. package/dist/exporters/matrix/testcase-summary-band.js.map +1 -0
  76. package/dist/exporters/matrix/wording.d.ts.map +1 -1
  77. package/dist/exporters/matrix/wording.js +13 -0
  78. package/dist/exporters/matrix/wording.js.map +1 -1
  79. package/dist/exporters/matrix/xlsx-cells.d.ts +38 -0
  80. package/dist/exporters/matrix/xlsx-cells.d.ts.map +1 -0
  81. package/dist/exporters/matrix/xlsx-cells.js +52 -0
  82. package/dist/exporters/matrix/xlsx-cells.js.map +1 -0
  83. package/dist/exporters/qa-env-secret-denylist.js +2 -2
  84. package/dist/exporters/qa-env-secret-denylist.js.map +1 -1
  85. package/dist/exporters/report-path-sanitizer.d.ts +38 -0
  86. package/dist/exporters/report-path-sanitizer.d.ts.map +1 -0
  87. package/dist/exporters/report-path-sanitizer.js +137 -0
  88. package/dist/exporters/report-path-sanitizer.js.map +1 -0
  89. package/dist/exporters/result-variants.d.ts.map +1 -1
  90. package/dist/exporters/result-variants.js +2 -1
  91. package/dist/exporters/result-variants.js.map +1 -1
  92. package/dist/exporters/sensitive-key.d.ts +31 -0
  93. package/dist/exporters/sensitive-key.d.ts.map +1 -0
  94. package/dist/exporters/sensitive-key.js +50 -0
  95. package/dist/exporters/sensitive-key.js.map +1 -0
  96. package/dist/exporters/test-data-resolver.d.ts +4 -1
  97. package/dist/exporters/test-data-resolver.d.ts.map +1 -1
  98. package/dist/exporters/test-data-resolver.js +12 -2
  99. package/dist/exporters/test-data-resolver.js.map +1 -1
  100. package/dist/exporters/xlsx-report-builder.d.ts +12 -1
  101. package/dist/exporters/xlsx-report-builder.d.ts.map +1 -1
  102. package/dist/exporters/xlsx-report-builder.js +10 -2
  103. package/dist/exporters/xlsx-report-builder.js.map +1 -1
  104. package/dist/generators/gherkin-parser/index.d.ts +10 -0
  105. package/dist/generators/gherkin-parser/index.d.ts.map +1 -1
  106. package/dist/generators/gherkin-parser/index.js +20 -12
  107. package/dist/generators/gherkin-parser/index.js.map +1 -1
  108. package/dist/generators/gherkin-parser/parent-scope-clause.d.ts +54 -0
  109. package/dist/generators/gherkin-parser/parent-scope-clause.d.ts.map +1 -0
  110. package/dist/generators/gherkin-parser/parent-scope-clause.js +109 -0
  111. package/dist/generators/gherkin-parser/parent-scope-clause.js.map +1 -0
  112. package/dist/generators/test-generator/adapters/adapter-interface.d.ts +23 -18
  113. package/dist/generators/test-generator/adapters/adapter-interface.d.ts.map +1 -1
  114. package/dist/generators/test-generator/adapters/appium/appium-adapter.d.ts +4 -19
  115. package/dist/generators/test-generator/adapters/appium/appium-adapter.d.ts.map +1 -1
  116. package/dist/generators/test-generator/adapters/appium/appium-adapter.js.map +1 -1
  117. package/dist/generators/test-generator/adapters/appium/os-support.d.ts +53 -0
  118. package/dist/generators/test-generator/adapters/appium/os-support.d.ts.map +1 -0
  119. package/dist/generators/test-generator/adapters/appium/os-support.js +200 -0
  120. package/dist/generators/test-generator/adapters/appium/os-support.js.map +1 -0
  121. package/dist/generators/test-generator/adapters/appium/templates/after-all.hbs +18 -0
  122. package/dist/generators/test-generator/adapters/appium/templates/after-each.hbs +18 -0
  123. package/dist/generators/test-generator/adapters/appium/templates/before-all.hbs +18 -0
  124. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/alert-fill-action.hbs +9 -2
  125. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/capture-variable.hbs +24 -1
  126. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/click-at-position-action.hbs +1 -0
  127. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/click-element-with-text.hbs +1 -1
  128. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/double-click-action.hbs +7 -0
  129. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/frame-enter-action.hbs +3 -6
  130. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/hover-action.hbs +6 -2
  131. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/hover-element-with-text.hbs +4 -3
  132. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/table-paginate-action.hbs +3 -0
  133. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/unknown-element-action.hbs +9 -0
  134. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/have-value-assertion.hbs +34 -1
  135. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/label-value-assertion.hbs +14 -6
  136. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/visible-assertion.hbs +1 -1
  137. package/dist/generators/test-generator/adapters/appium/templates/steps/gestures/go-back-action.hbs +21 -0
  138. package/dist/generators/test-generator/adapters/appium/templates/steps/gestures/long-press-action.hbs +4 -0
  139. package/dist/generators/test-generator/adapters/appium/templates/steps/gestures/pinch-zoom-action.hbs +4 -0
  140. package/dist/generators/test-generator/adapters/appium/templates/steps/gestures/set-geolocation-action.hbs +16 -0
  141. package/dist/generators/test-generator/adapters/appium/templates/steps/partials/locator.hbs +9 -1
  142. package/dist/generators/test-generator/adapters/appium/templates/test-file.hbs +62 -23
  143. package/dist/generators/test-generator/adapters/index.d.ts +1 -1
  144. package/dist/generators/test-generator/adapters/index.d.ts.map +1 -1
  145. package/dist/generators/test-generator/adapters/playwright/playwright-adapter.d.ts +4 -19
  146. package/dist/generators/test-generator/adapters/playwright/playwright-adapter.d.ts.map +1 -1
  147. package/dist/generators/test-generator/adapters/playwright/playwright-adapter.js.map +1 -1
  148. package/dist/generators/test-generator/adapters/playwright/templates/after-all.hbs +19 -1
  149. package/dist/generators/test-generator/adapters/playwright/templates/after-each.hbs +18 -0
  150. package/dist/generators/test-generator/adapters/playwright/templates/before-all.hbs +19 -1
  151. package/dist/generators/test-generator/adapters/playwright/templates/imports.hbs +3 -0
  152. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/check-action.hbs +6 -1
  153. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/click-at-position-action.hbs +23 -0
  154. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/expand-action.hbs +8 -8
  155. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/fill-editor-action.hbs +7 -2
  156. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row-nth.hbs +7 -2
  157. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row.hbs +7 -2
  158. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/table-paginate-action.hbs +5 -0
  159. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/uncheck-action.hbs +3 -1
  160. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/unknown-element-action.hbs +1 -1
  161. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/wait-for-page.hbs +18 -1
  162. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/all-contain-assertion.hbs +32 -4
  163. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/all-contain-element.hbs +5 -2
  164. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/checked-assertion.hbs +5 -1
  165. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/column-cell-assertion.hbs +13 -2
  166. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/contain-text-assertion.hbs +1 -1
  167. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-role-variable-assertion.hbs +2 -2
  168. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-variable-assertion.hbs +1 -1
  169. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/have-text-assertion.hbs +1 -1
  170. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-role-variable-assertion.hbs +2 -2
  171. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-variable-assertion.hbs +1 -1
  172. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/not-checked-assertion.hbs +2 -1
  173. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/selected-assertion.hbs +21 -3
  174. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/state-with-filter-assertion.hbs +20 -2
  175. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-empty.hbs +4 -1
  176. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-match-data.hbs +4 -1
  177. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-count.hbs +4 -1
  178. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-exists.hbs +12 -4
  179. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-not-exists.hbs +14 -2
  180. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-role-variable-assertion.hbs +3 -3
  181. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-value-assertion.hbs +1 -1
  182. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-variable-assertion.hbs +1 -1
  183. package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/checked-opts.hbs +8 -0
  184. package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator-base.hbs +8 -8
  185. package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator-nth.hbs +1 -1
  186. package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator-strategies/id.hbs +1 -1
  187. package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator-strategies/testid.hbs +1 -1
  188. package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator.hbs +8 -8
  189. package/dist/generators/test-generator/adapters/playwright/templates/test-file.hbs +10 -8
  190. package/dist/generators/test-generator/code-generator.d.ts +37 -0
  191. package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
  192. package/dist/generators/test-generator/code-generator.js +165 -40
  193. package/dist/generators/test-generator/code-generator.js.map +1 -1
  194. package/dist/generators/test-generator/diagnostics.d.ts +116 -6
  195. package/dist/generators/test-generator/diagnostics.d.ts.map +1 -1
  196. package/dist/generators/test-generator/diagnostics.js +115 -5
  197. package/dist/generators/test-generator/diagnostics.js.map +1 -1
  198. package/dist/generators/test-generator/patterns/index.d.ts +57 -11
  199. package/dist/generators/test-generator/patterns/index.d.ts.map +1 -1
  200. package/dist/generators/test-generator/patterns/index.js +163 -21
  201. package/dist/generators/test-generator/patterns/index.js.map +1 -1
  202. package/dist/generators/test-generator/patterns/types.d.ts +8 -0
  203. package/dist/generators/test-generator/patterns/types.d.ts.map +1 -1
  204. package/dist/generators/test-generator/patterns/with-parent-scope.d.ts +18 -0
  205. package/dist/generators/test-generator/patterns/with-parent-scope.d.ts.map +1 -0
  206. package/dist/generators/test-generator/patterns/with-parent-scope.js +40 -0
  207. package/dist/generators/test-generator/patterns/with-parent-scope.js.map +1 -0
  208. package/dist/generators/test-generator/step-mapper.d.ts +103 -10
  209. package/dist/generators/test-generator/step-mapper.d.ts.map +1 -1
  210. package/dist/generators/test-generator/step-mapper.js +266 -45
  211. package/dist/generators/test-generator/step-mapper.js.map +1 -1
  212. package/dist/generators/test-generator/template-engine.d.ts +4 -19
  213. package/dist/generators/test-generator/template-engine.d.ts.map +1 -1
  214. package/dist/generators/test-generator/template-engine.js +17 -12
  215. package/dist/generators/test-generator/template-engine.js.map +1 -1
  216. package/dist/generators/test-generator/utils/data-resolver.d.ts +7 -0
  217. package/dist/generators/test-generator/utils/data-resolver.d.ts.map +1 -1
  218. package/dist/generators/test-generator/utils/data-resolver.js +19 -2
  219. package/dist/generators/test-generator/utils/data-resolver.js.map +1 -1
  220. package/dist/generators/test-generator/utils/dialog-scope-identity.d.ts +41 -0
  221. package/dist/generators/test-generator/utils/dialog-scope-identity.d.ts.map +1 -0
  222. package/dist/generators/test-generator/utils/dialog-scope-identity.js +61 -0
  223. package/dist/generators/test-generator/utils/dialog-scope-identity.js.map +1 -0
  224. package/dist/generators/test-generator/utils/escape-js-string.d.ts +17 -0
  225. package/dist/generators/test-generator/utils/escape-js-string.d.ts.map +1 -0
  226. package/dist/generators/test-generator/utils/escape-js-string.js +29 -0
  227. package/dist/generators/test-generator/utils/escape-js-string.js.map +1 -0
  228. package/dist/generators/test-generator/utils/nearest-match.d.ts +24 -0
  229. package/dist/generators/test-generator/utils/nearest-match.d.ts.map +1 -0
  230. package/dist/generators/test-generator/utils/nearest-match.js +56 -0
  231. package/dist/generators/test-generator/utils/nearest-match.js.map +1 -0
  232. package/dist/generators/test-generator/utils/selector-entry-fields.d.ts +58 -0
  233. package/dist/generators/test-generator/utils/selector-entry-fields.d.ts.map +1 -0
  234. package/dist/generators/test-generator/utils/selector-entry-fields.js +119 -0
  235. package/dist/generators/test-generator/utils/selector-entry-fields.js.map +1 -0
  236. package/dist/generators/test-generator/utils/selector-entry-walk.d.ts +25 -0
  237. package/dist/generators/test-generator/utils/selector-entry-walk.d.ts.map +1 -0
  238. package/dist/generators/test-generator/utils/selector-entry-walk.js +54 -0
  239. package/dist/generators/test-generator/utils/selector-entry-walk.js.map +1 -0
  240. package/dist/generators/test-generator/utils/selector-nth-validation.d.ts +59 -0
  241. package/dist/generators/test-generator/utils/selector-nth-validation.d.ts.map +1 -0
  242. package/dist/generators/test-generator/utils/selector-nth-validation.js +91 -0
  243. package/dist/generators/test-generator/utils/selector-nth-validation.js.map +1 -0
  244. package/dist/generators/test-generator/utils/selector-resolver.d.ts +53 -2
  245. package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
  246. package/dist/generators/test-generator/utils/selector-resolver.js +273 -27
  247. package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -1
  248. package/dist/generators/test-generator/utils/selector-type-validation.d.ts +51 -0
  249. package/dist/generators/test-generator/utils/selector-type-validation.d.ts.map +1 -0
  250. package/dist/generators/test-generator/utils/selector-type-validation.js +77 -0
  251. package/dist/generators/test-generator/utils/selector-type-validation.js.map +1 -0
  252. package/dist/harness/audit.d.ts +3 -1
  253. package/dist/harness/audit.d.ts.map +1 -1
  254. package/dist/harness/audit.js +51 -28
  255. package/dist/harness/audit.js.map +1 -1
  256. package/dist/harness/capability-plan.d.ts +4 -0
  257. package/dist/harness/capability-plan.d.ts.map +1 -1
  258. package/dist/harness/capability-plan.js +32 -2
  259. package/dist/harness/capability-plan.js.map +1 -1
  260. package/dist/harness/catalog/drivers.yaml +1 -1
  261. package/dist/harness/catalog/universal-viewpoints.yaml +145 -0
  262. package/dist/harness/data-driven-lint.d.ts.map +1 -1
  263. package/dist/harness/data-driven-lint.js +217 -33
  264. package/dist/harness/data-driven-lint.js.map +1 -1
  265. package/dist/harness/parse.d.ts +6 -0
  266. package/dist/harness/parse.d.ts.map +1 -1
  267. package/dist/harness/parse.js +1 -1
  268. package/dist/harness/parse.js.map +1 -1
  269. package/dist/harness/repair.d.ts.map +1 -1
  270. package/dist/harness/repair.js +8 -1
  271. package/dist/harness/repair.js.map +1 -1
  272. package/dist/harness/script-check.d.ts +2 -2
  273. package/dist/harness/script-check.d.ts.map +1 -1
  274. package/dist/harness/script-check.js +186 -25
  275. package/dist/harness/script-check.js.map +1 -1
  276. package/dist/harness/sensors.d.ts +48 -0
  277. package/dist/harness/sensors.d.ts.map +1 -1
  278. package/dist/harness/sensors.js +26 -1
  279. package/dist/harness/sensors.js.map +1 -1
  280. package/dist/harness/viewpoint-ledger.d.ts +10 -0
  281. package/dist/harness/viewpoint-ledger.d.ts.map +1 -1
  282. package/dist/harness/viewpoint-ledger.js +23 -2
  283. package/dist/harness/viewpoint-ledger.js.map +1 -1
  284. package/dist/index.d.ts +2 -0
  285. package/dist/index.d.ts.map +1 -1
  286. package/dist/index.js +10 -1
  287. package/dist/index.js.map +1 -1
  288. package/dist/orchestrator/project-initializer.d.ts +6 -0
  289. package/dist/orchestrator/project-initializer.d.ts.map +1 -1
  290. package/dist/orchestrator/project-initializer.js +16 -0
  291. package/dist/orchestrator/project-initializer.js.map +1 -1
  292. package/dist/orchestrator/report-sanitize-reporter-install.d.ts +24 -0
  293. package/dist/orchestrator/report-sanitize-reporter-install.d.ts.map +1 -0
  294. package/dist/orchestrator/report-sanitize-reporter-install.js +161 -0
  295. package/dist/orchestrator/report-sanitize-reporter-install.js.map +1 -0
  296. package/dist/orchestrator/templates/ai-src/commands/delivery.md +4 -3
  297. package/dist/orchestrator/templates/ai-src/commands/run-test.md +9 -1
  298. package/dist/orchestrator/templates/ai-src/skills/sungen-api-coverage-model/SKILL.md +10 -0
  299. package/dist/orchestrator/templates/ai-src/skills/sungen-delivery/SKILL.md +14 -5
  300. package/dist/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +62 -3
  301. package/dist/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +126 -11
  302. package/dist/orchestrator/templates/ai-src/skills/sungen-mobile-gestures/SKILL.md +16 -1
  303. package/dist/orchestrator/templates/ai-src/skills/sungen-selector-fix/SKILL.md +12 -0
  304. package/dist/orchestrator/templates/ai-src/skills/sungen-selector-keys/SKILL.md +19 -5
  305. package/dist/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +88 -2
  306. package/dist/orchestrator/templates/ai-src/skills/sungen-tc-review/SKILL.md +62 -5
  307. package/dist/orchestrator/templates/ai-src/skills/sungen-test-design-techniques/SKILL.md +13 -0
  308. package/dist/orchestrator/templates/ai-src/skills/sungen-viewpoint/SKILL.md +59 -10
  309. package/dist/orchestrator/templates/ai-src/skills/sungen-viewpoint/group-f-mobile-native.md +419 -0
  310. package/dist/orchestrator/templates/playwright.config.ts +7 -0
  311. package/dist/orchestrator/templates/readme.md +1 -1
  312. package/dist/orchestrator/templates/specs-checked-state.d.ts +83 -0
  313. package/dist/orchestrator/templates/specs-checked-state.d.ts.map +1 -0
  314. package/dist/orchestrator/templates/specs-checked-state.js +261 -0
  315. package/dist/orchestrator/templates/specs-checked-state.js.map +1 -0
  316. package/dist/orchestrator/templates/specs-checked-state.ts +324 -0
  317. package/dist/orchestrator/templates/specs-pw-shape-reporter.ts +0 -0
  318. package/dist/orchestrator/templates/specs-report-path-sanitize-reporter.d.ts +36 -0
  319. package/dist/orchestrator/templates/specs-report-path-sanitize-reporter.d.ts.map +1 -0
  320. package/dist/orchestrator/templates/specs-report-path-sanitize-reporter.js +155 -0
  321. package/dist/orchestrator/templates/specs-report-path-sanitize-reporter.js.map +1 -0
  322. package/dist/orchestrator/templates/specs-report-path-sanitize-reporter.ts +142 -0
  323. package/dist/orchestrator/templates/specs-url-assert.d.ts +50 -25
  324. package/dist/orchestrator/templates/specs-url-assert.d.ts.map +1 -1
  325. package/dist/orchestrator/templates/specs-url-assert.js +65 -24
  326. package/dist/orchestrator/templates/specs-url-assert.js.map +1 -1
  327. package/dist/orchestrator/templates/specs-url-assert.ts +101 -28
  328. package/dist/orchestrator/templates/wdio.conf.ts +105 -1
  329. package/dist/utils/selector-types.d.ts +43 -1
  330. package/dist/utils/selector-types.d.ts.map +1 -1
  331. package/dist/utils/selector-types.js +51 -7
  332. package/dist/utils/selector-types.js.map +1 -1
  333. package/package.json +3 -3
  334. package/src/capabilities/discover.ts +146 -10
  335. package/src/capabilities/registry.ts +30 -0
  336. package/src/cli/commands/audit.ts +9 -0
  337. package/src/cli/commands/capability.ts +1 -1
  338. package/src/cli/commands/delivery.ts +2 -1
  339. package/src/cli/commands/generate.ts +5 -2
  340. package/src/cli/commands/inspect.ts +1 -1
  341. package/src/cli/commands/results-merge.ts +9 -2
  342. package/src/cli/commands/results-sanitize.ts +98 -0
  343. package/src/cli/commands/script-check.ts +3 -1
  344. package/src/cli/commands/update.ts +3 -0
  345. package/src/dashboard/templates/index.html +1 -1
  346. package/src/exporters/api-testcase-formatter.ts +5 -7
  347. package/src/exporters/feature-parser.ts +1 -1
  348. package/src/exporters/matrix/build.ts +17 -3
  349. package/src/exporters/matrix/item-labels.ts +78 -0
  350. package/src/exporters/matrix/render-coverage-sheet.ts +170 -0
  351. package/src/exporters/matrix/render-csv.ts +3 -1
  352. package/src/exporters/matrix/render-overview-sheet.ts +51 -0
  353. package/src/exporters/matrix/render-testcase-sheet.ts +178 -0
  354. package/src/exporters/matrix/render-xlsx.ts +67 -448
  355. package/src/exporters/matrix/result-totals.ts +37 -0
  356. package/src/exporters/matrix/testcase-summary-band.ts +74 -0
  357. package/src/exporters/matrix/wording.ts +13 -0
  358. package/src/exporters/matrix/xlsx-cells.ts +56 -0
  359. package/src/exporters/qa-env-secret-denylist.ts +1 -1
  360. package/src/exporters/report-path-sanitizer.ts +144 -0
  361. package/src/exporters/result-variants.ts +2 -1
  362. package/src/exporters/sensitive-key.ts +48 -0
  363. package/src/exporters/test-data-resolver.ts +12 -2
  364. package/src/exporters/xlsx-report-builder.ts +16 -2
  365. package/src/generators/gherkin-parser/index.ts +22 -11
  366. package/src/generators/gherkin-parser/parent-scope-clause.ts +130 -0
  367. package/src/generators/test-generator/adapters/adapter-interface.ts +25 -3
  368. package/src/generators/test-generator/adapters/appium/appium-adapter.ts +4 -4
  369. package/src/generators/test-generator/adapters/appium/os-support.ts +176 -0
  370. package/src/generators/test-generator/adapters/appium/templates/after-all.hbs +18 -0
  371. package/src/generators/test-generator/adapters/appium/templates/after-each.hbs +18 -0
  372. package/src/generators/test-generator/adapters/appium/templates/before-all.hbs +18 -0
  373. package/src/generators/test-generator/adapters/appium/templates/steps/actions/alert-fill-action.hbs +9 -2
  374. package/src/generators/test-generator/adapters/appium/templates/steps/actions/capture-variable.hbs +24 -1
  375. package/src/generators/test-generator/adapters/appium/templates/steps/actions/click-at-position-action.hbs +1 -0
  376. package/src/generators/test-generator/adapters/appium/templates/steps/actions/click-element-with-text.hbs +1 -1
  377. package/src/generators/test-generator/adapters/appium/templates/steps/actions/double-click-action.hbs +7 -0
  378. package/src/generators/test-generator/adapters/appium/templates/steps/actions/frame-enter-action.hbs +3 -6
  379. package/src/generators/test-generator/adapters/appium/templates/steps/actions/hover-action.hbs +6 -2
  380. package/src/generators/test-generator/adapters/appium/templates/steps/actions/hover-element-with-text.hbs +4 -3
  381. package/src/generators/test-generator/adapters/appium/templates/steps/actions/table-paginate-action.hbs +3 -0
  382. package/src/generators/test-generator/adapters/appium/templates/steps/actions/unknown-element-action.hbs +9 -0
  383. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/have-value-assertion.hbs +34 -1
  384. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/label-value-assertion.hbs +14 -6
  385. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/visible-assertion.hbs +1 -1
  386. package/src/generators/test-generator/adapters/appium/templates/steps/gestures/go-back-action.hbs +21 -0
  387. package/src/generators/test-generator/adapters/appium/templates/steps/gestures/long-press-action.hbs +4 -0
  388. package/src/generators/test-generator/adapters/appium/templates/steps/gestures/pinch-zoom-action.hbs +4 -0
  389. package/src/generators/test-generator/adapters/appium/templates/steps/gestures/set-geolocation-action.hbs +16 -0
  390. package/src/generators/test-generator/adapters/appium/templates/steps/partials/locator.hbs +9 -1
  391. package/src/generators/test-generator/adapters/appium/templates/test-file.hbs +62 -23
  392. package/src/generators/test-generator/adapters/index.ts +1 -1
  393. package/src/generators/test-generator/adapters/playwright/playwright-adapter.ts +4 -4
  394. package/src/generators/test-generator/adapters/playwright/templates/after-all.hbs +19 -1
  395. package/src/generators/test-generator/adapters/playwright/templates/after-each.hbs +18 -0
  396. package/src/generators/test-generator/adapters/playwright/templates/before-all.hbs +19 -1
  397. package/src/generators/test-generator/adapters/playwright/templates/imports.hbs +3 -0
  398. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/check-action.hbs +6 -1
  399. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/click-at-position-action.hbs +23 -0
  400. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/expand-action.hbs +8 -8
  401. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/fill-editor-action.hbs +7 -2
  402. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row-nth.hbs +7 -2
  403. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row.hbs +7 -2
  404. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/table-paginate-action.hbs +5 -0
  405. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/uncheck-action.hbs +3 -1
  406. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/unknown-element-action.hbs +1 -1
  407. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/wait-for-page.hbs +18 -1
  408. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/all-contain-assertion.hbs +32 -4
  409. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/all-contain-element.hbs +5 -2
  410. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/checked-assertion.hbs +5 -1
  411. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/column-cell-assertion.hbs +13 -2
  412. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/contain-text-assertion.hbs +1 -1
  413. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-role-variable-assertion.hbs +2 -2
  414. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-variable-assertion.hbs +1 -1
  415. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/have-text-assertion.hbs +1 -1
  416. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-role-variable-assertion.hbs +2 -2
  417. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-variable-assertion.hbs +1 -1
  418. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/not-checked-assertion.hbs +2 -1
  419. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/selected-assertion.hbs +21 -3
  420. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/state-with-filter-assertion.hbs +20 -2
  421. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-empty.hbs +4 -1
  422. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-match-data.hbs +4 -1
  423. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-count.hbs +4 -1
  424. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-exists.hbs +12 -4
  425. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-not-exists.hbs +14 -2
  426. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-role-variable-assertion.hbs +3 -3
  427. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-value-assertion.hbs +1 -1
  428. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-variable-assertion.hbs +1 -1
  429. package/src/generators/test-generator/adapters/playwright/templates/steps/partials/checked-opts.hbs +8 -0
  430. package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator-base.hbs +8 -8
  431. package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator-nth.hbs +1 -1
  432. package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator-strategies/id.hbs +1 -1
  433. package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator-strategies/testid.hbs +1 -1
  434. package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator.hbs +8 -8
  435. package/src/generators/test-generator/adapters/playwright/templates/test-file.hbs +10 -8
  436. package/src/generators/test-generator/code-generator.ts +181 -46
  437. package/src/generators/test-generator/diagnostics.ts +117 -6
  438. package/src/generators/test-generator/patterns/index.ts +175 -24
  439. package/src/generators/test-generator/patterns/types.ts +8 -0
  440. package/src/generators/test-generator/patterns/with-parent-scope.ts +41 -0
  441. package/src/generators/test-generator/step-mapper.ts +277 -43
  442. package/src/generators/test-generator/template-engine.ts +21 -21
  443. package/src/generators/test-generator/utils/data-resolver.ts +23 -2
  444. package/src/generators/test-generator/utils/dialog-scope-identity.ts +71 -0
  445. package/src/generators/test-generator/utils/escape-js-string.ts +24 -0
  446. package/src/generators/test-generator/utils/nearest-match.ts +55 -0
  447. package/src/generators/test-generator/utils/selector-entry-fields.ts +131 -0
  448. package/src/generators/test-generator/utils/selector-entry-walk.ts +58 -0
  449. package/src/generators/test-generator/utils/selector-nth-validation.ts +99 -0
  450. package/src/generators/test-generator/utils/selector-resolver.ts +333 -28
  451. package/src/generators/test-generator/utils/selector-type-validation.ts +87 -0
  452. package/src/harness/audit.ts +55 -30
  453. package/src/harness/capability-plan.ts +33 -1
  454. package/src/harness/catalog/drivers.yaml +1 -1
  455. package/src/harness/catalog/universal-viewpoints.yaml +145 -0
  456. package/src/harness/data-driven-lint.ts +192 -32
  457. package/src/harness/parse.ts +7 -1
  458. package/src/harness/repair.ts +8 -1
  459. package/src/harness/script-check.ts +186 -21
  460. package/src/harness/sensors.ts +75 -1
  461. package/src/harness/viewpoint-ledger.ts +26 -5
  462. package/src/index.ts +7 -0
  463. package/src/orchestrator/project-initializer.ts +17 -0
  464. package/src/orchestrator/report-sanitize-reporter-install.ts +109 -0
  465. package/src/orchestrator/templates/ai-src/commands/delivery.md +4 -3
  466. package/src/orchestrator/templates/ai-src/commands/run-test.md +9 -1
  467. package/src/orchestrator/templates/ai-src/skills/sungen-api-coverage-model/SKILL.md +10 -0
  468. package/src/orchestrator/templates/ai-src/skills/sungen-delivery/SKILL.md +14 -5
  469. package/src/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +62 -3
  470. package/src/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +126 -11
  471. package/src/orchestrator/templates/ai-src/skills/sungen-mobile-gestures/SKILL.md +16 -1
  472. package/src/orchestrator/templates/ai-src/skills/sungen-selector-fix/SKILL.md +12 -0
  473. package/src/orchestrator/templates/ai-src/skills/sungen-selector-keys/SKILL.md +19 -5
  474. package/src/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +88 -2
  475. package/src/orchestrator/templates/ai-src/skills/sungen-tc-review/SKILL.md +62 -5
  476. package/src/orchestrator/templates/ai-src/skills/sungen-test-design-techniques/SKILL.md +13 -0
  477. package/src/orchestrator/templates/ai-src/skills/sungen-viewpoint/SKILL.md +59 -10
  478. package/src/orchestrator/templates/ai-src/skills/sungen-viewpoint/group-f-mobile-native.md +419 -0
  479. package/src/orchestrator/templates/playwright.config.ts +7 -0
  480. package/src/orchestrator/templates/readme.md +1 -1
  481. package/src/orchestrator/templates/specs-checked-state.ts +324 -0
  482. package/src/orchestrator/templates/specs-pw-shape-reporter.ts +0 -0
  483. package/src/orchestrator/templates/specs-report-path-sanitize-reporter.ts +142 -0
  484. package/src/orchestrator/templates/specs-url-assert.ts +101 -28
  485. package/src/orchestrator/templates/wdio.conf.ts +105 -1
  486. package/src/utils/selector-types.ts +54 -5
@@ -0,0 +1,419 @@
1
+ # GROUP F: MOBILE NATIVE
2
+
3
+ > The user holds a device. The app is already launched, there is no URL, the OS interrupts, and a
4
+ > finger is the only pointer. These are the concerns the 17 web patterns have no concept of.
5
+
6
+ Patterns: 18. Bottom Sheet · 19. Tab Bar / Bottom Navigation · 20. Swipe-to-Delete Row · 21. Native Picker · 22. Permission Dialog · 23. Biometric Prompt · 24. Camera / Gallery Picker · 25. Push Notification · 26. Deep-link Entry · 27. Offline Banner · 28. Onboarding Carousel · 29. Pull-to-Refresh List · 30. Soft-Keyboard Overlap · 31. Settings Toggle List · 32. App Lifecycle & Orientation
7
+
8
+ See `SKILL.md` for the 4 Viewpoints, the platform-split Shared Checks, and the Security Tag Rules.
9
+ **Step syntax is NOT repeated here** — the step forms live in `sungen-gherkin-syntax` (Platform
10
+ Support + divergence table) and `sungen-mobile-gestures` (the gesture and device vocabulary). This
11
+ file answers only *what to check*. Every step quoted below compiles on the Appium adapter; check
12
+ `docs/spec/step-support-matrix.md` before inventing one.
13
+
14
+ ---
15
+
16
+ ## Read this first: mobile is web patterns PLUS Group F, never instead of
17
+
18
+ A mobile screen is still whatever it functionally is. A native login screen is **15. Login** and a
19
+ native product list is **10. List / Card View** — those patterns carry the business rules, and the
20
+ harness deliberately routes such a screen to `auth` / `ecommerce-list`, not to a `mobile-*`
21
+ page-type. Group F adds the **platform** concerns on top and never restates the functional ones.
22
+
23
+ Precedence, in order:
24
+
25
+ 1. **The functional pattern wins.** Route the screen by what it does (1–17), exactly as on web.
26
+ 2. **Then add the Group F patterns for the native surfaces present.** A native form screen is
27
+ **1. Form & Inputs** *and* **30. Soft-Keyboard Overlap** — the field rules are generated once, in
28
+ pattern 1; pattern 30 adds only the keyboard concern.
29
+ 3. **Generate each check once.** If a Group F row would repeat a check the functional pattern
30
+ already produced, drop the row — a duplicate scenario costs review time and scores nothing.
31
+ 4. **`is on [X] screen` is the app-launch anchor, not navigation.** It compiles to an empty comment
32
+ *by design* (the wdio capabilities launched the app). Change screens with a real tap or gesture;
33
+ an active `open [X] page` / `navigate to` on mobile reports **SG-W026** because it promises a
34
+ navigation it does not perform.
35
+ 5. **Reset between scenarios is a tag, not a step** — `@reset:none|soft|data|full` on the Feature.
36
+ A step that tries to establish app state (`Given the user is logged out`) reports **SG-W023**.
37
+
38
+ ---
39
+
40
+ ## Theme coverage map — the contract with the harness
41
+
42
+ `sungen audit` scores a mobile screen against `universal-viewpoints.yaml`. This table is the
43
+ authoritative link between what that catalog scores and what generates it; a
44
+ `tests/ai-skills/mobile-viewpoint-catalog-parity.run.ts` gate fails if the two ever drift apart.
45
+
46
+ Read it in the direction you need: **generating** → find the themes of your page-type and go to the
47
+ pattern named; **reviewing** → any theme with no scenario is a scored gap.
48
+
49
+ | Theme | Page-type | Oracle | Generated by |
50
+ |---|---|---|---|
51
+ | `theme:content-visibility` | `mobile-home` | sighting | **19** Tab Bar / Bottom Navigation |
52
+ | `theme:navigation-correctness` | `mobile-home` | sighting | **19** Tab Bar / Bottom Navigation |
53
+ | `theme:list-data` | `mobile-list` | **data** | **29** Pull-to-Refresh List |
54
+ | `theme:refresh-correctness` | `mobile-list` | **data** | **29** Pull-to-Refresh List |
55
+ | `theme:scroll-reachability` | `mobile-list` | **data** | **29** Pull-to-Refresh List · **20** Swipe-to-Delete Row |
56
+ | `theme:detail-data` | `mobile-detail` | **data** | `group-c` **10. List / Card View** — a native detail screen's data oracle is generic; Group F adds no native concern |
57
+ | `theme:list-detail-consistency` | `mobile-detail` | **data, cross-screen** | a **flow**: `User remember [List Item] text as {{v}} … User see [Detail Title] text contains {{v}}`. On a single screen this is honestly `@manual` deferred-to-flow, never a shallow sighting |
58
+ | `theme:field-validation` | `mobile-form` | **data** | `group-a` **1. Form & Inputs** · **21** Native Picker for picker-backed fields |
59
+ | `theme:keyboard-overlap` | `mobile-form` | sighting | **30** Soft-Keyboard Overlap |
60
+ | `theme:submit-correctness` | `mobile-form` | **data** | `group-a`/`group-b` **1** / **4** / **5** |
61
+ | `theme:credential-validation` | `mobile-auth` | **data** | `group-e` **15. Login / Logout** · **23** Biometric Prompt |
62
+ | `theme:session-persistence` | `mobile-auth` | **data** | **32** App Lifecycle & Orientation |
63
+ | `theme:toggle-state-correctness` | `mobile-settings` | **data** | **31** Settings Toggle List |
64
+ | `theme:setting-persistence` | `mobile-settings` | **data** | **31** Settings Toggle List |
65
+ | `theme:orientation-stability` | *universal* | reminder | **32** App Lifecycle & Orientation |
66
+ | `theme:connectivity-degraded` | *universal* | reminder | **27** Offline Banner |
67
+ | `theme:app-lifecycle-resume` | *universal* | reminder | **32** App Lifecycle & Orientation |
68
+ | `theme:permission-prompt` | *universal* | reminder | **22** Permission Dialog |
69
+ | `theme:gesture-reachability` | *universal* | reminder | **20** Swipe-to-Delete Row · **29** Pull-to-Refresh List |
70
+ | `theme:deep-link-entry` | *universal* | reminder | **26** Deep-link Entry |
71
+
72
+ **Oracle column — this is the whole point of the phase-06 catalog.** A theme marked **data** is not
73
+ covered by seeing the screen: it needs a value assertion (`text contains {{v}}`, `message contains
74
+ {{v}}`, `field with {{v}}`). A suite that only asserts presence scores as *thin* even with every
75
+ theme "covered". A **reminder** theme is real but unscored — it applies to some mobile screens and
76
+ not others, so generate it when the screen owes it, not to satisfy a gate.
77
+
78
+ **Patterns 18, 21, 24, 25, 28 carry no scored theme.** They are native surfaces the catalog does not
79
+ score, because not every mobile screen has them. Generate them for real coverage; do not expect a
80
+ score change.
81
+
82
+ ### Being on mobile does not select a `mobile-*` page-type {#page-type-selection}
83
+
84
+ A mobile target considers the mobile page-types **and the web ones**, and the winner is decided by
85
+ how many `detect_keywords` your scenarios and viewpoints actually hit — at least **2** distinct
86
+ keywords, and at least **1** more than the runner-up. Nothing about the target being mobile tips the
87
+ scale.
88
+
89
+ The consequence catches people out on the two most ordinary screens:
90
+
91
+ | You wrote | Selected type | Because |
92
+ |---|---|---|
93
+ | a login screen using *login · password · sign in · credential* | `auth` (web) | those are `auth`'s keywords; `mobile-auth` matches on *biometric · fingerprint · face id · touch id · app lock* |
94
+ | a form using *form · submit · field · input · validation* | `form` (web) | `mobile-form` matches on *soft keyboard · keyboard overlap · hide keyboard · on-screen keyboard · keyboard covers* |
95
+
96
+ So a mobile login screen is scored against the web `auth` themes, and `theme:session-persistence` /
97
+ `theme:credential-validation` are never demanded of it. That is the catalog's stated philosophy — a
98
+ native page-type is selected by native vocabulary, not by the platform flag — but it means **writing
99
+ a biometric scenario is how you opt in**, not a bonus on top.
100
+
101
+ **Opting into `mobile-form` costs an `@platform:android` tag.** The vocabulary that selects it is
102
+ keyboard vocabulary, and `hide the keyboard` is Android-only: on iOS the step is guarded out with
103
+ **no throw**, so a scenario written to reach this page-type would pass on iOS having done nothing.
104
+ Tag such a feature `@platform:android` — see **30. Soft-Keyboard Overlap**. `mobile-auth` has no
105
+ equivalent cost; biometric vocabulary runs on both.
106
+
107
+ Fewer than 2 hits, or a tie, and the page-type is **undetermined**: no themes are required at all and
108
+ the gate passes leniently. A near-miss therefore reads as a pass, not as a gap.
109
+
110
+ **To settle it deliberately, declare it.** `page-type: mobile-auth` in `test-viewpoint.md` overrides
111
+ detection outright — no keyword counting, no ties. Use that when the screen genuinely owes the native
112
+ themes and the prose does not happen to say the magic words.
113
+
114
+ *(Keywords above are copied from `universal-viewpoints.yaml`; that file is the source of truth if the
115
+ two ever disagree.)*
116
+
117
+ ---
118
+
119
+ ## 18. Bottom Sheet
120
+
121
+ **Apply when**: content slides up from the bottom edge over the current screen — a share sheet, a
122
+ filter sheet, an action sheet.
123
+
124
+ **Shared checks applied**: Loading State
125
+
126
+ | Check | Condition → Expected | VP | Priority | Theme |
127
+ |---|---|---|---|---|
128
+ | Sheet opens | Tap the trigger → the sheet's own title/content is visible | UI | @high | — |
129
+ | Sheet closes, **proven** | Swipe down on the sheet → `Then User see [Sheet] is hidden`. `dismiss [X]` is best-effort and never fails, so it can only be SETUP — a closure claim needs the hidden assertion | LOGIC | @high | — |
130
+ | Scrim tap | Tap outside the sheet → it closes (or is explicitly modal and does not) | LOGIC | @normal | — |
131
+ | Content behind is inert | While the sheet is up, the underlying control does not react to a tap | LOGIC | @normal | — |
132
+ | Half → full expansion | Swipe up on a half-height sheet → the previously clipped row becomes visible | UI | @low | — |
133
+
134
+ ---
135
+
136
+ ## 19. Tab Bar / Bottom Navigation
137
+
138
+ **Apply when**: a persistent bar of 3–5 destinations sits at the bottom (or top) of the app.
139
+
140
+ **Shared checks applied**: Loading State · Empty State
141
+
142
+ | Check | Condition → Expected | VP | Priority | Theme |
143
+ |---|---|---|---|---|
144
+ | Landing content | The launch screen shows its own content, not an empty shell | UI | @high | `theme:content-visibility` |
145
+ | Tab switches screen | Tap another tab → a marker unique to the destination is visible **and** the origin's own marker `is hidden` | LOGIC | @high | `theme:navigation-correctness` |
146
+ | Active indicator | After switching → the tapped tab reads selected, the previous one does not | UI | @normal | `theme:content-visibility` |
147
+ | State is kept per tab | Scroll a list, leave the tab, come back → the same position/filters, not a reset | LOGIC | @normal | `theme:navigation-correctness` |
148
+ | The bar occludes content | The last list row sits under the floating bar → `User tap top of [Last Row] row`. **`scroll to` cannot fix this** — `scrollIntoView` is a no-op on an element already inside the viewport, occluded or not | LOGIC | @high | `theme:navigation-correctness` |
149
+
150
+ > Two markers, not one. "Left Home" asserted only by seeing the destination passes when the app
151
+ > never moved and both screens share an element. Assert the destination marker AND the origin
152
+ > marker going `is hidden`.
153
+
154
+ ---
155
+
156
+ ## 20. Swipe-to-Delete Row
157
+
158
+ **Apply when**: a horizontal swipe on a list row reveals actions (delete, archive, pin).
159
+
160
+ **Shared checks applied**: Empty State
161
+
162
+ | Check | Condition → Expected | VP | Priority | Theme |
163
+ |---|---|---|---|---|
164
+ | Swipe reveals the action | `User swipe left on [List Item] row` → the action button is visible | UI | @high | `theme:gesture-reachability` |
165
+ | Delete removes the row's DATA | Confirm the delete → the removed value is gone from the list: `User see all [List Item] text contains {{remaining_label}}`, not merely "the row is hidden" | LOGIC | @high | `theme:scroll-reachability` |
166
+ | Swipe back cancels | Swipe the row the other way → the action hides, nothing was deleted | LOGIC | @normal | `theme:gesture-reachability` |
167
+ | Undo | An undo affordance appears → tapping it restores the row's value | LOGIC | @normal | `theme:scroll-reachability` |
168
+ | Off-screen row | The target row is below the fold → `User scroll to [Last List Item] row` first, then swipe | LOGIC | @normal | `theme:gesture-reachability` |
169
+ | Last row deleted | Delete the only row → the empty state shows, the layout does not break | UI | @normal | — |
170
+
171
+ ---
172
+
173
+ ## 21. Native Picker
174
+
175
+ **Apply when**: a field opens an OS picker — a wheel/spinner, a date picker, a dropdown sheet.
176
+
177
+ **Shared checks applied**: (no default shared check)
178
+
179
+ | Check | Condition → Expected | VP | Priority | Theme |
180
+ |---|---|---|---|---|
181
+ | Selection lands on the field | `User select {{country}} in [Country Picker] dropdown` → `Then User see [Country Picker] text contains {{country}}` | VAL | @high | `theme:field-validation` |
182
+ | Cancel keeps the old value | Open the picker, cancel → the field still holds its previous value | LOGIC | @normal | `theme:field-validation` |
183
+ | Constrained range | A date picker with a min/max → an out-of-range value cannot be selected, or is rejected with the spec's message | VAL | @high | `theme:field-validation` |
184
+ | Dependent picker | Choosing a parent value re-populates the child picker and clears a now-invalid child selection | LOGIC | @high | `theme:field-validation` |
185
+
186
+ > There is no `<select>` in a native tree. Which template a `select` step reaches is decided by the
187
+ > **selector's role**, not the step text: `role: combobox|listbox` → the native picker path,
188
+ > no role → a custom-dropdown two-tap. Both emit the same open-then-tap shape on mobile, so declare
189
+ > the role in `selectors.yaml` and assert the field afterwards rather than assuming.
190
+
191
+ ---
192
+
193
+ ## 22. Permission Dialog
194
+
195
+ **Apply when**: the screen needs a runtime permission — camera, location, notifications, contacts.
196
+
197
+ **Shared checks applied**: Permission over-request
198
+
199
+ | Check | Condition → Expected | VP | Priority | Theme |
200
+ |---|---|---|---|---|
201
+ | Granted path | `User grant camera permission` → the gated feature works and its content is visible | LOGIC | @high | `theme:permission-prompt` |
202
+ | Asked only in context | The prompt appears when the feature is used, not on cold launch | UI | @normal | `theme:permission-prompt` |
203
+ | Denied path | Deny → an in-app explanation with a route to Settings, **never a crash or a silent dead button**. No step denies a permission, so this is `@manual:M10` unless the project ships a selector for the OS dialog | LOGIC | @high | `theme:permission-prompt` |
204
+ | Never-ask-again | Deny twice, relaunch → the app must not loop the request; shows the Settings route instead. `@manual:M10` | LOGIC | @normal | `theme:permission-prompt` |
205
+ | Revoked while running | Revoke in Settings and return → the app re-checks rather than using a stale grant. `@manual:M10` | LOGIC | @normal | `theme:permission-prompt` |
206
+
207
+ > `grant [X] permission` is implemented on **both** OSes (Android `changePermissions`, iOS
208
+ > Simulator `setPermission`) — iOS additionally needs the `applesimutils` binary or the driver
209
+ > fails loud with the install hint. Only the *granted* cell is automatable today; the other three
210
+ > carry `@manual:M10` (device/OS capability), which is a reason code, not an excuse.
211
+
212
+ ---
213
+
214
+ ## 23. Biometric Prompt
215
+
216
+ **Apply when**: the app authenticates with fingerprint / Face ID, or locks behind a biometric gate.
217
+
218
+ **Shared checks applied**: (no default shared check)
219
+
220
+ | Check | Condition → Expected | VP | Priority | Theme |
221
+ |---|---|---|---|---|
222
+ | Match unlocks | `User pass biometric authentication` → the protected screen's own data is visible | LOGIC | @high | `theme:credential-validation` |
223
+ | Non-match is refused | `User fail biometric authentication` → the app stays locked and shows the spec's error, and the passcode fallback is offered | VAL | @high | `theme:credential-validation` |
224
+ | Fallback path | Decline biometrics → the password form is reachable and works | LOGIC | @high | `theme:credential-validation` |
225
+ | Not enrolled | No enrolled biometric on the device → the app falls back silently, no error dialog | LOGIC | @normal | `theme:credential-validation` |
226
+ | Lock-out | Repeated non-matches → the OS lock-out is handled with the passcode route, not a stuck screen. `@manual:M11` | LOGIC | @normal | `theme:credential-validation` |
227
+
228
+ > Emulator/Simulator ONLY (Android `mobile: fingerprint` needs finger 1 enrolled; iOS
229
+ > `sendBiometricMatch`). A real device rejects the command and the step fails loud — on a real-device
230
+ > lane these are `@manual:M11`.
231
+
232
+ ---
233
+
234
+ ## 24. Camera / Gallery Picker
235
+
236
+ **Apply when**: the flow leaves the app for the system camera or photo library and returns with a file.
237
+
238
+ **Shared checks applied**: Permission over-request
239
+
240
+ | Check | Condition → Expected | VP | Priority | Theme |
241
+ |---|---|---|---|---|
242
+ | Return with a file | Pick an image → the app shows the thumbnail/filename and the upload control enables | LOGIC | @high | — |
243
+ | Return with nothing | Cancel the picker → the app returns to the same state, no spinner left running | LOGIC | @high | — |
244
+ | Permission refused | Library/camera access denied → the in-app explanation shows, the picker is not launched | LOGIC | @high | — |
245
+ | Oversized / wrong type | A file past the spec's limit or of a rejected type → the spec's error, no upload | VAL | @high | — |
246
+ | Killed while away | The OS reclaims the app while the camera is open → returning re-enters a valid state, not a blank screen. `@manual:M10` | LOGIC | @normal | — |
247
+
248
+ > The system camera and library are **other apps**. Automating them means driving a foreign UI, so
249
+ > most of this pattern is honestly `@manual:M11` (real camera) / `@manual:M10` (OS picker variance).
250
+ > Write the checks anyway — a manual case with a real oracle beats a missing one.
251
+
252
+ ---
253
+
254
+ ## 25. Push Notification
255
+
256
+ **Apply when**: the app receives push messages, or a notification deep-links into a screen.
257
+
258
+ **Shared checks applied**: (no default shared check)
259
+
260
+ | Check | Condition → Expected | VP | Priority | Theme |
261
+ |---|---|---|---|---|
262
+ | Shade shows the message | `User open notifications` → the notification's title/body matches the spec. **Android only** → tag the scenario `@platform:android` | UI | @high | — |
263
+ | Tap routes correctly | Tap the notification → the app opens the screen the payload names, with that item's data | LOGIC | @high | — |
264
+ | Foreground arrival | A push arrives while the app is open → in-app banner per spec, no OS shade duplicate | UI | @normal | — |
265
+ | Badge / count | Reading the item clears the badge and the unread count | LOGIC | @normal | — |
266
+ | Real token | Delivery from the real push service needs a real device token → `@manual:M11` | LOGIC | @high | — |
267
+
268
+ > `open notifications` is the **notification shade** and XCUITest has no shade automation — the step
269
+ > throws loud on iOS. Keep any scenario that uses it `@platform:android`; iOS coverage of the same
270
+ > concern is `@manual:M10`.
271
+
272
+ ---
273
+
274
+ ## 26. Deep-link Entry
275
+
276
+ **Apply when**: an external link, a notification payload, or a QR code opens a specific screen.
277
+
278
+ **Shared checks applied**: Deep-link param injection
279
+
280
+ | Check | Condition → Expected | VP | Priority | Theme |
281
+ |---|---|---|---|---|
282
+ | Cold-start entry | `User open deep link {{item_url}}` from a killed app → the target screen shows **that item's** data, not the default screen | LOGIC | @high | `theme:deep-link-entry` |
283
+ | Warm entry | The same link while the app is running → routes without losing the current stack in a way the spec forbids | LOGIC | @high | `theme:deep-link-entry` |
284
+ | Auth-gated target | A deep link to a protected screen while signed out → the login screen, and after signing in the app lands on the original target | SEC | @high | `theme:deep-link-entry` |
285
+ | Unknown / stale target | A link to a deleted or non-existent id → the spec's not-found state, never a crash or a blank screen | LOGIC | @high | `theme:deep-link-entry` |
286
+ | Malicious param | A path-traversal / script / oversized param in the link → treated as data, no crash, no privileged screen reached | SEC | @high | `theme:deep-link-entry` |
287
+
288
+ ---
289
+
290
+ ## 27. Offline Banner
291
+
292
+ **Apply when**: the screen reacts to connectivity — an offline banner, cached content, a retry button.
293
+
294
+ **Shared checks applied**: Loading State · Empty State
295
+
296
+ All scenarios here need `@platform:android`: connectivity is toggled with `mobile: setConnectivity`
297
+ and XCUITest cannot toggle it, so the step throws loud on iOS.
298
+
299
+ | Check | Condition → Expected | VP | Priority | Theme |
300
+ |---|---|---|---|---|
301
+ | Banner appears | `User turn wifi off` → the offline banner is visible with the spec's text | UI | @high | `theme:connectivity-degraded` |
302
+ | Cached content survives | Offline on a screen already loaded → the previously fetched values are still asserted, not a blank list | LOGIC | @high | `theme:connectivity-degraded` |
303
+ | Action while offline | Submit while offline → a clear failure message and the entered data is preserved, never a silent loss | LOGIC | @high | `theme:connectivity-degraded` |
304
+ | Recovery | Turn connectivity back on → the banner goes `is hidden` and the data refreshes without a manual reload | LOGIC | @high | `theme:connectivity-degraded` |
305
+ | Cold launch offline | Launch with no connection → the offline state, not an indefinite spinner | UI | @normal | `theme:connectivity-degraded` |
306
+
307
+ > Do **not** author a cleanup step to restore connectivity "in case the test dies". The generated
308
+ > `wdio.conf.ts` restores the baseline (airplane off, wifi/data/location on) in `onPrepare` /
309
+ > `onComplete`, so even a run whose Appium session died mid-toggle heals itself.
310
+
311
+ ---
312
+
313
+ ## 28. Onboarding Carousel
314
+
315
+ **Apply when**: first launch shows swipeable intro slides, a tutorial, or a what's-new sheet.
316
+
317
+ **Shared checks applied**: (no default shared check)
318
+
319
+ | Check | Condition → Expected | VP | Priority | Theme |
320
+ |---|---|---|---|---|
321
+ | Slides advance | Swipe left on the carousel → slide 2's own text is visible and slide 1's `is hidden` | UI | @high | — |
322
+ | Page indicator | The dot/counter tracks the current slide | UI | @normal | — |
323
+ | Skip / Done | Skip or finish → the app lands on the real first screen with its content loaded | LOGIC | @high | — |
324
+ | Shown once | `User restart the app` after finishing → the onboarding `is hidden` and the app opens straight to the main screen | LOGIC | @high | — |
325
+ | Reappears after reinstall | `User reinstall the app` → onboarding shows again (it is install-time state, not session state) | LOGIC | @normal | — |
326
+
327
+ > "Shown once" is the classic false pass: asserting only that the main screen appears passes even
328
+ > when the carousel is on top of it. Assert the carousel's own marker going `is hidden`.
329
+
330
+ ---
331
+
332
+ ## 29. Pull-to-Refresh List
333
+
334
+ **Apply when**: a feed or list reloads by dragging down, pages as it scrolls, or has a Load More control.
335
+
336
+ **Shared checks applied**: Loading State · Empty State
337
+
338
+ | Check | Condition → Expected | VP | Priority | Theme |
339
+ |---|---|---|---|---|
340
+ | Rows carry the expected DATA | `User see all [List Item] text contains {{expected_label}}` — a row count or a sighting is **not** this check | VAL | @high | `theme:list-data` |
341
+ | Refresh changes the data | `User pull to refresh [List] section` → `User see all [List Item] text contains {{expected_label}}` for the refreshed set, so a no-op refresh fails | LOGIC | @high | `theme:refresh-correctness` |
342
+ | Spinner resolves | The refresh indicator appears and then goes `is hidden` — a stuck spinner is a real defect | UI | @normal | `theme:refresh-correctness` |
343
+ | Off-screen item is reachable | `User scroll to [Last List Item] row` → `User see [Last List Item] text contains {{expected_last}}` | LOGIC | @high | `theme:scroll-reachability` |
344
+ | Next page appends | Reaching the end loads more and **keeps** the earlier rows rather than replacing them | LOGIC | @high | `theme:scroll-reachability` |
345
+ | Empty feed | No records → the empty state's own message, and pulling to refresh from it does not crash | UI | @normal | `theme:list-data` |
346
+
347
+ > `scroll to [X]` has two measured failure modes worth knowing before you rely on it: it throws when
348
+ > the screen has no `android.widget.ScrollView` node, and it is a **no-op** when the target is already
349
+ > inside the viewport but hidden behind a floating bar. For the occluded case use `tap top of [X]`.
350
+
351
+ ---
352
+
353
+ ## 30. Soft-Keyboard Overlap
354
+
355
+ **Apply when**: the screen has any text field — the keyboard covers roughly half the screen.
356
+
357
+ **Shared checks applied**: (no default shared check)
358
+
359
+ | Check | Condition → Expected | VP | Priority | Theme |
360
+ |---|---|---|---|---|
361
+ | Focused field stays visible | Tap the lowest field → the field itself is still visible above the keyboard | UI | @high | `theme:keyboard-overlap` |
362
+ | The submit control is reachable | With the keyboard up, the primary action is either visible or reachable by scrolling — not permanently underneath | UI | @high | `theme:keyboard-overlap` |
363
+ | Dismissing reveals what was covered | `User hide keyboard` → the element the keyboard covered is visible again. Tag `@platform:android`: the iOS path is guarded out with **no** throw, so on iOS the step does nothing and this oracle would pass having proven nothing | LOGIC | @high | `theme:keyboard-overlap` |
364
+ | The error message is not hidden | A validation error on a bottom field → the message is visible with the keyboard up | VAL | @high | `theme:keyboard-overlap` |
365
+ | Return-key action | The keyboard's Next/Done key moves focus or submits per spec | LOGIC | @normal | `theme:keyboard-overlap` |
366
+
367
+ > This is the one Group F theme whose honest oracle is a **sighting**, not a value: after the
368
+ > keyboard is gone the field and its action are visible again. Do not invent a data assertion here.
369
+
370
+ ---
371
+
372
+ ## 31. Settings Toggle List
373
+
374
+ **Apply when**: a list of switches, preferences, or a profile-settings screen.
375
+
376
+ **Shared checks applied**: (no default shared check)
377
+
378
+ | Check | Condition → Expected | VP | Priority | Theme |
379
+ |---|---|---|---|---|
380
+ | Toggle reflects the stored state | `User see [Notifications Toggle] text contains {{expected_state}}` — read the state, do not assume the default | VAL | @high | `theme:toggle-state-correctness` |
381
+ | Flipping takes effect | `User check [Notifications Toggle] checkbox` → the dependent UI appears/disappears **and** the toggle reads the new state | LOGIC | @high | `theme:toggle-state-correctness` |
382
+ | Setting survives a restart | `User restart the app` → `User see [Notifications Toggle] text contains {{expected_state}}` | LOGIC | @high | `theme:setting-persistence` |
383
+ | Failed save reverts | The save fails (offline / server error) → the toggle returns to its real state instead of lying | LOGIC | @high | `theme:setting-persistence` |
384
+ | Dependent settings | Turning a parent off disables its children and their stored values are unchanged when it is turned back on | LOGIC | @normal | `theme:toggle-state-correctness` |
385
+
386
+ > Use `check`/`uncheck`, never `click`, on a switch — those templates read the current state first
387
+ > and are idempotent, so a re-run does not silently invert the setting.
388
+
389
+ ---
390
+
391
+ ## 32. App Lifecycle & Orientation
392
+
393
+ **Apply when**: always. Every mobile screen can be backgrounded, rotated, and relaunched.
394
+
395
+ **Shared checks applied**: Recents / screenshot leak
396
+
397
+ | Check | Condition → Expected | VP | Priority | Theme |
398
+ |---|---|---|---|---|
399
+ | Resume restores the screen | `User background the app for 5 seconds` → the same screen with its own data, not an empty shell or a re-login | LOGIC | @high | `theme:app-lifecycle-resume` |
400
+ | In-progress input survives | Background mid-form → returning keeps the typed values (or clears them deliberately per spec) | LOGIC | @high | `theme:app-lifecycle-resume` |
401
+ | Session survives a restart | `User restart the app` → `User see [Account Name] text contains {{user_name}}` | LOGIC | @high | `theme:session-persistence` |
402
+ | Rotation keeps state | `User rotate to landscape` → the content and any entered values survive; `User rotate to portrait` restores the layout | UI | @normal | `theme:orientation-stability` |
403
+ | Rotation does not duplicate work | Rotating mid-load does not fire a second request or double-submit | LOGIC | @normal | `theme:orientation-stability` |
404
+ | Process death | The OS kills a backgrounded app and the user returns → the screen is restored from saved state, not a crash. Not expressible as a step → `@manual:M10` | LOGIC | @high | `theme:app-lifecycle-resume` |
405
+
406
+ > `restart the app` (kill → relaunch) is THE persistence oracle — reach for it for session,
407
+ > setting, dismissal and show-once claims. `reinstall the app` clears install-time state instead,
408
+ > and requires the session to have installed via `APP_APK` / `IOS_APP`; attaching by package makes
409
+ > the step fail loud with that exact fix.
410
+
411
+ ---
412
+
413
+ ## ⚡ Cross-pattern interactions
414
+
415
+ - **19 + 30**: The keyboard opens over a bottom tab bar → the bar must not float above the keyboard, and the focused field stays visible.
416
+ - **22 + 24**: Permission denied then granted inside one flow → the picker becomes usable without a relaunch.
417
+ - **26 + 15**: A deep link into a protected screen while signed out → login, then land on the original target, not the default home screen.
418
+ - **27 + 29**: Pull to refresh while offline → the offline message, and the previously loaded rows are still asserted rather than cleared.
419
+ - **32 + 31**: Change a setting, background the app, return → the change is still applied and still reads correctly.
@@ -84,9 +84,16 @@ export default defineConfig({
84
84
  /* Output file path is controlled by PLAYWRIGHT_JSON_OUTPUT_NAME env var for per-screen isolation. */
85
85
  /* When SUNGEN_ENV is set, the env name is inserted before `.json` so locale */
86
86
  /* runs don't overwrite each other (e.g. `<name>-test-result.vi.json`). */
87
+ /* The sanitize reporter rewrites the JSON report's absolute machine paths to project-relative ones on
88
+ exit — the file is committed next to the spec, so a username or machine layout must not ship in it.
89
+ Registered only while its file exists (`sungen init`/`generate`/`update` write it): a cleaned
90
+ specs/generated must not stop Playwright from loading this config. */
87
91
  reporter: [
88
92
  ['html'],
89
93
  ['json', { outputFile: resolveJsonOutputFile() }],
94
+ ...(fs.existsSync(path.join(__dirname, 'specs', 'generated', 'report-path-sanitize-reporter.ts'))
95
+ ? [['./specs/generated/report-path-sanitize-reporter.ts'] as [string]]
96
+ : []),
90
97
  ],
91
98
  /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
92
99
  use: {
@@ -150,7 +150,7 @@ Add to `.vscode/settings.json` to auto-load Gherkin syntax when editing `.featur
150
150
  | Pattern | Example |
151
151
  |---|---|
152
152
  | Navigate | `User is on [login] page` |
153
- | Navigate with data | `User is on [user detail] page with {{user_id}}` |
153
+ | Navigate with data | `User is on [user detail] page with {{user_query}}` — `{{v}}` is a query/fragment (`?id=200`, `#tab`) appended to the page value, never a bare id |
154
154
  | Click | `User click [Submit] button` |
155
155
  | Fill | `User fill [Email] field with {{email}}` |
156
156
  | Select | `User select [Country] dropdown with {{country}}` |