@sun-asterisk/sungen 3.2.29 → 3.2.31

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 (335) hide show
  1. package/dist/cli/commands/delivery.d.ts.map +1 -1
  2. package/dist/cli/commands/delivery.js +2 -1
  3. package/dist/cli/commands/delivery.js.map +1 -1
  4. package/dist/cli/commands/generate.d.ts.map +1 -1
  5. package/dist/cli/commands/generate.js +6 -2
  6. package/dist/cli/commands/generate.js.map +1 -1
  7. package/dist/cli/commands/inspect.js +1 -1
  8. package/dist/cli/commands/inspect.js.map +1 -1
  9. package/dist/cli/commands/results-merge.d.ts.map +1 -1
  10. package/dist/cli/commands/results-merge.js +9 -2
  11. package/dist/cli/commands/results-merge.js.map +1 -1
  12. package/dist/cli/commands/results-sanitize.d.ts +24 -0
  13. package/dist/cli/commands/results-sanitize.d.ts.map +1 -0
  14. package/dist/cli/commands/results-sanitize.js +126 -0
  15. package/dist/cli/commands/results-sanitize.js.map +1 -0
  16. package/dist/cli/commands/script-check.d.ts.map +1 -1
  17. package/dist/cli/commands/script-check.js +3 -1
  18. package/dist/cli/commands/script-check.js.map +1 -1
  19. package/dist/cli/commands/update.d.ts.map +1 -1
  20. package/dist/cli/commands/update.js +3 -0
  21. package/dist/cli/commands/update.js.map +1 -1
  22. package/dist/exporters/api-testcase-formatter.d.ts +3 -6
  23. package/dist/exporters/api-testcase-formatter.d.ts.map +1 -1
  24. package/dist/exporters/api-testcase-formatter.js +7 -10
  25. package/dist/exporters/api-testcase-formatter.js.map +1 -1
  26. package/dist/exporters/matrix/build.d.ts.map +1 -1
  27. package/dist/exporters/matrix/build.js +4 -2
  28. package/dist/exporters/matrix/build.js.map +1 -1
  29. package/dist/exporters/matrix/render-coverage-sheet.d.ts.map +1 -1
  30. package/dist/exporters/matrix/render-coverage-sheet.js +3 -1
  31. package/dist/exporters/matrix/render-coverage-sheet.js.map +1 -1
  32. package/dist/exporters/matrix/render-csv.d.ts.map +1 -1
  33. package/dist/exporters/matrix/render-csv.js +3 -1
  34. package/dist/exporters/matrix/render-csv.js.map +1 -1
  35. package/dist/exporters/matrix/render-overview-sheet.d.ts.map +1 -1
  36. package/dist/exporters/matrix/render-overview-sheet.js +5 -9
  37. package/dist/exporters/matrix/render-overview-sheet.js.map +1 -1
  38. package/dist/exporters/matrix/result-totals.d.ts +23 -0
  39. package/dist/exporters/matrix/result-totals.d.ts.map +1 -0
  40. package/dist/exporters/matrix/result-totals.js +21 -0
  41. package/dist/exporters/matrix/result-totals.js.map +1 -0
  42. package/dist/exporters/matrix/testcase-summary-band.d.ts.map +1 -1
  43. package/dist/exporters/matrix/testcase-summary-band.js +2 -6
  44. package/dist/exporters/matrix/testcase-summary-band.js.map +1 -1
  45. package/dist/exporters/qa-env-secret-denylist.js +2 -2
  46. package/dist/exporters/qa-env-secret-denylist.js.map +1 -1
  47. package/dist/exporters/report-path-sanitizer.d.ts +38 -0
  48. package/dist/exporters/report-path-sanitizer.d.ts.map +1 -0
  49. package/dist/exporters/report-path-sanitizer.js +137 -0
  50. package/dist/exporters/report-path-sanitizer.js.map +1 -0
  51. package/dist/exporters/result-variants.d.ts.map +1 -1
  52. package/dist/exporters/result-variants.js +2 -1
  53. package/dist/exporters/result-variants.js.map +1 -1
  54. package/dist/exporters/sensitive-key.d.ts +31 -0
  55. package/dist/exporters/sensitive-key.d.ts.map +1 -0
  56. package/dist/exporters/sensitive-key.js +50 -0
  57. package/dist/exporters/sensitive-key.js.map +1 -0
  58. package/dist/exporters/test-data-resolver.d.ts +4 -1
  59. package/dist/exporters/test-data-resolver.d.ts.map +1 -1
  60. package/dist/exporters/test-data-resolver.js +12 -2
  61. package/dist/exporters/test-data-resolver.js.map +1 -1
  62. package/dist/generators/gherkin-parser/index.d.ts +3 -0
  63. package/dist/generators/gherkin-parser/index.d.ts.map +1 -1
  64. package/dist/generators/gherkin-parser/index.js +17 -9
  65. package/dist/generators/gherkin-parser/index.js.map +1 -1
  66. package/dist/generators/gherkin-parser/parent-scope-clause.d.ts +54 -0
  67. package/dist/generators/gherkin-parser/parent-scope-clause.d.ts.map +1 -0
  68. package/dist/generators/gherkin-parser/parent-scope-clause.js +109 -0
  69. package/dist/generators/gherkin-parser/parent-scope-clause.js.map +1 -0
  70. package/dist/generators/test-generator/adapters/adapter-interface.d.ts +23 -18
  71. package/dist/generators/test-generator/adapters/adapter-interface.d.ts.map +1 -1
  72. package/dist/generators/test-generator/adapters/appium/appium-adapter.d.ts +4 -19
  73. package/dist/generators/test-generator/adapters/appium/appium-adapter.d.ts.map +1 -1
  74. package/dist/generators/test-generator/adapters/appium/appium-adapter.js.map +1 -1
  75. package/dist/generators/test-generator/adapters/appium/templates/after-all.hbs +18 -0
  76. package/dist/generators/test-generator/adapters/appium/templates/after-each.hbs +18 -0
  77. package/dist/generators/test-generator/adapters/appium/templates/before-all.hbs +18 -0
  78. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/click-at-position-action.hbs +1 -0
  79. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/click-element-with-text.hbs +1 -1
  80. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/double-click-action.hbs +7 -0
  81. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/frame-enter-action.hbs +3 -6
  82. package/dist/generators/test-generator/adapters/appium/templates/steps/actions/table-paginate-action.hbs +3 -0
  83. package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/visible-assertion.hbs +1 -1
  84. package/dist/generators/test-generator/adapters/appium/templates/steps/gestures/long-press-action.hbs +4 -0
  85. package/dist/generators/test-generator/adapters/appium/templates/steps/gestures/pinch-zoom-action.hbs +4 -0
  86. package/dist/generators/test-generator/adapters/appium/templates/steps/partials/locator.hbs +9 -1
  87. package/dist/generators/test-generator/adapters/appium/templates/test-file.hbs +54 -23
  88. package/dist/generators/test-generator/adapters/index.d.ts +1 -1
  89. package/dist/generators/test-generator/adapters/index.d.ts.map +1 -1
  90. package/dist/generators/test-generator/adapters/playwright/playwright-adapter.d.ts +4 -19
  91. package/dist/generators/test-generator/adapters/playwright/playwright-adapter.d.ts.map +1 -1
  92. package/dist/generators/test-generator/adapters/playwright/playwright-adapter.js.map +1 -1
  93. package/dist/generators/test-generator/adapters/playwright/templates/after-all.hbs +19 -1
  94. package/dist/generators/test-generator/adapters/playwright/templates/after-each.hbs +18 -0
  95. package/dist/generators/test-generator/adapters/playwright/templates/before-all.hbs +19 -1
  96. package/dist/generators/test-generator/adapters/playwright/templates/imports.hbs +3 -0
  97. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/check-action.hbs +6 -1
  98. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/click-at-position-action.hbs +23 -0
  99. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/expand-action.hbs +8 -8
  100. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/fill-editor-action.hbs +7 -2
  101. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row-nth.hbs +3 -1
  102. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row.hbs +3 -1
  103. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/table-paginate-action.hbs +5 -0
  104. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/uncheck-action.hbs +3 -1
  105. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/unknown-element-action.hbs +1 -1
  106. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/wait-for-page.hbs +18 -1
  107. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/all-contain-assertion.hbs +32 -4
  108. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/all-contain-element.hbs +5 -2
  109. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/checked-assertion.hbs +5 -1
  110. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/column-cell-assertion.hbs +13 -2
  111. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/contain-text-assertion.hbs +1 -1
  112. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-role-variable-assertion.hbs +2 -2
  113. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-variable-assertion.hbs +1 -1
  114. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/have-text-assertion.hbs +1 -1
  115. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-role-variable-assertion.hbs +2 -2
  116. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-variable-assertion.hbs +1 -1
  117. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/not-checked-assertion.hbs +2 -1
  118. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/selected-assertion.hbs +14 -3
  119. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/state-with-filter-assertion.hbs +13 -2
  120. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-role-variable-assertion.hbs +3 -3
  121. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-value-assertion.hbs +1 -1
  122. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-variable-assertion.hbs +1 -1
  123. package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/checked-opts.hbs +8 -0
  124. package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator-nth.hbs +1 -1
  125. package/dist/generators/test-generator/adapters/playwright/templates/test-file.hbs +10 -8
  126. package/dist/generators/test-generator/code-generator.d.ts +37 -0
  127. package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
  128. package/dist/generators/test-generator/code-generator.js +160 -39
  129. package/dist/generators/test-generator/code-generator.js.map +1 -1
  130. package/dist/generators/test-generator/diagnostics.d.ts +79 -5
  131. package/dist/generators/test-generator/diagnostics.d.ts.map +1 -1
  132. package/dist/generators/test-generator/diagnostics.js +78 -4
  133. package/dist/generators/test-generator/diagnostics.js.map +1 -1
  134. package/dist/generators/test-generator/patterns/index.d.ts +24 -5
  135. package/dist/generators/test-generator/patterns/index.d.ts.map +1 -1
  136. package/dist/generators/test-generator/patterns/index.js +92 -14
  137. package/dist/generators/test-generator/patterns/index.js.map +1 -1
  138. package/dist/generators/test-generator/patterns/with-parent-scope.d.ts +18 -0
  139. package/dist/generators/test-generator/patterns/with-parent-scope.d.ts.map +1 -0
  140. package/dist/generators/test-generator/patterns/with-parent-scope.js +40 -0
  141. package/dist/generators/test-generator/patterns/with-parent-scope.js.map +1 -0
  142. package/dist/generators/test-generator/step-mapper.d.ts +63 -9
  143. package/dist/generators/test-generator/step-mapper.d.ts.map +1 -1
  144. package/dist/generators/test-generator/step-mapper.js +166 -28
  145. package/dist/generators/test-generator/step-mapper.js.map +1 -1
  146. package/dist/generators/test-generator/template-engine.d.ts +4 -19
  147. package/dist/generators/test-generator/template-engine.d.ts.map +1 -1
  148. package/dist/generators/test-generator/template-engine.js +17 -12
  149. package/dist/generators/test-generator/template-engine.js.map +1 -1
  150. package/dist/generators/test-generator/utils/data-resolver.d.ts +7 -0
  151. package/dist/generators/test-generator/utils/data-resolver.d.ts.map +1 -1
  152. package/dist/generators/test-generator/utils/data-resolver.js +19 -2
  153. package/dist/generators/test-generator/utils/data-resolver.js.map +1 -1
  154. package/dist/generators/test-generator/utils/dialog-scope-identity.d.ts +41 -0
  155. package/dist/generators/test-generator/utils/dialog-scope-identity.d.ts.map +1 -0
  156. package/dist/generators/test-generator/utils/dialog-scope-identity.js +61 -0
  157. package/dist/generators/test-generator/utils/dialog-scope-identity.js.map +1 -0
  158. package/dist/generators/test-generator/utils/escape-js-string.d.ts +17 -0
  159. package/dist/generators/test-generator/utils/escape-js-string.d.ts.map +1 -0
  160. package/dist/generators/test-generator/utils/escape-js-string.js +29 -0
  161. package/dist/generators/test-generator/utils/escape-js-string.js.map +1 -0
  162. package/dist/generators/test-generator/utils/nearest-match.d.ts +24 -0
  163. package/dist/generators/test-generator/utils/nearest-match.d.ts.map +1 -0
  164. package/dist/generators/test-generator/utils/nearest-match.js +56 -0
  165. package/dist/generators/test-generator/utils/nearest-match.js.map +1 -0
  166. package/dist/generators/test-generator/utils/selector-entry-fields.d.ts +58 -0
  167. package/dist/generators/test-generator/utils/selector-entry-fields.d.ts.map +1 -0
  168. package/dist/generators/test-generator/utils/selector-entry-fields.js +119 -0
  169. package/dist/generators/test-generator/utils/selector-entry-fields.js.map +1 -0
  170. package/dist/generators/test-generator/utils/selector-entry-walk.d.ts +25 -0
  171. package/dist/generators/test-generator/utils/selector-entry-walk.d.ts.map +1 -0
  172. package/dist/generators/test-generator/utils/selector-entry-walk.js +54 -0
  173. package/dist/generators/test-generator/utils/selector-entry-walk.js.map +1 -0
  174. package/dist/generators/test-generator/utils/selector-nth-validation.d.ts +59 -0
  175. package/dist/generators/test-generator/utils/selector-nth-validation.d.ts.map +1 -0
  176. package/dist/generators/test-generator/utils/selector-nth-validation.js +91 -0
  177. package/dist/generators/test-generator/utils/selector-nth-validation.js.map +1 -0
  178. package/dist/generators/test-generator/utils/selector-resolver.d.ts +30 -1
  179. package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
  180. package/dist/generators/test-generator/utils/selector-resolver.js +195 -15
  181. package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -1
  182. package/dist/generators/test-generator/utils/selector-type-validation.d.ts +51 -0
  183. package/dist/generators/test-generator/utils/selector-type-validation.d.ts.map +1 -0
  184. package/dist/generators/test-generator/utils/selector-type-validation.js +77 -0
  185. package/dist/generators/test-generator/utils/selector-type-validation.js.map +1 -0
  186. package/dist/harness/data-driven-lint.d.ts.map +1 -1
  187. package/dist/harness/data-driven-lint.js +217 -33
  188. package/dist/harness/data-driven-lint.js.map +1 -1
  189. package/dist/harness/script-check.d.ts +2 -2
  190. package/dist/harness/script-check.d.ts.map +1 -1
  191. package/dist/harness/script-check.js +186 -25
  192. package/dist/harness/script-check.js.map +1 -1
  193. package/dist/index.d.ts +2 -0
  194. package/dist/index.d.ts.map +1 -1
  195. package/dist/index.js +10 -1
  196. package/dist/index.js.map +1 -1
  197. package/dist/orchestrator/project-initializer.d.ts +6 -0
  198. package/dist/orchestrator/project-initializer.d.ts.map +1 -1
  199. package/dist/orchestrator/project-initializer.js +16 -0
  200. package/dist/orchestrator/project-initializer.js.map +1 -1
  201. package/dist/orchestrator/report-sanitize-reporter-install.d.ts +24 -0
  202. package/dist/orchestrator/report-sanitize-reporter-install.d.ts.map +1 -0
  203. package/dist/orchestrator/report-sanitize-reporter-install.js +161 -0
  204. package/dist/orchestrator/report-sanitize-reporter-install.js.map +1 -0
  205. package/dist/orchestrator/templates/ai-src/commands/run-test.md +9 -1
  206. package/dist/orchestrator/templates/ai-src/skills/sungen-api-coverage-model/SKILL.md +10 -0
  207. package/dist/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +14 -2
  208. package/dist/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +108 -8
  209. package/dist/orchestrator/templates/ai-src/skills/sungen-selector-fix/SKILL.md +1 -0
  210. package/dist/orchestrator/templates/ai-src/skills/sungen-selector-keys/SKILL.md +9 -2
  211. package/dist/orchestrator/templates/ai-src/skills/sungen-tc-review/SKILL.md +4 -4
  212. package/dist/orchestrator/templates/playwright.config.ts +7 -0
  213. package/dist/orchestrator/templates/specs-checked-state.d.ts +83 -0
  214. package/dist/orchestrator/templates/specs-checked-state.d.ts.map +1 -0
  215. package/dist/orchestrator/templates/specs-checked-state.js +261 -0
  216. package/dist/orchestrator/templates/specs-checked-state.js.map +1 -0
  217. package/dist/orchestrator/templates/specs-checked-state.ts +324 -0
  218. package/dist/orchestrator/templates/specs-report-path-sanitize-reporter.d.ts +36 -0
  219. package/dist/orchestrator/templates/specs-report-path-sanitize-reporter.d.ts.map +1 -0
  220. package/dist/orchestrator/templates/specs-report-path-sanitize-reporter.js +155 -0
  221. package/dist/orchestrator/templates/specs-report-path-sanitize-reporter.js.map +1 -0
  222. package/dist/orchestrator/templates/specs-report-path-sanitize-reporter.ts +142 -0
  223. package/dist/orchestrator/templates/specs-url-assert.d.ts +50 -25
  224. package/dist/orchestrator/templates/specs-url-assert.d.ts.map +1 -1
  225. package/dist/orchestrator/templates/specs-url-assert.js +65 -24
  226. package/dist/orchestrator/templates/specs-url-assert.js.map +1 -1
  227. package/dist/orchestrator/templates/specs-url-assert.ts +101 -28
  228. package/dist/utils/selector-types.d.ts +43 -1
  229. package/dist/utils/selector-types.d.ts.map +1 -1
  230. package/dist/utils/selector-types.js +51 -7
  231. package/dist/utils/selector-types.js.map +1 -1
  232. package/package.json +3 -3
  233. package/src/cli/commands/delivery.ts +2 -1
  234. package/src/cli/commands/generate.ts +5 -2
  235. package/src/cli/commands/inspect.ts +1 -1
  236. package/src/cli/commands/results-merge.ts +9 -2
  237. package/src/cli/commands/results-sanitize.ts +98 -0
  238. package/src/cli/commands/script-check.ts +3 -1
  239. package/src/cli/commands/update.ts +3 -0
  240. package/src/exporters/api-testcase-formatter.ts +5 -7
  241. package/src/exporters/matrix/build.ts +4 -2
  242. package/src/exporters/matrix/render-coverage-sheet.ts +3 -1
  243. package/src/exporters/matrix/render-csv.ts +3 -1
  244. package/src/exporters/matrix/render-overview-sheet.ts +5 -10
  245. package/src/exporters/matrix/result-totals.ts +37 -0
  246. package/src/exporters/matrix/testcase-summary-band.ts +2 -7
  247. package/src/exporters/qa-env-secret-denylist.ts +1 -1
  248. package/src/exporters/report-path-sanitizer.ts +144 -0
  249. package/src/exporters/result-variants.ts +2 -1
  250. package/src/exporters/sensitive-key.ts +48 -0
  251. package/src/exporters/test-data-resolver.ts +12 -2
  252. package/src/generators/gherkin-parser/index.ts +21 -10
  253. package/src/generators/gherkin-parser/parent-scope-clause.ts +130 -0
  254. package/src/generators/test-generator/adapters/adapter-interface.ts +25 -3
  255. package/src/generators/test-generator/adapters/appium/appium-adapter.ts +4 -4
  256. package/src/generators/test-generator/adapters/appium/templates/after-all.hbs +18 -0
  257. package/src/generators/test-generator/adapters/appium/templates/after-each.hbs +18 -0
  258. package/src/generators/test-generator/adapters/appium/templates/before-all.hbs +18 -0
  259. package/src/generators/test-generator/adapters/appium/templates/steps/actions/click-at-position-action.hbs +1 -0
  260. package/src/generators/test-generator/adapters/appium/templates/steps/actions/click-element-with-text.hbs +1 -1
  261. package/src/generators/test-generator/adapters/appium/templates/steps/actions/double-click-action.hbs +7 -0
  262. package/src/generators/test-generator/adapters/appium/templates/steps/actions/frame-enter-action.hbs +3 -6
  263. package/src/generators/test-generator/adapters/appium/templates/steps/actions/table-paginate-action.hbs +3 -0
  264. package/src/generators/test-generator/adapters/appium/templates/steps/assertions/visible-assertion.hbs +1 -1
  265. package/src/generators/test-generator/adapters/appium/templates/steps/gestures/long-press-action.hbs +4 -0
  266. package/src/generators/test-generator/adapters/appium/templates/steps/gestures/pinch-zoom-action.hbs +4 -0
  267. package/src/generators/test-generator/adapters/appium/templates/steps/partials/locator.hbs +9 -1
  268. package/src/generators/test-generator/adapters/appium/templates/test-file.hbs +54 -23
  269. package/src/generators/test-generator/adapters/index.ts +1 -1
  270. package/src/generators/test-generator/adapters/playwright/playwright-adapter.ts +4 -4
  271. package/src/generators/test-generator/adapters/playwright/templates/after-all.hbs +19 -1
  272. package/src/generators/test-generator/adapters/playwright/templates/after-each.hbs +18 -0
  273. package/src/generators/test-generator/adapters/playwright/templates/before-all.hbs +19 -1
  274. package/src/generators/test-generator/adapters/playwright/templates/imports.hbs +3 -0
  275. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/check-action.hbs +6 -1
  276. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/click-at-position-action.hbs +23 -0
  277. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/expand-action.hbs +8 -8
  278. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/fill-editor-action.hbs +7 -2
  279. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row-nth.hbs +3 -1
  280. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row.hbs +3 -1
  281. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/table-paginate-action.hbs +5 -0
  282. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/uncheck-action.hbs +3 -1
  283. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/unknown-element-action.hbs +1 -1
  284. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/wait-for-page.hbs +18 -1
  285. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/all-contain-assertion.hbs +32 -4
  286. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/all-contain-element.hbs +5 -2
  287. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/checked-assertion.hbs +5 -1
  288. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/column-cell-assertion.hbs +13 -2
  289. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/contain-text-assertion.hbs +1 -1
  290. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-role-variable-assertion.hbs +2 -2
  291. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-variable-assertion.hbs +1 -1
  292. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/have-text-assertion.hbs +1 -1
  293. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-role-variable-assertion.hbs +2 -2
  294. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-variable-assertion.hbs +1 -1
  295. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/not-checked-assertion.hbs +2 -1
  296. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/selected-assertion.hbs +14 -3
  297. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/state-with-filter-assertion.hbs +13 -2
  298. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-role-variable-assertion.hbs +3 -3
  299. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-value-assertion.hbs +1 -1
  300. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-variable-assertion.hbs +1 -1
  301. package/src/generators/test-generator/adapters/playwright/templates/steps/partials/checked-opts.hbs +8 -0
  302. package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator-nth.hbs +1 -1
  303. package/src/generators/test-generator/adapters/playwright/templates/test-file.hbs +10 -8
  304. package/src/generators/test-generator/code-generator.ts +176 -45
  305. package/src/generators/test-generator/diagnostics.ts +79 -5
  306. package/src/generators/test-generator/patterns/index.ts +97 -16
  307. package/src/generators/test-generator/patterns/with-parent-scope.ts +41 -0
  308. package/src/generators/test-generator/step-mapper.ts +170 -26
  309. package/src/generators/test-generator/template-engine.ts +21 -21
  310. package/src/generators/test-generator/utils/data-resolver.ts +23 -2
  311. package/src/generators/test-generator/utils/dialog-scope-identity.ts +71 -0
  312. package/src/generators/test-generator/utils/escape-js-string.ts +24 -0
  313. package/src/generators/test-generator/utils/nearest-match.ts +55 -0
  314. package/src/generators/test-generator/utils/selector-entry-fields.ts +131 -0
  315. package/src/generators/test-generator/utils/selector-entry-walk.ts +58 -0
  316. package/src/generators/test-generator/utils/selector-nth-validation.ts +99 -0
  317. package/src/generators/test-generator/utils/selector-resolver.ts +245 -16
  318. package/src/generators/test-generator/utils/selector-type-validation.ts +87 -0
  319. package/src/harness/data-driven-lint.ts +192 -32
  320. package/src/harness/script-check.ts +186 -21
  321. package/src/index.ts +7 -0
  322. package/src/orchestrator/project-initializer.ts +17 -0
  323. package/src/orchestrator/report-sanitize-reporter-install.ts +109 -0
  324. package/src/orchestrator/templates/ai-src/commands/run-test.md +9 -1
  325. package/src/orchestrator/templates/ai-src/skills/sungen-api-coverage-model/SKILL.md +10 -0
  326. package/src/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +14 -2
  327. package/src/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +108 -8
  328. package/src/orchestrator/templates/ai-src/skills/sungen-selector-fix/SKILL.md +1 -0
  329. package/src/orchestrator/templates/ai-src/skills/sungen-selector-keys/SKILL.md +9 -2
  330. package/src/orchestrator/templates/ai-src/skills/sungen-tc-review/SKILL.md +4 -4
  331. package/src/orchestrator/templates/playwright.config.ts +7 -0
  332. package/src/orchestrator/templates/specs-checked-state.ts +324 -0
  333. package/src/orchestrator/templates/specs-report-path-sanitize-reporter.ts +142 -0
  334. package/src/orchestrator/templates/specs-url-assert.ts +101 -28
  335. package/src/utils/selector-types.ts +54 -5
