@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,94 @@
1
+ import { ParsedStep } from '../../gherkin-parser';
2
+ import { StepPattern } from './types';
3
+
4
+ /**
5
+ * Setup and precondition patterns: application setup, authentication state, etc.
6
+ * Uses templates for framework-agnostic code generation
7
+ */
8
+ export const setupPatterns: StepPattern[] = [
9
+ {
10
+ name: 'application-running',
11
+ matcher: (step: ParsedStep) =>
12
+ step.text.includes('application is running') ||
13
+ step.text.includes('application running') ||
14
+ step.text.includes('app is running'),
15
+ generator: (step, context) => {
16
+ const code = context.templateEngine.renderStep('application-running', {});
17
+
18
+ return {
19
+ code,
20
+ comment: `Setup: Application is running`,
21
+ };
22
+ },
23
+ priority: 5,
24
+ },
25
+ {
26
+ name: 'user-not-logged-in',
27
+ matcher: (step: ParsedStep) =>
28
+ step.text.includes('user is not logged in') ||
29
+ step.text.includes('not logged in') ||
30
+ step.text.includes('logged out'),
31
+ generator: (step, context) => {
32
+ const code = context.templateEngine.renderStep('clear-auth', {});
33
+
34
+ return {
35
+ code,
36
+ comment: `Clear authentication state (ensure user is logged out)`,
37
+ };
38
+ },
39
+ priority: 9,
40
+ },
41
+ {
42
+ name: 'user-logged-in',
43
+ matcher: (step: ParsedStep) =>
44
+ (step.text.includes('user is logged in') ||
45
+ step.text.includes('logged in as')) &&
46
+ !step.text.includes('not logged in'),
47
+ generator: (step, context) => {
48
+ // Check if there's a data reference for user credentials
49
+ const userRef = step.dataRef || 'valid_user';
50
+
51
+ const code = context.templateEngine.renderStep('user-login-todo', {
52
+ userRef,
53
+ });
54
+
55
+ return {
56
+ code,
57
+ comment: `Setup: User logged in as ${userRef}`,
58
+ };
59
+ },
60
+ priority: 9,
61
+ },
62
+ {
63
+ name: 'clear-database',
64
+ matcher: (step: ParsedStep) =>
65
+ step.text.includes('database is empty') ||
66
+ step.text.includes('database is cleared') ||
67
+ step.text.includes('clear database'),
68
+ generator: (step, context) => {
69
+ const code = context.templateEngine.renderStep('clear-database', {});
70
+
71
+ return {
72
+ code,
73
+ comment: `Setup: Clear/reset database`,
74
+ };
75
+ },
76
+ priority: 7,
77
+ },
78
+ {
79
+ name: 'browser-state-clean',
80
+ matcher: (step: ParsedStep) =>
81
+ step.text.includes('clean browser state') ||
82
+ step.text.includes('fresh browser') ||
83
+ step.text.includes('new browser session'),
84
+ generator: (step, context) => {
85
+ const code = context.templateEngine.renderStep('clear-browser-state', {});
86
+
87
+ return {
88
+ code,
89
+ comment: `Clear browser state (cookies, storage)`,
90
+ };
91
+ },
92
+ priority: 8,
93
+ },
94
+ ];
@@ -0,0 +1,41 @@
1
+ import { ParsedStep } from '../../gherkin-parser';
2
+ import { MappedStep } from '../step-mapper';
3
+ import { SelectorResolver } from '../utils/selector-resolver';
4
+ import { DataResolver } from '../utils/data-resolver';
5
+
6
+ /**
7
+ * Pattern matcher function or regex
8
+ */
9
+ export type PatternMatcher = RegExp | ((step: ParsedStep) => boolean);
10
+
11
+ /**
12
+ * Pattern generator function
13
+ */
14
+ export type PatternGenerator = (step: ParsedStep, context: PatternContext) => MappedStep;
15
+
16
+ /**
17
+ * Context passed to pattern generators
18
+ */
19
+ export interface PatternContext {
20
+ stepCounter: number;
21
+ extractScreenId: (selectorRef: string) => string;
22
+ templateEngine: any;
23
+ selectorResolver: SelectorResolver;
24
+ dataResolver: DataResolver;
25
+ renderLocator: (resolved: any) => string;
26
+ baseURL?: string; // Base URL from config (e.g., 'http://localhost:3000')
27
+ featureName?: string; // Feature name for data resolution (e.g., 'login')
28
+ screenName?: string; // Screen name for path inference (e.g., 'sign-in')
29
+ featurePath?: string; // Path metadata from feature file (e.g., '/login')
30
+ scenarioSteps?: ParsedStep[]; // All steps in scenario for path variable extraction
31
+ }
32
+
33
+ /**
34
+ * Step pattern definition
35
+ */
36
+ export interface StepPattern {
37
+ name: string;
38
+ matcher: PatternMatcher;
39
+ generator: PatternGenerator;
40
+ priority?: number; // Higher priority = checked first (default: 0)
41
+ }
@@ -0,0 +1,254 @@
1
+ import { ParsedStep } from '../gherkin-parser';
2
+ import { AIStepMapper } from './ai-step-mapper';
3
+ import { TemplateEngine } from './template-engine';
4
+ import { PatternRegistry, PatternContext } from './patterns';
5
+ import { SelectorResolver } from './utils/selector-resolver';
6
+ import { DataResolver } from './utils/data-resolver';
7
+ import * as path from 'path';
8
+
9
+ export interface MappedStep {
10
+ code: string; // Generated Playwright code
11
+ comment?: string; // Optional comment
12
+ imports?: string[]; // Required imports
13
+ }
14
+
15
+ /**
16
+ * StepMapper - Orchestrates step-to-code conversion using pattern registry
17
+ * Refactored from 907 lines to < 200 lines
18
+ */
19
+ export class StepMapper {
20
+ private stepCounter: number = 0;
21
+ private aiMapper: AIStepMapper | null = null;
22
+ private useAI: boolean = false;
23
+ private verbose: boolean = false;
24
+ private templateEngine: TemplateEngine;
25
+ private patternRegistry: PatternRegistry;
26
+ private selectorResolver: SelectorResolver;
27
+ private dataResolver: DataResolver;
28
+ private baseURL: string;
29
+ private featureName?: string;
30
+ private screenName?: string;
31
+ private featurePath?: string; // Path metadata from feature file (e.g., "/login")
32
+ private currentScenarioSteps?: ParsedStep[]; // All steps in current scenario for context
33
+
34
+ constructor(options: { useAI?: boolean; verbose?: boolean; baseURL?: string; featureName?: string; screenName?: string; featurePath?: string } = {}) {
35
+ this.useAI = options.useAI ?? false;
36
+ this.verbose = options.verbose ?? false;
37
+ this.baseURL = options.baseURL || null; // null means path-only navigation
38
+ this.featureName = options.featureName;
39
+ this.screenName = options.screenName;
40
+ this.featurePath = options.featurePath;
41
+ // Use Playwright templates as default for pattern-based generation
42
+ const playwrightTemplatesDir = path.join(__dirname, 'adapters', 'playwright', 'templates');
43
+ this.templateEngine = new TemplateEngine(playwrightTemplatesDir);
44
+ this.patternRegistry = new PatternRegistry();
45
+ this.selectorResolver = new SelectorResolver(undefined, options.screenName);
46
+ this.dataResolver = new DataResolver(undefined, options.screenName);
47
+
48
+ if (this.useAI) {
49
+ try {
50
+ this.aiMapper = new AIStepMapper(this.verbose);
51
+ if (this.verbose) {
52
+ console.log(` [StepMapper] AI fallback enabled (${this.patternRegistry.getPatternCount()} patterns loaded)`);
53
+ }
54
+ } catch (error) {
55
+ console.warn('[StepMapper] AI mapper initialization failed:', error);
56
+ this.useAI = false;
57
+ }
58
+ } else if (this.verbose) {
59
+ console.log(` [StepMapper] Dictionary mode (${this.patternRegistry.getPatternCount()} patterns loaded)`);
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Set feature context for data and selector resolution
65
+ */
66
+ setFeatureContext(featureName: string, featurePath?: string): void {
67
+ this.featureName = featureName;
68
+ this.featurePath = featurePath;
69
+ this.selectorResolver.setFeatureContext(featureName);
70
+ }
71
+
72
+ /**
73
+ * Set scenario context for path variable resolution
74
+ */
75
+ setScenarioContext(steps: ParsedStep[]): void {
76
+ this.currentScenarioSteps = steps;
77
+ }
78
+
79
+ /**
80
+ * Map a Gherkin step to Playwright code
81
+ * Uses pattern registry first, falls back to AI if enabled
82
+ */
83
+ mapStep(step: ParsedStep): MappedStep | Promise<MappedStep> {
84
+ this.stepCounter++;
85
+
86
+ // Try pattern registry first
87
+ const context = this.createPatternContext();
88
+ const mappedStep = this.patternRegistry.generateStep(step, context);
89
+
90
+ if (mappedStep) {
91
+ if (this.verbose) {
92
+ console.log(` ✓ Pattern matched: ${step.text.substring(0, 50)}...`);
93
+ }
94
+ return mappedStep;
95
+ }
96
+
97
+ // Fallback: Try legacy patterns for backward compatibility
98
+ const legacyStep = this.tryLegacyPatterns(step);
99
+ if (legacyStep) {
100
+ if (this.verbose) {
101
+ console.log(` ✓ Legacy pattern matched: ${step.text.substring(0, 50)}...`);
102
+ }
103
+ return legacyStep;
104
+ }
105
+
106
+ // Fallback to AI if enabled
107
+ if (this.useAI && this.aiMapper) {
108
+ if (this.verbose) {
109
+ console.log(` → AI fallback for: ${step.text.substring(0, 50)}...`);
110
+ }
111
+ return this.aiMapper.mapStep(step);
112
+ }
113
+
114
+ // No pattern matched and no AI - return generic code with comment
115
+ return {
116
+ code: `// TODO: Implement step: ${step.text}`,
117
+ comment: `Unrecognized step pattern: ${step.text}`,
118
+ };
119
+ }
120
+
121
+ /**
122
+ * Create pattern context for generators
123
+ */
124
+ private createPatternContext(): PatternContext {
125
+ return {
126
+ stepCounter: this.stepCounter,
127
+ extractScreenId: this.extractScreenId.bind(this),
128
+ templateEngine: this.templateEngine,
129
+ selectorResolver: this.selectorResolver,
130
+ dataResolver: this.dataResolver,
131
+ renderLocator: (resolved) => this.templateEngine.renderStep('locator', resolved),
132
+ baseURL: this.baseURL,
133
+ featureName: this.featureName,
134
+ screenName: this.screenName,
135
+ featurePath: this.featurePath, // Pass feature path to patterns
136
+ scenarioSteps: this.currentScenarioSteps || [], // Pass scenario steps for path variables
137
+ };
138
+ }
139
+
140
+ /**
141
+ * Extract screen ID from selector reference
142
+ */
143
+ private extractScreenId(selectorRef: string): string {
144
+ const match = selectorRef.match(/\[([\w-]+)\./);
145
+ return match ? match[1] : 'unknown';
146
+ }
147
+
148
+ /**
149
+ * Try legacy patterns for backward compatibility
150
+ * These are patterns not yet migrated to the pattern registry
151
+ */
152
+ private tryLegacyPatterns(step: ParsedStep): MappedStep | null {
153
+ const { text, selectorRef, dataRef, value } = step;
154
+
155
+ // Login pattern
156
+ if (text.includes('user is logged in as') && dataRef) {
157
+ return this.mapLoginStep(dataRef);
158
+ }
159
+
160
+ // Error message assertions
161
+ if (text.includes('error message') && text.includes('should')) {
162
+ return this.mapErrorMessageAssertion();
163
+ }
164
+
165
+ // Generic message assertions
166
+ if (text.includes('message') && text.includes('should be displayed')) {
167
+ return this.mapGenericMessageAssertion(text);
168
+ }
169
+
170
+ // Message with value assertions
171
+ if (text.includes('should see message') && value) {
172
+ return this.mapMessageAssertion(value, selectorRef);
173
+ }
174
+
175
+ // AI response assertions
176
+ if (text.includes('user should see') && text.includes('AI response') && selectorRef) {
177
+ return this.mapAIResponseAssertion(selectorRef);
178
+ }
179
+
180
+ // Message count assertions
181
+ if (text.includes('messages in') && selectorRef) {
182
+ return this.mapMessageCountAssertion(text, selectorRef);
183
+ }
184
+
185
+ // Message contains assertions
186
+ if (text.includes('should contain') && text.includes('messages') && selectorRef) {
187
+ return this.mapMessageCountAssertion(text, selectorRef);
188
+ }
189
+
190
+ return null;
191
+ }
192
+
193
+ // ========================================
194
+ // LEGACY METHODS (to be migrated to patterns)
195
+ // ========================================
196
+
197
+ private mapLoginStep(dataRef: string): MappedStep {
198
+ const varName = dataRef.replace(/[^a-zA-Z0-9]/g, '_') + '_' + this.stepCounter;
199
+ return {
200
+ code: this.templateEngine.renderStep('login', { varName, dataRef }),
201
+ comment: `Login as ${dataRef}`,
202
+ };
203
+ }
204
+
205
+ private mapErrorMessageAssertion(): MappedStep {
206
+ return {
207
+ code: this.templateEngine.renderStep('error-message-assertion', {}),
208
+ comment: 'Assert error message is displayed',
209
+ };
210
+ }
211
+
212
+ private mapGenericMessageAssertion(text: string): MappedStep {
213
+ const messageType = text.includes('welcome') ? 'welcome' :
214
+ text.includes('success') ? 'success' : 'message';
215
+ return {
216
+ code: this.templateEngine.renderStep('generic-message-assertion', { messageType }),
217
+ comment: `Assert ${messageType} message is displayed`,
218
+ };
219
+ }
220
+
221
+ private mapMessageAssertion(value: string, selectorRef?: string): MappedStep {
222
+ const varName = (selectorRef || 'message').replace(/[^a-zA-Z0-9]/g, '_') + '_' + this.stepCounter;
223
+ return {
224
+ code: this.templateEngine.renderStep('message-assertion-body', { varName, value, selectorRef }),
225
+ comment: `Assert message: ${value}`,
226
+ };
227
+ }
228
+
229
+ private mapAIResponseAssertion(selectorRef: string): MappedStep {
230
+ const screenId = this.extractScreenId(selectorRef);
231
+ const varName = selectorRef.replace(/[^a-zA-Z0-9]/g, '_') + '_' + this.stepCounter;
232
+ return {
233
+ code: this.templateEngine.renderStep('ai-response-assertion-selector', { varName, selectorRef, screenId }),
234
+ comment: `Assert AI response in ${selectorRef}`,
235
+ };
236
+ }
237
+
238
+ private mapMessageCountAssertion(text: string, selectorRef: string): MappedStep {
239
+ const match = text.match(/(\d+)\s+messages?/);
240
+ const expectedCount = match ? parseInt(match[1]) : 1;
241
+ const screenId = this.extractScreenId(selectorRef);
242
+ const varName = selectorRef.replace(/[^a-zA-Z0-9]/g, '_') + '_' + this.stepCounter;
243
+
244
+ return {
245
+ code: this.templateEngine.renderStep('message-count-assertion', {
246
+ varName,
247
+ selectorRef,
248
+ screenId,
249
+ expectedCount,
250
+ }),
251
+ comment: `Assert ${expectedCount} messages in ${selectorRef}`,
252
+ };
253
+ }
254
+ }
@@ -0,0 +1,160 @@
1
+ import Handlebars from 'handlebars';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+
5
+ export class TemplateEngine {
6
+ private templates: Map<string, HandlebarsTemplateDelegate> = new Map();
7
+ private templatesDir: string;
8
+ private stepsTemplatesDir: string;
9
+
10
+ constructor(templatesDir: string) {
11
+ this.templatesDir = templatesDir;
12
+ this.stepsTemplatesDir = path.join(this.templatesDir, 'steps');
13
+ this.registerHelpers();
14
+ this.registerPartials();
15
+ }
16
+
17
+ private registerHelpers(): void {
18
+ Handlebars.registerHelper('indent', function(text: string, spaces: number) {
19
+ const indentation = ' '.repeat(spaces);
20
+ return text.split('\n').map(line => indentation + line).join('\n');
21
+ });
22
+
23
+ Handlebars.registerHelper('escapeQuotes', function(text: string) {
24
+ return text.replace(/'/g, "\\'");
25
+ });
26
+
27
+ // Comparison helpers for conditional logic
28
+ Handlebars.registerHelper('eq', function(a: any, b: any) {
29
+ return a === b;
30
+ });
31
+
32
+ Handlebars.registerHelper('or', function(...args: any[]) {
33
+ // Remove Handlebars options object from end
34
+ const values = args.slice(0, -1);
35
+ return values.some(v => !!v);
36
+ });
37
+
38
+ Handlebars.registerHelper('and', function(...args: any[]) {
39
+ // Remove Handlebars options object from end
40
+ const values = args.slice(0, -1);
41
+ return values.every(v => !!v);
42
+ });
43
+
44
+ // Comparison helpers
45
+ Handlebars.registerHelper('gt', function(a: any, b: any) {
46
+ return a > b;
47
+ });
48
+
49
+ Handlebars.registerHelper('lt', function(a: any, b: any) {
50
+ return a < b;
51
+ });
52
+
53
+ Handlebars.registerHelper('gte', function(a: any, b: any) {
54
+ return a >= b;
55
+ });
56
+
57
+ Handlebars.registerHelper('lte', function(a: any, b: any) {
58
+ return a <= b;
59
+ });
60
+
61
+ // Math helpers
62
+ Handlebars.registerHelper('subtract', function(a: any, b: any) {
63
+ return a - b;
64
+ });
65
+
66
+ Handlebars.registerHelper('add', function(a: any, b: any) {
67
+ return a + b;
68
+ });
69
+
70
+ // Check if value is defined (not null/undefined) - useful for nth: 0
71
+ Handlebars.registerHelper('isDefined', function(value: any) {
72
+ return value !== undefined && value !== null;
73
+ });
74
+ }
75
+
76
+ private registerPartials(): void {
77
+ // Register locator partial for reusable selector rendering
78
+ const locatorPath = path.join(this.stepsTemplatesDir, 'partials', 'locator.hbs');
79
+ if (fs.existsSync(locatorPath)) {
80
+ const locatorContent = fs.readFileSync(locatorPath, 'utf-8');
81
+ Handlebars.registerPartial('locator', locatorContent);
82
+ }
83
+ }
84
+
85
+ private loadTemplate(templateName: string, isStepTemplate: boolean = false): HandlebarsTemplateDelegate {
86
+ if (this.templates.has(templateName)) {
87
+ return this.templates.get(templateName)!;
88
+ }
89
+
90
+ const baseDir = isStepTemplate ? this.stepsTemplatesDir : this.templatesDir;
91
+
92
+ // Try to find template in organized folders
93
+ if (isStepTemplate) {
94
+ const folders = ['actions', 'assertions', 'navigation', 'setup', 'partials'];
95
+
96
+ for (const folder of folders) {
97
+ const templatePath = path.join(baseDir, folder, `${templateName}.hbs`);
98
+ if (fs.existsSync(templatePath)) {
99
+ const templateContent = fs.readFileSync(templatePath, 'utf-8');
100
+ const template = Handlebars.compile(templateContent, { noEscape: true });
101
+ this.templates.set(templateName, template);
102
+ return template;
103
+ }
104
+ }
105
+
106
+ // Fallback: try root steps directory
107
+ const templatePath = path.join(baseDir, `${templateName}.hbs`);
108
+ if (fs.existsSync(templatePath)) {
109
+ const templateContent = fs.readFileSync(templatePath, 'utf-8');
110
+ const template = Handlebars.compile(templateContent, { noEscape: true });
111
+ this.templates.set(templateName, template);
112
+ return template;
113
+ }
114
+
115
+ throw new Error(`Template not found: ${templateName}.hbs in any subfolder`);
116
+ } else {
117
+ const templatePath = path.join(baseDir, `${templateName}.hbs`);
118
+ const templateContent = fs.readFileSync(templatePath, 'utf-8');
119
+ const template = Handlebars.compile(templateContent, { noEscape: true });
120
+ this.templates.set(templateName, template);
121
+ return template;
122
+ }
123
+ }
124
+
125
+ render(templateName: string, data: any, isStepTemplate: boolean = false): string {
126
+ const template = this.loadTemplate(templateName, isStepTemplate);
127
+ return template(data);
128
+ }
129
+
130
+ renderStep(stepTemplateName: string, data: any): string {
131
+ return this.render(stepTemplateName, data, true);
132
+ }
133
+
134
+ renderImports(): string {
135
+ return this.render('imports', {});
136
+ }
137
+
138
+ renderTestFile(data: {
139
+ imports: string;
140
+ featureName: string;
141
+ featureDescription?: string;
142
+ background?: string;
143
+ scenarios: string[];
144
+ }): string {
145
+ return this.render('test-file', data);
146
+ }
147
+
148
+ renderBeforeEach(data: {
149
+ steps: Array<{ comment?: string; code: string }>;
150
+ }): string {
151
+ return this.render('before-each', data);
152
+ }
153
+
154
+ renderScenario(data: {
155
+ scenarioName: string;
156
+ steps: Array<{ comment?: string; code: string }>;
157
+ }): string {
158
+ return this.render('scenario', data);
159
+ }
160
+ }
@@ -0,0 +1,147 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import yaml from 'yaml';
4
+
5
+ /**
6
+ * DataResolver - Resolves data references to actual values
7
+ * at generation time (not runtime)
8
+ */
9
+ export class DataResolver {
10
+ private dataCache = new Map<string, any>();
11
+ private testDataDir: string;
12
+ private screenName?: string;
13
+
14
+ constructor(testDataDir?: string, screenName?: string) {
15
+ this.testDataDir = testDataDir || path.join(process.cwd(), 'qa', 'test-data');
16
+ this.screenName = screenName;
17
+ }
18
+
19
+ /**
20
+ * Set screen context for data resolution
21
+ */
22
+ setScreenContext(screenName: string): void {
23
+ this.screenName = screenName;
24
+ }
25
+
26
+ /**
27
+ * Resolve data reference to actual value
28
+ * @param dataRef - Format: email.valid (path.to.value without filename)
29
+ * @param featureName - Name of the feature file (e.g., "login" from "login.feature")
30
+ * @returns The resolved value
31
+ */
32
+ resolveData(dataRef: string, featureName?: string): string {
33
+ // Split into parts: email.valid -> [email, valid]
34
+ // Use only dot (.) as separator
35
+ const parts = dataRef.split('.');
36
+
37
+ if (parts.length < 1) {
38
+ throw new Error(`Invalid data reference: ${dataRef}. Expected format: path.to.value`);
39
+ }
40
+
41
+ // If featureName provided, use it as the file name
42
+ // Otherwise, use first part as filename (backward compatibility)
43
+ let fileName: string;
44
+ let valuePath: string[];
45
+
46
+ if (featureName) {
47
+ fileName = featureName;
48
+ valuePath = parts;
49
+ } else {
50
+ if (parts.length < 2) {
51
+ throw new Error(`Invalid data reference: ${dataRef}. Expected format: file.path.to.value or provide featureName`);
52
+ }
53
+ fileName = parts[0];
54
+ valuePath = parts.slice(1);
55
+ }
56
+
57
+ // Load data file
58
+ const data = this.loadDataFile(fileName);
59
+
60
+ // Navigate to the value
61
+ let current = data;
62
+ for (const key of valuePath) {
63
+ if (current && typeof current === 'object' && key in current) {
64
+ current = current[key];
65
+ } else {
66
+ throw new Error(
67
+ `Data path not found: ${dataRef}. Failed at key: ${key}`
68
+ );
69
+ }
70
+ }
71
+
72
+ // Return as string
73
+ if (typeof current === 'string') {
74
+ return current;
75
+ } else if (typeof current === 'number' || typeof current === 'boolean') {
76
+ return String(current);
77
+ } else {
78
+ throw new Error(
79
+ `Data reference ${dataRef} must resolve to a primitive value, got: ${typeof current}`
80
+ );
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Load data file from disk (with caching)
86
+ * Searches new screen-based directory structure only
87
+ */
88
+ private loadDataFile(fileName: string): any {
89
+ if (this.dataCache.has(fileName)) {
90
+ return this.dataCache.get(fileName)!;
91
+ }
92
+
93
+ const filePath = this.findDataFilePath(fileName);
94
+
95
+ if (!filePath) {
96
+ const possiblePaths = this.getPossibleDataPaths(fileName);
97
+ throw new Error(
98
+ `Data file not found. Tried:\n${possiblePaths.join('\n')}`
99
+ );
100
+ }
101
+
102
+ const content = fs.readFileSync(filePath, 'utf-8');
103
+ const data = yaml.parse(content);
104
+
105
+ this.dataCache.set(fileName, data);
106
+ return data;
107
+ }
108
+
109
+ /**
110
+ * Find data file path (checks new screen-based structure)
111
+ */
112
+ private findDataFilePath(fileName: string): string | null {
113
+ const possiblePaths = this.getPossibleDataPaths(fileName);
114
+
115
+ for (const p of possiblePaths) {
116
+ if (fs.existsSync(p)) {
117
+ return p;
118
+ }
119
+ }
120
+
121
+ return null;
122
+ }
123
+
124
+ /**
125
+ * Get list of possible data file paths (priority order)
126
+ */
127
+ private getPossibleDataPaths(fileName: string): string[] {
128
+ const paths: string[] = [];
129
+
130
+ // New structure: qa/screens/{screenName}/test-data/{fileName}.yaml
131
+ if (this.screenName) {
132
+ const cwd = process.cwd();
133
+ const newPath = path.join(cwd, 'qa', 'screens', this.screenName, 'test-data', `${fileName}.yaml`);
134
+ const newPathYml = path.join(cwd, 'qa', 'screens', this.screenName, 'test-data', `${fileName}.yml`);
135
+ paths.push(newPath, newPathYml);
136
+ }
137
+
138
+ return paths;
139
+ }
140
+
141
+ /**
142
+ * Clear cache (useful for testing)
143
+ */
144
+ clearCache(): void {
145
+ this.dataCache.clear();
146
+ }
147
+ }