@sun-asterisk/sungen 1.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 (451) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +490 -0
  3. package/bin/sungen.js +12 -0
  4. package/dist/cli/commands/auto-tag-command.d.ts +8 -0
  5. package/dist/cli/commands/auto-tag-command.d.ts.map +1 -0
  6. package/dist/cli/commands/auto-tag-command.js +104 -0
  7. package/dist/cli/commands/auto-tag-command.js.map +1 -0
  8. package/dist/cli/index.d.ts +7 -0
  9. package/dist/cli/index.d.ts.map +1 -0
  10. package/dist/cli/index.js +196 -0
  11. package/dist/cli/index.js.map +1 -0
  12. package/dist/config/ai-providers.yaml +56 -0
  13. package/dist/config/config-loader.d.ts +51 -0
  14. package/dist/config/config-loader.d.ts.map +1 -0
  15. package/dist/config/config-loader.js +216 -0
  16. package/dist/config/config-loader.js.map +1 -0
  17. package/dist/config/config-schema.d.ts +121 -0
  18. package/dist/config/config-schema.d.ts.map +1 -0
  19. package/dist/config/config-schema.js +7 -0
  20. package/dist/config/config-schema.js.map +1 -0
  21. package/dist/config/default.config.yaml +101 -0
  22. package/dist/config/framework.config.yaml +52 -0
  23. package/dist/config/routes.yaml +31 -0
  24. package/dist/core/selector-base/annotation-handler.d.ts +45 -0
  25. package/dist/core/selector-base/annotation-handler.d.ts.map +1 -0
  26. package/dist/core/selector-base/annotation-handler.js +102 -0
  27. package/dist/core/selector-base/annotation-handler.js.map +1 -0
  28. package/dist/core/selector-base/base-generator.d.ts +49 -0
  29. package/dist/core/selector-base/base-generator.d.ts.map +1 -0
  30. package/dist/core/selector-base/base-generator.js +214 -0
  31. package/dist/core/selector-base/base-generator.js.map +1 -0
  32. package/dist/core/selector-base/gherkin-parser.d.ts +24 -0
  33. package/dist/core/selector-base/gherkin-parser.d.ts.map +1 -0
  34. package/dist/core/selector-base/gherkin-parser.js +42 -0
  35. package/dist/core/selector-base/gherkin-parser.js.map +1 -0
  36. package/dist/core/selector-mapper/priority-mapper.d.ts +74 -0
  37. package/dist/core/selector-mapper/priority-mapper.d.ts.map +1 -0
  38. package/dist/core/selector-mapper/priority-mapper.js +477 -0
  39. package/dist/core/selector-mapper/priority-mapper.js.map +1 -0
  40. package/dist/core/ui-scanner/heuristics/base-heuristic.d.ts +91 -0
  41. package/dist/core/ui-scanner/heuristics/base-heuristic.d.ts.map +1 -0
  42. package/dist/core/ui-scanner/heuristics/base-heuristic.js +175 -0
  43. package/dist/core/ui-scanner/heuristics/base-heuristic.js.map +1 -0
  44. package/dist/core/ui-scanner/react-scanner.d.ts +32 -0
  45. package/dist/core/ui-scanner/react-scanner.d.ts.map +1 -0
  46. package/dist/core/ui-scanner/react-scanner.js +163 -0
  47. package/dist/core/ui-scanner/react-scanner.js.map +1 -0
  48. package/dist/core/ui-scanner/scanner-interface.d.ts +94 -0
  49. package/dist/core/ui-scanner/scanner-interface.d.ts.map +1 -0
  50. package/dist/core/ui-scanner/scanner-interface.js +33 -0
  51. package/dist/core/ui-scanner/scanner-interface.js.map +1 -0
  52. package/dist/core/ui-scanner/strict-scanner.d.ts +81 -0
  53. package/dist/core/ui-scanner/strict-scanner.d.ts.map +1 -0
  54. package/dist/core/ui-scanner/strict-scanner.js +511 -0
  55. package/dist/core/ui-scanner/strict-scanner.js.map +1 -0
  56. package/dist/executor/playwright/playwright-generator.d.ts +33 -0
  57. package/dist/executor/playwright/playwright-generator.d.ts.map +1 -0
  58. package/dist/executor/playwright/playwright-generator.js +136 -0
  59. package/dist/executor/playwright/playwright-generator.js.map +1 -0
  60. package/dist/executor/test-generator.d.ts +63 -0
  61. package/dist/executor/test-generator.d.ts.map +1 -0
  62. package/dist/executor/test-generator.js +30 -0
  63. package/dist/executor/test-generator.js.map +1 -0
  64. package/dist/external/ai-provider.d.ts +60 -0
  65. package/dist/external/ai-provider.d.ts.map +1 -0
  66. package/dist/external/ai-provider.js +30 -0
  67. package/dist/external/ai-provider.js.map +1 -0
  68. package/dist/external/anthropic-provider.d.ts +29 -0
  69. package/dist/external/anthropic-provider.d.ts.map +1 -0
  70. package/dist/external/anthropic-provider.js +85 -0
  71. package/dist/external/anthropic-provider.js.map +1 -0
  72. package/dist/generators/cache/cache-manager.d.ts +66 -0
  73. package/dist/generators/cache/cache-manager.d.ts.map +1 -0
  74. package/dist/generators/cache/cache-manager.js +286 -0
  75. package/dist/generators/cache/cache-manager.js.map +1 -0
  76. package/dist/generators/cli.d.ts +7 -0
  77. package/dist/generators/cli.d.ts.map +1 -0
  78. package/dist/generators/cli.js +570 -0
  79. package/dist/generators/cli.js.map +1 -0
  80. package/dist/generators/dsl-writer/index.d.ts +33 -0
  81. package/dist/generators/dsl-writer/index.d.ts.map +1 -0
  82. package/dist/generators/dsl-writer/index.js +226 -0
  83. package/dist/generators/dsl-writer/index.js.map +1 -0
  84. package/dist/generators/gherkin-parser/index.d.ts +47 -0
  85. package/dist/generators/gherkin-parser/index.d.ts.map +1 -0
  86. package/dist/generators/gherkin-parser/index.js +149 -0
  87. package/dist/generators/gherkin-parser/index.js.map +1 -0
  88. package/dist/generators/gherkin-parser/selector-extractor.d.ts +37 -0
  89. package/dist/generators/gherkin-parser/selector-extractor.d.ts.map +1 -0
  90. package/dist/generators/gherkin-parser/selector-extractor.js +108 -0
  91. package/dist/generators/gherkin-parser/selector-extractor.js.map +1 -0
  92. package/dist/generators/scaffold-generator/index.d.ts +111 -0
  93. package/dist/generators/scaffold-generator/index.d.ts.map +1 -0
  94. package/dist/generators/scaffold-generator/index.js +408 -0
  95. package/dist/generators/scaffold-generator/index.js.map +1 -0
  96. package/dist/generators/selector-mapper/ai-mapper.d.ts +56 -0
  97. package/dist/generators/selector-mapper/ai-mapper.d.ts.map +1 -0
  98. package/dist/generators/selector-mapper/ai-mapper.js +457 -0
  99. package/dist/generators/selector-mapper/ai-mapper.js.map +1 -0
  100. package/dist/generators/selector-mapper/hybrid-mapper.d.ts +67 -0
  101. package/dist/generators/selector-mapper/hybrid-mapper.d.ts.map +1 -0
  102. package/dist/generators/selector-mapper/hybrid-mapper.js +349 -0
  103. package/dist/generators/selector-mapper/hybrid-mapper.js.map +1 -0
  104. package/dist/generators/selector-mapper/index.d.ts +8 -0
  105. package/dist/generators/selector-mapper/index.d.ts.map +1 -0
  106. package/dist/generators/selector-mapper/index.js +12 -0
  107. package/dist/generators/selector-mapper/index.js.map +1 -0
  108. package/dist/generators/selector-mapper/intelligent-mapper.d.ts +125 -0
  109. package/dist/generators/selector-mapper/intelligent-mapper.d.ts.map +1 -0
  110. package/dist/generators/selector-mapper/intelligent-mapper.js +391 -0
  111. package/dist/generators/selector-mapper/intelligent-mapper.js.map +1 -0
  112. package/dist/generators/test-generator/adapters/adapter-interface.d.ts +49 -0
  113. package/dist/generators/test-generator/adapters/adapter-interface.d.ts.map +1 -0
  114. package/dist/generators/test-generator/adapters/adapter-interface.js +7 -0
  115. package/dist/generators/test-generator/adapters/adapter-interface.js.map +1 -0
  116. package/dist/generators/test-generator/adapters/adapter-registry.d.ts +29 -0
  117. package/dist/generators/test-generator/adapters/adapter-registry.d.ts.map +1 -0
  118. package/dist/generators/test-generator/adapters/adapter-registry.js +50 -0
  119. package/dist/generators/test-generator/adapters/adapter-registry.js.map +1 -0
  120. package/dist/generators/test-generator/adapters/index.d.ts +4 -0
  121. package/dist/generators/test-generator/adapters/index.d.ts.map +1 -0
  122. package/dist/generators/test-generator/adapters/index.js +13 -0
  123. package/dist/generators/test-generator/adapters/index.js.map +1 -0
  124. package/dist/generators/test-generator/adapters/playwright/playwright-adapter.d.ts +23 -0
  125. package/dist/generators/test-generator/adapters/playwright/playwright-adapter.d.ts.map +1 -0
  126. package/dist/generators/test-generator/adapters/playwright/playwright-adapter.js +38 -0
  127. package/dist/generators/test-generator/adapters/playwright/playwright-adapter.js.map +1 -0
  128. package/dist/generators/test-generator/adapters/playwright/templates/before-each.hbs +8 -0
  129. package/dist/generators/test-generator/adapters/playwright/templates/imports.hbs +5 -0
  130. package/dist/generators/test-generator/adapters/playwright/templates/scenario.hbs +8 -0
  131. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/check-action.hbs +1 -0
  132. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/clear-action.hbs +1 -0
  133. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/click-action.hbs +1 -0
  134. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/double-click-action.hbs +1 -0
  135. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/fill-action.hbs +1 -0
  136. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/hover-action.hbs +1 -0
  137. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/press-action.hbs +1 -0
  138. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/select-action.hbs +1 -0
  139. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/uncheck-action.hbs +1 -0
  140. package/dist/generators/test-generator/adapters/playwright/templates/steps/active-state-assertion.hbs +2 -0
  141. package/dist/generators/test-generator/adapters/playwright/templates/steps/ai-response-assertion-selector.hbs +5 -0
  142. package/dist/generators/test-generator/adapters/playwright/templates/steps/ai-response-assertion-simple.hbs +1 -0
  143. package/dist/generators/test-generator/adapters/playwright/templates/steps/application-running.hbs +1 -0
  144. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/checked-assertion.hbs +1 -0
  145. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/contain-text-assertion.hbs +1 -0
  146. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/count-assertion.hbs +1 -0
  147. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-assertion.hbs +2 -0
  148. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/empty-assertion.hbs +2 -0
  149. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/enabled-assertion.hbs +2 -0
  150. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/focused-assertion.hbs +1 -0
  151. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/have-text-assertion.hbs +1 -0
  152. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/not-checked-assertion.hbs +1 -0
  153. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/not-visible-assertion.hbs +1 -0
  154. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-assertion.hbs +1 -0
  155. package/dist/generators/test-generator/adapters/playwright/templates/steps/check-action.hbs +1 -0
  156. package/dist/generators/test-generator/adapters/playwright/templates/steps/checkbox.hbs +2 -0
  157. package/dist/generators/test-generator/adapters/playwright/templates/steps/checked-assertion.hbs +1 -0
  158. package/dist/generators/test-generator/adapters/playwright/templates/steps/clear-action.hbs +1 -0
  159. package/dist/generators/test-generator/adapters/playwright/templates/steps/clear-auth.hbs +6 -0
  160. package/dist/generators/test-generator/adapters/playwright/templates/steps/clear-browser-state.hbs +6 -0
  161. package/dist/generators/test-generator/adapters/playwright/templates/steps/clear-database.hbs +4 -0
  162. package/dist/generators/test-generator/adapters/playwright/templates/steps/clear.hbs +2 -0
  163. package/dist/generators/test-generator/adapters/playwright/templates/steps/click-action.hbs +1 -0
  164. package/dist/generators/test-generator/adapters/playwright/templates/steps/click.hbs +2 -0
  165. package/dist/generators/test-generator/adapters/playwright/templates/steps/contain-text-assertion.hbs +1 -0
  166. package/dist/generators/test-generator/adapters/playwright/templates/steps/contains-text-assertion.hbs +2 -0
  167. package/dist/generators/test-generator/adapters/playwright/templates/steps/count-assertion.hbs +1 -0
  168. package/dist/generators/test-generator/adapters/playwright/templates/steps/count-greater-than.hbs +3 -0
  169. package/dist/generators/test-generator/adapters/playwright/templates/steps/count-less-than.hbs +3 -0
  170. package/dist/generators/test-generator/adapters/playwright/templates/steps/disabled-assertion.hbs +2 -0
  171. package/dist/generators/test-generator/adapters/playwright/templates/steps/displayed-containing-text.hbs +3 -0
  172. package/dist/generators/test-generator/adapters/playwright/templates/steps/displayed-with-text.hbs +3 -0
  173. package/dist/generators/test-generator/adapters/playwright/templates/steps/double-click-action.hbs +1 -0
  174. package/dist/generators/test-generator/adapters/playwright/templates/steps/empty-assertion-advanced.hbs +3 -0
  175. package/dist/generators/test-generator/adapters/playwright/templates/steps/empty-assertion.hbs +2 -0
  176. package/dist/generators/test-generator/adapters/playwright/templates/steps/enabled-assertion.hbs +2 -0
  177. package/dist/generators/test-generator/adapters/playwright/templates/steps/error-message-assertion.hbs +3 -0
  178. package/dist/generators/test-generator/adapters/playwright/templates/steps/fill-action.hbs +1 -0
  179. package/dist/generators/test-generator/adapters/playwright/templates/steps/fill.hbs +2 -0
  180. package/dist/generators/test-generator/adapters/playwright/templates/steps/focused-assertion.hbs +1 -0
  181. package/dist/generators/test-generator/adapters/playwright/templates/steps/generic-message-assertion.hbs +3 -0
  182. package/dist/generators/test-generator/adapters/playwright/templates/steps/has-attribute.hbs +2 -0
  183. package/dist/generators/test-generator/adapters/playwright/templates/steps/has-class.hbs +2 -0
  184. package/dist/generators/test-generator/adapters/playwright/templates/steps/has-count.hbs +2 -0
  185. package/dist/generators/test-generator/adapters/playwright/templates/steps/has-image-src.hbs +3 -0
  186. package/dist/generators/test-generator/adapters/playwright/templates/steps/has-link.hbs +3 -0
  187. package/dist/generators/test-generator/adapters/playwright/templates/steps/has-placeholder.hbs +3 -0
  188. package/dist/generators/test-generator/adapters/playwright/templates/steps/has-value.hbs +2 -0
  189. package/dist/generators/test-generator/adapters/playwright/templates/steps/have-text-assertion.hbs +1 -0
  190. package/dist/generators/test-generator/adapters/playwright/templates/steps/hover-action.hbs +1 -0
  191. package/dist/generators/test-generator/adapters/playwright/templates/steps/html5-validation-check.hbs +4 -0
  192. package/dist/generators/test-generator/adapters/playwright/templates/steps/is-checked.hbs +2 -0
  193. package/dist/generators/test-generator/adapters/playwright/templates/steps/is-editable.hbs +2 -0
  194. package/dist/generators/test-generator/adapters/playwright/templates/steps/is-focused.hbs +2 -0
  195. package/dist/generators/test-generator/adapters/playwright/templates/steps/is-hidden.hbs +2 -0
  196. package/dist/generators/test-generator/adapters/playwright/templates/steps/is-unchecked.hbs +2 -0
  197. package/dist/generators/test-generator/adapters/playwright/templates/steps/locator.hbs +1 -0
  198. package/dist/generators/test-generator/adapters/playwright/templates/steps/login.hbs +8 -0
  199. package/dist/generators/test-generator/adapters/playwright/templates/steps/message-assertion-body.hbs +1 -0
  200. package/dist/generators/test-generator/adapters/playwright/templates/steps/message-assertion-selector.hbs +2 -0
  201. package/dist/generators/test-generator/adapters/playwright/templates/steps/message-count-assertion.hbs +3 -0
  202. package/dist/generators/test-generator/adapters/playwright/templates/steps/navigation/navigation.hbs +1 -0
  203. package/dist/generators/test-generator/adapters/playwright/templates/steps/navigation/route-assertion.hbs +2 -0
  204. package/dist/generators/test-generator/adapters/playwright/templates/steps/navigation/wait-for-element.hbs +1 -0
  205. package/dist/generators/test-generator/adapters/playwright/templates/steps/navigation/wait-timeout.hbs +1 -0
  206. package/dist/generators/test-generator/adapters/playwright/templates/steps/navigation.hbs +1 -0
  207. package/dist/generators/test-generator/adapters/playwright/templates/steps/not-checked-assertion.hbs +1 -0
  208. package/dist/generators/test-generator/adapters/playwright/templates/steps/not-visible-assertion.hbs +1 -0
  209. package/dist/generators/test-generator/adapters/playwright/templates/steps/not-visible.hbs +2 -0
  210. package/dist/generators/test-generator/adapters/playwright/templates/steps/notification-assertion.hbs +4 -0
  211. package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator.hbs +1 -0
  212. package/dist/generators/test-generator/adapters/playwright/templates/steps/press-action.hbs +1 -0
  213. package/dist/generators/test-generator/adapters/playwright/templates/steps/press-enter.hbs +2 -0
  214. package/dist/generators/test-generator/adapters/playwright/templates/steps/redirect-assertion.hbs +3 -0
  215. package/dist/generators/test-generator/adapters/playwright/templates/steps/route-assertion.hbs +2 -0
  216. package/dist/generators/test-generator/adapters/playwright/templates/steps/screen-navigation.hbs +3 -0
  217. package/dist/generators/test-generator/adapters/playwright/templates/steps/scroll-bottom-assertion.hbs +5 -0
  218. package/dist/generators/test-generator/adapters/playwright/templates/steps/select-action.hbs +1 -0
  219. package/dist/generators/test-generator/adapters/playwright/templates/steps/select.hbs +2 -0
  220. package/dist/generators/test-generator/adapters/playwright/templates/steps/setup/application-running.hbs +1 -0
  221. package/dist/generators/test-generator/adapters/playwright/templates/steps/setup/clear-auth.hbs +6 -0
  222. package/dist/generators/test-generator/adapters/playwright/templates/steps/setup/clear-browser-state.hbs +6 -0
  223. package/dist/generators/test-generator/adapters/playwright/templates/steps/setup/clear-database.hbs +4 -0
  224. package/dist/generators/test-generator/adapters/playwright/templates/steps/setup/user-login-todo.hbs +6 -0
  225. package/dist/generators/test-generator/adapters/playwright/templates/steps/text-matches-pattern.hbs +3 -0
  226. package/dist/generators/test-generator/adapters/playwright/templates/steps/uncheck-action.hbs +1 -0
  227. package/dist/generators/test-generator/adapters/playwright/templates/steps/user-login-todo.hbs +6 -0
  228. package/dist/generators/test-generator/adapters/playwright/templates/steps/visibility-assertion.hbs +2 -0
  229. package/dist/generators/test-generator/adapters/playwright/templates/steps/visible-assertion.hbs +1 -0
  230. package/dist/generators/test-generator/adapters/playwright/templates/steps/wait-for-element.hbs +1 -0
  231. package/dist/generators/test-generator/adapters/playwright/templates/steps/wait-timeout.hbs +1 -0
  232. package/dist/generators/test-generator/adapters/playwright/templates/steps/wait.hbs +1 -0
  233. package/dist/generators/test-generator/adapters/playwright/templates/test-file.hbs +19 -0
  234. package/dist/generators/test-generator/ai-step-mapper.d.ts +27 -0
  235. package/dist/generators/test-generator/ai-step-mapper.d.ts.map +1 -0
  236. package/dist/generators/test-generator/ai-step-mapper.js +204 -0
  237. package/dist/generators/test-generator/ai-step-mapper.js.map +1 -0
  238. package/dist/generators/test-generator/code-generator.d.ts +52 -0
  239. package/dist/generators/test-generator/code-generator.d.ts.map +1 -0
  240. package/dist/generators/test-generator/code-generator.js +191 -0
  241. package/dist/generators/test-generator/code-generator.js.map +1 -0
  242. package/dist/generators/test-generator/patterns/assertion-patterns.d.ts +7 -0
  243. package/dist/generators/test-generator/patterns/assertion-patterns.d.ts.map +1 -0
  244. package/dist/generators/test-generator/patterns/assertion-patterns.js +173 -0
  245. package/dist/generators/test-generator/patterns/assertion-patterns.js.map +1 -0
  246. package/dist/generators/test-generator/patterns/form-patterns.d.ts +8 -0
  247. package/dist/generators/test-generator/patterns/form-patterns.d.ts.map +1 -0
  248. package/dist/generators/test-generator/patterns/form-patterns.js +110 -0
  249. package/dist/generators/test-generator/patterns/form-patterns.js.map +1 -0
  250. package/dist/generators/test-generator/patterns/index.d.ts +45 -0
  251. package/dist/generators/test-generator/patterns/index.d.ts.map +1 -0
  252. package/dist/generators/test-generator/patterns/index.js +106 -0
  253. package/dist/generators/test-generator/patterns/index.js.map +1 -0
  254. package/dist/generators/test-generator/patterns/interaction-patterns.d.ts +7 -0
  255. package/dist/generators/test-generator/patterns/interaction-patterns.d.ts.map +1 -0
  256. package/dist/generators/test-generator/patterns/interaction-patterns.js +100 -0
  257. package/dist/generators/test-generator/patterns/interaction-patterns.js.map +1 -0
  258. package/dist/generators/test-generator/patterns/navigation-patterns.d.ts +8 -0
  259. package/dist/generators/test-generator/patterns/navigation-patterns.d.ts.map +1 -0
  260. package/dist/generators/test-generator/patterns/navigation-patterns.js +92 -0
  261. package/dist/generators/test-generator/patterns/navigation-patterns.js.map +1 -0
  262. package/dist/generators/test-generator/patterns/setup-patterns.d.ts +7 -0
  263. package/dist/generators/test-generator/patterns/setup-patterns.d.ts.map +1 -0
  264. package/dist/generators/test-generator/patterns/setup-patterns.js +84 -0
  265. package/dist/generators/test-generator/patterns/setup-patterns.js.map +1 -0
  266. package/dist/generators/test-generator/patterns/types.d.ts +38 -0
  267. package/dist/generators/test-generator/patterns/types.d.ts.map +1 -0
  268. package/dist/generators/test-generator/patterns/types.js +3 -0
  269. package/dist/generators/test-generator/patterns/types.js.map +1 -0
  270. package/dist/generators/test-generator/step-mapper-old.d.ts +180 -0
  271. package/dist/generators/test-generator/step-mapper-old.d.ts.map +1 -0
  272. package/dist/generators/test-generator/step-mapper-old.js +752 -0
  273. package/dist/generators/test-generator/step-mapper-old.js.map +1 -0
  274. package/dist/generators/test-generator/step-mapper-refactored.d.ts +47 -0
  275. package/dist/generators/test-generator/step-mapper-refactored.d.ts.map +1 -0
  276. package/dist/generators/test-generator/step-mapper-refactored.js +182 -0
  277. package/dist/generators/test-generator/step-mapper-refactored.js.map +1 -0
  278. package/dist/generators/test-generator/step-mapper.d.ts +66 -0
  279. package/dist/generators/test-generator/step-mapper.d.ts.map +1 -0
  280. package/dist/generators/test-generator/step-mapper.js +248 -0
  281. package/dist/generators/test-generator/step-mapper.js.map +1 -0
  282. package/dist/generators/test-generator/template-engine.d.ts +33 -0
  283. package/dist/generators/test-generator/template-engine.d.ts.map +1 -0
  284. package/dist/generators/test-generator/template-engine.js +129 -0
  285. package/dist/generators/test-generator/template-engine.js.map +1 -0
  286. package/dist/generators/test-generator/utils/data-resolver.d.ts +39 -0
  287. package/dist/generators/test-generator/utils/data-resolver.d.ts.map +1 -0
  288. package/dist/generators/test-generator/utils/data-resolver.js +162 -0
  289. package/dist/generators/test-generator/utils/data-resolver.js.map +1 -0
  290. package/dist/generators/test-generator/utils/path-inference.d.ts +49 -0
  291. package/dist/generators/test-generator/utils/path-inference.d.ts.map +1 -0
  292. package/dist/generators/test-generator/utils/path-inference.js +286 -0
  293. package/dist/generators/test-generator/utils/path-inference.js.map +1 -0
  294. package/dist/generators/test-generator/utils/selector-resolver.d.ts +93 -0
  295. package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -0
  296. package/dist/generators/test-generator/utils/selector-resolver.js +408 -0
  297. package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -0
  298. package/dist/generators/types.d.ts +118 -0
  299. package/dist/generators/types.d.ts.map +1 -0
  300. package/dist/generators/types.js +48 -0
  301. package/dist/generators/types.js.map +1 -0
  302. package/dist/generators/ui-model-builder/deep-scanner.d.ts +121 -0
  303. package/dist/generators/ui-model-builder/deep-scanner.d.ts.map +1 -0
  304. package/dist/generators/ui-model-builder/deep-scanner.js +1113 -0
  305. package/dist/generators/ui-model-builder/deep-scanner.js.map +1 -0
  306. package/dist/generators/ui-model-builder/enhanced-deep-scanner.d.ts +110 -0
  307. package/dist/generators/ui-model-builder/enhanced-deep-scanner.d.ts.map +1 -0
  308. package/dist/generators/ui-model-builder/enhanced-deep-scanner.js +608 -0
  309. package/dist/generators/ui-model-builder/enhanced-deep-scanner.js.map +1 -0
  310. package/dist/generators/ui-model-builder/react-scanner.d.ts +107 -0
  311. package/dist/generators/ui-model-builder/react-scanner.d.ts.map +1 -0
  312. package/dist/generators/ui-model-builder/react-scanner.js +797 -0
  313. package/dist/generators/ui-model-builder/react-scanner.js.map +1 -0
  314. package/dist/input/cli-adapter.d.ts +63 -0
  315. package/dist/input/cli-adapter.d.ts.map +1 -0
  316. package/dist/input/cli-adapter.js +173 -0
  317. package/dist/input/cli-adapter.js.map +1 -0
  318. package/dist/input/config-adapter.d.ts +25 -0
  319. package/dist/input/config-adapter.d.ts.map +1 -0
  320. package/dist/input/config-adapter.js +70 -0
  321. package/dist/input/config-adapter.js.map +1 -0
  322. package/dist/input/input-adapter.d.ts +28 -0
  323. package/dist/input/input-adapter.d.ts.map +1 -0
  324. package/dist/input/input-adapter.js +17 -0
  325. package/dist/input/input-adapter.js.map +1 -0
  326. package/dist/input/vscode-adapter.d.ts +62 -0
  327. package/dist/input/vscode-adapter.d.ts.map +1 -0
  328. package/dist/input/vscode-adapter.js +64 -0
  329. package/dist/input/vscode-adapter.js.map +1 -0
  330. package/dist/orchestrator/cache-manager.d.ts +37 -0
  331. package/dist/orchestrator/cache-manager.d.ts.map +1 -0
  332. package/dist/orchestrator/cache-manager.js +148 -0
  333. package/dist/orchestrator/cache-manager.js.map +1 -0
  334. package/dist/orchestrator/pipeline.d.ts +73 -0
  335. package/dist/orchestrator/pipeline.d.ts.map +1 -0
  336. package/dist/orchestrator/pipeline.js +607 -0
  337. package/dist/orchestrator/pipeline.js.map +1 -0
  338. package/dist/orchestrator/project-initializer.d.ts +51 -0
  339. package/dist/orchestrator/project-initializer.d.ts.map +1 -0
  340. package/dist/orchestrator/project-initializer.js +326 -0
  341. package/dist/orchestrator/project-initializer.js.map +1 -0
  342. package/dist/orchestrator/reporter.d.ts +15 -0
  343. package/dist/orchestrator/reporter.d.ts.map +1 -0
  344. package/dist/orchestrator/reporter.js +30 -0
  345. package/dist/orchestrator/reporter.js.map +1 -0
  346. package/dist/orchestrator/screen-manager.d.ts +47 -0
  347. package/dist/orchestrator/screen-manager.d.ts.map +1 -0
  348. package/dist/orchestrator/screen-manager.js +271 -0
  349. package/dist/orchestrator/screen-manager.js.map +1 -0
  350. package/dist/tools/auto-tagger.d.ts +107 -0
  351. package/dist/tools/auto-tagger.d.ts.map +1 -0
  352. package/dist/tools/auto-tagger.js +502 -0
  353. package/dist/tools/auto-tagger.js.map +1 -0
  354. package/package.json +73 -0
  355. package/src/cli/commands/auto-tag-command.ts +80 -0
  356. package/src/cli/index.ts +205 -0
  357. package/src/config/ai-providers.yaml +56 -0
  358. package/src/config/config-loader.ts +248 -0
  359. package/src/config/config-schema.ts +148 -0
  360. package/src/config/default.config.yaml +101 -0
  361. package/src/config/framework.config.yaml +52 -0
  362. package/src/config/routes.yaml +31 -0
  363. package/src/core/selector-base/annotation-handler.ts +127 -0
  364. package/src/core/selector-base/base-generator.ts +234 -0
  365. package/src/core/selector-base/gherkin-parser.ts +57 -0
  366. package/src/core/selector-mapper/priority-mapper.ts +607 -0
  367. package/src/core/ui-scanner/heuristics/base-heuristic.ts +216 -0
  368. package/src/core/ui-scanner/react-scanner.ts +156 -0
  369. package/src/core/ui-scanner/scanner-interface.ts +133 -0
  370. package/src/core/ui-scanner/strict-scanner.ts +629 -0
  371. package/src/executor/playwright/playwright-generator.ts +125 -0
  372. package/src/executor/test-generator.ts +90 -0
  373. package/src/external/ai-provider.ts +90 -0
  374. package/src/external/anthropic-provider.ts +114 -0
  375. package/src/generators/README.md +410 -0
  376. package/src/generators/cache/cache-manager.ts +322 -0
  377. package/src/generators/cli.ts +640 -0
  378. package/src/generators/dsl-writer/index.ts +253 -0
  379. package/src/generators/gherkin-parser/index.ts +155 -0
  380. package/src/generators/gherkin-parser/selector-extractor.ts +142 -0
  381. package/src/generators/scaffold-generator/index.ts +524 -0
  382. package/src/generators/selector-mapper/ai-mapper.ts +528 -0
  383. package/src/generators/selector-mapper/hybrid-mapper.ts +427 -0
  384. package/src/generators/selector-mapper/index.ts +10 -0
  385. package/src/generators/selector-mapper/intelligent-mapper.ts +530 -0
  386. package/src/generators/test-generator/adapters/adapter-interface.ts +49 -0
  387. package/src/generators/test-generator/adapters/adapter-registry.ts +56 -0
  388. package/src/generators/test-generator/adapters/index.ts +9 -0
  389. package/src/generators/test-generator/adapters/playwright/playwright-adapter.ts +40 -0
  390. package/src/generators/test-generator/adapters/playwright/templates/before-each.hbs +8 -0
  391. package/src/generators/test-generator/adapters/playwright/templates/imports.hbs +5 -0
  392. package/src/generators/test-generator/adapters/playwright/templates/scenario.hbs +8 -0
  393. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/check-action.hbs +1 -0
  394. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/clear-action.hbs +1 -0
  395. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/click-action.hbs +1 -0
  396. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/double-click-action.hbs +1 -0
  397. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/fill-action.hbs +1 -0
  398. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/hover-action.hbs +1 -0
  399. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/press-action.hbs +1 -0
  400. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/select-action.hbs +1 -0
  401. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/uncheck-action.hbs +1 -0
  402. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/checked-assertion.hbs +1 -0
  403. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/contain-text-assertion.hbs +1 -0
  404. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/count-assertion.hbs +1 -0
  405. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-assertion.hbs +2 -0
  406. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/empty-assertion.hbs +2 -0
  407. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/enabled-assertion.hbs +2 -0
  408. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/focused-assertion.hbs +1 -0
  409. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/have-text-assertion.hbs +1 -0
  410. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/not-checked-assertion.hbs +1 -0
  411. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/not-visible-assertion.hbs +1 -0
  412. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-assertion.hbs +1 -0
  413. package/src/generators/test-generator/adapters/playwright/templates/steps/navigation/navigation.hbs +1 -0
  414. package/src/generators/test-generator/adapters/playwright/templates/steps/navigation/route-assertion.hbs +2 -0
  415. package/src/generators/test-generator/adapters/playwright/templates/steps/navigation/wait-for-element.hbs +1 -0
  416. package/src/generators/test-generator/adapters/playwright/templates/steps/navigation/wait-timeout.hbs +1 -0
  417. package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator.hbs +1 -0
  418. package/src/generators/test-generator/adapters/playwright/templates/steps/setup/application-running.hbs +1 -0
  419. package/src/generators/test-generator/adapters/playwright/templates/steps/setup/clear-auth.hbs +6 -0
  420. package/src/generators/test-generator/adapters/playwright/templates/steps/setup/clear-browser-state.hbs +6 -0
  421. package/src/generators/test-generator/adapters/playwright/templates/steps/setup/clear-database.hbs +4 -0
  422. package/src/generators/test-generator/adapters/playwright/templates/steps/setup/user-login-todo.hbs +6 -0
  423. package/src/generators/test-generator/adapters/playwright/templates/test-file.hbs +19 -0
  424. package/src/generators/test-generator/ai-step-mapper.ts +224 -0
  425. package/src/generators/test-generator/code-generator.ts +235 -0
  426. package/src/generators/test-generator/patterns/assertion-patterns.ts +183 -0
  427. package/src/generators/test-generator/patterns/form-patterns.ts +124 -0
  428. package/src/generators/test-generator/patterns/index.ts +97 -0
  429. package/src/generators/test-generator/patterns/interaction-patterns.ts +119 -0
  430. package/src/generators/test-generator/patterns/navigation-patterns.ts +110 -0
  431. package/src/generators/test-generator/patterns/setup-patterns.ts +94 -0
  432. package/src/generators/test-generator/patterns/types.ts +41 -0
  433. package/src/generators/test-generator/step-mapper.ts +254 -0
  434. package/src/generators/test-generator/template-engine.ts +160 -0
  435. package/src/generators/test-generator/utils/data-resolver.ts +147 -0
  436. package/src/generators/test-generator/utils/path-inference.ts +344 -0
  437. package/src/generators/test-generator/utils/selector-resolver.ts +480 -0
  438. package/src/generators/types.ts +226 -0
  439. package/src/generators/ui-model-builder/deep-scanner.ts +1244 -0
  440. package/src/generators/ui-model-builder/enhanced-deep-scanner.ts +731 -0
  441. package/src/generators/ui-model-builder/react-scanner.ts +959 -0
  442. package/src/input/cli-adapter.ts +185 -0
  443. package/src/input/config-adapter.ts +71 -0
  444. package/src/input/input-adapter.ts +32 -0
  445. package/src/input/vscode-adapter.ts +90 -0
  446. package/src/orchestrator/cache-manager.ts +138 -0
  447. package/src/orchestrator/pipeline.ts +713 -0
  448. package/src/orchestrator/project-initializer.ts +315 -0
  449. package/src/orchestrator/reporter.ts +36 -0
  450. package/src/orchestrator/screen-manager.ts +268 -0
  451. package/src/tools/auto-tagger.ts +572 -0