@@ -52,6 +52,18 @@ class DataResolver {
52
52
  clearCaptured() {
53
53
  this.capturedVars.clear();
54
54
  }
55
+ /** Register the head of a variable bound by the feature's `@beforeAll` hook (feature-scoped). */
56
+ registerFeatureCaptured(head) {
57
+ this.featureCaptured.add(head);
58
+ }
59
+ /** Clear feature-scoped captured vars — call at the start of each feature. */
60
+ clearFeatureCaptured() {
61
+ this.featureCaptured.clear();
62
+ }
63
+ /** Runtime-only ref (scenario-captured, or bound by the feature's `@beforeAll` hook)? */
64
+ isCaptured(dataRef) {
65
+ return this.capturedVars.has(dataRef) || this.featureCaptured.has(dataRef.split(/[.[]/)[0]);
66
+ }
55
67
  constructor(testDataDir, screenName, runtimeMode = false) {
56
68
  this.dataCache = new Map();
57
69
  this.flowMode = false;
@@ -59,6 +71,11 @@ class DataResolver {
59
71
  // these skip YAML validation (they don't exist in test-data.yaml) and resolve
60
72
  // to testData.get('var') — populated by the capture step's testData.set('var', …).
61
73
  this.capturedVars = new Set();
74
+ // Vars bound by a `@beforeAll` hook's `@api:`/`@query:` preconditions. The hook runs before every
75
+ // test of the feature, so its bindings are readable from EVERY scenario — they survive the
76
+ // per-scenario clearCaptured(). Stored by head (`login`) and matched against the ref's head
77
+ // (`login.body.token` → `login`), since a scenario may read any sub-path of the bound response.
78
+ this.featureCaptured = new Set();
62
79
  this.testDataDir = testDataDir || path.join(process.cwd(), 'qa', 'test-data');
63
80
  this.screenName = screenName;
64
81
  this.runtimeMode = runtimeMode;
@@ -78,7 +95,7 @@ class DataResolver {
78
95
  resolveData(dataRef, featureName) {
79
96
  // Captured vars exist only at runtime → emit a marker (→ testData.get) and
80
97
  // skip YAML validation. Requires runtime mode (capture writes testData.set).
81
- if (this.capturedVars.has(dataRef)) {
98
+ if (this.isCaptured(dataRef)) {
82
99
  return DataResolver.encodeMarker(dataRef);
83
100
  }
84
101
  if (this.runtimeMode) {
@@ -98,7 +115,7 @@ class DataResolver {
98
115
  * anything said about it belongs in a warning, never a gate.
99
116
  */
100
117
  peekBaseValue(dataRef, featureName) {
101
- if (this.capturedVars.has(dataRef))
118
+ if (this.isCaptured(dataRef))
102
119
  return undefined;
103
120
  try {
104
121
  return this.resolveValue(dataRef, featureName);
@@ -1 +1 @@
1
- {"version":3,"file":"data-resolver.js","sourceRoot":"","sources":["../../../../src/generators/test-generator/utils/data-resolver.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"data-resolver.js","sourceRoot":"","sources":["../../../../src/generators/test-generator/utils/data-resolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Identity of a locator as the `locator` partial actually renders it — issue #692.
3
+ *
4
+ * `Given User is on [X] dialog` records a scope root, and the `pageRoot` helper prefixes every
5
+ * locator rendered afterwards with it. That is the whole point of the scope — except when a later
6
+ * step names the SAME element as the scope root, where the prefix nests the dialog inside itself:
7
+ *
8
+ * page.getByRole('dialog', { name: 'Confirm' }).getByRole('dialog', { name: 'Confirm' })
9
+ *
10
+ * A dialog cannot contain itself, so that query can never resolve. It compiles clean, emits no
11
+ * diagnostic, and fails as a plain timeout — which reads as "the dialog never opened" rather than
12
+ * "the query is impossible". Re-asserting the dialog you are scoped inside is the natural thing to
13
+ * write straight after the `Given`, so the scope root is made idempotent instead.
14
+ *
15
+ * The guard needs exactly one question answered: does this element render to the same locator as
16
+ * the active scope root? So the key carries the fields the partial reads FOR THAT STRATEGY and
17
+ * nothing else — two entries share a key iff they render the same expression. Comparing role+name
18
+ * alone (the shape the issue first suggested) would miss `type: locator` and `type: testid`
19
+ * dialogs, which self-nest just the same.
20
+ *
21
+ * Deliberately says nothing about a `with {{v}}` filtered root: that root is
22
+ * `getByRole('dialog').filter({ hasText })`, which is not expressible as the element's own
23
+ * locator, so an identity match there would be meaningless. The caller skips the guard in that
24
+ * case — see the `dialogFilterText` check in `pageRoot`.
25
+ */
26
+ /** The subset of a resolved selector that the `locator` partial reads. */
27
+ export interface LocatorIdentityFields {
28
+ strategy?: string;
29
+ value?: string;
30
+ role?: string;
31
+ name?: string;
32
+ exact?: boolean;
33
+ nth?: number;
34
+ scope?: string;
35
+ }
36
+ /**
37
+ * A stable key for the locator `fields` renders to, or undefined when there is no strategy to
38
+ * render (nothing to compare, so no guard).
39
+ */
40
+ export declare function locatorIdentityKey(fields: LocatorIdentityFields | undefined): string | undefined;
41
+ //# sourceMappingURL=dialog-scope-identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dialog-scope-identity.d.ts","sourceRoot":"","sources":["../../../../src/generators/test-generator/utils/dialog-scope-identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,0EAA0E;AAC1E,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,qBAAqB,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CA6BhG"}
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ /**
3
+ * Identity of a locator as the `locator` partial actually renders it — issue #692.
4
+ *
5
+ * `Given User is on [X] dialog` records a scope root, and the `pageRoot` helper prefixes every
6
+ * locator rendered afterwards with it. That is the whole point of the scope — except when a later
7
+ * step names the SAME element as the scope root, where the prefix nests the dialog inside itself:
8
+ *
9
+ * page.getByRole('dialog', { name: 'Confirm' }).getByRole('dialog', { name: 'Confirm' })
10
+ *
11
+ * A dialog cannot contain itself, so that query can never resolve. It compiles clean, emits no
12
+ * diagnostic, and fails as a plain timeout — which reads as "the dialog never opened" rather than
13
+ * "the query is impossible". Re-asserting the dialog you are scoped inside is the natural thing to
14
+ * write straight after the `Given`, so the scope root is made idempotent instead.
15
+ *
16
+ * The guard needs exactly one question answered: does this element render to the same locator as
17
+ * the active scope root? So the key carries the fields the partial reads FOR THAT STRATEGY and
18
+ * nothing else — two entries share a key iff they render the same expression. Comparing role+name
19
+ * alone (the shape the issue first suggested) would miss `type: locator` and `type: testid`
20
+ * dialogs, which self-nest just the same.
21
+ *
22
+ * Deliberately says nothing about a `with {{v}}` filtered root: that root is
23
+ * `getByRole('dialog').filter({ hasText })`, which is not expressible as the element's own
24
+ * locator, so an identity match there would be meaningless. The caller skips the guard in that
25
+ * case — see the `dialogFilterText` check in `pageRoot`.
26
+ */
27
+ Object.defineProperty(exports, "__esModule", { value: true });
28
+ exports.locatorIdentityKey = locatorIdentityKey;
29
+ /**
30
+ * A stable key for the locator `fields` renders to, or undefined when there is no strategy to
31
+ * render (nothing to compare, so no guard).
32
+ */
33
+ function locatorIdentityKey(fields) {
34
+ if (!fields || !fields.strategy)
35
+ return undefined;
36
+ // `scope: dialog` is the dialog-rooting sentinel rather than part of the element's own
37
+ // identity — renderDialogRoot strips it before rendering the root for the same reason.
38
+ const scope = fields.scope && fields.scope !== 'dialog' ? fields.scope : '';
39
+ const nth = typeof fields.nth === 'number' && fields.nth >= 0 ? String(fields.nth) : '';
40
+ const exact = fields.exact ? '1' : '';
41
+ const parts = [];
42
+ switch (fields.strategy) {
43
+ case 'role':
44
+ // getByRole reads role/name/exact — never `value`.
45
+ parts.push('role', fields.role || '', fields.name || '', exact);
46
+ break;
47
+ case 'testid':
48
+ parts.push('testid', fields.value || '');
49
+ break;
50
+ case 'placeholder':
51
+ case 'label':
52
+ case 'text':
53
+ parts.push(fields.strategy, fields.value || '', exact);
54
+ break;
55
+ default:
56
+ // 'locator', 'id', 'css' and the partial's own default all render locator('<value>').
57
+ parts.push('locator', fields.value || '');
58
+ }
59
+ return [...parts, `nth=${nth}`, `scope=${scope}`].join('|');
60
+ }
61
+ //# sourceMappingURL=dialog-scope-identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dialog-scope-identity.js","sourceRoot":"","sources":["../../../../src/generators/test-generator/utils/dialog-scope-identity.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;;AAiBH,gDA6BC;AAjCD;;;GAGG;AACH,SAAgB,kBAAkB,CAAC,MAAyC;IAC1E,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ;QAAE,OAAO,SAAS,CAAC;IAElD,uFAAuF;IACvF,uFAAuF;IACvF,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5E,MAAM,GAAG,GAAG,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACxF,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAEtC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,QAAQ,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxB,KAAK,MAAM;YACT,mDAAmD;YACnD,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE,EAAE,KAAK,CAAC,CAAC;YAChE,MAAM;QACR,KAAK,QAAQ;YACX,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;YACzC,MAAM;QACR,KAAK,aAAa,CAAC;QACnB,KAAK,OAAO,CAAC;QACb,KAAK,MAAM;YACT,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,IAAI,EAAE,EAAE,KAAK,CAAC,CAAC;YACvD,MAAM;QACR;YACE,sFAAsF;YACtF,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO,CAAC,GAAG,KAAK,EAAE,OAAO,GAAG,EAAE,EAAE,SAAS,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC9D,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Escape a raw string for embedding inside a SINGLE-QUOTED JS string literal.
3
+ *
4
+ * Order matters: backslash first, or the escapes added afterwards get re-escaped. Getting this
5
+ * half-right is worse than not doing it — a value ending in `\` turns `'…\'` into an escaped
6
+ * closing quote, and the string literal runs on into the rest of the file, so the generated
7
+ * `.spec.ts` stops parsing and EVERY scenario in it is lost rather than the one step.
8
+ *
9
+ * The line terminators are not cosmetic either: a card's accessible text is routinely a composite
10
+ * of several lines (a Flutter content-desc, a multi-line heading), and a literal newline inside
11
+ * `'…'` is a syntax error.
12
+ *
13
+ * Lives here rather than inside the Handlebars helper because the pattern layer also builds locator
14
+ * strings by hand — the parent-scope chain among them — and two copies of this rule drift.
15
+ */
16
+ export declare function escapeSingleQuoted(text: unknown): string;
17
+ //# sourceMappingURL=escape-js-string.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escape-js-string.d.ts","sourceRoot":"","sources":["../../../../src/generators/test-generator/utils/escape-js-string.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAQxD"}
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.escapeSingleQuoted = escapeSingleQuoted;
4
+ /**
5
+ * Escape a raw string for embedding inside a SINGLE-QUOTED JS string literal.
6
+ *
7
+ * Order matters: backslash first, or the escapes added afterwards get re-escaped. Getting this
8
+ * half-right is worse than not doing it — a value ending in `\` turns `'…\'` into an escaped
9
+ * closing quote, and the string literal runs on into the rest of the file, so the generated
10
+ * `.spec.ts` stops parsing and EVERY scenario in it is lost rather than the one step.
11
+ *
12
+ * The line terminators are not cosmetic either: a card's accessible text is routinely a composite
13
+ * of several lines (a Flutter content-desc, a multi-line heading), and a literal newline inside
14
+ * `'…'` is a syntax error.
15
+ *
16
+ * Lives here rather than inside the Handlebars helper because the pattern layer also builds locator
17
+ * strings by hand — the parent-scope chain among them — and two copies of this rule drift.
18
+ */
19
+ function escapeSingleQuoted(text) {
20
+ if (text == null)
21
+ return '';
22
+ return String(text)
23
+ .replace(/\\/g, '\\\\')
24
+ .replace(/'/g, "\\'")
25
+ .replace(/\n/g, '\\n')
26
+ .replace(/\r/g, '\\r')
27
+ .replace(/\t/g, '\\t');
28
+ }
29
+ //# sourceMappingURL=escape-js-string.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escape-js-string.js","sourceRoot":"","sources":["../../../../src/generators/test-generator/utils/escape-js-string.ts"],"names":[],"mappings":";;AAeA,gDAQC;AAvBD;;;;;;;;;;;;;;GAcG;AACH,SAAgB,kBAAkB,CAAC,IAAa;IAC9C,IAAI,IAAI,IAAI,IAAI;QAAE,OAAO,EAAE,CAAC;IAC5B,OAAO,MAAM,CAAC,IAAI,CAAC;SAChB,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;SACpB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Nearest-known-spelling suggestion, shared by the selector-surface checks.
3
+ *
4
+ * Two checks need the same judgement about the same class of author mistake — SG-W004 on an entry
5
+ * FIELD nobody reads (#712) and SG-E027 on an entry `type:` VALUE nothing dispatches (#711) — so
6
+ * the rule lives in one place rather than being re-tuned independently in each. The tuning is the
7
+ * substance here, not the edit distance:
8
+ *
9
+ * - A case-only difference is returned first and always. `testId` for `testid` and
10
+ * `contentEditable` for `contenteditable` are the single likeliest way to write either
11
+ * wrongly, and both surfaces are lowercase throughout, so this is a near-certainty rather
12
+ * than a guess.
13
+ * - Otherwise a distance of 1-2 is a typo worth naming.
14
+ * - Anything further is a DIFFERENT word, and guessing at it sends the author somewhere wrong.
15
+ * `selector` is not a misspelling of `locator` — it is someone reasonably assuming a field
16
+ * that does not exist, and "did you mean locator?" would be a worse answer than silence.
17
+ * The caller supplies its own hint for that case.
18
+ */
19
+ /**
20
+ * The nearest candidate to `value`, when one is close enough to be a likely typo rather than a
21
+ * different word. Returns undefined when nothing is close enough to name honestly.
22
+ */
23
+ export declare function nearestMatch(value: string, candidates: Iterable<string>, maxDistance?: number): string | undefined;
24
+ //# sourceMappingURL=nearest-match.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nearest-match.d.ts","sourceRoot":"","sources":["../../../../src/generators/test-generator/utils/nearest-match.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAoBH;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,SAAI,GAC3D,MAAM,GAAG,SAAS,CAWpB"}
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ /**
3
+ * Nearest-known-spelling suggestion, shared by the selector-surface checks.
4
+ *
5
+ * Two checks need the same judgement about the same class of author mistake — SG-W004 on an entry
6
+ * FIELD nobody reads (#712) and SG-E027 on an entry `type:` VALUE nothing dispatches (#711) — so
7
+ * the rule lives in one place rather than being re-tuned independently in each. The tuning is the
8
+ * substance here, not the edit distance:
9
+ *
10
+ * - A case-only difference is returned first and always. `testId` for `testid` and
11
+ * `contentEditable` for `contenteditable` are the single likeliest way to write either
12
+ * wrongly, and both surfaces are lowercase throughout, so this is a near-certainty rather
13
+ * than a guess.
14
+ * - Otherwise a distance of 1-2 is a typo worth naming.
15
+ * - Anything further is a DIFFERENT word, and guessing at it sends the author somewhere wrong.
16
+ * `selector` is not a misspelling of `locator` — it is someone reasonably assuming a field
17
+ * that does not exist, and "did you mean locator?" would be a worse answer than silence.
18
+ * The caller supplies its own hint for that case.
19
+ */
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.nearestMatch = nearestMatch;
22
+ /** Levenshtein distance. Bounded use only — these are short identifiers. */
23
+ function distance(a, b) {
24
+ const m = a.length, n = b.length;
25
+ let prev = Array.from({ length: n + 1 }, (_, j) => j);
26
+ for (let i = 1; i <= m; i++) {
27
+ const curr = [i];
28
+ for (let j = 1; j <= n; j++) {
29
+ curr[j] = Math.min(prev[j] + 1, curr[j - 1] + 1, prev[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1));
30
+ }
31
+ prev = curr;
32
+ }
33
+ return prev[n];
34
+ }
35
+ /**
36
+ * The nearest candidate to `value`, when one is close enough to be a likely typo rather than a
37
+ * different word. Returns undefined when nothing is close enough to name honestly.
38
+ */
39
+ function nearestMatch(value, candidates, maxDistance = 2) {
40
+ const lower = value.toLowerCase();
41
+ const all = [...candidates];
42
+ for (const c of all)
43
+ if (c.toLowerCase() === lower)
44
+ return c;
45
+ let best;
46
+ let bestDist = Infinity;
47
+ for (const c of all) {
48
+ const d = distance(lower, c.toLowerCase());
49
+ if (d < bestDist) {
50
+ bestDist = d;
51
+ best = c;
52
+ }
53
+ }
54
+ return bestDist <= maxDistance ? best : undefined;
55
+ }
56
+ //# sourceMappingURL=nearest-match.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nearest-match.js","sourceRoot":"","sources":["../../../../src/generators/test-generator/utils/nearest-match.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;GAiBG;;AAwBH,oCAaC;AAnCD,4EAA4E;AAC5E,SAAS,QAAQ,CAAC,CAAS,EAAE,CAAS;IACpC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,IAAI,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IACtD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;QACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5B,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAChB,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,EACX,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EACf,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAC9C,CAAC;QACJ,CAAC;QACD,IAAI,GAAG,IAAI,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,SAAgB,YAAY,CAC1B,KAAa,EAAE,UAA4B,EAAE,WAAW,GAAG,CAAC;IAE5D,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAClC,MAAM,GAAG,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC;IAC5B,KAAK,MAAM,CAAC,IAAI,GAAG;QAAE,IAAI,CAAC,CAAC,WAAW,EAAE,KAAK,KAAK;YAAE,OAAO,CAAC,CAAC;IAC7D,IAAI,IAAwB,CAAC;IAC7B,IAAI,QAAQ,GAAG,QAAQ,CAAC;IACxB,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;QACpB,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QAC3C,IAAI,CAAC,GAAG,QAAQ,EAAE,CAAC;YAAC,QAAQ,GAAG,CAAC,CAAC;YAAC,IAAI,GAAG,CAAC,CAAC;QAAC,CAAC;IAC/C,CAAC;IACD,OAAO,QAAQ,IAAI,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AACpD,CAAC"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * The selector-entry field partition, and the SG-W004 check built on it (issue #712).
3
+ *
4
+ * The root cause behind #690, #711 and #712 is one shape: `selectors.yaml` has a DOCUMENTED
5
+ * surface wider than the compiler's IMPLEMENTED surface, and nothing compared the two. A field
6
+ * could be declared on `SelectorEntry`, assigned onto `ResolvedSelector`, and printed in the
7
+ * public reference while no consumer ever read it back — discovered only by grepping.
8
+ *
9
+ * This module states the contract as a partition, the same way #690 answered the equivalent
10
+ * question for `type:` values (STRATEGY_SELECTOR_TYPES vs NON_STRATEGY_SELECTOR_TYPES). Every
11
+ * field an author may write belongs to exactly one set, each entry naming who reads it — so the
12
+ * next unconsumed field is a failing check with a name attached, not an archaeology exercise.
13
+ *
14
+ * The check is deliberately a WARNING, not an error. An unknown key is inert (the compiler simply
15
+ * never reads it), so refusing to compile would break projects over a stray comment-turned-key
16
+ * while teaching nothing extra. `--strict` already turns the whole channel non-zero for CI.
17
+ */
18
+ import type { DiagnosticsCollector } from '../diagnostics';
19
+ /**
20
+ * Fields a consumer actually reads. The comment on each names WHO — that is the part that rots,
21
+ * so it is recorded next to the claim rather than in prose elsewhere. Adding a field here without
22
+ * a named consumer re-opens exactly the hole #712 was filed for.
23
+ */
24
+ export declare const CONSUMED_ENTRY_FIELDS: ReadonlySet<string>;
25
+ /**
26
+ * Fields that are metadata by design — written for humans or for a non-codegen consumer, with no
27
+ * template behind them. Empty today: every field the schema accepts is now read by something.
28
+ *
29
+ * It is kept (rather than folded away) as the declared home for the NEXT such field, so that
30
+ * "nothing reads this" is an explicit, reviewable choice recorded here instead of an accident
31
+ * nobody notices for a release — which is precisely how `pagination:` and `contenteditable:`
32
+ * survived as documented no-ops.
33
+ */
34
+ export declare const DECLARATIVE_ENTRY_FIELDS: ReadonlySet<string>;
35
+ /** Everything an author may legitimately write on an entry. */
36
+ export declare const KNOWN_ENTRY_FIELDS: ReadonlySet<string>;
37
+ /** Keys of a `columns.<name>` definition — a column def is not a SelectorEntry. */
38
+ export declare const COLUMN_DEF_FIELDS: ReadonlySet<string>;
39
+ export interface UnknownField {
40
+ /** Dotted path to the offending key, e.g. `orders.pagination` or `login.anchor`. */
41
+ path: string;
42
+ field: string;
43
+ /** A near-miss known field, when one is close enough to be worth naming. */
44
+ suggestion?: string;
45
+ }
46
+ /** Every key in `file` that no consumer will ever read. */
47
+ export declare function collectUnknownEntryFields(file: Record<string, unknown>): UnknownField[];
48
+ /**
49
+ * SG-W004 — report every entry field nothing reads.
50
+ *
51
+ * Runs once per selector FILE (the resolver's load is cached), not once per step, so a table named
52
+ * by twenty row steps is reported once. Silent when there is no diagnostics channel attached.
53
+ */
54
+ export declare function reportUnknownEntryFields(file: Record<string, unknown>, opts: {
55
+ feature?: string;
56
+ diagnostics?: DiagnosticsCollector;
57
+ }): void;
58
+ //# sourceMappingURL=selector-entry-fields.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selector-entry-fields.d.ts","sourceRoot":"","sources":["../../../../src/generators/test-generator/utils/selector-entry-fields.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAI3D;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,WAAW,CAAC,MAAM,CA6BpD,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB,EAAE,WAAW,CAAC,MAAM,CAAe,CAAC;AAEzE,+DAA+D;AAC/D,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAGjD,CAAC;AAEH,mFAAmF;AACnF,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAA4C,CAAC;AAE/F,MAAM,WAAW,YAAY;IAC3B,oFAAoF;IACpF,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,2DAA2D;AAC3D,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,YAAY,EAAE,CAmBvF;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,oBAAoB,CAAA;CAAE,GAC7D,IAAI,CAaN"}
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ /**
3
+ * The selector-entry field partition, and the SG-W004 check built on it (issue #712).
4
+ *
5
+ * The root cause behind #690, #711 and #712 is one shape: `selectors.yaml` has a DOCUMENTED
6
+ * surface wider than the compiler's IMPLEMENTED surface, and nothing compared the two. A field
7
+ * could be declared on `SelectorEntry`, assigned onto `ResolvedSelector`, and printed in the
8
+ * public reference while no consumer ever read it back — discovered only by grepping.
9
+ *
10
+ * This module states the contract as a partition, the same way #690 answered the equivalent
11
+ * question for `type:` values (STRATEGY_SELECTOR_TYPES vs NON_STRATEGY_SELECTOR_TYPES). Every
12
+ * field an author may write belongs to exactly one set, each entry naming who reads it — so the
13
+ * next unconsumed field is a failing check with a name attached, not an archaeology exercise.
14
+ *
15
+ * The check is deliberately a WARNING, not an error. An unknown key is inert (the compiler simply
16
+ * never reads it), so refusing to compile would break projects over a stray comment-turned-key
17
+ * while teaching nothing extra. `--strict` already turns the whole channel non-zero for CI.
18
+ */
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.COLUMN_DEF_FIELDS = exports.KNOWN_ENTRY_FIELDS = exports.DECLARATIVE_ENTRY_FIELDS = exports.CONSUMED_ENTRY_FIELDS = void 0;
21
+ exports.collectUnknownEntryFields = collectUnknownEntryFields;
22
+ exports.reportUnknownEntryFields = reportUnknownEntryFields;
23
+ const nearest_match_1 = require("./nearest-match");
24
+ const selector_entry_walk_1 = require("./selector-entry-walk");
25
+ /**
26
+ * Fields a consumer actually reads. The comment on each names WHO — that is the part that rots,
27
+ * so it is recorded next to the claim rather than in prose elsewhere. Adding a field here without
28
+ * a named consumer re-opens exactly the hole #712 was filed for.
29
+ */
30
+ exports.CONSUMED_ENTRY_FIELDS = new Set([
31
+ 'locator', // resolveFromEntry → strategy 'css'/'locator'
32
+ 'type', // the strategy switch; also ResolvedSelector.selectorType (#690)
33
+ 'value', // every strategy template
34
+ 'name', // role templates; `name: null` disables the filter
35
+ 'nth', // locator-nth partial
36
+ 'exact', // has-text-value partial / anchored-regex assertions
37
+ 'inputMethod', // driver-ui fill pattern → fill-editor-action
38
+ 'scope', // dialog/landmark scoping in the locator partial
39
+ 'match', // collapses into `exact` for getByText
40
+ 'anchor', // page assertions — the rendered-content proof (#662)
41
+ 'android', // appium adapter → androidSelector (#392)
42
+ 'ios', // appium adapter → iosSelector (#392)
43
+ 'variant', // widget recipes / native select / upload subtype
44
+ 'trigger', // upload step — the visible button over a hidden input
45
+ 'frame', // frame-enter/exit steps → page.frameLocator
46
+ 'contenteditable', // resolveFromEntry → inputMethod 'pressSequentially' (#712)
47
+ 'columns', // table column-index lookup in StepMapper
48
+ 'pagination', // driver-ui table-paginate pattern (#712)
49
+ 'rows', // table row templates, the row-shape universe (#688, SG-W016)
50
+ 'attribute', // "has attribute" assertions → toHaveAttribute
51
+ 'pattern', // regex for the attribute value
52
+ 'expanded', // expand/collapse state signal
53
+ // Two spellings of ONE signal — how a control that publishes no ARIA marks its ON state, as a
54
+ // class or as a boolean attribute (issue #730). Normalised to `checkedClass`/`checkedAttribute`
55
+ // in selector-resolver, then read by setCheckedState/expectCheckedState via the checked-opts
56
+ // partial.
57
+ 'checked', // checked state signal → setCheckedState/expectCheckedState
58
+ 'selected', // alias of `checked` for card/tab pickers
59
+ ]);
60
+ /**
61
+ * Fields that are metadata by design — written for humans or for a non-codegen consumer, with no
62
+ * template behind them. Empty today: every field the schema accepts is now read by something.
63
+ *
64
+ * It is kept (rather than folded away) as the declared home for the NEXT such field, so that
65
+ * "nothing reads this" is an explicit, reviewable choice recorded here instead of an accident
66
+ * nobody notices for a release — which is precisely how `pagination:` and `contenteditable:`
67
+ * survived as documented no-ops.
68
+ */
69
+ exports.DECLARATIVE_ENTRY_FIELDS = new Set([]);
70
+ /** Everything an author may legitimately write on an entry. */
71
+ exports.KNOWN_ENTRY_FIELDS = new Set([
72
+ ...exports.CONSUMED_ENTRY_FIELDS,
73
+ ...exports.DECLARATIVE_ENTRY_FIELDS,
74
+ ]);
75
+ /** Keys of a `columns.<name>` definition — a column def is not a SelectorEntry. */
76
+ exports.COLUMN_DEF_FIELDS = new Set(['index', 'header', 'elements']);
77
+ /** Every key in `file` that no consumer will ever read. */
78
+ function collectUnknownEntryFields(file) {
79
+ const out = [];
80
+ (0, selector_entry_walk_1.walkSelectorEntries)(file, {
81
+ entry(entry, path) {
82
+ for (const field of Object.keys(entry)) {
83
+ if (exports.KNOWN_ENTRY_FIELDS.has(field))
84
+ continue;
85
+ out.push({ path, field, suggestion: (0, nearest_match_1.nearestMatch)(field, exports.KNOWN_ENTRY_FIELDS) });
86
+ }
87
+ },
88
+ // A column DEFINITION has its own small key set — this is the one check that judges it, and
89
+ // the reason the walk offers the visit at all.
90
+ columnDef(def, path) {
91
+ for (const field of Object.keys(def)) {
92
+ if (exports.COLUMN_DEF_FIELDS.has(field))
93
+ continue;
94
+ out.push({ path, field, suggestion: (0, nearest_match_1.nearestMatch)(field, exports.COLUMN_DEF_FIELDS) });
95
+ }
96
+ },
97
+ });
98
+ return out;
99
+ }
100
+ /**
101
+ * SG-W004 — report every entry field nothing reads.
102
+ *
103
+ * Runs once per selector FILE (the resolver's load is cached), not once per step, so a table named
104
+ * by twenty row steps is reported once. Silent when there is no diagnostics channel attached.
105
+ */
106
+ function reportUnknownEntryFields(file, opts) {
107
+ const sink = opts.diagnostics;
108
+ if (!sink)
109
+ return;
110
+ for (const { path, field, suggestion } of collectUnknownEntryFields(file)) {
111
+ const hint = suggestion
112
+ ? ` Did you mean "${suggestion}"?`
113
+ : ' A locator goes in "value:" (with a "type:") or "locator:" (raw CSS).';
114
+ sink.add('SG-W004', `selectors.yaml entry "${path}" declares "${field}", which no consumer reads — `
115
+ + `writing it has no effect on the generated test and never will.${hint} `
116
+ + `See the selector reference for the fields an entry supports.`, { feature: opts.feature });
117
+ }
118
+ }
119
+ //# sourceMappingURL=selector-entry-fields.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selector-entry-fields.js","sourceRoot":"","sources":["../../../../src/generators/test-generator/utils/selector-entry-fields.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * One walk over the entries of a `selectors.yaml` file, shared by every per-entry check.
3
+ *
4
+ * SG-W004 (#712), SG-E027 (#711) and SG-W018 (#720) ask three different questions about the same
5
+ * shape — an unknown KEY, an unknown VALUE for `type:`, an out-of-contract VALUE for `nth:` — and
6
+ * each shipped its own copy of the same recursion. Three copies of "where do entries live" is how
7
+ * a check silently stops covering a nesting level: #711's gate has an explicit case for
8
+ * `columns.*.elements.*` precisely because that level was easy to miss. The recursion lives here
9
+ * once, so a new nesting level is added in one place and every check gains it at the same moment.
10
+ */
11
+ /** Sub-entries that are themselves full SelectorEntry values, so they recurse. */
12
+ export declare const NESTED_ENTRY_FIELDS: readonly ["anchor", "android", "ios"];
13
+ export declare function isEntryObject(v: unknown): v is Record<string, unknown>;
14
+ export interface WalkVisitors {
15
+ /** Every SelectorEntry in the file, with its dotted path (`save`, `greeting.ios`, …). */
16
+ entry(entry: Record<string, unknown>, path: string): void;
17
+ /**
18
+ * Each `columns.<name>` DEFINITION, which is not a SelectorEntry (it holds index/header/
19
+ * elements). Only SG-W004 has business with these; the other checks omit it.
20
+ */
21
+ columnDef?(def: Record<string, unknown>, path: string): void;
22
+ }
23
+ /** Visit every entry (and, on request, every column definition) in a parsed selector file. */
24
+ export declare function walkSelectorEntries(file: Record<string, unknown>, visit: WalkVisitors): void;
25
+ //# sourceMappingURL=selector-entry-walk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selector-entry-walk.d.ts","sourceRoot":"","sources":["../../../../src/generators/test-generator/utils/selector-entry-walk.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,kFAAkF;AAClF,eAAO,MAAM,mBAAmB,uCAAwC,CAAC;AAEzE,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEtE;AAED,MAAM,WAAW,YAAY;IAC3B,yFAAyF;IACzF,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1D;;;OAGG;IACH,SAAS,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9D;AA0BD,8FAA8F;AAC9F,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAI5F"}
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ /**
3
+ * One walk over the entries of a `selectors.yaml` file, shared by every per-entry check.
4
+ *
5
+ * SG-W004 (#712), SG-E027 (#711) and SG-W018 (#720) ask three different questions about the same
6
+ * shape — an unknown KEY, an unknown VALUE for `type:`, an out-of-contract VALUE for `nth:` — and
7
+ * each shipped its own copy of the same recursion. Three copies of "where do entries live" is how
8
+ * a check silently stops covering a nesting level: #711's gate has an explicit case for
9
+ * `columns.*.elements.*` precisely because that level was easy to miss. The recursion lives here
10
+ * once, so a new nesting level is added in one place and every check gains it at the same moment.
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.NESTED_ENTRY_FIELDS = void 0;
14
+ exports.isEntryObject = isEntryObject;
15
+ exports.walkSelectorEntries = walkSelectorEntries;
16
+ /** Sub-entries that are themselves full SelectorEntry values, so they recurse. */
17
+ exports.NESTED_ENTRY_FIELDS = ['anchor', 'android', 'ios'];
18
+ function isEntryObject(v) {
19
+ return !!v && typeof v === 'object' && !Array.isArray(v);
20
+ }
21
+ function walkEntry(entry, entryPath, visit) {
22
+ visit.entry(entry, entryPath);
23
+ for (const sub of exports.NESTED_ENTRY_FIELDS) {
24
+ const v = entry[sub];
25
+ if (isEntryObject(v))
26
+ walkEntry(v, `${entryPath}.${sub}`, visit);
27
+ }
28
+ // A column DEFINITION is not a SelectorEntry, but the entries under its `elements:` map are,
29
+ // and each carries its own `type:` / `nth:`.
30
+ const columns = entry.columns;
31
+ if (!isEntryObject(columns))
32
+ return;
33
+ for (const [colName, colDef] of Object.entries(columns)) {
34
+ if (!isEntryObject(colDef))
35
+ continue;
36
+ const colPath = `${entryPath}.columns.${colName}`;
37
+ visit.columnDef?.(colDef, colPath);
38
+ const elements = colDef.elements;
39
+ if (!isEntryObject(elements))
40
+ continue;
41
+ for (const [elName, elEntry] of Object.entries(elements)) {
42
+ if (isEntryObject(elEntry))
43
+ walkEntry(elEntry, `${colPath}.elements.${elName}`, visit);
44
+ }
45
+ }
46
+ }
47
+ /** Visit every entry (and, on request, every column definition) in a parsed selector file. */
48
+ function walkSelectorEntries(file, visit) {
49
+ for (const [label, entry] of Object.entries(file)) {
50
+ if (isEntryObject(entry))
51
+ walkEntry(entry, label, visit);
52
+ }
53
+ }
54
+ //# sourceMappingURL=selector-entry-walk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selector-entry-walk.js","sourceRoot":"","sources":["../../../../src/generators/test-generator/utils/selector-entry-walk.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;AAKH,sCAEC;AAqCD,kDAIC;AA9CD,kFAAkF;AACrE,QAAA,mBAAmB,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,CAAU,CAAC;AAEzE,SAAgB,aAAa,CAAC,CAAU;IACtC,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAC3D,CAAC;AAYD,SAAS,SAAS,CAAC,KAA8B,EAAE,SAAiB,EAAE,KAAmB;IACvF,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IAE9B,KAAK,MAAM,GAAG,IAAI,2BAAmB,EAAE,CAAC;QACtC,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;QACrB,IAAI,aAAa,CAAC,CAAC,CAAC;YAAE,SAAS,CAAC,CAAC,EAAE,GAAG,SAAS,IAAI,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;IACnE,CAAC;IAED,6FAA6F;IAC7F,6CAA6C;IAC7C,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC9B,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC;QAAE,OAAO;IACpC,KAAK,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACxD,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;YAAE,SAAS;QACrC,MAAM,OAAO,GAAG,GAAG,SAAS,YAAY,OAAO,EAAE,CAAC;QAClD,KAAK,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACnC,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;QACjC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC;YAAE,SAAS;QACvC,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzD,IAAI,aAAa,CAAC,OAAO,CAAC;gBAAE,SAAS,CAAC,OAAO,EAAE,GAAG,OAAO,aAAa,MAAM,EAAE,EAAE,KAAK,CAAC,CAAC;QACzF,CAAC;IACH,CAAC;AACH,CAAC;AAED,8FAA8F;AAC9F,SAAgB,mBAAmB,CAAC,IAA6B,EAAE,KAAmB;IACpF,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAClD,IAAI,aAAa,CAAC,KAAK,CAAC;YAAE,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC"}