@sun-asterisk/sungen 1.0.24 → 2.0.1

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 (378) hide show
  1. package/README.md +198 -74
  2. package/dist/cli/commands/add.d.ts.map +1 -1
  3. package/dist/cli/commands/add.js +5 -3
  4. package/dist/cli/commands/add.js.map +1 -1
  5. package/dist/cli/commands/generate.d.ts.map +1 -1
  6. package/dist/cli/commands/generate.js +110 -35
  7. package/dist/cli/commands/generate.js.map +1 -1
  8. package/dist/cli/index.d.ts +2 -2
  9. package/dist/cli/index.js +5 -16
  10. package/dist/cli/index.js.map +1 -1
  11. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/frame-enter-action.hbs +1 -0
  12. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/frame-exit-action.hbs +1 -0
  13. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/keyboard-global-action.hbs +1 -0
  14. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/scroll-action.hbs +1 -0
  15. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row.hbs +2 -0
  16. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-filter.hbs +3 -0
  17. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-index.hbs +3 -0
  18. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-column-exists.hbs +2 -0
  19. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-empty.hbs +2 -0
  20. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-count.hbs +2 -0
  21. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-exists.hbs +2 -0
  22. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-not-exists.hbs +2 -0
  23. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-value-assertion.hbs +1 -1
  24. package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator-base.hbs +11 -2
  25. package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator.hbs +11 -2
  26. package/dist/generators/test-generator/code-generator.d.ts +0 -1
  27. package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
  28. package/dist/generators/test-generator/code-generator.js +10 -47
  29. package/dist/generators/test-generator/code-generator.js.map +1 -1
  30. package/dist/generators/test-generator/patterns/assertion-patterns.d.ts.map +1 -1
  31. package/dist/generators/test-generator/patterns/assertion-patterns.js +2 -0
  32. package/dist/generators/test-generator/patterns/assertion-patterns.js.map +1 -1
  33. package/dist/generators/test-generator/patterns/index.d.ts +4 -1
  34. package/dist/generators/test-generator/patterns/index.d.ts.map +1 -1
  35. package/dist/generators/test-generator/patterns/index.js +17 -5
  36. package/dist/generators/test-generator/patterns/index.js.map +1 -1
  37. package/dist/generators/test-generator/patterns/interaction-patterns.js +1 -1
  38. package/dist/generators/test-generator/patterns/interaction-patterns.js.map +1 -1
  39. package/dist/generators/test-generator/patterns/keyboard-patterns.d.ts +7 -0
  40. package/dist/generators/test-generator/patterns/keyboard-patterns.d.ts.map +1 -0
  41. package/dist/generators/test-generator/patterns/keyboard-patterns.js +47 -0
  42. package/dist/generators/test-generator/patterns/keyboard-patterns.js.map +1 -0
  43. package/dist/generators/test-generator/patterns/scope-patterns.d.ts +7 -0
  44. package/dist/generators/test-generator/patterns/scope-patterns.d.ts.map +1 -0
  45. package/dist/generators/test-generator/patterns/scope-patterns.js +36 -0
  46. package/dist/generators/test-generator/patterns/scope-patterns.js.map +1 -0
  47. package/dist/generators/test-generator/patterns/scroll-patterns.d.ts +7 -0
  48. package/dist/generators/test-generator/patterns/scroll-patterns.d.ts.map +1 -0
  49. package/dist/generators/test-generator/patterns/scroll-patterns.js +25 -0
  50. package/dist/generators/test-generator/patterns/scroll-patterns.js.map +1 -0
  51. package/dist/generators/test-generator/patterns/table-patterns.d.ts +7 -0
  52. package/dist/generators/test-generator/patterns/table-patterns.d.ts.map +1 -0
  53. package/dist/generators/test-generator/patterns/table-patterns.js +192 -0
  54. package/dist/generators/test-generator/patterns/table-patterns.js.map +1 -0
  55. package/dist/generators/test-generator/step-mapper.d.ts +5 -3
  56. package/dist/generators/test-generator/step-mapper.d.ts.map +1 -1
  57. package/dist/generators/test-generator/step-mapper.js +38 -27
  58. package/dist/generators/test-generator/step-mapper.js.map +1 -1
  59. package/dist/generators/test-generator/template-engine.d.ts.map +1 -1
  60. package/dist/generators/test-generator/template-engine.js +4 -1
  61. package/dist/generators/test-generator/template-engine.js.map +1 -1
  62. package/dist/generators/test-generator/types.d.ts +7 -24
  63. package/dist/generators/test-generator/types.d.ts.map +1 -1
  64. package/dist/generators/test-generator/types.js +2 -101
  65. package/dist/generators/test-generator/types.js.map +1 -1
  66. package/dist/generators/test-generator/utils/selector-resolver.d.ts +14 -0
  67. package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
  68. package/dist/generators/test-generator/utils/selector-resolver.js +37 -11
  69. package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -1
  70. package/dist/orchestrator/project-initializer.d.ts +12 -0
  71. package/dist/orchestrator/project-initializer.d.ts.map +1 -1
  72. package/dist/orchestrator/project-initializer.js +72 -160
  73. package/dist/orchestrator/project-initializer.js.map +1 -1
  74. package/dist/orchestrator/screen-manager.d.ts +1 -32
  75. package/dist/orchestrator/screen-manager.d.ts.map +1 -1
  76. package/dist/orchestrator/screen-manager.js +55 -216
  77. package/dist/orchestrator/screen-manager.js.map +1 -1
  78. package/dist/orchestrator/templates/ai-rules.md +189 -0
  79. package/dist/orchestrator/templates/gitignore +16 -0
  80. package/dist/orchestrator/templates/playwright.config.d.ts +10 -0
  81. package/dist/orchestrator/templates/playwright.config.d.ts.map +1 -0
  82. package/dist/orchestrator/templates/playwright.config.js +77 -0
  83. package/dist/orchestrator/templates/playwright.config.js.map +1 -0
  84. package/dist/orchestrator/templates/playwright.config.ts +80 -0
  85. package/dist/orchestrator/templates/readme.md +197 -0
  86. package/dist/utils/selector-types.d.ts +1 -1
  87. package/dist/utils/selector-types.d.ts.map +1 -1
  88. package/dist/utils/selector-types.js +3 -0
  89. package/dist/utils/selector-types.js.map +1 -1
  90. package/docs/gherkin standards/gherkin-core-standard.md +377 -0
  91. package/docs/gherkin standards/gherkin-core-standard.vi.md +303 -0
  92. package/docs/gherkin-dictionary.md +1071 -0
  93. package/docs/makeauth.md +225 -0
  94. package/package.json +4 -3
  95. package/src/cli/commands/add.ts +5 -3
  96. package/src/cli/commands/generate.ts +90 -38
  97. package/src/cli/index.ts +5 -16
  98. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/frame-enter-action.hbs +1 -0
  99. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/frame-exit-action.hbs +1 -0
  100. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/keyboard-global-action.hbs +1 -0
  101. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/scroll-action.hbs +1 -0
  102. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row.hbs +2 -0
  103. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-filter.hbs +3 -0
  104. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-index.hbs +3 -0
  105. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-column-exists.hbs +2 -0
  106. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-empty.hbs +2 -0
  107. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-count.hbs +2 -0
  108. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-exists.hbs +2 -0
  109. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-not-exists.hbs +2 -0
  110. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-value-assertion.hbs +1 -1
  111. package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator-base.hbs +11 -2
  112. package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator.hbs +11 -2
  113. package/src/generators/test-generator/code-generator.ts +11 -59
  114. package/src/generators/test-generator/patterns/assertion-patterns.ts +2 -0
  115. package/src/generators/test-generator/patterns/index.ts +12 -3
  116. package/src/generators/test-generator/patterns/interaction-patterns.ts +1 -1
  117. package/src/generators/test-generator/patterns/keyboard-patterns.ts +51 -0
  118. package/src/generators/test-generator/patterns/scope-patterns.ts +40 -0
  119. package/src/generators/test-generator/patterns/scroll-patterns.ts +27 -0
  120. package/src/generators/test-generator/patterns/table-patterns.ts +232 -0
  121. package/src/generators/test-generator/step-mapper.ts +42 -27
  122. package/src/generators/test-generator/template-engine.ts +3 -1
  123. package/src/generators/test-generator/types.ts +7 -112
  124. package/src/generators/test-generator/utils/selector-resolver.ts +70 -25
  125. package/src/orchestrator/project-initializer.ts +75 -160
  126. package/src/orchestrator/screen-manager.ts +61 -233
  127. package/src/orchestrator/templates/ai-rules.md +189 -0
  128. package/src/orchestrator/templates/gitignore +16 -0
  129. package/src/orchestrator/templates/playwright.config.ts +80 -0
  130. package/src/orchestrator/templates/readme.md +197 -0
  131. package/src/utils/selector-types.ts +3 -0
  132. package/dist/cli/commands/cache-clear.d.ts +0 -3
  133. package/dist/cli/commands/cache-clear.d.ts.map +0 -1
  134. package/dist/cli/commands/cache-clear.js +0 -24
  135. package/dist/cli/commands/cache-clear.js.map +0 -1
  136. package/dist/cli/commands/full.d.ts +0 -3
  137. package/dist/cli/commands/full.d.ts.map +0 -1
  138. package/dist/cli/commands/full.js +0 -37
  139. package/dist/cli/commands/full.js.map +0 -1
  140. package/dist/cli/commands/live-scan.d.ts +0 -3
  141. package/dist/cli/commands/live-scan.d.ts.map +0 -1
  142. package/dist/cli/commands/live-scan.js +0 -78
  143. package/dist/cli/commands/live-scan.js.map +0 -1
  144. package/dist/cli/commands/map.d.ts +0 -3
  145. package/dist/cli/commands/map.d.ts.map +0 -1
  146. package/dist/cli/commands/map.js +0 -93
  147. package/dist/cli/commands/map.js.map +0 -1
  148. package/dist/cli/commands/validate.d.ts +0 -3
  149. package/dist/cli/commands/validate.d.ts.map +0 -1
  150. package/dist/cli/commands/validate.js +0 -43
  151. package/dist/cli/commands/validate.js.map +0 -1
  152. package/dist/cli/utils.d.ts +0 -6
  153. package/dist/cli/utils.d.ts.map +0 -1
  154. package/dist/cli/utils.js +0 -101
  155. package/dist/cli/utils.js.map +0 -1
  156. package/dist/config/config-loader.d.ts +0 -51
  157. package/dist/config/config-loader.d.ts.map +0 -1
  158. package/dist/config/config-loader.js +0 -216
  159. package/dist/config/config-loader.js.map +0 -1
  160. package/dist/config/config-schema.d.ts +0 -121
  161. package/dist/config/config-schema.d.ts.map +0 -1
  162. package/dist/config/config-schema.js +0 -7
  163. package/dist/config/config-schema.js.map +0 -1
  164. package/dist/core/live-scanner/config-reader.d.ts +0 -10
  165. package/dist/core/live-scanner/config-reader.d.ts.map +0 -1
  166. package/dist/core/live-scanner/config-reader.js +0 -87
  167. package/dist/core/live-scanner/config-reader.js.map +0 -1
  168. package/dist/core/live-scanner/element-finder.d.ts +0 -20
  169. package/dist/core/live-scanner/element-finder.d.ts.map +0 -1
  170. package/dist/core/live-scanner/element-finder.js +0 -481
  171. package/dist/core/live-scanner/element-finder.js.map +0 -1
  172. package/dist/core/live-scanner/index.d.ts +0 -8
  173. package/dist/core/live-scanner/index.d.ts.map +0 -1
  174. package/dist/core/live-scanner/index.js +0 -33
  175. package/dist/core/live-scanner/index.js.map +0 -1
  176. package/dist/core/live-scanner/matrix-reader.d.ts +0 -17
  177. package/dist/core/live-scanner/matrix-reader.d.ts.map +0 -1
  178. package/dist/core/live-scanner/matrix-reader.js +0 -60
  179. package/dist/core/live-scanner/matrix-reader.js.map +0 -1
  180. package/dist/core/live-scanner/matrix-writer.d.ts +0 -7
  181. package/dist/core/live-scanner/matrix-writer.d.ts.map +0 -1
  182. package/dist/core/live-scanner/matrix-writer.js +0 -103
  183. package/dist/core/live-scanner/matrix-writer.js.map +0 -1
  184. package/dist/core/live-scanner/role-fallback.d.ts +0 -15
  185. package/dist/core/live-scanner/role-fallback.d.ts.map +0 -1
  186. package/dist/core/live-scanner/role-fallback.js +0 -46
  187. package/dist/core/live-scanner/role-fallback.js.map +0 -1
  188. package/dist/core/live-scanner/scanner.d.ts +0 -22
  189. package/dist/core/live-scanner/scanner.d.ts.map +0 -1
  190. package/dist/core/live-scanner/scanner.js +0 -303
  191. package/dist/core/live-scanner/scanner.js.map +0 -1
  192. package/dist/core/live-scanner/step-replayer.d.ts +0 -26
  193. package/dist/core/live-scanner/step-replayer.d.ts.map +0 -1
  194. package/dist/core/live-scanner/step-replayer.js +0 -473
  195. package/dist/core/live-scanner/step-replayer.js.map +0 -1
  196. package/dist/core/live-scanner/types.d.ts +0 -52
  197. package/dist/core/live-scanner/types.d.ts.map +0 -1
  198. package/dist/core/live-scanner/types.js +0 -14
  199. package/dist/core/live-scanner/types.js.map +0 -1
  200. package/dist/core/selector-base/annotation-handler.d.ts +0 -45
  201. package/dist/core/selector-base/annotation-handler.d.ts.map +0 -1
  202. package/dist/core/selector-base/annotation-handler.js +0 -102
  203. package/dist/core/selector-base/annotation-handler.js.map +0 -1
  204. package/dist/core/selector-base/base-generator.d.ts +0 -49
  205. package/dist/core/selector-base/base-generator.d.ts.map +0 -1
  206. package/dist/core/selector-base/base-generator.js +0 -214
  207. package/dist/core/selector-base/base-generator.js.map +0 -1
  208. package/dist/core/selector-base/gherkin-parser.d.ts +0 -24
  209. package/dist/core/selector-base/gherkin-parser.d.ts.map +0 -1
  210. package/dist/core/selector-base/gherkin-parser.js +0 -42
  211. package/dist/core/selector-base/gherkin-parser.js.map +0 -1
  212. package/dist/core/selector-mapper/priority-mapper.d.ts +0 -74
  213. package/dist/core/selector-mapper/priority-mapper.d.ts.map +0 -1
  214. package/dist/core/selector-mapper/priority-mapper.js +0 -477
  215. package/dist/core/selector-mapper/priority-mapper.js.map +0 -1
  216. package/dist/core/ui-scanner/heuristics/base-heuristic.d.ts +0 -91
  217. package/dist/core/ui-scanner/heuristics/base-heuristic.d.ts.map +0 -1
  218. package/dist/core/ui-scanner/heuristics/base-heuristic.js +0 -175
  219. package/dist/core/ui-scanner/heuristics/base-heuristic.js.map +0 -1
  220. package/dist/core/ui-scanner/react-scanner.d.ts +0 -32
  221. package/dist/core/ui-scanner/react-scanner.d.ts.map +0 -1
  222. package/dist/core/ui-scanner/react-scanner.js +0 -163
  223. package/dist/core/ui-scanner/react-scanner.js.map +0 -1
  224. package/dist/core/ui-scanner/scanner-interface.d.ts +0 -94
  225. package/dist/core/ui-scanner/scanner-interface.d.ts.map +0 -1
  226. package/dist/core/ui-scanner/scanner-interface.js +0 -33
  227. package/dist/core/ui-scanner/scanner-interface.js.map +0 -1
  228. package/dist/core/ui-scanner/strict-scanner.d.ts +0 -81
  229. package/dist/core/ui-scanner/strict-scanner.d.ts.map +0 -1
  230. package/dist/core/ui-scanner/strict-scanner.js +0 -511
  231. package/dist/core/ui-scanner/strict-scanner.js.map +0 -1
  232. package/dist/core/validator/data-validator.d.ts +0 -38
  233. package/dist/core/validator/data-validator.d.ts.map +0 -1
  234. package/dist/core/validator/data-validator.js +0 -212
  235. package/dist/core/validator/data-validator.js.map +0 -1
  236. package/dist/core/validator/feature-validator.d.ts +0 -27
  237. package/dist/core/validator/feature-validator.d.ts.map +0 -1
  238. package/dist/core/validator/feature-validator.js +0 -182
  239. package/dist/core/validator/feature-validator.js.map +0 -1
  240. package/dist/core/validator/index.d.ts +0 -46
  241. package/dist/core/validator/index.d.ts.map +0 -1
  242. package/dist/core/validator/index.js +0 -17
  243. package/dist/core/validator/index.js.map +0 -1
  244. package/dist/core/validator/screen-validator.d.ts +0 -35
  245. package/dist/core/validator/screen-validator.d.ts.map +0 -1
  246. package/dist/core/validator/screen-validator.js +0 -195
  247. package/dist/core/validator/screen-validator.js.map +0 -1
  248. package/dist/core/validator/selector-validator.d.ts +0 -36
  249. package/dist/core/validator/selector-validator.d.ts.map +0 -1
  250. package/dist/core/validator/selector-validator.js +0 -210
  251. package/dist/core/validator/selector-validator.js.map +0 -1
  252. package/dist/external/ai-provider.d.ts +0 -60
  253. package/dist/external/ai-provider.d.ts.map +0 -1
  254. package/dist/external/ai-provider.js +0 -30
  255. package/dist/external/ai-provider.js.map +0 -1
  256. package/dist/external/anthropic-provider.d.ts +0 -29
  257. package/dist/external/anthropic-provider.d.ts.map +0 -1
  258. package/dist/external/anthropic-provider.js +0 -85
  259. package/dist/external/anthropic-provider.js.map +0 -1
  260. package/dist/generators/cache/cache-manager.d.ts +0 -66
  261. package/dist/generators/cache/cache-manager.d.ts.map +0 -1
  262. package/dist/generators/cache/cache-manager.js +0 -286
  263. package/dist/generators/cache/cache-manager.js.map +0 -1
  264. package/dist/generators/dsl-writer/index.d.ts +0 -33
  265. package/dist/generators/dsl-writer/index.d.ts.map +0 -1
  266. package/dist/generators/dsl-writer/index.js +0 -226
  267. package/dist/generators/dsl-writer/index.js.map +0 -1
  268. package/dist/generators/scaffold-generator/index.d.ts +0 -162
  269. package/dist/generators/scaffold-generator/index.d.ts.map +0 -1
  270. package/dist/generators/scaffold-generator/index.js +0 -877
  271. package/dist/generators/scaffold-generator/index.js.map +0 -1
  272. package/dist/generators/selector-mapper/ai-mapper.d.ts +0 -56
  273. package/dist/generators/selector-mapper/ai-mapper.d.ts.map +0 -1
  274. package/dist/generators/selector-mapper/ai-mapper.js +0 -457
  275. package/dist/generators/selector-mapper/ai-mapper.js.map +0 -1
  276. package/dist/generators/selector-mapper/hybrid-mapper.d.ts +0 -67
  277. package/dist/generators/selector-mapper/hybrid-mapper.d.ts.map +0 -1
  278. package/dist/generators/selector-mapper/hybrid-mapper.js +0 -349
  279. package/dist/generators/selector-mapper/hybrid-mapper.js.map +0 -1
  280. package/dist/generators/selector-mapper/index.d.ts +0 -8
  281. package/dist/generators/selector-mapper/index.d.ts.map +0 -1
  282. package/dist/generators/selector-mapper/index.js +0 -12
  283. package/dist/generators/selector-mapper/index.js.map +0 -1
  284. package/dist/generators/selector-mapper/intelligent-mapper.d.ts +0 -125
  285. package/dist/generators/selector-mapper/intelligent-mapper.d.ts.map +0 -1
  286. package/dist/generators/selector-mapper/intelligent-mapper.js +0 -391
  287. package/dist/generators/selector-mapper/intelligent-mapper.js.map +0 -1
  288. package/dist/generators/test-generator/ai-step-mapper.d.ts +0 -27
  289. package/dist/generators/test-generator/ai-step-mapper.d.ts.map +0 -1
  290. package/dist/generators/test-generator/ai-step-mapper.js +0 -204
  291. package/dist/generators/test-generator/ai-step-mapper.js.map +0 -1
  292. package/dist/generators/test-generator/auth-setup-generator.d.ts +0 -18
  293. package/dist/generators/test-generator/auth-setup-generator.d.ts.map +0 -1
  294. package/dist/generators/test-generator/auth-setup-generator.js +0 -82
  295. package/dist/generators/test-generator/auth-setup-generator.js.map +0 -1
  296. package/dist/generators/test-generator/patterns/legacy-patterns.d.ts +0 -7
  297. package/dist/generators/test-generator/patterns/legacy-patterns.d.ts.map +0 -1
  298. package/dist/generators/test-generator/patterns/legacy-patterns.js +0 -98
  299. package/dist/generators/test-generator/patterns/legacy-patterns.js.map +0 -1
  300. package/dist/generators/test-generator/templates/auth-setup.ts.hbs +0 -36
  301. package/dist/generators/ui-model-builder/deep-scanner.d.ts +0 -121
  302. package/dist/generators/ui-model-builder/deep-scanner.d.ts.map +0 -1
  303. package/dist/generators/ui-model-builder/deep-scanner.js +0 -1113
  304. package/dist/generators/ui-model-builder/deep-scanner.js.map +0 -1
  305. package/dist/generators/ui-model-builder/enhanced-deep-scanner.d.ts +0 -110
  306. package/dist/generators/ui-model-builder/enhanced-deep-scanner.d.ts.map +0 -1
  307. package/dist/generators/ui-model-builder/enhanced-deep-scanner.js +0 -608
  308. package/dist/generators/ui-model-builder/enhanced-deep-scanner.js.map +0 -1
  309. package/dist/generators/ui-model-builder/react-scanner.d.ts +0 -107
  310. package/dist/generators/ui-model-builder/react-scanner.d.ts.map +0 -1
  311. package/dist/generators/ui-model-builder/react-scanner.js +0 -797
  312. package/dist/generators/ui-model-builder/react-scanner.js.map +0 -1
  313. package/dist/orchestrator/cache-manager.d.ts +0 -15
  314. package/dist/orchestrator/cache-manager.d.ts.map +0 -1
  315. package/dist/orchestrator/cache-manager.js +0 -62
  316. package/dist/orchestrator/cache-manager.js.map +0 -1
  317. package/dist/orchestrator/pipeline.d.ts +0 -56
  318. package/dist/orchestrator/pipeline.d.ts.map +0 -1
  319. package/dist/orchestrator/pipeline.js +0 -298
  320. package/dist/orchestrator/pipeline.js.map +0 -1
  321. package/dist/orchestrator/reporter.d.ts +0 -15
  322. package/dist/orchestrator/reporter.d.ts.map +0 -1
  323. package/dist/orchestrator/reporter.js +0 -30
  324. package/dist/orchestrator/reporter.js.map +0 -1
  325. package/src/cli/commands/cache-clear.ts +0 -22
  326. package/src/cli/commands/full.ts +0 -35
  327. package/src/cli/commands/live-scan.ts +0 -82
  328. package/src/cli/commands/map.ts +0 -97
  329. package/src/cli/commands/validate.ts +0 -43
  330. package/src/cli/utils.ts +0 -106
  331. package/src/config/ai-providers.yaml +0 -56
  332. package/src/config/config-loader.ts +0 -248
  333. package/src/config/config-schema.ts +0 -148
  334. package/src/config/default.config.yaml +0 -107
  335. package/src/config/framework.config.yaml +0 -52
  336. package/src/config/routes.yaml +0 -31
  337. package/src/core/live-scanner/config-reader.ts +0 -57
  338. package/src/core/live-scanner/element-finder.ts +0 -534
  339. package/src/core/live-scanner/index.ts +0 -7
  340. package/src/core/live-scanner/matrix-reader.ts +0 -65
  341. package/src/core/live-scanner/matrix-writer.ts +0 -77
  342. package/src/core/live-scanner/role-fallback.ts +0 -44
  343. package/src/core/live-scanner/scanner.ts +0 -321
  344. package/src/core/live-scanner/step-replayer.ts +0 -503
  345. package/src/core/live-scanner/types.ts +0 -58
  346. package/src/core/selector-base/annotation-handler.ts +0 -127
  347. package/src/core/selector-base/base-generator.ts +0 -234
  348. package/src/core/selector-base/gherkin-parser.ts +0 -57
  349. package/src/core/selector-mapper/priority-mapper.ts +0 -607
  350. package/src/core/ui-scanner/heuristics/base-heuristic.ts +0 -216
  351. package/src/core/ui-scanner/react-scanner.ts +0 -156
  352. package/src/core/ui-scanner/scanner-interface.ts +0 -133
  353. package/src/core/ui-scanner/strict-scanner.ts +0 -629
  354. package/src/core/validator/data-validator.ts +0 -202
  355. package/src/core/validator/feature-validator.ts +0 -176
  356. package/src/core/validator/index.ts +0 -57
  357. package/src/core/validator/screen-validator.ts +0 -209
  358. package/src/core/validator/selector-validator.ts +0 -209
  359. package/src/external/ai-provider.ts +0 -90
  360. package/src/external/anthropic-provider.ts +0 -114
  361. package/src/generators/README.md +0 -410
  362. package/src/generators/cache/cache-manager.ts +0 -322
  363. package/src/generators/dsl-writer/index.ts +0 -253
  364. package/src/generators/scaffold-generator/index.ts +0 -1029
  365. package/src/generators/selector-mapper/ai-mapper.ts +0 -528
  366. package/src/generators/selector-mapper/hybrid-mapper.ts +0 -427
  367. package/src/generators/selector-mapper/index.ts +0 -10
  368. package/src/generators/selector-mapper/intelligent-mapper.ts +0 -530
  369. package/src/generators/test-generator/ai-step-mapper.ts +0 -224
  370. package/src/generators/test-generator/auth-setup-generator.ts +0 -59
  371. package/src/generators/test-generator/patterns/legacy-patterns.ts +0 -104
  372. package/src/generators/test-generator/templates/auth-setup.ts.hbs +0 -36
  373. package/src/generators/ui-model-builder/deep-scanner.ts +0 -1244
  374. package/src/generators/ui-model-builder/enhanced-deep-scanner.ts +0 -731
  375. package/src/generators/ui-model-builder/react-scanner.ts +0 -959
  376. package/src/orchestrator/cache-manager.ts +0 -32
  377. package/src/orchestrator/pipeline.ts +0 -354
  378. package/src/orchestrator/reporter.ts +0 -36
