@sun-asterisk/sungen 1.0.23 → 2.0.0

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 (364) 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/label-value-assertion.hbs +2 -0
  17. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-filter.hbs +3 -0
  18. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-index.hbs +3 -0
  19. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-column-exists.hbs +2 -0
  20. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-empty.hbs +2 -0
  21. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-count.hbs +2 -0
  22. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-exists.hbs +2 -0
  23. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-not-exists.hbs +2 -0
  24. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-value-assertion.hbs +1 -1
  25. package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator-base.hbs +11 -2
  26. package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator.hbs +11 -2
  27. package/dist/generators/test-generator/code-generator.d.ts +0 -1
  28. package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
  29. package/dist/generators/test-generator/code-generator.js +0 -47
  30. package/dist/generators/test-generator/code-generator.js.map +1 -1
  31. package/dist/generators/test-generator/patterns/assertion-patterns.d.ts.map +1 -1
  32. package/dist/generators/test-generator/patterns/assertion-patterns.js +33 -8
  33. package/dist/generators/test-generator/patterns/assertion-patterns.js.map +1 -1
  34. package/dist/generators/test-generator/patterns/index.d.ts +4 -1
  35. package/dist/generators/test-generator/patterns/index.d.ts.map +1 -1
  36. package/dist/generators/test-generator/patterns/index.js +17 -5
  37. package/dist/generators/test-generator/patterns/index.js.map +1 -1
  38. package/dist/generators/test-generator/patterns/interaction-patterns.js +1 -1
  39. package/dist/generators/test-generator/patterns/interaction-patterns.js.map +1 -1
  40. package/dist/generators/test-generator/patterns/keyboard-patterns.d.ts +7 -0
  41. package/dist/generators/test-generator/patterns/keyboard-patterns.d.ts.map +1 -0
  42. package/dist/generators/test-generator/patterns/keyboard-patterns.js +47 -0
  43. package/dist/generators/test-generator/patterns/keyboard-patterns.js.map +1 -0
  44. package/dist/generators/test-generator/patterns/scope-patterns.d.ts +7 -0
  45. package/dist/generators/test-generator/patterns/scope-patterns.d.ts.map +1 -0
  46. package/dist/generators/test-generator/patterns/scope-patterns.js +36 -0
  47. package/dist/generators/test-generator/patterns/scope-patterns.js.map +1 -0
  48. package/dist/generators/test-generator/patterns/scroll-patterns.d.ts +7 -0
  49. package/dist/generators/test-generator/patterns/scroll-patterns.d.ts.map +1 -0
  50. package/dist/generators/test-generator/patterns/scroll-patterns.js +25 -0
  51. package/dist/generators/test-generator/patterns/scroll-patterns.js.map +1 -0
  52. package/dist/generators/test-generator/patterns/table-patterns.d.ts +7 -0
  53. package/dist/generators/test-generator/patterns/table-patterns.d.ts.map +1 -0
  54. package/dist/generators/test-generator/patterns/table-patterns.js +192 -0
  55. package/dist/generators/test-generator/patterns/table-patterns.js.map +1 -0
  56. package/dist/generators/test-generator/step-mapper.d.ts +1 -3
  57. package/dist/generators/test-generator/step-mapper.d.ts.map +1 -1
  58. package/dist/generators/test-generator/step-mapper.js +36 -34
  59. package/dist/generators/test-generator/step-mapper.js.map +1 -1
  60. package/dist/generators/test-generator/template-engine.d.ts.map +1 -1
  61. package/dist/generators/test-generator/template-engine.js +4 -1
  62. package/dist/generators/test-generator/template-engine.js.map +1 -1
  63. package/dist/generators/test-generator/types.d.ts +7 -24
  64. package/dist/generators/test-generator/types.d.ts.map +1 -1
  65. package/dist/generators/test-generator/types.js +2 -101
  66. package/dist/generators/test-generator/types.js.map +1 -1
  67. package/dist/generators/test-generator/utils/selector-resolver.d.ts +14 -0
  68. package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
  69. package/dist/generators/test-generator/utils/selector-resolver.js +37 -11
  70. package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -1
  71. package/dist/orchestrator/project-initializer.d.ts +8 -0
  72. package/dist/orchestrator/project-initializer.d.ts.map +1 -1
  73. package/dist/orchestrator/project-initializer.js +343 -32
  74. package/dist/orchestrator/project-initializer.js.map +1 -1
  75. package/dist/orchestrator/screen-manager.d.ts +1 -32
  76. package/dist/orchestrator/screen-manager.d.ts.map +1 -1
  77. package/dist/orchestrator/screen-manager.js +55 -216
  78. package/dist/orchestrator/screen-manager.js.map +1 -1
  79. package/dist/utils/selector-types.d.ts +1 -1
  80. package/dist/utils/selector-types.d.ts.map +1 -1
  81. package/dist/utils/selector-types.js +3 -0
  82. package/dist/utils/selector-types.js.map +1 -1
  83. package/package.json +2 -2
  84. package/src/cli/commands/add.ts +5 -3
  85. package/src/cli/commands/generate.ts +90 -38
  86. package/src/cli/index.ts +5 -16
  87. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/frame-enter-action.hbs +1 -0
  88. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/frame-exit-action.hbs +1 -0
  89. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/keyboard-global-action.hbs +1 -0
  90. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/scroll-action.hbs +1 -0
  91. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/table-action-in-row.hbs +2 -0
  92. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/label-value-assertion.hbs +2 -0
  93. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-filter.hbs +3 -0
  94. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-index.hbs +3 -0
  95. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-column-exists.hbs +2 -0
  96. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-empty.hbs +2 -0
  97. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-count.hbs +2 -0
  98. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-exists.hbs +2 -0
  99. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-not-exists.hbs +2 -0
  100. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-value-assertion.hbs +1 -1
  101. package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator-base.hbs +11 -2
  102. package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator.hbs +11 -2
  103. package/src/generators/test-generator/code-generator.ts +0 -59
  104. package/src/generators/test-generator/patterns/assertion-patterns.ts +39 -8
  105. package/src/generators/test-generator/patterns/index.ts +12 -3
  106. package/src/generators/test-generator/patterns/interaction-patterns.ts +1 -1
  107. package/src/generators/test-generator/patterns/keyboard-patterns.ts +51 -0
  108. package/src/generators/test-generator/patterns/scope-patterns.ts +40 -0
  109. package/src/generators/test-generator/patterns/scroll-patterns.ts +27 -0
  110. package/src/generators/test-generator/patterns/table-patterns.ts +232 -0
  111. package/src/generators/test-generator/step-mapper.ts +39 -34
  112. package/src/generators/test-generator/template-engine.ts +3 -1
  113. package/src/generators/test-generator/types.ts +7 -112
  114. package/src/generators/test-generator/utils/selector-resolver.ts +70 -25
  115. package/src/orchestrator/project-initializer.ts +345 -32
  116. package/src/orchestrator/screen-manager.ts +61 -233
  117. package/src/utils/selector-types.ts +3 -0
  118. package/dist/cli/commands/cache-clear.d.ts +0 -3
  119. package/dist/cli/commands/cache-clear.d.ts.map +0 -1
  120. package/dist/cli/commands/cache-clear.js +0 -24
  121. package/dist/cli/commands/cache-clear.js.map +0 -1
  122. package/dist/cli/commands/full.d.ts +0 -3
  123. package/dist/cli/commands/full.d.ts.map +0 -1
  124. package/dist/cli/commands/full.js +0 -37
  125. package/dist/cli/commands/full.js.map +0 -1
  126. package/dist/cli/commands/live-scan.d.ts +0 -3
  127. package/dist/cli/commands/live-scan.d.ts.map +0 -1
  128. package/dist/cli/commands/live-scan.js +0 -78
  129. package/dist/cli/commands/live-scan.js.map +0 -1
  130. package/dist/cli/commands/map.d.ts +0 -3
  131. package/dist/cli/commands/map.d.ts.map +0 -1
  132. package/dist/cli/commands/map.js +0 -93
  133. package/dist/cli/commands/map.js.map +0 -1
  134. package/dist/cli/commands/validate.d.ts +0 -3
  135. package/dist/cli/commands/validate.d.ts.map +0 -1
  136. package/dist/cli/commands/validate.js +0 -43
  137. package/dist/cli/commands/validate.js.map +0 -1
  138. package/dist/cli/utils.d.ts +0 -6
  139. package/dist/cli/utils.d.ts.map +0 -1
  140. package/dist/cli/utils.js +0 -101
  141. package/dist/cli/utils.js.map +0 -1
  142. package/dist/config/config-loader.d.ts +0 -51
  143. package/dist/config/config-loader.d.ts.map +0 -1
  144. package/dist/config/config-loader.js +0 -216
  145. package/dist/config/config-loader.js.map +0 -1
  146. package/dist/config/config-schema.d.ts +0 -121
  147. package/dist/config/config-schema.d.ts.map +0 -1
  148. package/dist/config/config-schema.js +0 -7
  149. package/dist/config/config-schema.js.map +0 -1
  150. package/dist/core/live-scanner/config-reader.d.ts +0 -10
  151. package/dist/core/live-scanner/config-reader.d.ts.map +0 -1
  152. package/dist/core/live-scanner/config-reader.js +0 -87
  153. package/dist/core/live-scanner/config-reader.js.map +0 -1
  154. package/dist/core/live-scanner/element-finder.d.ts +0 -20
  155. package/dist/core/live-scanner/element-finder.d.ts.map +0 -1
  156. package/dist/core/live-scanner/element-finder.js +0 -486
  157. package/dist/core/live-scanner/element-finder.js.map +0 -1
  158. package/dist/core/live-scanner/index.d.ts +0 -8
  159. package/dist/core/live-scanner/index.d.ts.map +0 -1
  160. package/dist/core/live-scanner/index.js +0 -33
  161. package/dist/core/live-scanner/index.js.map +0 -1
  162. package/dist/core/live-scanner/matrix-reader.d.ts +0 -17
  163. package/dist/core/live-scanner/matrix-reader.d.ts.map +0 -1
  164. package/dist/core/live-scanner/matrix-reader.js +0 -60
  165. package/dist/core/live-scanner/matrix-reader.js.map +0 -1
  166. package/dist/core/live-scanner/matrix-writer.d.ts +0 -7
  167. package/dist/core/live-scanner/matrix-writer.d.ts.map +0 -1
  168. package/dist/core/live-scanner/matrix-writer.js +0 -103
  169. package/dist/core/live-scanner/matrix-writer.js.map +0 -1
  170. package/dist/core/live-scanner/role-fallback.d.ts +0 -15
  171. package/dist/core/live-scanner/role-fallback.d.ts.map +0 -1
  172. package/dist/core/live-scanner/role-fallback.js +0 -45
  173. package/dist/core/live-scanner/role-fallback.js.map +0 -1
  174. package/dist/core/live-scanner/scanner.d.ts +0 -13
  175. package/dist/core/live-scanner/scanner.d.ts.map +0 -1
  176. package/dist/core/live-scanner/scanner.js +0 -243
  177. package/dist/core/live-scanner/scanner.js.map +0 -1
  178. package/dist/core/live-scanner/step-replayer.d.ts +0 -26
  179. package/dist/core/live-scanner/step-replayer.d.ts.map +0 -1
  180. package/dist/core/live-scanner/step-replayer.js +0 -286
  181. package/dist/core/live-scanner/step-replayer.js.map +0 -1
  182. package/dist/core/live-scanner/types.d.ts +0 -52
  183. package/dist/core/live-scanner/types.d.ts.map +0 -1
  184. package/dist/core/live-scanner/types.js +0 -14
  185. package/dist/core/live-scanner/types.js.map +0 -1
  186. package/dist/core/selector-base/annotation-handler.d.ts +0 -45
  187. package/dist/core/selector-base/annotation-handler.d.ts.map +0 -1
  188. package/dist/core/selector-base/annotation-handler.js +0 -102
  189. package/dist/core/selector-base/annotation-handler.js.map +0 -1
  190. package/dist/core/selector-base/base-generator.d.ts +0 -49
  191. package/dist/core/selector-base/base-generator.d.ts.map +0 -1
  192. package/dist/core/selector-base/base-generator.js +0 -214
  193. package/dist/core/selector-base/base-generator.js.map +0 -1
  194. package/dist/core/selector-base/gherkin-parser.d.ts +0 -24
  195. package/dist/core/selector-base/gherkin-parser.d.ts.map +0 -1
  196. package/dist/core/selector-base/gherkin-parser.js +0 -42
  197. package/dist/core/selector-base/gherkin-parser.js.map +0 -1
  198. package/dist/core/selector-mapper/priority-mapper.d.ts +0 -74
  199. package/dist/core/selector-mapper/priority-mapper.d.ts.map +0 -1
  200. package/dist/core/selector-mapper/priority-mapper.js +0 -477
  201. package/dist/core/selector-mapper/priority-mapper.js.map +0 -1
  202. package/dist/core/ui-scanner/heuristics/base-heuristic.d.ts +0 -91
  203. package/dist/core/ui-scanner/heuristics/base-heuristic.d.ts.map +0 -1
  204. package/dist/core/ui-scanner/heuristics/base-heuristic.js +0 -175
  205. package/dist/core/ui-scanner/heuristics/base-heuristic.js.map +0 -1
  206. package/dist/core/ui-scanner/react-scanner.d.ts +0 -32
  207. package/dist/core/ui-scanner/react-scanner.d.ts.map +0 -1
  208. package/dist/core/ui-scanner/react-scanner.js +0 -163
  209. package/dist/core/ui-scanner/react-scanner.js.map +0 -1
  210. package/dist/core/ui-scanner/scanner-interface.d.ts +0 -94
  211. package/dist/core/ui-scanner/scanner-interface.d.ts.map +0 -1
  212. package/dist/core/ui-scanner/scanner-interface.js +0 -33
  213. package/dist/core/ui-scanner/scanner-interface.js.map +0 -1
  214. package/dist/core/ui-scanner/strict-scanner.d.ts +0 -81
  215. package/dist/core/ui-scanner/strict-scanner.d.ts.map +0 -1
  216. package/dist/core/ui-scanner/strict-scanner.js +0 -511
  217. package/dist/core/ui-scanner/strict-scanner.js.map +0 -1
  218. package/dist/core/validator/data-validator.d.ts +0 -38
  219. package/dist/core/validator/data-validator.d.ts.map +0 -1
  220. package/dist/core/validator/data-validator.js +0 -212
  221. package/dist/core/validator/data-validator.js.map +0 -1
  222. package/dist/core/validator/feature-validator.d.ts +0 -27
  223. package/dist/core/validator/feature-validator.d.ts.map +0 -1
  224. package/dist/core/validator/feature-validator.js +0 -182
  225. package/dist/core/validator/feature-validator.js.map +0 -1
  226. package/dist/core/validator/index.d.ts +0 -46
  227. package/dist/core/validator/index.d.ts.map +0 -1
  228. package/dist/core/validator/index.js +0 -17
  229. package/dist/core/validator/index.js.map +0 -1
  230. package/dist/core/validator/screen-validator.d.ts +0 -35
  231. package/dist/core/validator/screen-validator.d.ts.map +0 -1
  232. package/dist/core/validator/screen-validator.js +0 -195
  233. package/dist/core/validator/screen-validator.js.map +0 -1
  234. package/dist/core/validator/selector-validator.d.ts +0 -36
  235. package/dist/core/validator/selector-validator.d.ts.map +0 -1
  236. package/dist/core/validator/selector-validator.js +0 -210
  237. package/dist/core/validator/selector-validator.js.map +0 -1
  238. package/dist/external/ai-provider.d.ts +0 -60
  239. package/dist/external/ai-provider.d.ts.map +0 -1
  240. package/dist/external/ai-provider.js +0 -30
  241. package/dist/external/ai-provider.js.map +0 -1
  242. package/dist/external/anthropic-provider.d.ts +0 -29
  243. package/dist/external/anthropic-provider.d.ts.map +0 -1
  244. package/dist/external/anthropic-provider.js +0 -85
  245. package/dist/external/anthropic-provider.js.map +0 -1
  246. package/dist/generators/cache/cache-manager.d.ts +0 -66
  247. package/dist/generators/cache/cache-manager.d.ts.map +0 -1
  248. package/dist/generators/cache/cache-manager.js +0 -286
  249. package/dist/generators/cache/cache-manager.js.map +0 -1
  250. package/dist/generators/dsl-writer/index.d.ts +0 -33
  251. package/dist/generators/dsl-writer/index.d.ts.map +0 -1
  252. package/dist/generators/dsl-writer/index.js +0 -226
  253. package/dist/generators/dsl-writer/index.js.map +0 -1
  254. package/dist/generators/scaffold-generator/index.d.ts +0 -162
  255. package/dist/generators/scaffold-generator/index.d.ts.map +0 -1
  256. package/dist/generators/scaffold-generator/index.js +0 -868
  257. package/dist/generators/scaffold-generator/index.js.map +0 -1
  258. package/dist/generators/selector-mapper/ai-mapper.d.ts +0 -56
  259. package/dist/generators/selector-mapper/ai-mapper.d.ts.map +0 -1
  260. package/dist/generators/selector-mapper/ai-mapper.js +0 -457
  261. package/dist/generators/selector-mapper/ai-mapper.js.map +0 -1
  262. package/dist/generators/selector-mapper/hybrid-mapper.d.ts +0 -67
  263. package/dist/generators/selector-mapper/hybrid-mapper.d.ts.map +0 -1
  264. package/dist/generators/selector-mapper/hybrid-mapper.js +0 -349
  265. package/dist/generators/selector-mapper/hybrid-mapper.js.map +0 -1
  266. package/dist/generators/selector-mapper/index.d.ts +0 -8
  267. package/dist/generators/selector-mapper/index.d.ts.map +0 -1
  268. package/dist/generators/selector-mapper/index.js +0 -12
  269. package/dist/generators/selector-mapper/index.js.map +0 -1
  270. package/dist/generators/selector-mapper/intelligent-mapper.d.ts +0 -125
  271. package/dist/generators/selector-mapper/intelligent-mapper.d.ts.map +0 -1
  272. package/dist/generators/selector-mapper/intelligent-mapper.js +0 -391
  273. package/dist/generators/selector-mapper/intelligent-mapper.js.map +0 -1
  274. package/dist/generators/test-generator/ai-step-mapper.d.ts +0 -27
  275. package/dist/generators/test-generator/ai-step-mapper.d.ts.map +0 -1
  276. package/dist/generators/test-generator/ai-step-mapper.js +0 -204
  277. package/dist/generators/test-generator/ai-step-mapper.js.map +0 -1
  278. package/dist/generators/test-generator/auth-setup-generator.d.ts +0 -18
  279. package/dist/generators/test-generator/auth-setup-generator.d.ts.map +0 -1
  280. package/dist/generators/test-generator/auth-setup-generator.js +0 -82
  281. package/dist/generators/test-generator/auth-setup-generator.js.map +0 -1
  282. package/dist/generators/test-generator/patterns/legacy-patterns.d.ts +0 -7
  283. package/dist/generators/test-generator/patterns/legacy-patterns.d.ts.map +0 -1
  284. package/dist/generators/test-generator/patterns/legacy-patterns.js +0 -98
  285. package/dist/generators/test-generator/patterns/legacy-patterns.js.map +0 -1
  286. package/dist/generators/test-generator/templates/auth-setup.ts.hbs +0 -36
  287. package/dist/generators/ui-model-builder/deep-scanner.d.ts +0 -121
  288. package/dist/generators/ui-model-builder/deep-scanner.d.ts.map +0 -1
  289. package/dist/generators/ui-model-builder/deep-scanner.js +0 -1113
  290. package/dist/generators/ui-model-builder/deep-scanner.js.map +0 -1
  291. package/dist/generators/ui-model-builder/enhanced-deep-scanner.d.ts +0 -110
  292. package/dist/generators/ui-model-builder/enhanced-deep-scanner.d.ts.map +0 -1
  293. package/dist/generators/ui-model-builder/enhanced-deep-scanner.js +0 -608
  294. package/dist/generators/ui-model-builder/enhanced-deep-scanner.js.map +0 -1
  295. package/dist/generators/ui-model-builder/react-scanner.d.ts +0 -107
  296. package/dist/generators/ui-model-builder/react-scanner.d.ts.map +0 -1
  297. package/dist/generators/ui-model-builder/react-scanner.js +0 -797
  298. package/dist/generators/ui-model-builder/react-scanner.js.map +0 -1
  299. package/dist/orchestrator/cache-manager.d.ts +0 -15
  300. package/dist/orchestrator/cache-manager.d.ts.map +0 -1
  301. package/dist/orchestrator/cache-manager.js +0 -62
  302. package/dist/orchestrator/cache-manager.js.map +0 -1
  303. package/dist/orchestrator/pipeline.d.ts +0 -56
  304. package/dist/orchestrator/pipeline.d.ts.map +0 -1
  305. package/dist/orchestrator/pipeline.js +0 -298
  306. package/dist/orchestrator/pipeline.js.map +0 -1
  307. package/dist/orchestrator/reporter.d.ts +0 -15
  308. package/dist/orchestrator/reporter.d.ts.map +0 -1
  309. package/dist/orchestrator/reporter.js +0 -30
  310. package/dist/orchestrator/reporter.js.map +0 -1
  311. package/src/cli/commands/cache-clear.ts +0 -22
  312. package/src/cli/commands/full.ts +0 -35
  313. package/src/cli/commands/live-scan.ts +0 -82
  314. package/src/cli/commands/map.ts +0 -97
  315. package/src/cli/commands/validate.ts +0 -43
  316. package/src/cli/utils.ts +0 -106
  317. package/src/config/ai-providers.yaml +0 -56
  318. package/src/config/config-loader.ts +0 -248
  319. package/src/config/config-schema.ts +0 -148
  320. package/src/config/default.config.yaml +0 -107
  321. package/src/config/framework.config.yaml +0 -52
  322. package/src/config/routes.yaml +0 -31
  323. package/src/core/live-scanner/config-reader.ts +0 -57
  324. package/src/core/live-scanner/element-finder.ts +0 -541
  325. package/src/core/live-scanner/index.ts +0 -7
  326. package/src/core/live-scanner/matrix-reader.ts +0 -65
  327. package/src/core/live-scanner/matrix-writer.ts +0 -77
  328. package/src/core/live-scanner/role-fallback.ts +0 -43
  329. package/src/core/live-scanner/scanner.ts +0 -254
  330. package/src/core/live-scanner/step-replayer.ts +0 -306
  331. package/src/core/live-scanner/types.ts +0 -58
  332. package/src/core/selector-base/annotation-handler.ts +0 -127
  333. package/src/core/selector-base/base-generator.ts +0 -234
  334. package/src/core/selector-base/gherkin-parser.ts +0 -57
  335. package/src/core/selector-mapper/priority-mapper.ts +0 -607
  336. package/src/core/ui-scanner/heuristics/base-heuristic.ts +0 -216
  337. package/src/core/ui-scanner/react-scanner.ts +0 -156
  338. package/src/core/ui-scanner/scanner-interface.ts +0 -133
  339. package/src/core/ui-scanner/strict-scanner.ts +0 -629
  340. package/src/core/validator/data-validator.ts +0 -202
  341. package/src/core/validator/feature-validator.ts +0 -176
  342. package/src/core/validator/index.ts +0 -57
  343. package/src/core/validator/screen-validator.ts +0 -209
  344. package/src/core/validator/selector-validator.ts +0 -209
  345. package/src/external/ai-provider.ts +0 -90
  346. package/src/external/anthropic-provider.ts +0 -114
  347. package/src/generators/README.md +0 -410
  348. package/src/generators/cache/cache-manager.ts +0 -322
  349. package/src/generators/dsl-writer/index.ts +0 -253
  350. package/src/generators/scaffold-generator/index.ts +0 -1019
  351. package/src/generators/selector-mapper/ai-mapper.ts +0 -528
  352. package/src/generators/selector-mapper/hybrid-mapper.ts +0 -427
  353. package/src/generators/selector-mapper/index.ts +0 -10
  354. package/src/generators/selector-mapper/intelligent-mapper.ts +0 -530
  355. package/src/generators/test-generator/ai-step-mapper.ts +0 -224
  356. package/src/generators/test-generator/auth-setup-generator.ts +0 -59
  357. package/src/generators/test-generator/patterns/legacy-patterns.ts +0 -104
  358. package/src/generators/test-generator/templates/auth-setup.ts.hbs +0 -36
  359. package/src/generators/ui-model-builder/deep-scanner.ts +0 -1244
  360. package/src/generators/ui-model-builder/enhanced-deep-scanner.ts +0 -731
  361. package/src/generators/ui-model-builder/react-scanner.ts +0 -959
  362. package/src/orchestrator/cache-manager.ts +0 -32
  363. package/src/orchestrator/pipeline.ts +0 -354
  364. package/src/orchestrator/reporter.ts +0 -36
