@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 @@
1
+ await {{> locator}}.fill('{{fillValue}}');
@@ -0,0 +1 @@
1
+ await {{> locator}}.press('{{key}}');
@@ -0,0 +1 @@
1
+ await {{> locator}}.selectOption('{{selectValue}}');
@@ -0,0 +1 @@
1
+ await expect({{> locator}}).toBeChecked();
@@ -0,0 +1 @@
1
+ await expect({{> locator}}).toContainText('{{expectedText}}');
@@ -0,0 +1 @@
1
+ await expect({{> locator}}).toHaveCount({{expectedCount}});
@@ -0,0 +1,2 @@
1
+ const {{varName}} = await pw.getElement('[{{selectorRef}}]', '{{screenId}}');
2
+ await expect({{varName}}).toBeDisabled();
@@ -0,0 +1,2 @@
1
+ const {{varName}} = await pw.getElement('[{{selectorRef}}]', '{{screenId}}');
2
+ await expect({{varName}}).toBeEmpty();
@@ -0,0 +1,2 @@
1
+ const {{varName}} = await pw.getElement('[{{selectorRef}}]', '{{screenId}}');
2
+ await expect({{varName}}).toBeEnabled();
@@ -0,0 +1 @@
1
+ await expect({{> locator}}).toBeFocused();
@@ -0,0 +1 @@
1
+ await expect({{> locator}}).toHaveText('{{expectedText}}');
@@ -0,0 +1 @@
1
+ await expect({{> locator}}).not.toBeChecked();
@@ -0,0 +1 @@
1
+ await expect({{> locator}}).not.toBeVisible();
@@ -0,0 +1 @@
1
+ await expect({{> locator}}).toBeVisible();
@@ -0,0 +1 @@
1
+ await page.goto('{{#if baseURL}}{{baseURL}}{{/if}}{{path}}');
@@ -0,0 +1,2 @@
1
+ await page.waitForURL('**{{path}}', { timeout: 5000 });
2
+ expect(page.url()).toContain('{{path}}');
@@ -0,0 +1 @@
1
+ await {{> locator}}.waitFor({ state: '{{state}}' });
@@ -0,0 +1 @@
1
+ await page.waitForTimeout({{duration}});
@@ -0,0 +1 @@
1
+ {{#if (eq strategy 'testid')}}page.getByTestId('{{value}}'){{else if (eq strategy 'role')}}page.getByRole('{{role}}', { name: '{{escapeQuotes name}}' }){{else if (eq strategy 'placeholder')}}page.getByPlaceholder('{{escapeQuotes value}}'){{else if (eq strategy 'label')}}page.getByLabel('{{escapeQuotes value}}'){{else if (eq strategy 'text')}}page.getByText('{{escapeQuotes value}}'){{else if (eq strategy 'id')}}page.locator('{{selector}}'){{else}}page.locator('{{escapeQuotes selector}}'){{/if}}{{#if (and (isDefined nth) (gt nth 0))}}.nth({{subtract nth 1}}){{/if}}
@@ -0,0 +1 @@
1
+ // Application should be running (no action needed)
@@ -0,0 +1,6 @@
1
+ // Clear authentication state
2
+ await page.context().clearCookies();
3
+ await page.evaluate(() => {
4
+ localStorage.clear();
5
+ sessionStorage.clear();
6
+ });
@@ -0,0 +1,6 @@
1
+ // Clear browser state
2
+ await page.context().clearCookies();
3
+ await page.evaluate(() => {
4
+ localStorage.clear();
5
+ sessionStorage.clear();
6
+ });
@@ -0,0 +1,4 @@
1
+ // TODO: Clear database
2
+ // This typically requires:
3
+ // 1. API call to test endpoint
4
+ // 2. Or database reset script
@@ -0,0 +1,6 @@
1
+ // TODO: Implement login for user: {{userRef}}
2
+ // You may need to:
3
+ // 1. Navigate to login page
4
+ // 2. Fill credentials
5
+ // 3. Submit login form
6
+ // 4. Wait for successful login
@@ -0,0 +1,19 @@
1
+ {{imports}}
2
+
3
+ {{#if featureDescription}}
4
+ /**
5
+ * Feature: {{featureName}}
6
+ * {{featureDescription}}
7
+ */
8
+ {{/if}}
9
+
10
+ test.describe('{{featureName}}', () => {
11
+ {{#if background}}
12
+ {{background}}
13
+
14
+ {{/if}}
15
+ {{#each scenarios}}
16
+ {{this}}
17
+
18
+ {{/each}}
19
+ });
@@ -0,0 +1,224 @@
1
+ /**
2
+ * AI-Based Step Mapper
3
+ * Fallback for dictionary when Gherkin patterns are ambiguous or unknown
4
+ */
5
+
6
+ import Anthropic from '@anthropic-ai/sdk';
7
+ import { ParsedStep } from '../gherkin-parser';
8
+ import { MappedStep } from './step-mapper';
9
+
10
+ export class AIStepMapper {
11
+ private client: Anthropic;
12
+ private verbose: boolean;
13
+
14
+ constructor(verbose: boolean = false) {
15
+ const apiKey = process.env.ANTHROPIC_API_KEY;
16
+ if (!apiKey) {
17
+ throw new Error('ANTHROPIC_API_KEY environment variable is required for AI step mapping');
18
+ }
19
+
20
+ this.client = new Anthropic({ apiKey });
21
+ this.verbose = verbose;
22
+ }
23
+
24
+ /**
25
+ * Map a Gherkin step to Playwright code using AI
26
+ * Provides rich context to help AI understand the intent
27
+ */
28
+ async mapStep(step: ParsedStep): Promise<MappedStep> {
29
+ if (this.verbose) {
30
+ console.log(` [AI] Mapping step: "${step.text}"`);
31
+ }
32
+
33
+ const prompt = this.buildPrompt(step);
34
+
35
+ try {
36
+ const message = await this.client.messages.create({
37
+ model: 'claude-3-5-haiku-20241022', // Fast & cheap for code generation
38
+ max_tokens: 500,
39
+ temperature: 0, // Deterministic for code generation
40
+ messages: [{
41
+ role: 'user',
42
+ content: prompt
43
+ }]
44
+ });
45
+
46
+ const content = message.content[0];
47
+ if (content.type !== 'text') {
48
+ throw new Error('Unexpected response type from AI');
49
+ }
50
+
51
+ const code = this.extractCode(content.text);
52
+
53
+ if (this.verbose) {
54
+ console.log(` [AI] Generated code (${code.split('\n').length} lines)`);
55
+ }
56
+
57
+ return {
58
+ code,
59
+ comment: `AI-generated from: ${step.text}`
60
+ };
61
+ } catch (error) {
62
+ console.error(`[AI] Failed to map step: ${error}`);
63
+
64
+ // Fallback to TODO comment
65
+ return {
66
+ code: `// TODO: AI mapping failed - implement manually: ${step.text}`,
67
+ comment: `AI mapping error: ${error instanceof Error ? error.message : 'Unknown error'}`
68
+ };
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Build context-rich prompt for AI
74
+ * Includes examples, patterns, and clear instructions
75
+ */
76
+ private buildPrompt(step: ParsedStep): string {
77
+ const { keyword, text, selectorRef, dataRef, value } = step;
78
+
79
+ return `You are an expert Playwright test code generator.
80
+
81
+ **Task**: Convert this Gherkin step into Playwright TypeScript code.
82
+
83
+ **Gherkin Step**:
84
+ ${keyword} ${text}
85
+
86
+ **Parsed Information**:
87
+ - Element ID: ${selectorRef || 'N/A'}
88
+ - Data Reference: ${dataRef || 'N/A'}
89
+ - Value: ${value || 'N/A'}
90
+
91
+ **Context**:
92
+ - We use a custom selector helper: \`pw.fill(elementId, value, screenId)\`
93
+ - Element IDs are in format: [screen.element-name]
94
+ - Screen ID is extracted from element ID (e.g., "chat" from "[chat.input]")
95
+ - For assertions, use: \`await pw.getElement(elementId, screenId)\` then \`expect(element)...\`
96
+
97
+ **Common Patterns & Examples**:
98
+
99
+ 1. **Fill/Input Actions**:
100
+ - "user fills/inputs/enters [element] with value"
101
+ - "user types value in/into [element]"
102
+ → \`await pw.fill('[element]', 'value', 'screen');\`
103
+
104
+ 2. **Click Actions**:
105
+ - "user clicks/taps/presses [element]"
106
+ - "user clicks on [element]"
107
+ → \`await pw.click('[element]', 'screen');\`
108
+
109
+ 3. **Keyboard Actions**:
110
+ - "user presses Enter in [element]"
111
+ - "user hits Tab key in [element]"
112
+ → \`const el = await pw.getElement('[element]', 'screen');\n await el.press('Enter');\`
113
+
114
+ 4. **Visibility Assertions**:
115
+ - "user should see [element]"
116
+ - "[element] is/should be visible"
117
+ - "[element] appears/shows"
118
+ → \`const el = await pw.getElement('[element]', 'screen');\n await expect(el).toBeVisible();\`
119
+
120
+ 5. **State Assertions**:
121
+ - "[element] should be disabled/enabled"
122
+ - "[element] is checked/unchecked"
123
+ → \`const el = await pw.getElement('[element]', 'screen');\n await expect(el).toBeDisabled();\`
124
+
125
+ 6. **Text Content Assertions**:
126
+ - "[element] should contain text \\"value\\""
127
+ - "[element] has/displays text \\"value\\""
128
+ → \`const el = await pw.getElement('[element]', 'screen');\n await expect(el).toContainText('value');\`
129
+
130
+ 7. **Collection State**:
131
+ - "[element] should be empty"
132
+ - "[element] has no items"
133
+ → \`const el = await pw.getElement('[element]', 'screen');\n const items = await el.locator('> *').all();\n expect(items.length).toBe(0);\`
134
+
135
+ 8. **Scroll State**:
136
+ - "[element] should be scrolled to bottom"
137
+ → \`const el = await pw.getElement('[element]', 'screen');\n const scrollHeight = await el.evaluate(el => el.scrollHeight);\n const scrollTop = await el.evaluate(el => el.scrollTop);\n const clientHeight = await el.evaluate(el => el.clientHeight);\n expect(scrollTop + clientHeight).toBeGreaterThanOrEqual(scrollHeight - 10);\`
138
+
139
+ **Important Rules**:
140
+ 1. Extract screen ID from element ID: "[chat.input]" → screen="chat"
141
+ 2. Use proper TypeScript syntax with await
142
+ 3. Use descriptive variable names (element, el, container, etc.)
143
+ 4. Add helpful comments for complex assertions
144
+ 5. NEVER use page.evaluate() unless absolutely necessary
145
+ 6. NEVER generate partial or incomplete statements
146
+ 7. Each step should generate COMPLETE, SELF-CONTAINED code
147
+ 8. If you can't map the step, return a comment: // TODO: Implement step
148
+
149
+ **Output Format**:
150
+ Return ONLY complete Playwright TypeScript statements, no explanations, no markdown blocks.
151
+ Each statement must be syntactically complete and can be inserted directly into a test function.
152
+
153
+ **Example Output**:
154
+ const chat_input_123 = await pw.getElement('[chat.input]', 'chat');
155
+ await expect(chat_input_123).toBeVisible();
156
+
157
+ Now generate code for the given step.`;
158
+ }
159
+
160
+ /**
161
+ * Extract clean code from AI response
162
+ * Remove markdown code blocks, explanations, etc.
163
+ */
164
+ private extractCode(response: string): string {
165
+ let code = response.trim();
166
+
167
+ // Remove markdown code blocks
168
+ code = code.replace(/```(?:typescript|ts|javascript|js)?\n?/g, '');
169
+ code = code.replace(/```\n?/g, '');
170
+
171
+ // Remove leading/trailing whitespace
172
+ code = code.trim();
173
+
174
+ // If response contains explanations, try to extract only code
175
+ const lines = code.split('\n');
176
+ const codeLines = lines.filter(line => {
177
+ const trimmed = line.trim();
178
+
179
+ // Skip lines that are clearly explanations (start with text, not code)
180
+ // But keep all valid TypeScript/JavaScript syntax
181
+ if (trimmed === '') return true; // Keep empty lines
182
+ if (trimmed.startsWith('//')) return true; // Keep comments
183
+
184
+ // Exclude lines that look like natural language explanations
185
+ // (start with capital letter and contain spaces, no semicolons/operators)
186
+ if (/^[A-Z][a-z]+ [\w\s]+$/.test(trimmed) && !trimmed.includes(';')) {
187
+ return false; // This looks like an explanation
188
+ }
189
+
190
+ // Keep lines that contain code-like patterns
191
+ const codePatterns = [
192
+ 'await ', 'const ', 'let ', 'var ', 'return ', 'expect(', 'if ', 'else',
193
+ 'for ', 'while ', 'function ', '=>', 'pw.', 'page.',
194
+ ')', '}', '];', '});', '})', 'import ', 'export ',
195
+ '.', '(', '[', '=', '+', '-', '*', '/', '%', '&&', '||'
196
+ ];
197
+
198
+ return codePatterns.some(pattern => trimmed.includes(pattern));
199
+ });
200
+
201
+ // If we filtered too much, return original
202
+ if (codeLines.length === 0) {
203
+ return code;
204
+ }
205
+
206
+ let finalCode = codeLines.join('\n');
207
+
208
+ // Safety check: Remove incomplete page.evaluate statements
209
+ // If we find "page.evaluate(" without proper closing, remove it
210
+ const evaluatePattern = /await\s+page\.evaluate\(\(\)\s*=>\s*\{\s*$/gm;
211
+ if (evaluatePattern.test(finalCode)) {
212
+ // Has unclosed page.evaluate at end - this is incomplete, return TODO
213
+ return '// TODO: Implement step (AI generated incomplete code)';
214
+ }
215
+
216
+ // Safety check: If code ends with an opening brace/paren, it's incomplete
217
+ const endsIncomplete = /[\({]\s*$/.test(finalCode);
218
+ if (endsIncomplete) {
219
+ return '// TODO: Implement step (AI generated incomplete code)';
220
+ }
221
+
222
+ return finalCode;
223
+ }
224
+ }
@@ -0,0 +1,235 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { ParsedFeature, ParsedScenario, ParsedStep } from '../gherkin-parser';
4
+ import { StepMapper } from './step-mapper';
5
+ import { TestGeneratorAdapter, adapterRegistry } from './adapters';
6
+
7
+ /**
8
+ * Result of test generation for a single feature file
9
+ */
10
+ export interface GeneratedTest {
11
+ featureName: string;
12
+ filePath: string;
13
+ code: string;
14
+ sourceFile?: string; // Source feature file path
15
+ stepCount?: number; // Total steps in generated test
16
+ }
17
+
18
+ export class CodeGenerator {
19
+ private stepMapper: StepMapper;
20
+ private adapter: TestGeneratorAdapter;
21
+ private screenName?: string;
22
+
23
+ constructor(options: { useAI?: boolean; verbose?: boolean; framework?: string; baseURL?: string; screenName?: string } = {}) {
24
+ this.screenName = options.screenName;
25
+ this.stepMapper = new StepMapper(options);
26
+
27
+ // Get adapter from registry (default: playwright)
28
+ const frameworkName = options.framework || 'playwright';
29
+ this.adapter = adapterRegistry.getAdapter(frameworkName);
30
+
31
+ if (options.verbose) {
32
+ console.log(`[CodeGenerator] Using ${this.adapter.frameworkName} adapter`);
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Generate test file from parsed feature
38
+ */
39
+ async generateTest(
40
+ feature: ParsedFeature,
41
+ outputDir: string
42
+ ): Promise<GeneratedTest> {
43
+ // Use source file name if available, otherwise derive from feature name
44
+ let fileName: string;
45
+ if (feature.sourceFile) {
46
+ // Extract filename and replace .feature with .spec.ts
47
+ const baseName = path.basename(feature.sourceFile, path.extname(feature.sourceFile));
48
+ fileName = `${baseName}.spec.ts`;
49
+ } else {
50
+ // Fallback to converting feature name
51
+ fileName = this.featureNameToFileName(feature.name);
52
+ }
53
+
54
+ // Extract screen name from source file path if available
55
+ // qa/screens/{screenName}/features/{featureName}.feature -> screenName
56
+ let screenSubdir = '';
57
+ if (feature.sourceFile) {
58
+ const sourceDir = path.dirname(feature.sourceFile);
59
+ const parts = sourceDir.split(path.sep);
60
+ const screensIndex = parts.indexOf('screens');
61
+ if (screensIndex >= 0 && screensIndex < parts.length - 2) {
62
+ screenSubdir = parts[screensIndex + 1]; // screen name after 'screens'
63
+ }
64
+ }
65
+
66
+ // Build output path with screen subdirectory
67
+ const filePath = screenSubdir
68
+ ? path.join(outputDir, screenSubdir, fileName)
69
+ : path.join(outputDir, fileName);
70
+
71
+ // Generate imports using adapter
72
+ const imports = this.adapter.renderImports();
73
+
74
+ // Generate test code (async now to support AI mapping)
75
+ const testCode = await this.generateTestCode(feature);
76
+
77
+ // Combine
78
+ const code = `${imports}\n\n${testCode}`;
79
+
80
+ return {
81
+ featureName: feature.name,
82
+ filePath,
83
+ code,
84
+ sourceFile: feature.sourceFile,
85
+ stepCount: this.countSteps(feature),
86
+ };
87
+ }
88
+
89
+ /**
90
+ * Count total steps in feature (excluding background)
91
+ */
92
+ private countSteps(feature: ParsedFeature): number {
93
+ let total = 0;
94
+ for (const scenario of feature.scenarios) {
95
+ total += scenario.steps.length;
96
+ }
97
+ return total;
98
+ }
99
+
100
+ /**
101
+ * Write generated test to file
102
+ */
103
+ writeTest(generatedTest: GeneratedTest): void {
104
+ const dir = path.dirname(generatedTest.filePath);
105
+ if (!fs.existsSync(dir)) {
106
+ fs.mkdirSync(dir, { recursive: true });
107
+ }
108
+
109
+ fs.writeFileSync(generatedTest.filePath, generatedTest.code, 'utf-8');
110
+ }
111
+
112
+ private async generateTestCode(feature: ParsedFeature): Promise<string> {
113
+ // Extract feature name from source file if available, otherwise derive from feature name
114
+ let featureName: string;
115
+ if (feature.sourceFile) {
116
+ // Extract filename without extension: "/path/to/login.feature" -> "login"
117
+ featureName = path.basename(feature.sourceFile, path.extname(feature.sourceFile));
118
+ } else {
119
+ // Fallback: derive from feature name (e.g., "User Authentication - Login" -> "login")
120
+ featureName = this.featureNameToFileName(feature.name).replace('.spec.ts', '');
121
+ }
122
+
123
+ // Set feature context for data resolution and navigation
124
+ this.stepMapper.setFeatureContext(featureName, feature.path);
125
+
126
+ // Generate background if exists
127
+ let background: string | undefined;
128
+ if (feature.background) {
129
+ background = await this.generateBeforeEach(feature.background);
130
+ }
131
+
132
+ // Generate all scenarios
133
+ const scenarios: string[] = [];
134
+ for (const scenario of feature.scenarios) {
135
+ scenarios.push(await this.generateScenario(scenario, !!feature.background));
136
+ }
137
+
138
+ // Use adapter to render the complete test file structure
139
+ return this.adapter.renderTestFile({
140
+ imports: '', // Not used in template as it's rendered separately
141
+ featureName: feature.name,
142
+ featureDescription: feature.description,
143
+ background,
144
+ scenarios,
145
+ });
146
+ }
147
+
148
+ private async generateBeforeEach(background: ParsedScenario): Promise<string> {
149
+ // Map all steps
150
+ const steps: Array<{ comment?: string; code: string }> = [];
151
+ for (const step of background.steps) {
152
+ const mapped = await Promise.resolve(this.stepMapper.mapStep(step));
153
+ steps.push({
154
+ comment: mapped.comment,
155
+ code: this.indentCode(mapped.code, 4),
156
+ });
157
+ }
158
+
159
+ // Use adapter to render beforeEach
160
+ return this.adapter.renderBeforeEach({
161
+ steps,
162
+ });
163
+ }
164
+
165
+ private async generateScenario(scenario: ParsedScenario, hasBackground: boolean): Promise<string> {
166
+ // Set scenario context for path variable resolution
167
+ this.stepMapper.setScenarioContext(scenario.steps);
168
+
169
+ // Map all steps
170
+ const steps: Array<{ comment?: string; code: string }> = [];
171
+ for (const step of scenario.steps) {
172
+ const mapped = await Promise.resolve(this.stepMapper.mapStep(step));
173
+ steps.push({
174
+ comment: mapped.comment,
175
+ code: this.indentCode(mapped.code, 4),
176
+ });
177
+ }
178
+
179
+ // Use adapter to render scenario
180
+ return this.adapter.renderScenario({
181
+ scenarioName: scenario.name,
182
+ steps,
183
+ });
184
+ }
185
+
186
+ /**
187
+ * Indent code lines with specified number of spaces
188
+ */
189
+ private indentCode(code: string, spaces: number): string {
190
+ const indentation = ' '.repeat(spaces);
191
+ return code.split('\n').map(line => indentation + line).join('\n');
192
+ }
193
+
194
+ /**
195
+ * Convert feature name to file name
196
+ * Example: "User Login" → "user-login.spec.ts"
197
+ */
198
+ private featureNameToFileName(featureName: string): string {
199
+ return (
200
+ featureName
201
+ .toLowerCase()
202
+ .replace(/[^a-z0-9]+/g, '-')
203
+ .replace(/^-|-$/g, '') + '.spec.ts'
204
+ );
205
+ }
206
+
207
+ /**
208
+ * Generate tests for all features in a directory
209
+ */
210
+ async generateAllTests(
211
+ featuresDir: string,
212
+ outputDir: string,
213
+ featureFiles: string[]
214
+ ): Promise<GeneratedTest[]> {
215
+ const { GherkinParser } = require('../gherkin-parser');
216
+ const parser = new GherkinParser();
217
+
218
+ const results: GeneratedTest[] = [];
219
+
220
+ for (const featureFile of featureFiles) {
221
+ try {
222
+ const feature = parser.parseFeatureFile(featureFile);
223
+ const generatedTest = await this.generateTest(feature, outputDir);
224
+ this.writeTest(generatedTest);
225
+ results.push(generatedTest);
226
+
227
+ console.log(`✓ Generated: ${path.basename(generatedTest.filePath)}`);
228
+ } catch (error) {
229
+ console.error(`✗ Failed to generate test for ${featureFile}:`, error);
230
+ }
231
+ }
232
+
233
+ return results;
234
+ }
235
+ }