@@ -1,534 +0,0 @@
1
- /**
2
- * Element Finder
3
- *
4
- * Searches for elements using Playwright's own locator strategies in priority order:
5
- * ① getByTestId — data-testid attribute
6
- * ② getByRole — ARIA role + accessible name (exact match, then fallback roles)
7
- * ③ getByLabel — associated <label> text
8
- * ④ getByPlaceholder — placeholder attribute
9
- * ⑤ getByText — visible text content
10
- *
11
- * The result records WHICH Playwright strategy found the element,
12
- * so `map` can generate the correct locator code.
13
- */
14
-
15
- import type { Page, Locator } from 'playwright';
16
- import { getRoleFallbacks, isTextOnlyType } from './role-fallback';
17
- import { LiveElement, MatchMethod, SelectorType, ElementContext } from './types';
18
-
19
- interface FindResult {
20
- locator: Locator;
21
- selectorType: SelectorType;
22
- selectorValue: string;
23
- role: string;
24
- matchMethod: MatchMethod;
25
- warning: string | null;
26
- }
27
-
28
- /**
29
- * Find an element on the page using cascading Playwright locator strategies.
30
- */
31
- export async function findElement(
32
- page: Page,
33
- gherkinRef: string,
34
- gherkinType: string,
35
- nth: number = 0,
36
- context: ElementContext = 'page'
37
- ): Promise<LiveElement> {
38
- const namePattern = new RegExp(escapeRegex(gherkinRef), 'i');
39
-
40
- const result = await cascadingSearch(page, gherkinRef, gherkinType, namePattern, nth, context);
41
-
42
- if (!result) {
43
- return buildUnresolvedElement(gherkinRef, gherkinType);
44
- }
45
-
46
- const attrs = await extractElementAttributes(result.locator);
47
-
48
- // Use Playwright's computed accessible name (includes alt text, aria-label, etc.)
49
- // This matches what getByRole/getByText actually see, unlike textContent
50
- let playwrightName = '';
51
- try {
52
- playwrightName = await result.locator.evaluate((el) => {
53
- // computedRole/computedLabel not available in all browsers, fallback to aria
54
- const raw = (el as any).computedName
55
- || el.getAttribute('aria-label')
56
- || el.textContent?.trim()?.substring(0, 100)
57
- || '';
58
- return raw.replace(/[\n\r\t]/g, ' ').replace(/\s+/g, ' ').trim();
59
- });
60
- // Better approach: use Playwright's accessibility snapshot
61
- const ariaSnapshot = await result.locator.ariaSnapshot();
62
- // Parse accessible name from snapshot (format: "- role \"name\"" or "- role \"name\": ...")
63
- // Regex handles escaped quotes (\") inside the name string
64
- const nameMatch = ariaSnapshot?.match(/"((?:[^"\\]|\\.)*)"/);
65
- if (nameMatch) {
66
- playwrightName = unescapeAriaSnapshot(nameMatch[1]);
67
- }
68
- } catch {
69
- playwrightName = attrs.accessibleName || gherkinRef;
70
- }
71
-
72
- const actualName = playwrightName || attrs.accessibleName || gherkinRef;
73
- const isExactMatch = actualName.toLowerCase().trim() === gherkinRef.toLowerCase().trim();
74
-
75
- return {
76
- gherkinRef,
77
- gherkinType,
78
- selectorType: result.selectorType,
79
- selectorValue: result.selectorValue,
80
- role: result.role,
81
- name: actualName,
82
- testid: attrs.testid,
83
- tag: attrs.tag,
84
- contenteditable: attrs.contenteditable,
85
- placeholder: attrs.placeholder,
86
- label: attrs.label,
87
- context: 'page',
88
- matchMethod: result.matchMethod,
89
- exact: isExactMatch,
90
- warning: result.warning,
91
- };
92
- }
93
-
94
- async function cascadingSearch(
95
- page: Page,
96
- gherkinRef: string,
97
- gherkinType: string,
98
- namePattern: RegExp,
99
- nth: number,
100
- context: ElementContext = 'page'
101
- ): Promise<FindResult | null> {
102
- // ① getByTestId
103
- const testidResult = await tryTestId(page, gherkinRef, nth);
104
- if (testidResult) return testidResult;
105
-
106
- // For text-only types (text, message, error), skip role and go to text
107
- if (!isTextOnlyType(gherkinType)) {
108
- // ② getByRole — exact role match
109
- const roles = getRoleFallbacks(gherkinType);
110
- if (roles.length > 0) {
111
- const exactResult = await tryRole(page, roles[0], gherkinRef, namePattern, nth);
112
- if (exactResult) {
113
- return {
114
- ...exactResult,
115
- matchMethod: 'exact_role',
116
- warning: null,
117
- };
118
- }
119
-
120
- // ③ getByRole — fallback roles
121
- for (let i = 1; i < roles.length; i++) {
122
- const fallbackResult = await tryRole(page, roles[i], gherkinRef, namePattern, nth);
123
- if (fallbackResult) {
124
- return {
125
- ...fallbackResult,
126
- matchMethod: 'role_fallback',
127
- warning: `Gherkin says '${gherkinType}' but found role '${roles[i]}'`,
128
- };
129
- }
130
- }
131
- }
132
-
133
- // ④ getByLabel — for form elements
134
- const labelResult = await tryLabel(page, gherkinRef, namePattern, nth);
135
- if (labelResult) return labelResult;
136
-
137
- // ⑤ getByPlaceholder — for input fields
138
- const placeholderResult = await tryPlaceholder(page, gherkinRef, namePattern, nth);
139
- if (placeholderResult) return placeholderResult;
140
-
141
- // ⑤.5 contenteditable — for rich text editors (textarea/textbox/field types)
142
- // When role match fails (editor has role="textbox" but no accessible name),
143
- // try to find a [contenteditable="true"] element scoped to the current context
144
- if (isEditableType(gherkinType)) {
145
- const ceResult = await tryContentEditable(page, nth, context);
146
- if (ceResult) return ceResult;
147
- }
148
- }
149
-
150
- // ⑥ getByText — final fallback
151
- const textResult = await tryText(page, gherkinRef, namePattern, nth);
152
- if (textResult) return textResult;
153
-
154
- return null;
155
- }
156
-
157
- // ① getByTestId
158
- async function tryTestId(page: Page, ref: string, nth: number): Promise<FindResult | null> {
159
- const normalized = ref.toLowerCase().replace(/[\s_-]+/g, '-');
160
- const patterns = [normalized, ref.toLowerCase().replace(/\s+/g, '')];
161
-
162
- for (const pattern of patterns) {
163
- try {
164
- const locator = page.locator(`[data-testid*="${pattern}" i]`);
165
- const count = await locator.count();
166
- if (count > 0) {
167
- const target = nth > 0 ? locator.nth(nth) : locator.first();
168
- if (await target.isVisible({ timeout: 3000 })) {
169
- const testid = await target.getAttribute('data-testid');
170
- return {
171
- locator: target,
172
- selectorType: 'testid',
173
- selectorValue: testid || pattern,
174
- role: '',
175
- matchMethod: 'testid',
176
- warning: null,
177
- };
178
- }
179
- }
180
- } catch {
181
- // Continue
182
- }
183
- }
184
- return null;
185
- }
186
-
187
- // ② ③ getByRole — regex first, exact disambiguation when ambiguous
188
- async function tryRole(
189
- page: Page,
190
- role: string,
191
- gherkinRef: string,
192
- namePattern: RegExp,
193
- nth: number
194
- ): Promise<FindResult | null> {
195
- try {
196
- const locator = page.getByRole(role as any, { name: namePattern });
197
- const count = await locator.count();
198
- if (count === 0) return null;
199
-
200
- if (count === 1) {
201
- const target = nth > 0 ? locator.nth(nth) : locator.first();
202
- if (await target.isVisible({ timeout: 3000 })) {
203
- return {
204
- locator: target,
205
- selectorType: 'role',
206
- selectorValue: role,
207
- role: role,
208
- matchMethod: 'exact_role',
209
- warning: null,
210
- };
211
- }
212
- } else {
213
- // Multiple matches — try exact to disambiguate
214
- try {
215
- const exactLocator = page.getByRole(role as any, { name: gherkinRef, exact: true });
216
- const exactCount = await exactLocator.count();
217
- if (exactCount > 0) {
218
- const target = nth > 0 ? exactLocator.nth(nth) : exactLocator.first();
219
- if (await target.isVisible({ timeout: 3000 })) {
220
- return {
221
- locator: target,
222
- selectorType: 'role',
223
- selectorValue: role,
224
- role: role,
225
- matchMethod: 'exact_role',
226
- warning: null,
227
- };
228
- }
229
- }
230
- } catch {
231
- // Exact disambiguation failed
232
- }
233
-
234
- // Fall back to first regex match
235
- const target = nth > 0 ? locator.nth(nth) : locator.first();
236
- if (await target.isVisible({ timeout: 3000 })) {
237
- return {
238
- locator: target,
239
- selectorType: 'role',
240
- selectorValue: role,
241
- role: role,
242
- matchMethod: 'exact_role',
243
- warning: null,
244
- };
245
- }
246
- }
247
- } catch {
248
- // Role not found
249
- }
250
- return null;
251
- }
252
-
253
- // ④ getByLabel — regex first, exact disambiguation when ambiguous
254
- async function tryLabel(page: Page, gherkinRef: string, namePattern: RegExp, nth: number): Promise<FindResult | null> {
255
- try {
256
- const locator = page.getByLabel(namePattern);
257
- const count = await locator.count();
258
- if (count === 0) return null;
259
-
260
- if (count > 1) {
261
- // Multiple matches — try exact to disambiguate
262
- try {
263
- const exactLocator = page.getByLabel(gherkinRef, { exact: true });
264
- const exactCount = await exactLocator.count();
265
- if (exactCount > 0) {
266
- const target = nth > 0 ? exactLocator.nth(nth) : exactLocator.first();
267
- if (await target.isVisible({ timeout: 3000 })) {
268
- return {
269
- locator: target,
270
- selectorType: 'label',
271
- selectorValue: '',
272
- role: '',
273
- matchMethod: 'label',
274
- warning: null,
275
- };
276
- }
277
- }
278
- } catch {
279
- // Exact disambiguation failed
280
- }
281
- }
282
-
283
- // Single match or exact failed — use first regex match
284
- const target = nth > 0 ? locator.nth(nth) : locator.first();
285
- if (await target.isVisible({ timeout: 3000 })) {
286
- return {
287
- locator: target,
288
- selectorType: 'label',
289
- selectorValue: '',
290
- role: '',
291
- matchMethod: 'label',
292
- warning: null,
293
- };
294
- }
295
- } catch {
296
- // Label not found
297
- }
298
- return null;
299
- }
300
-
301
- // ⑤ getByPlaceholder — regex first, exact disambiguation when ambiguous
302
- async function tryPlaceholder(page: Page, gherkinRef: string, namePattern: RegExp, nth: number): Promise<FindResult | null> {
303
- try {
304
- const locator = page.getByPlaceholder(namePattern);
305
- const count = await locator.count();
306
- if (count === 0) return null;
307
-
308
- if (count > 1) {
309
- // Multiple matches — try exact to disambiguate
310
- try {
311
- const exactLocator = page.getByPlaceholder(gherkinRef, { exact: true });
312
- const exactCount = await exactLocator.count();
313
- if (exactCount > 0) {
314
- const target = nth > 0 ? exactLocator.nth(nth) : exactLocator.first();
315
- if (await target.isVisible({ timeout: 3000 })) {
316
- const rawPlaceholder = await target.getAttribute('placeholder');
317
- return {
318
- locator: target,
319
- selectorType: 'placeholder',
320
- selectorValue: sanitizeText(rawPlaceholder || ''),
321
- role: '',
322
- matchMethod: 'placeholder',
323
- warning: null,
324
- };
325
- }
326
- }
327
- } catch {
328
- // Exact disambiguation failed
329
- }
330
- }
331
-
332
- // Single match or exact failed — use first regex match
333
- const target = nth > 0 ? locator.nth(nth) : locator.first();
334
- if (await target.isVisible({ timeout: 3000 })) {
335
- const rawPlaceholder = await target.getAttribute('placeholder');
336
- return {
337
- locator: target,
338
- selectorType: 'placeholder',
339
- selectorValue: sanitizeText(rawPlaceholder || ''),
340
- role: '',
341
- matchMethod: 'placeholder',
342
- warning: null,
343
- };
344
- }
345
- } catch {
346
- // Placeholder not found
347
- }
348
- return null;
349
- }
350
-
351
- /**
352
- * Check if gherkinType is an editable/input type that could be a contenteditable div
353
- */
354
- function isEditableType(gherkinType: string): boolean {
355
- const normalized = gherkinType.toLowerCase().trim();
356
- return normalized === 'textarea' || normalized === 'textbox' || normalized === 'field' || normalized === 'editor';
357
- }
358
-
359
-
360
-
361
- // ⑤.5 contenteditable — for rich text editors
362
- // Scoped to current context (dialog/page) to avoid matching wrong editor.
363
- // The nth from Gherkin refers to text matches, not contenteditable count,
364
- // so we try the requested nth first, then fall back to first match.
365
- async function tryContentEditable(page: Page, nth: number, context: ElementContext): Promise<FindResult | null> {
366
- try {
367
- // Scope the search to the current context
368
- const root = context === 'dialog' ? page.getByRole('dialog') : page;
369
- const locator = root.locator('[contenteditable="true"]');
370
- const count = await locator.count();
371
- if (count === 0) return null;
372
-
373
- // Try requested nth first, then fall back to first visible
374
- const candidates = nth > 0 && count > nth ? [nth, 0] : [0];
375
- for (const idx of candidates) {
376
- const target = idx > 0 ? locator.nth(idx) : locator.first();
377
- if (await target.isVisible({ timeout: 3000 })) {
378
- return {
379
- locator: target,
380
- selectorType: 'locator',
381
- selectorValue: '[contenteditable="true"]',
382
- role: 'textbox',
383
- matchMethod: 'contenteditable',
384
- warning: count > 1
385
- ? `${count} contenteditable elements in ${context}, using index ${idx}. Use nth in Gherkin to disambiguate.`
386
- : null,
387
- };
388
- }
389
- }
390
- } catch {
391
- // Not found
392
- }
393
- return null;
394
- }
395
-
396
- // ⑥ getByText — regex first, exact disambiguation when ambiguous
397
- async function tryText(page: Page, gherkinRef: string, namePattern: RegExp, nth: number): Promise<FindResult | null> {
398
- try {
399
- const locator = page.getByText(namePattern);
400
- const count = await locator.count();
401
- if (count === 0) return null;
402
-
403
- if (count > 1) {
404
- // Multiple matches — try exact to disambiguate
405
- try {
406
- const exactLocator = page.getByText(gherkinRef, { exact: true });
407
- const exactCount = await exactLocator.count();
408
- if (exactCount > 0) {
409
- const target = nth > 0 ? exactLocator.nth(nth) : exactLocator.first();
410
- if (await target.isVisible({ timeout: 3000 })) {
411
- return {
412
- locator: target,
413
- selectorType: 'text',
414
- selectorValue: '',
415
- role: '',
416
- matchMethod: 'text_only',
417
- warning: null,
418
- };
419
- }
420
- }
421
- } catch {
422
- // Exact disambiguation failed
423
- }
424
- }
425
-
426
- // Single match or exact failed — use first regex match
427
- const target = nth > 0 ? locator.nth(nth) : locator.first();
428
- if (await target.isVisible({ timeout: 3000 })) {
429
- return {
430
- locator: target,
431
- selectorType: 'text',
432
- selectorValue: '',
433
- role: '',
434
- matchMethod: 'text_only',
435
- warning: null,
436
- };
437
- }
438
- } catch {
439
- // Text not found
440
- }
441
- return null;
442
- }
443
-
444
- async function extractElementAttributes(locator: Locator): Promise<{
445
- testid: string | null;
446
- tag: string;
447
- contenteditable: boolean;
448
- accessibleName: string;
449
- placeholder: string | null;
450
- label: string | null;
451
- }> {
452
- try {
453
- return await locator.evaluate((el) => {
454
- // Inline sanitizer — browser context can't access Node functions
455
- const clean = (s: string | null | undefined): string =>
456
- (s || '').replace(/[\n\r\t]/g, ' ').replace(/\s+/g, ' ').trim();
457
-
458
- // Find associated label
459
- let label: string | null = null;
460
- if (el.id) {
461
- const labelEl = el.ownerDocument.querySelector(`label[for="${el.id}"]`);
462
- if (labelEl) label = clean(labelEl.textContent) || null;
463
- }
464
- if (!label && el.closest('label')) {
465
- label = clean(el.closest('label')?.textContent) || null;
466
- }
467
-
468
- // Detect contenteditable: check element itself and ancestors (rich text editors
469
- // often have contenteditable on a parent div wrapping the editable area)
470
- const isContentEditable = el.getAttribute('contenteditable') === 'true'
471
- || el.isContentEditable;
472
-
473
- return {
474
- testid: el.getAttribute('data-testid'),
475
- tag: el.tagName.toLowerCase(),
476
- contenteditable: isContentEditable,
477
- accessibleName: clean(el.getAttribute('aria-label') || el.textContent?.trim()?.substring(0, 100)),
478
- placeholder: clean(el.getAttribute('placeholder')) || null,
479
- label,
480
- };
481
- });
482
- } catch {
483
- return { testid: null, tag: 'unknown', contenteditable: false, accessibleName: '', placeholder: null, label: null };
484
- }
485
- }
486
-
487
- function buildUnresolvedElement(gherkinRef: string, gherkinType: string): LiveElement {
488
- return {
489
- gherkinRef,
490
- gherkinType,
491
- selectorType: '',
492
- selectorValue: '',
493
- role: '',
494
- name: gherkinRef,
495
- testid: null,
496
- tag: '',
497
- contenteditable: false,
498
- placeholder: null,
499
- label: null,
500
- context: 'page',
501
- matchMethod: 'unresolved',
502
- exact: false,
503
- warning: 'Element not found on page',
504
- };
505
- }
506
-
507
- /**
508
- * Normalize a DOM text value for YAML output:
509
- * collapse real newlines/tabs/carriage-returns into spaces, then deduplicate whitespace.
510
- * Runs in both browser evaluate() and Node context.
511
- */
512
- function sanitizeText(str: string): string {
513
- return str.replace(/[\n\r\t]/g, ' ').replace(/\s+/g, ' ').trim();
514
- }
515
-
516
- /**
517
- * Unescape a string extracted from Playwright's ariaSnapshot() output.
518
- * ariaSnapshot encodes special chars as literal escape sequences:
519
- * \n → newline, \t → tab, \\ → backslash, \" → quote
520
- * We unescape them then normalize whitespace.
521
- */
522
- function unescapeAriaSnapshot(str: string): string {
523
- return str
524
- .replace(/\\n/g, ' ')
525
- .replace(/\\t/g, ' ')
526
- .replace(/\\"/g, '"')
527
- .replace(/\\\\/g, '\\')
528
- .replace(/\s+/g, ' ')
529
- .trim();
530
- }
531
-
532
- function escapeRegex(str: string): string {
533
- return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
534
- }
@@ -1,7 +0,0 @@
1
- export { LiveScanner } from './scanner';
2
- export { findElement } from './element-finder';
3
- export { getRoleFallbacks, isTextOnlyType } from './role-fallback';
4
- export { writeMatrix } from './matrix-writer';
5
- export { readMatrix, mergeMatrixElements } from './matrix-reader';
6
- export { readBaseUrlFromPlaywrightConfig } from './config-reader';
7
- export * from './types';
@@ -1,65 +0,0 @@
1
- /**
2
- * Matrix Reader
3
- * Loads and parses a .live-scan.yaml file for consumption by the map command.
4
- * Merges elements across scenarios (first match wins).
5
- */
6
-
7
- import { readYamlIfExists } from '../../utils/yaml-io';
8
- import { LiveElement, LiveScanResult } from './types';
9
-
10
- /**
11
- * Read a .live-scan.yaml file and return the parsed result.
12
- * Returns null if file doesn't exist.
13
- */
14
- export function readMatrix(filePath: string): LiveScanResult | null {
15
- const parsed = readYamlIfExists<any>(filePath);
16
-
17
- if (!parsed || !parsed.scenarios) {
18
- return null;
19
- }
20
-
21
- return parsed as LiveScanResult;
22
- }
23
-
24
- /**
25
- * Merge all elements across scenarios into a flat map.
26
- * First successful (non-unresolved) match wins for duplicate keys.
27
- */
28
- export function mergeMatrixElements(result: LiveScanResult): Record<string, LiveElement> {
29
- const merged: Record<string, LiveElement> = {};
30
-
31
- for (const scenario of Object.values(result.scenarios)) {
32
- const elements = (scenario as any).elements;
33
- if (!elements) continue;
34
-
35
- for (const [key, raw] of Object.entries(elements)) {
36
- const el = raw as any;
37
-
38
- // Convert from YAML snake_case to interface camelCase
39
- const element: LiveElement = {
40
- gherkinRef: el.name || key,
41
- gherkinType: el.gherkin_type || '',
42
- selectorType: el.selector_type || '',
43
- selectorValue: el.selector_value || '',
44
- role: el.role || '',
45
- name: el.name || '',
46
- testid: el.testid || null,
47
- tag: el.tag || '',
48
- contenteditable: el.contenteditable === true,
49
- placeholder: el.placeholder || null,
50
- label: el.label || null,
51
- context: (el.context as any) || 'page',
52
- matchMethod: (el.match_method as any) || 'unresolved',
53
- exact: el.exact === true,
54
- warning: el.warning || null,
55
- };
56
-
57
- // First non-unresolved match wins
58
- if (!merged[key] || (merged[key].matchMethod === 'unresolved' && element.matchMethod !== 'unresolved')) {
59
- merged[key] = element;
60
- }
61
- }
62
- }
63
-
64
- return merged;
65
- }
@@ -1,77 +0,0 @@
1
- /**
2
- * Matrix Writer
3
- * Writes LiveScanResult to a .live-scan.yaml file.
4
- */
5
-
6
- import * as fs from 'fs';
7
- import * as yaml from 'yaml';
8
- import { LiveScanResult } from './types';
9
-
10
- /**
11
- * Sanitize a string value before YAML serialization:
12
- * collapse newlines/tabs/carriage-returns into spaces to prevent
13
- * broken escape sequences (e.g. \\n) in QUOTE_DOUBLE output.
14
- */
15
- function sanitizeForYaml(value: string | null): string | null {
16
- if (!value) return value;
17
- return value.replace(/[\n\r\t]/g, ' ').replace(/\s+/g, ' ').trim() || null;
18
- }
19
-
20
- export function writeMatrix(result: LiveScanResult, outputPath: string): void {
21
- const output: any = {
22
- screen: result.screen,
23
- baseUrl: result.baseUrl,
24
- scannedAt: result.scannedAt,
25
- scenarios: {},
26
- };
27
-
28
- for (const [scenarioKey, scenario] of Object.entries(result.scenarios)) {
29
- const scenarioData: any = {
30
- auth: scenario.auth,
31
- path: scenario.path,
32
- };
33
-
34
- if (scenario.extends) {
35
- scenarioData.extends = scenario.extends;
36
- }
37
-
38
- scenarioData.elements = {};
39
-
40
- for (const [elementKey, element] of Object.entries(scenario.elements)) {
41
- scenarioData.elements[elementKey] = {
42
- gherkin_type: element.gherkinType,
43
- selector_type: element.selectorType,
44
- selector_value: sanitizeForYaml(element.selectorValue),
45
- role: element.role,
46
- name: sanitizeForYaml(element.name),
47
- testid: element.testid,
48
- tag: element.tag,
49
- contenteditable: element.contenteditable,
50
- placeholder: sanitizeForYaml(element.placeholder),
51
- label: sanitizeForYaml(element.label),
52
- context: element.context,
53
- match_method: element.matchMethod,
54
- exact: element.exact,
55
- warning: element.warning,
56
- };
57
- }
58
-
59
- output.scenarios[scenarioKey] = scenarioData;
60
- }
61
-
62
- const header = [
63
- `# Auto-generated by sungen live-scan`,
64
- `# Screen: ${result.screen} | Base URL: ${result.baseUrl}`,
65
- `# Scanned: ${result.scannedAt}`,
66
- `# Do not edit manually — re-run 'sungen live-scan' to regenerate`,
67
- '',
68
- ].join('\n');
69
-
70
- const yamlStr = yaml.stringify(output, {
71
- lineWidth: 120,
72
- defaultStringType: 'QUOTE_DOUBLE',
73
- nullStr: 'null',
74
- });
75
-
76
- fs.writeFileSync(outputPath, header + yamlStr, 'utf-8');
77
- }