@@ -0,0 +1,629 @@
1
+ /**
2
+ * Strict UI Scanner - v3.1
3
+ *
4
+ * Priority-based, deterministic scanner with strict filtering
5
+ *
6
+ * Key Principles:
7
+ * 1. Only scan INTERACTIVE elements (input, button, a, select, textarea)
8
+ * 2. Only include elements with data-testid OR role attributes
9
+ * 3. Discard generic containers (div, span) unless they have id
10
+ * 4. 80-90% noise reduction vs deep scanner
11
+ *
12
+ * Philosophy: AI is a fallback, not the primary solution
13
+ */
14
+
15
+ import * as parser from '@babel/parser';
16
+ import traverse from '@babel/traverse';
17
+ import * as t from '@babel/types';
18
+ import * as fs from 'fs';
19
+ import * as path from 'path';
20
+
21
+ // ============================================================================
22
+ // TYPES
23
+ // ============================================================================
24
+
25
+ export interface StrictScanConfig {
26
+ sourceRoot: string;
27
+ projectRoot: string;
28
+ strictMode: boolean;
29
+ filterRules: {
30
+ allowedTags: string[];
31
+ requireAttributes: string[];
32
+ allowGenericWithId: boolean;
33
+ };
34
+ verbose?: boolean;
35
+ }
36
+
37
+ export interface StrictUIElement {
38
+ // Flat, locator-centric schema
39
+ logicalName: string; // e.g., "email-input"
40
+ primaryLocator: string; // e.g., "[data-testid='login-email']"
41
+ fallbackStrategy: string; // e.g., "role=textbox[name='email']"
42
+
43
+ // Metadata
44
+ tag: string; // e.g., "input"
45
+ elementType: string; // e.g., "email", "button", "link"
46
+
47
+ // Discovery info
48
+ discoveryMethod: 'direct-id' | 'accessibility' | 'heuristic';
49
+ confidence: 'high' | 'medium' | 'low';
50
+
51
+ // Source tracking
52
+ sourceFile: string;
53
+
54
+ // Optional attributes
55
+ label?: string;
56
+ placeholder?: string;
57
+ ariaLabel?: string;
58
+ role?: string;
59
+ text?: string;
60
+
61
+ // Raw props for reference
62
+ props: Record<string, any>;
63
+ }
64
+
65
+ export interface StrictScanResult {
66
+ screen: string;
67
+ timestamp: number;
68
+ framework: string;
69
+ sourceFiles: string[];
70
+ elements: StrictUIElement[];
71
+ stats: {
72
+ totalScanned: number;
73
+ totalFiltered: number;
74
+ totalIncluded: number;
75
+ filterRate: number;
76
+ directIdMatches: number;
77
+ accessibilityMatches: number;
78
+ heuristicMatches: number;
79
+ scanDuration: number;
80
+ };
81
+ }
82
+
83
+ // ============================================================================
84
+ // STRICT FILTER
85
+ // ============================================================================
86
+
87
+ class StrictElementFilter {
88
+ private config: StrictScanConfig;
89
+
90
+ constructor(config: StrictScanConfig) {
91
+ this.config = config;
92
+ }
93
+
94
+ /**
95
+ * Determine if element should be included in scan results
96
+ *
97
+ * Priority filtering:
98
+ * 1. Interactive tags (input, button, a, select, textarea)
99
+ * 2. Elements with data-testid or role
100
+ * 3. Generic containers (div, span) ONLY if they have id
101
+ */
102
+ shouldInclude(element: any): boolean {
103
+ const tag = element.tag?.toLowerCase();
104
+ const props = element.props || {};
105
+
106
+ // Priority 1: Interactive elements
107
+ const interactiveTags = this.config.filterRules.allowedTags;
108
+ if (interactiveTags.includes(tag)) {
109
+ return true;
110
+ }
111
+
112
+ // Priority 2: Elements with required attributes (data-testid or role)
113
+ const hasRequiredAttr = this.config.filterRules.requireAttributes.some(
114
+ attr => props[attr] !== undefined && props[attr] !== null
115
+ );
116
+ if (hasRequiredAttr) {
117
+ return true;
118
+ }
119
+
120
+ // Priority 3: Generic containers with ID
121
+ if (this.config.filterRules.allowGenericWithId) {
122
+ const genericTags = ['div', 'span'];
123
+ if (genericTags.includes(tag) && props.id) {
124
+ return true;
125
+ }
126
+ }
127
+
128
+ // Filter out everything else
129
+ return false;
130
+ }
131
+
132
+ /**
133
+ * Get filter reason for logging/debugging
134
+ */
135
+ getFilterReason(element: any): string {
136
+ const tag = element.tag?.toLowerCase();
137
+ const props = element.props || {};
138
+
139
+ if (this.config.filterRules.allowedTags.includes(tag)) {
140
+ return 'interactive-tag';
141
+ }
142
+
143
+ const hasRequiredAttr = this.config.filterRules.requireAttributes.some(
144
+ attr => props[attr] !== undefined
145
+ );
146
+ if (hasRequiredAttr) {
147
+ return 'has-required-attribute';
148
+ }
149
+
150
+ if (['div', 'span'].includes(tag) && props.id) {
151
+ return 'generic-with-id';
152
+ }
153
+
154
+ return 'filtered-out';
155
+ }
156
+ }
157
+
158
+ // ============================================================================
159
+ // LOGICAL NAME GENERATOR
160
+ // ============================================================================
161
+
162
+ class LogicalNameGenerator {
163
+ /**
164
+ * Generate logical, human-readable name for element
165
+ *
166
+ * Examples:
167
+ * - input[type=email] → "email-input"
168
+ * - button[type=submit] → "submit-btn"
169
+ * - a[href="/login"] → "login-link"
170
+ */
171
+ generate(element: any, index: number): string {
172
+ const tag = element.tag?.toLowerCase();
173
+ const props = element.props || {};
174
+
175
+ let name = '';
176
+
177
+ // Use data-testid if available (most stable)
178
+ if (props['data-testid']) {
179
+ return this.cleanName(props['data-testid']);
180
+ }
181
+
182
+ // Use name attribute
183
+ if (props.name) {
184
+ name = props.name;
185
+ }
186
+ // Use id attribute
187
+ else if (props.id) {
188
+ name = props.id;
189
+ }
190
+ // Use aria-label
191
+ else if (props['aria-label']) {
192
+ name = props['aria-label'];
193
+ }
194
+ // Use placeholder for inputs
195
+ else if (props.placeholder && tag === 'input') {
196
+ name = props.placeholder;
197
+ }
198
+ // Use text content for buttons/links
199
+ else if (element.text && ['button', 'a'].includes(tag)) {
200
+ name = element.text;
201
+ }
202
+ // Use type for inputs
203
+ else if (props.type && tag === 'input') {
204
+ name = props.type;
205
+ }
206
+ // Fallback to tag + index
207
+ else {
208
+ name = `${tag}-${index}`;
209
+ }
210
+
211
+ // Add suffix based on tag
212
+ const suffix = this.getSuffix(tag);
213
+
214
+ return this.cleanName(name) + suffix;
215
+ }
216
+
217
+ private getSuffix(tag: string): string {
218
+ const suffixMap: Record<string, string> = {
219
+ 'input': '-input',
220
+ 'textarea': '-textarea',
221
+ 'select': '-select',
222
+ 'button': '-btn',
223
+ 'a': '-link',
224
+ };
225
+
226
+ return suffixMap[tag] || '';
227
+ }
228
+
229
+ private cleanName(name: string): string {
230
+ return name
231
+ .toLowerCase()
232
+ .replace(/[^a-z0-9]+/g, '-')
233
+ .replace(/^-+|-+$/g, '');
234
+ }
235
+ }
236
+
237
+ // ============================================================================
238
+ // LOCATOR GENERATOR
239
+ // ============================================================================
240
+
241
+ class LocatorGenerator {
242
+ /**
243
+ * Generate primary locator (Playwright-compatible)
244
+ *
245
+ * Priority:
246
+ * 1. data-testid (most stable)
247
+ * 2. role + aria-label (semantic)
248
+ * 3. id attribute
249
+ * 4. name attribute
250
+ * 5. type + other attributes
251
+ */
252
+ generatePrimary(element: any): { locator: string; method: string; confidence: string } {
253
+ const tag = element.tag?.toLowerCase();
254
+ const props = element.props || {};
255
+
256
+ // Priority 1: data-testid (BEST - deterministic, stable)
257
+ if (props['data-testid']) {
258
+ return {
259
+ locator: `[data-testid="${props['data-testid']}"]`,
260
+ method: 'direct-id',
261
+ confidence: 'high',
262
+ };
263
+ }
264
+
265
+ // Priority 2: role + aria-label (GOOD - semantic, accessible)
266
+ if (props.role && props['aria-label']) {
267
+ return {
268
+ locator: `[role="${props.role}"][aria-label="${props['aria-label']}"]`,
269
+ method: 'accessibility',
270
+ confidence: 'high',
271
+ };
272
+ }
273
+
274
+ // Priority 2b: role only
275
+ if (props.role) {
276
+ return {
277
+ locator: `[role="${props.role}"]`,
278
+ method: 'accessibility',
279
+ confidence: 'medium',
280
+ };
281
+ }
282
+
283
+ // Priority 3: id attribute (OKAY - might change)
284
+ if (props.id) {
285
+ return {
286
+ locator: `#${props.id}`,
287
+ method: 'heuristic',
288
+ confidence: 'medium',
289
+ };
290
+ }
291
+
292
+ // Priority 4: name attribute (for form fields)
293
+ if (props.name && ['input', 'select', 'textarea'].includes(tag)) {
294
+ return {
295
+ locator: `${tag}[name="${props.name}"]`,
296
+ method: 'heuristic',
297
+ confidence: 'medium',
298
+ };
299
+ }
300
+
301
+ // Priority 5: type + placeholder (for inputs)
302
+ if (tag === 'input' && props.type && props.placeholder) {
303
+ return {
304
+ locator: `input[type="${props.type}"][placeholder="${props.placeholder}"]`,
305
+ method: 'heuristic',
306
+ confidence: 'low',
307
+ };
308
+ }
309
+
310
+ // Priority 6: tag + type
311
+ if (props.type) {
312
+ return {
313
+ locator: `${tag}[type="${props.type}"]`,
314
+ method: 'heuristic',
315
+ confidence: 'low',
316
+ };
317
+ }
318
+
319
+ // Fallback: tag only (WEAK)
320
+ return {
321
+ locator: tag,
322
+ method: 'heuristic',
323
+ confidence: 'low',
324
+ };
325
+ }
326
+
327
+ /**
328
+ * Generate fallback strategy (when primary fails)
329
+ */
330
+ generateFallback(element: any): string {
331
+ const tag = element.tag?.toLowerCase();
332
+ const props = element.props || {};
333
+
334
+ const strategies: string[] = [];
335
+
336
+ // Strategy 1: Text content
337
+ if (element.text && ['button', 'a'].includes(tag)) {
338
+ strategies.push(`${tag}:has-text("${element.text}")`);
339
+ }
340
+
341
+ // Strategy 2: Placeholder
342
+ if (props.placeholder) {
343
+ strategies.push(`${tag}[placeholder="${props.placeholder}"]`);
344
+ }
345
+
346
+ // Strategy 3: Name
347
+ if (props.name) {
348
+ strategies.push(`${tag}[name="${props.name}"]`);
349
+ }
350
+
351
+ // Strategy 4: Type
352
+ if (props.type) {
353
+ strategies.push(`${tag}[type="${props.type}"]`);
354
+ }
355
+
356
+ // Return first strategy or tag as ultimate fallback
357
+ return strategies.length > 0 ? strategies[0] : tag;
358
+ }
359
+ }
360
+
361
+ // ============================================================================
362
+ // STRICT SCANNER
363
+ // ============================================================================
364
+
365
+ export class StrictScanner {
366
+ private config: StrictScanConfig;
367
+ private filter: StrictElementFilter;
368
+ private nameGenerator: LogicalNameGenerator;
369
+ private locatorGenerator: LocatorGenerator;
370
+
371
+ private elements: StrictUIElement[] = [];
372
+ private scannedFiles = new Set<string>();
373
+ private stats = {
374
+ totalScanned: 0,
375
+ totalFiltered: 0,
376
+ totalIncluded: 0,
377
+ directIdMatches: 0,
378
+ accessibilityMatches: 0,
379
+ heuristicMatches: 0,
380
+ };
381
+
382
+ constructor(config: StrictScanConfig) {
383
+ this.config = config;
384
+ this.filter = new StrictElementFilter(config);
385
+ this.nameGenerator = new LogicalNameGenerator();
386
+ this.locatorGenerator = new LocatorGenerator();
387
+ }
388
+
389
+ /**
390
+ * Scan a screen and generate strict UI model
391
+ */
392
+ async scan(screenName: string): Promise<StrictScanResult> {
393
+ const startTime = Date.now();
394
+
395
+ // Find entry file for screen
396
+ const entryFile = this.findEntryFile(screenName);
397
+ if (!entryFile) {
398
+ throw new Error(`Entry file not found for screen: ${screenName}`);
399
+ }
400
+
401
+ // Scan recursively
402
+ await this.scanFile(entryFile);
403
+
404
+ const duration = Date.now() - startTime;
405
+
406
+ return {
407
+ screen: screenName,
408
+ timestamp: Date.now(),
409
+ framework: 'react',
410
+ sourceFiles: Array.from(this.scannedFiles),
411
+ elements: this.elements,
412
+ stats: {
413
+ ...this.stats,
414
+ filterRate: this.stats.totalScanned > 0
415
+ ? (this.stats.totalFiltered / this.stats.totalScanned) * 100
416
+ : 0,
417
+ scanDuration: duration,
418
+ },
419
+ };
420
+ }
421
+
422
+ private findEntryFile(screenName: string): string | null {
423
+ // Convert screen name to path: auth-login -> auth/login
424
+ const screenPath = screenName.replace(/-/g, '/');
425
+
426
+ // Try common patterns
427
+ const patterns = [
428
+ `${screenPath}/page.tsx`,
429
+ `${screenPath}/index.tsx`,
430
+ `${screenPath}.tsx`,
431
+ `${screenPath}/page.js`,
432
+ `${screenPath}/index.js`,
433
+ `${screenPath}.js`,
434
+ ];
435
+
436
+ for (const pattern of patterns) {
437
+ const filePath = path.join(this.config.sourceRoot, pattern);
438
+ if (fs.existsSync(filePath)) {
439
+ return filePath;
440
+ }
441
+ }
442
+
443
+ return null;
444
+ }
445
+
446
+ private async scanFile(filePath: string): Promise<void> {
447
+ // Avoid re-scanning
448
+ if (this.scannedFiles.has(filePath)) {
449
+ return;
450
+ }
451
+
452
+ this.scannedFiles.add(filePath);
453
+
454
+ // Read file
455
+ const code = fs.readFileSync(filePath, 'utf-8');
456
+
457
+ // Parse with Babel
458
+ const ast = parser.parse(code, {
459
+ sourceType: 'module',
460
+ plugins: ['jsx', 'typescript'],
461
+ });
462
+
463
+ // Traverse AST and extract elements
464
+ traverse(ast, {
465
+ JSXElement: (path) => {
466
+ this.processJSXElement(path.node, filePath);
467
+ },
468
+ });
469
+ }
470
+
471
+ private processJSXElement(node: any, sourceFile: string): void {
472
+ const element = this.extractElementData(node);
473
+
474
+ this.stats.totalScanned++;
475
+
476
+ // Apply strict filter
477
+ if (!this.filter.shouldInclude(element)) {
478
+ this.stats.totalFiltered++;
479
+
480
+ if (this.config.verbose) {
481
+ const reason = this.filter.getFilterReason(element);
482
+ console.log(`[FILTERED] ${element.tag} - ${reason}`);
483
+ }
484
+
485
+ return;
486
+ }
487
+
488
+ // Element passed filter - process it
489
+ this.stats.totalIncluded++;
490
+
491
+ const strictElement = this.buildStrictElement(element, sourceFile);
492
+ this.elements.push(strictElement);
493
+
494
+ // Update discovery stats
495
+ if (strictElement.discoveryMethod === 'direct-id') {
496
+ this.stats.directIdMatches++;
497
+ } else if (strictElement.discoveryMethod === 'accessibility') {
498
+ this.stats.accessibilityMatches++;
499
+ } else {
500
+ this.stats.heuristicMatches++;
501
+ }
502
+
503
+ if (this.config.verbose) {
504
+ console.log(
505
+ `[INCLUDED] ${strictElement.logicalName} - ${strictElement.discoveryMethod} (${strictElement.confidence})`
506
+ );
507
+ }
508
+ }
509
+
510
+ private extractElementData(node: any): any {
511
+ // Extract tag name
512
+ const openingElement = node.openingElement;
513
+ const tag = this.getTagName(openingElement.name);
514
+
515
+ // Extract props
516
+ const props: Record<string, any> = {};
517
+ for (const attr of openingElement.attributes || []) {
518
+ if (t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name)) {
519
+ const name = attr.name.name;
520
+ const value = this.getAttributeValue(attr.value);
521
+ props[name] = value;
522
+ }
523
+ }
524
+
525
+ // Extract text content
526
+ const text = this.extractTextContent(node);
527
+
528
+ return { tag, props, text };
529
+ }
530
+
531
+ private getTagName(name: any): string {
532
+ if (t.isJSXIdentifier(name)) {
533
+ return name.name;
534
+ }
535
+ if (t.isJSXMemberExpression(name)) {
536
+ // Handle <Form.Input> → "input"
537
+ return this.getTagName(name.property);
538
+ }
539
+ return 'unknown';
540
+ }
541
+
542
+ private getAttributeValue(value: any): any {
543
+ if (!value) return true; // Boolean attribute
544
+ if (t.isStringLiteral(value)) return value.value;
545
+ if (t.isJSXExpressionContainer(value)) {
546
+ if (t.isStringLiteral(value.expression)) {
547
+ return value.expression.value;
548
+ }
549
+ if (t.isBooleanLiteral(value.expression)) {
550
+ return value.expression.value;
551
+ }
552
+ if (t.isNumericLiteral(value.expression)) {
553
+ return value.expression.value;
554
+ }
555
+ }
556
+ return undefined;
557
+ }
558
+
559
+ private extractTextContent(node: any): string | null {
560
+ const children = node.children || [];
561
+
562
+ for (const child of children) {
563
+ if (t.isJSXText(child)) {
564
+ const text = child.value.trim();
565
+ if (text) return text;
566
+ }
567
+ if (t.isJSXExpressionContainer(child)) {
568
+ if (t.isStringLiteral(child.expression)) {
569
+ return child.expression.value;
570
+ }
571
+ }
572
+ }
573
+
574
+ return null;
575
+ }
576
+
577
+ private buildStrictElement(element: any, sourceFile: string): StrictUIElement {
578
+ // Generate logical name
579
+ const logicalName = this.nameGenerator.generate(element, this.elements.length);
580
+
581
+ // Generate locators
582
+ const primary = this.locatorGenerator.generatePrimary(element);
583
+ const fallback = this.locatorGenerator.generateFallback(element);
584
+
585
+ // Determine element type
586
+ const elementType = this.inferElementType(element);
587
+
588
+ return {
589
+ logicalName,
590
+ primaryLocator: primary.locator,
591
+ fallbackStrategy: fallback,
592
+
593
+ tag: element.tag,
594
+ elementType,
595
+
596
+ discoveryMethod: primary.method as any,
597
+ confidence: primary.confidence as any,
598
+
599
+ sourceFile,
600
+
601
+ label: element.props.label,
602
+ placeholder: element.props.placeholder,
603
+ ariaLabel: element.props['aria-label'],
604
+ role: element.props.role,
605
+ text: element.text,
606
+
607
+ props: element.props,
608
+ };
609
+ }
610
+
611
+ private inferElementType(element: any): string {
612
+ const tag = element.tag?.toLowerCase();
613
+ const props = element.props || {};
614
+
615
+ if (tag === 'input' && props.type) {
616
+ return props.type; // email, password, text, etc.
617
+ }
618
+
619
+ if (tag === 'button') {
620
+ return props.type || 'button';
621
+ }
622
+
623
+ if (tag === 'a') {
624
+ return 'link';
625
+ }
626
+
627
+ return tag;
628
+ }
629
+ }