@@ -1,731 +0,0 @@
1
- /**
2
- * ENHANCED Deep Scanner with Semantic Context Extraction
3
- *
4
- * Enhancements over standard deep-scanner:
5
- * 1. Extract ARIA attributes (role, aria-label, aria-labelledby)
6
- * 2. Capture form context (form name, field names)
7
- * 3. Record spatial context (preceding text, parent sections)
8
- * 4. Infer semantic purpose (input/navigation/action/display)
9
- * 5. Generate multiple selector strategies (ARIA, semantic, testid, CSS)
10
- *
11
- * This enables intelligent context-aware selector mapping with 90-95% accuracy.
12
- */
13
-
14
- import * as parser from '@babel/parser';
15
- import traverse from '@babel/traverse';
16
- import * as t from '@babel/types';
17
- import * as fs from 'fs';
18
- import * as path from 'path';
19
-
20
- // ============================================================================
21
- // TYPES
22
- // ============================================================================
23
-
24
- type Purpose = 'input' | 'navigation' | 'action' | 'display' | 'container';
25
- type InteractionType = 'click' | 'fill' | 'select' | 'check' | 'none';
26
- type SelectorType = 'aria' | 'semantic' | 'testid' | 'css';
27
- type Confidence = 'high' | 'medium' | 'low';
28
-
29
- interface SemanticContext {
30
- purpose: Purpose;
31
- section: string;
32
- interactionType: InteractionType;
33
-
34
- formContext?: {
35
- formName: string;
36
- formPurpose: string;
37
- fieldName: string;
38
- fieldType: string;
39
- };
40
-
41
- spatialContext: {
42
- precedingText?: string;
43
- followingText?: string;
44
- parentContainer?: string;
45
- nearbyLabels?: string[];
46
- sectionHeading?: string;
47
- };
48
-
49
- accessibility: {
50
- ariaRole?: string;
51
- ariaLabel?: string;
52
- ariaLabelledBy?: string;
53
- ariaDescribedBy?: string;
54
- implicitRole?: string;
55
- };
56
- }
57
-
58
- interface SelectorStrategy {
59
- type: SelectorType;
60
- selector: string;
61
- confidence: Confidence;
62
- stability: 'high' | 'medium' | 'low';
63
- playwrightCode?: string;
64
- }
65
-
66
- interface EnhancedUIElement {
67
- key: string;
68
- tag: string;
69
- text: string | null;
70
- testId?: string;
71
- role?: string;
72
- id?: string;
73
- name?: string;
74
- placeholder?: string;
75
- source: string;
76
-
77
- // HTML attributes
78
- props: Record<string, any>;
79
-
80
- // Enhanced: Rich semantic context
81
- semanticContext: SemanticContext;
82
-
83
- // Enhanced: Multiple selector strategies
84
- selectorStrategies: SelectorStrategy[];
85
-
86
- // Metadata
87
- metadata?: {
88
- frameworkComponent?: string;
89
- originalImport?: string;
90
- };
91
- }
92
-
93
- interface DeepScanConfig {
94
- sourceRoot: string;
95
- projectRoot: string;
96
- maxDepth: number;
97
- verbose?: boolean;
98
- }
99
-
100
- // ============================================================================
101
- // SEMANTIC CONTEXT EXTRACTOR
102
- // ============================================================================
103
-
104
- class SemanticContextExtractor {
105
- /**
106
- * Extract rich semantic context from element
107
- */
108
- extractContext(
109
- element: any,
110
- parentElement?: any,
111
- siblings?: any[],
112
- formContext?: any
113
- ): SemanticContext {
114
- const context: SemanticContext = {
115
- purpose: this.inferPurpose(element),
116
- section: this.inferSection(element, parentElement),
117
- interactionType: this.inferInteractionType(element),
118
- spatialContext: this.extractSpatialContext(element, siblings),
119
- accessibility: this.extractAccessibility(element),
120
- };
121
-
122
- // Add form context if element is inside a form
123
- if (formContext) {
124
- context.formContext = this.buildFormContext(element, formContext);
125
- }
126
-
127
- return context;
128
- }
129
-
130
- private inferPurpose(element: any): Purpose {
131
- const tag = element.tag?.toLowerCase();
132
- const type = element.props?.type;
133
-
134
- // Interactive inputs
135
- if (['input', 'textarea', 'select'].includes(tag)) {
136
- return 'input';
137
- }
138
-
139
- // Navigation elements
140
- if (tag === 'a' || element.props?.href) {
141
- return 'navigation';
142
- }
143
-
144
- // Action elements
145
- if (tag === 'button' || type === 'submit' || type === 'button') {
146
- return 'action';
147
- }
148
-
149
- // Display elements
150
- if (['p', 'span', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'label'].includes(tag)) {
151
- return 'display';
152
- }
153
-
154
- return 'container';
155
- }
156
-
157
- private inferSection(element: any, parent?: any): string {
158
- // Check for semantic HTML5 sections
159
- const semanticSections = ['header', 'nav', 'main', 'aside', 'footer', 'form', 'section', 'article'];
160
-
161
- let current = parent;
162
- while (current) {
163
- const tag = current.tag?.toLowerCase();
164
- if (semanticSections.includes(tag)) {
165
- return tag;
166
- }
167
- if (current.props?.['data-section']) {
168
- return current.props['data-section'];
169
- }
170
- if (current.props?.role) {
171
- const role = current.props.role;
172
- if (['banner', 'navigation', 'main', 'complementary', 'contentinfo'].includes(role)) {
173
- return role;
174
- }
175
- }
176
- current = current.parent;
177
- }
178
-
179
- // Infer from className
180
- if (element.props?.className) {
181
- const className = element.props.className.toLowerCase();
182
- if (className.includes('header')) return 'header';
183
- if (className.includes('sidebar')) return 'sidebar';
184
- if (className.includes('footer')) return 'footer';
185
- if (className.includes('modal')) return 'modal';
186
- if (className.includes('nav')) return 'navigation';
187
- }
188
-
189
- return 'main';
190
- }
191
-
192
- private inferInteractionType(element: any): InteractionType {
193
- const tag = element.tag?.toLowerCase();
194
- const type = element.props?.type;
195
-
196
- if (['checkbox', 'radio'].includes(type)) return 'check';
197
- if (tag === 'select') return 'select';
198
- if (['input', 'textarea'].includes(tag)) return 'fill';
199
- if (['button', 'a'].includes(tag)) return 'click';
200
- if (element.props?.onClick) return 'click';
201
-
202
- return 'none';
203
- }
204
-
205
- private extractSpatialContext(element: any, siblings?: any[]): SemanticContext['spatialContext'] {
206
- const context: SemanticContext['spatialContext'] = {};
207
-
208
- if (!siblings) return context;
209
-
210
- const elementIndex = siblings.findIndex(s => s.key === element.key);
211
- if (elementIndex === -1) return context;
212
-
213
- // Find preceding text (look backward)
214
- for (let i = elementIndex - 1; i >= Math.max(0, elementIndex - 3); i--) {
215
- const sibling = siblings[i];
216
- if (sibling.text && sibling.tag !== 'script' && sibling.tag !== 'style') {
217
- context.precedingText = sibling.text.trim();
218
- break;
219
- }
220
- }
221
-
222
- // Find following text (look forward)
223
- for (let i = elementIndex + 1; i < Math.min(siblings.length, elementIndex + 3); i++) {
224
- const sibling = siblings[i];
225
- if (sibling.text && sibling.tag !== 'script' && sibling.tag !== 'style') {
226
- context.followingText = sibling.text.trim();
227
- break;
228
- }
229
- }
230
-
231
- // Find nearby labels
232
- context.nearbyLabels = siblings
233
- .filter(s => s.tag === 'label' && Math.abs(siblings.indexOf(s) - elementIndex) <= 2)
234
- .map(s => s.text)
235
- .filter(Boolean);
236
-
237
- return context;
238
- }
239
-
240
- private extractAccessibility(element: any): SemanticContext['accessibility'] {
241
- const props = element.props || {};
242
-
243
- return {
244
- ariaRole: props['role'] || props['aria-role'],
245
- ariaLabel: props['aria-label'] || props['ariaLabel'],
246
- ariaLabelledBy: props['aria-labelledby'] || props['ariaLabelledBy'],
247
- ariaDescribedBy: props['aria-describedby'] || props['ariaDescribedBy'],
248
- implicitRole: this.getImplicitRole(element.tag),
249
- };
250
- }
251
-
252
- private buildFormContext(element: any, formElement: any): SemanticContext['formContext'] {
253
- const formProps = formElement.props || {};
254
-
255
- return {
256
- formName: formProps.name || formProps.id || 'unnamed-form',
257
- formPurpose: this.inferFormPurpose(formElement),
258
- fieldName: element.props?.name || element.props?.id || 'unnamed-field',
259
- fieldType: element.props?.type || element.tag,
260
- };
261
- }
262
-
263
- private inferFormPurpose(formElement: any): string {
264
- const formName = (formElement.props?.name || '').toLowerCase();
265
- const formId = (formElement.props?.id || '').toLowerCase();
266
-
267
- if (formName.includes('login') || formId.includes('login')) return 'login';
268
- if (formName.includes('register') || formId.includes('register')) return 'registration';
269
- if (formName.includes('search') || formId.includes('search')) return 'search';
270
- if (formName.includes('contact') || formId.includes('contact')) return 'contact';
271
- if (formName.includes('settings') || formId.includes('settings')) return 'settings';
272
-
273
- return 'generic';
274
- }
275
-
276
- private getImplicitRole(tag: string): string | undefined {
277
- const implicitRoles: Record<string, string> = {
278
- 'button': 'button',
279
- 'a': 'link',
280
- 'input': 'textbox',
281
- 'textarea': 'textbox',
282
- 'select': 'combobox',
283
- 'nav': 'navigation',
284
- 'main': 'main',
285
- 'header': 'banner',
286
- 'footer': 'contentinfo',
287
- 'form': 'form',
288
- 'img': 'img',
289
- };
290
-
291
- return implicitRoles[tag?.toLowerCase()];
292
- }
293
- }
294
-
295
- // ============================================================================
296
- // SELECTOR STRATEGY GENERATOR
297
- // ============================================================================
298
-
299
- class SelectorStrategyGenerator {
300
- /**
301
- * Generate multiple selector strategies for an element
302
- */
303
- generateStrategies(element: EnhancedUIElement): SelectorStrategy[] {
304
- const strategies: SelectorStrategy[] = [];
305
-
306
- // 1. ARIA-based selector (highest priority)
307
- const ariaStrategy = this.generateAriaSelector(element);
308
- if (ariaStrategy) strategies.push(ariaStrategy);
309
-
310
- // 2. Semantic structure selector
311
- const semanticStrategy = this.generateSemanticSelector(element);
312
- if (semanticStrategy) strategies.push(semanticStrategy);
313
-
314
- // 3. data-testid selector (if exists)
315
- if (element.testId) {
316
- strategies.push({
317
- type: 'testid',
318
- selector: `[data-testid="${element.testId}"]`,
319
- confidence: 'high',
320
- stability: 'high',
321
- playwrightCode: `page.locator('[data-testid="${element.testId}"]')`,
322
- });
323
- }
324
-
325
- // 4. ID selector (if exists and semantic)
326
- if (element.id && !element.id.match(/^(mui|react|auto)-/)) {
327
- strategies.push({
328
- type: 'css',
329
- selector: `#${element.id}`,
330
- confidence: 'high',
331
- stability: 'medium',
332
- playwrightCode: `page.locator('#${element.id}')`,
333
- });
334
- }
335
-
336
- // 5. Name attribute (for form fields)
337
- if (element.name) {
338
- strategies.push({
339
- type: 'css',
340
- selector: `${element.tag}[name="${element.name}"]`,
341
- confidence: 'medium',
342
- stability: 'high',
343
- playwrightCode: `page.locator('${element.tag}[name="${element.name}"]')`,
344
- });
345
- }
346
-
347
- // 6. CSS fallback
348
- if (strategies.length === 0) {
349
- const cssStrategy = this.generateCssSelector(element);
350
- if (cssStrategy) strategies.push(cssStrategy);
351
- }
352
-
353
- return strategies;
354
- }
355
-
356
- private generateAriaSelector(element: EnhancedUIElement): SelectorStrategy | null {
357
- const { accessibility } = element.semanticContext;
358
-
359
- // Explicit ARIA role and label
360
- if (accessibility.ariaRole && accessibility.ariaLabel) {
361
- return {
362
- type: 'aria',
363
- selector: `role=${accessibility.ariaRole}[name="${accessibility.ariaLabel}"]`,
364
- confidence: 'high',
365
- stability: 'high',
366
- playwrightCode: `page.getByRole('${accessibility.ariaRole}', { name: '${accessibility.ariaLabel}' })`,
367
- };
368
- }
369
-
370
- // Implicit role from HTML tag + text
371
- if (accessibility.implicitRole && element.text && element.text.length < 50) {
372
- return {
373
- type: 'aria',
374
- selector: `role=${accessibility.implicitRole}[name="${element.text}"]`,
375
- confidence: 'high',
376
- stability: 'high',
377
- playwrightCode: `page.getByRole('${accessibility.implicitRole}', { name: '${element.text}' })`,
378
- };
379
- }
380
-
381
- // Role + aria-labelledby
382
- if (accessibility.ariaRole && accessibility.ariaLabelledBy) {
383
- return {
384
- type: 'aria',
385
- selector: `role=${accessibility.ariaRole}[aria-labelledby="${accessibility.ariaLabelledBy}"]`,
386
- confidence: 'medium',
387
- stability: 'medium',
388
- playwrightCode: `page.locator('[role="${accessibility.ariaRole}"][aria-labelledby="${accessibility.ariaLabelledBy}"]')`,
389
- };
390
- }
391
-
392
- // Placeholder as fallback label for inputs
393
- if (accessibility.implicitRole === 'textbox' && element.placeholder) {
394
- return {
395
- type: 'aria',
396
- selector: `role=textbox[name="${element.placeholder}"]`,
397
- confidence: 'medium',
398
- stability: 'medium',
399
- playwrightCode: `page.getByRole('textbox', { name: '${element.placeholder}' })`,
400
- };
401
- }
402
-
403
- return null;
404
- }
405
-
406
- private generateSemanticSelector(element: EnhancedUIElement): SelectorStrategy | null {
407
- const { formContext, section } = element.semanticContext;
408
-
409
- // Form field with name
410
- if (formContext && formContext.fieldName && formContext.formName) {
411
- const selector = `form[name="${formContext.formName}"] ${element.tag}[name="${formContext.fieldName}"]`;
412
- return {
413
- type: 'semantic',
414
- selector,
415
- confidence: 'high',
416
- stability: 'high',
417
- playwrightCode: `page.locator('${selector}')`,
418
- };
419
- }
420
-
421
- // Link with href
422
- if (element.tag === 'a' && element.props.href) {
423
- const selector = section !== 'main'
424
- ? `${section} a[href="${element.props.href}"]`
425
- : `a[href="${element.props.href}"]`;
426
-
427
- return {
428
- type: 'semantic',
429
- selector,
430
- confidence: 'medium',
431
- stability: 'medium',
432
- playwrightCode: `page.locator('${selector}')`,
433
- };
434
- }
435
-
436
- // Button with type in section
437
- if (element.tag === 'button' && element.props.type) {
438
- const selector = section !== 'main'
439
- ? `${section} button[type="${element.props.type}"]`
440
- : `button[type="${element.props.type}"]`;
441
-
442
- return {
443
- type: 'semantic',
444
- selector,
445
- confidence: 'low',
446
- stability: 'medium',
447
- playwrightCode: `page.locator('${selector}')`,
448
- };
449
- }
450
-
451
- return null;
452
- }
453
-
454
- private generateCssSelector(element: EnhancedUIElement): SelectorStrategy {
455
- let selector = element.tag;
456
-
457
- if (element.id) {
458
- selector = `#${element.id}`;
459
- } else if (element.name) {
460
- selector = `${element.tag}[name="${element.name}"]`;
461
- } else if (element.props.type) {
462
- selector = `${element.tag}[type="${element.props.type}"]`;
463
- } else if (element.props.className) {
464
- // Use first meaningful class (avoid utility classes)
465
- const classes = element.props.className.split(' ');
466
- const meaningfulClass = classes.find((c: string) =>
467
- !c.match(/^(text-|bg-|p-|m-|flex|grid|rounded|border|shadow)/)
468
- );
469
- if (meaningfulClass) {
470
- selector = `${element.tag}.${meaningfulClass}`;
471
- }
472
- }
473
-
474
- return {
475
- type: 'css',
476
- selector,
477
- confidence: 'low',
478
- stability: 'low',
479
- playwrightCode: `page.locator('${selector}')`,
480
- };
481
- }
482
- }
483
-
484
- // ============================================================================
485
- // ENHANCED DEEP SCANNER
486
- // ============================================================================
487
-
488
- export class EnhancedDeepScanner {
489
- private config: DeepScanConfig;
490
- private elements: EnhancedUIElement[] = [];
491
- private contextExtractor = new SemanticContextExtractor();
492
- private strategyGenerator = new SelectorStrategyGenerator();
493
- private scannedFiles = new Set<string>();
494
- private elementCounter = 0;
495
- private currentFormContext: any = null;
496
-
497
- constructor(config: DeepScanConfig) {
498
- this.config = config;
499
- }
500
-
501
- /**
502
- * Scan a React component file and extract all UI elements with context
503
- */
504
- async scanFile(
505
- filePath: string,
506
- depth: number = 0,
507
- parentProps?: Record<string, any>,
508
- parentElement?: any,
509
- formContext?: any
510
- ): Promise<void> {
511
- if (depth > this.config.maxDepth) return;
512
- if (this.scannedFiles.has(filePath)) return;
513
-
514
- this.scannedFiles.add(filePath);
515
-
516
- if (this.config.verbose) {
517
- console.log(`${' '.repeat(depth)}Scanning: ${path.basename(filePath)}`);
518
- }
519
-
520
- const code = fs.readFileSync(filePath, 'utf-8');
521
- const ast = parser.parse(code, {
522
- sourceType: 'module',
523
- plugins: ['jsx', 'typescript'],
524
- });
525
-
526
- const self = this;
527
- const currentDepth = depth;
528
- const sourceFileName = path.basename(filePath);
529
-
530
- traverse(ast, {
531
- JSXElement(nodePath) {
532
- const openingElement = nodePath.node.openingElement;
533
- const tagName = self.getTagName(openingElement);
534
-
535
- // Extract all attributes
536
- const attrs = self.extractAttributes(openingElement);
537
-
538
- // Merge with parent props
539
- const mergedAttrs = { ...parentProps, ...attrs };
540
-
541
- // Extract text content
542
- const text = self.extractText(nodePath.node);
543
-
544
- // Detect if we entered a form
545
- let currentFormCtx = formContext;
546
- if (tagName === 'form') {
547
- currentFormCtx = {
548
- tag: 'form',
549
- props: mergedAttrs,
550
- };
551
- }
552
-
553
- // Build base element
554
- const baseElement = {
555
- key: `e${++self.elementCounter}`,
556
- tag: tagName,
557
- text,
558
- testId: attrs['data-testid'],
559
- role: attrs['role'],
560
- id: attrs['id'],
561
- name: attrs['name'],
562
- placeholder: attrs['placeholder'],
563
- source: sourceFileName,
564
- props: mergedAttrs,
565
- };
566
-
567
- // Add semantic context
568
- const semanticContext = self.contextExtractor.extractContext(
569
- baseElement,
570
- parentElement,
571
- undefined, // siblings would need to be tracked
572
- currentFormCtx
573
- );
574
-
575
- // Create enhanced element
576
- const enhancedElement: EnhancedUIElement = {
577
- ...baseElement,
578
- semanticContext,
579
- selectorStrategies: [],
580
- };
581
-
582
- // Generate selector strategies
583
- enhancedElement.selectorStrategies = self.strategyGenerator.generateStrategies(enhancedElement);
584
-
585
- // Add to collection if it's a meaningful UI element
586
- if (self.isMeaningfulElement(enhancedElement)) {
587
- self.elements.push(enhancedElement);
588
-
589
- if (self.config.verbose) {
590
- console.log(` ${' '.repeat(depth)} Found: <${tagName}> ${text || ''} [${enhancedElement.selectorStrategies.length} strategies]`);
591
- }
592
- }
593
- },
594
- });
595
- }
596
-
597
- /**
598
- * Check if element is meaningful for testing
599
- */
600
- private isMeaningfulElement(element: EnhancedUIElement): boolean {
601
- const interactiveTags = ['button', 'input', 'textarea', 'select', 'a'];
602
- const meaningfulTags = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'label'];
603
-
604
- // Interactive elements
605
- if (interactiveTags.includes(element.tag)) return true;
606
-
607
- // Elements with text content
608
- if (meaningfulTags.includes(element.tag) && element.text) return true;
609
-
610
- // Elements with test IDs
611
- if (element.testId) return true;
612
-
613
- // Elements with ARIA labels
614
- if (element.semanticContext.accessibility.ariaLabel) return true;
615
-
616
- // Form elements
617
- if (element.semanticContext.formContext) return true;
618
-
619
- return false;
620
- }
621
-
622
- private getTagName(element: t.JSXOpeningElement): string {
623
- const name = element.name;
624
- if (t.isJSXIdentifier(name)) {
625
- return name.name;
626
- } else if (t.isJSXMemberExpression(name)) {
627
- return `${(name.object as t.JSXIdentifier).name}.${name.property.name}`;
628
- }
629
- return 'unknown';
630
- }
631
-
632
- private extractAttributes(element: t.JSXOpeningElement): Record<string, any> {
633
- const attrs: Record<string, any> = {};
634
-
635
- element.attributes.forEach((attr) => {
636
- if (t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name)) {
637
- const key = attr.name.name;
638
- let value: any = true;
639
-
640
- if (attr.value) {
641
- if (t.isStringLiteral(attr.value)) {
642
- value = attr.value.value;
643
- } else if (t.isJSXExpressionContainer(attr.value)) {
644
- const expr = attr.value.expression;
645
- if (t.isStringLiteral(expr)) {
646
- value = expr.value;
647
- } else if (t.isBooleanLiteral(expr)) {
648
- value = expr.value;
649
- } else if (t.isNumericLiteral(expr)) {
650
- value = expr.value;
651
- } else {
652
- value = '{...}';
653
- }
654
- }
655
- }
656
-
657
- attrs[key] = value;
658
- }
659
- });
660
-
661
- return attrs;
662
- }
663
-
664
- private extractText(node: t.JSXElement): string | null {
665
- let text = '';
666
-
667
- node.children.forEach((child) => {
668
- if (t.isJSXText(child)) {
669
- text += child.value.trim();
670
- } else if (t.isJSXExpressionContainer(child)) {
671
- if (t.isStringLiteral(child.expression)) {
672
- text += child.expression.value;
673
- }
674
- }
675
- });
676
-
677
- return text.trim() || null;
678
- }
679
-
680
- /**
681
- * Get all discovered elements
682
- */
683
- getElements(): EnhancedUIElement[] {
684
- return this.elements;
685
- }
686
-
687
- /**
688
- * Get scanning stats
689
- */
690
- getStats() {
691
- return {
692
- totalElements: this.elements.length,
693
- filesScanned: this.scannedFiles.size,
694
- strategyBreakdown: this.getStrategyBreakdown(),
695
- purposeBreakdown: this.getPurposeBreakdown(),
696
- };
697
- }
698
-
699
- private getStrategyBreakdown() {
700
- const breakdown: Record<string, number> = {
701
- aria: 0,
702
- semantic: 0,
703
- testid: 0,
704
- css: 0,
705
- };
706
-
707
- this.elements.forEach(el => {
708
- el.selectorStrategies.forEach(strategy => {
709
- breakdown[strategy.type]++;
710
- });
711
- });
712
-
713
- return breakdown;
714
- }
715
-
716
- private getPurposeBreakdown() {
717
- const breakdown: Record<string, number> = {
718
- input: 0,
719
- navigation: 0,
720
- action: 0,
721
- display: 0,
722
- container: 0,
723
- };
724
-
725
- this.elements.forEach(el => {
726
- breakdown[el.semanticContext.purpose]++;
727
- });
728
-
729
- return breakdown;
730
- }
731
- }