@sun-asterisk/sungen 1.0.19 → 1.0.21

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 (295) hide show
  1. package/README.md +3 -3
  2. package/dist/cli/commands/add.d.ts +3 -0
  3. package/dist/cli/commands/add.d.ts.map +1 -0
  4. package/dist/cli/commands/add.js +27 -0
  5. package/dist/cli/commands/add.js.map +1 -0
  6. package/dist/cli/commands/cache-clear.d.ts +3 -0
  7. package/dist/cli/commands/cache-clear.d.ts.map +1 -0
  8. package/dist/cli/commands/cache-clear.js +24 -0
  9. package/dist/cli/commands/cache-clear.js.map +1 -0
  10. package/dist/cli/commands/full.d.ts +3 -0
  11. package/dist/cli/commands/full.d.ts.map +1 -0
  12. package/dist/cli/commands/full.js +37 -0
  13. package/dist/cli/commands/full.js.map +1 -0
  14. package/dist/cli/commands/generate.d.ts +3 -0
  15. package/dist/cli/commands/generate.d.ts.map +1 -0
  16. package/dist/cli/commands/generate.js +53 -0
  17. package/dist/cli/commands/generate.js.map +1 -0
  18. package/dist/cli/commands/init.d.ts +3 -0
  19. package/dist/cli/commands/init.d.ts.map +1 -0
  20. package/dist/cli/commands/init.js +20 -0
  21. package/dist/cli/commands/init.js.map +1 -0
  22. package/dist/cli/commands/live-scan.d.ts +3 -0
  23. package/dist/cli/commands/live-scan.d.ts.map +1 -0
  24. package/dist/cli/commands/{live-scan-command.js → live-scan.js} +22 -16
  25. package/dist/cli/commands/live-scan.js.map +1 -0
  26. package/dist/cli/commands/makeauth.d.ts +3 -0
  27. package/dist/cli/commands/makeauth.d.ts.map +1 -0
  28. package/dist/cli/commands/makeauth.js +76 -0
  29. package/dist/cli/commands/makeauth.js.map +1 -0
  30. package/dist/cli/commands/map.d.ts +3 -0
  31. package/dist/cli/commands/map.d.ts.map +1 -0
  32. package/dist/cli/commands/map.js +93 -0
  33. package/dist/cli/commands/map.js.map +1 -0
  34. package/dist/cli/commands/validate.d.ts +3 -0
  35. package/dist/cli/commands/validate.d.ts.map +1 -0
  36. package/dist/cli/commands/validate.js +43 -0
  37. package/dist/cli/commands/validate.js.map +1 -0
  38. package/dist/cli/index.js +29 -442
  39. package/dist/cli/index.js.map +1 -1
  40. package/dist/cli/types.d.ts +9 -0
  41. package/dist/cli/types.d.ts.map +1 -0
  42. package/dist/cli/types.js +7 -0
  43. package/dist/cli/types.js.map +1 -0
  44. package/dist/cli/utils.d.ts +6 -0
  45. package/dist/cli/utils.d.ts.map +1 -0
  46. package/dist/cli/utils.js +101 -0
  47. package/dist/cli/utils.js.map +1 -0
  48. package/dist/core/live-scanner/matrix-reader.d.ts.map +1 -1
  49. package/dist/core/live-scanner/matrix-reader.js +2 -40
  50. package/dist/core/live-scanner/matrix-reader.js.map +1 -1
  51. package/dist/core/live-scanner/scanner.d.ts.map +1 -1
  52. package/dist/core/live-scanner/scanner.js +22 -4
  53. package/dist/core/live-scanner/scanner.js.map +1 -1
  54. package/dist/core/live-scanner/step-replayer.d.ts +1 -1
  55. package/dist/core/live-scanner/step-replayer.d.ts.map +1 -1
  56. package/dist/core/live-scanner/step-replayer.js +107 -6
  57. package/dist/core/live-scanner/step-replayer.js.map +1 -1
  58. package/dist/core/live-scanner/types.d.ts +1 -0
  59. package/dist/core/live-scanner/types.d.ts.map +1 -1
  60. package/dist/core/validator/selector-validator.d.ts.map +1 -1
  61. package/dist/core/validator/selector-validator.js +2 -1
  62. package/dist/core/validator/selector-validator.js.map +1 -1
  63. package/dist/generators/scaffold-generator/index.d.ts +2 -1
  64. package/dist/generators/scaffold-generator/index.d.ts.map +1 -1
  65. package/dist/generators/scaffold-generator/index.js +21 -1
  66. package/dist/generators/scaffold-generator/index.js.map +1 -1
  67. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/click-select-action.hbs +2 -0
  68. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/wait-for-role-with-data.hbs +1 -0
  69. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/wait-for-role.hbs +1 -0
  70. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/checked-assertion.hbs +2 -1
  71. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/column-cell-assertion.hbs +3 -0
  72. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/contain-text-assertion.hbs +2 -1
  73. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/count-assertion.hbs +2 -1
  74. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-assertion.hbs +2 -1
  75. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-filter-assertion.hbs +2 -1
  76. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-role-variable-assertion.hbs +4 -3
  77. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-variable-assertion.hbs +2 -1
  78. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/empty-assertion.hbs +2 -1
  79. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/enabled-assertion.hbs +2 -1
  80. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/focused-assertion.hbs +2 -1
  81. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/have-text-assertion.hbs +2 -1
  82. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-dialog-heading-assertion.hbs +2 -0
  83. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-filter-assertion.hbs +2 -1
  84. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-role-variable-assertion.hbs +4 -3
  85. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-variable-assertion.hbs +2 -1
  86. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/is-hidden-assertion.hbs +1 -0
  87. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/list-item-count-assertion.hbs +2 -1
  88. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/not-checked-assertion.hbs +2 -1
  89. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/page-assertion.hbs +1 -0
  90. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-assertion.hbs +2 -1
  91. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-dialog-heading-assertion.hbs +2 -0
  92. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-locator-variable-assertion.hbs +2 -1
  93. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-role-variable-assertion.hbs +4 -3
  94. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-value-assertion.hbs +2 -1
  95. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-variable-assertion.hbs +1 -0
  96. package/dist/generators/test-generator/adapters/playwright/templates/steps/navigation/navigation.hbs +1 -1
  97. package/dist/generators/test-generator/adapters/playwright/templates/steps/navigation/wait-for-element-with-text.hbs +1 -1
  98. package/dist/generators/test-generator/patterns/assertion-patterns.d.ts.map +1 -1
  99. package/dist/generators/test-generator/patterns/assertion-patterns.js +95 -58
  100. package/dist/generators/test-generator/patterns/assertion-patterns.js.map +1 -1
  101. package/dist/generators/test-generator/patterns/form-patterns.d.ts +0 -2
  102. package/dist/generators/test-generator/patterns/form-patterns.d.ts.map +1 -1
  103. package/dist/generators/test-generator/patterns/form-patterns.js +34 -47
  104. package/dist/generators/test-generator/patterns/form-patterns.js.map +1 -1
  105. package/dist/generators/test-generator/patterns/index.d.ts +3 -1
  106. package/dist/generators/test-generator/patterns/index.d.ts.map +1 -1
  107. package/dist/generators/test-generator/patterns/index.js +20 -3
  108. package/dist/generators/test-generator/patterns/index.js.map +1 -1
  109. package/dist/generators/test-generator/patterns/interaction-patterns.d.ts +0 -1
  110. package/dist/generators/test-generator/patterns/interaction-patterns.d.ts.map +1 -1
  111. package/dist/generators/test-generator/patterns/interaction-patterns.js +44 -85
  112. package/dist/generators/test-generator/patterns/interaction-patterns.js.map +1 -1
  113. package/dist/generators/test-generator/patterns/legacy-patterns.d.ts +7 -0
  114. package/dist/generators/test-generator/patterns/legacy-patterns.d.ts.map +1 -0
  115. package/dist/generators/test-generator/patterns/legacy-patterns.js +98 -0
  116. package/dist/generators/test-generator/patterns/legacy-patterns.js.map +1 -0
  117. package/dist/generators/test-generator/patterns/navigation-patterns.d.ts +0 -2
  118. package/dist/generators/test-generator/patterns/navigation-patterns.d.ts.map +1 -1
  119. package/dist/generators/test-generator/patterns/navigation-patterns.js +14 -42
  120. package/dist/generators/test-generator/patterns/navigation-patterns.js.map +1 -1
  121. package/dist/generators/test-generator/patterns/setup-patterns.d.ts +0 -1
  122. package/dist/generators/test-generator/patterns/setup-patterns.d.ts.map +1 -1
  123. package/dist/generators/test-generator/patterns/setup-patterns.js +23 -35
  124. package/dist/generators/test-generator/patterns/setup-patterns.js.map +1 -1
  125. package/dist/generators/test-generator/patterns/types.d.ts +18 -3
  126. package/dist/generators/test-generator/patterns/types.d.ts.map +1 -1
  127. package/dist/generators/test-generator/step-mapper.d.ts +0 -15
  128. package/dist/generators/test-generator/step-mapper.d.ts.map +1 -1
  129. package/dist/generators/test-generator/step-mapper.js +4 -106
  130. package/dist/generators/test-generator/step-mapper.js.map +1 -1
  131. package/dist/{executor/test-generator.d.ts → generators/test-generator/types.d.ts} +4 -25
  132. package/dist/generators/test-generator/types.d.ts.map +1 -0
  133. package/dist/generators/test-generator/types.js +106 -0
  134. package/dist/generators/test-generator/types.js.map +1 -0
  135. package/dist/generators/test-generator/utils/data-resolver.d.ts.map +1 -1
  136. package/dist/generators/test-generator/utils/data-resolver.js +8 -17
  137. package/dist/generators/test-generator/utils/data-resolver.js.map +1 -1
  138. package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
  139. package/dist/generators/test-generator/utils/selector-resolver.js +10 -18
  140. package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -1
  141. package/dist/orchestrator/cache-manager.d.ts +1 -23
  142. package/dist/orchestrator/cache-manager.d.ts.map +1 -1
  143. package/dist/orchestrator/cache-manager.js +1 -87
  144. package/dist/orchestrator/cache-manager.js.map +1 -1
  145. package/dist/orchestrator/pipeline.d.ts +11 -28
  146. package/dist/orchestrator/pipeline.d.ts.map +1 -1
  147. package/dist/orchestrator/pipeline.js +52 -371
  148. package/dist/orchestrator/pipeline.js.map +1 -1
  149. package/dist/orchestrator/reporter.d.ts +1 -1
  150. package/dist/orchestrator/reporter.d.ts.map +1 -1
  151. package/dist/orchestrator/screen-manager.js +1 -1
  152. package/dist/orchestrator/screen-manager.js.map +1 -1
  153. package/dist/utils/feature-finder.d.ts +9 -0
  154. package/dist/utils/feature-finder.d.ts.map +1 -0
  155. package/dist/utils/feature-finder.js +67 -0
  156. package/dist/utils/feature-finder.js.map +1 -0
  157. package/dist/utils/screen-paths.d.ts +10 -0
  158. package/dist/utils/screen-paths.d.ts.map +1 -0
  159. package/dist/utils/screen-paths.js +73 -0
  160. package/dist/utils/screen-paths.js.map +1 -0
  161. package/dist/utils/selector-loader.d.ts +6 -0
  162. package/dist/utils/selector-loader.d.ts.map +1 -0
  163. package/dist/utils/selector-loader.js +20 -0
  164. package/dist/utils/selector-loader.js.map +1 -0
  165. package/dist/utils/selector-types.d.ts +7 -0
  166. package/dist/utils/selector-types.d.ts.map +1 -0
  167. package/dist/utils/selector-types.js +19 -0
  168. package/dist/utils/selector-types.js.map +1 -0
  169. package/dist/utils/test-data-loader.d.ts +6 -0
  170. package/dist/utils/test-data-loader.d.ts.map +1 -0
  171. package/dist/utils/test-data-loader.js +20 -0
  172. package/dist/utils/test-data-loader.js.map +1 -0
  173. package/dist/utils/yaml-io.d.ts +14 -0
  174. package/dist/utils/yaml-io.d.ts.map +1 -0
  175. package/dist/utils/yaml-io.js +72 -0
  176. package/dist/utils/yaml-io.js.map +1 -0
  177. package/package.json +1 -1
  178. package/src/cli/commands/add.ts +25 -0
  179. package/src/cli/commands/cache-clear.ts +22 -0
  180. package/src/cli/commands/full.ts +35 -0
  181. package/src/cli/commands/generate.ts +55 -0
  182. package/src/cli/commands/init.ts +17 -0
  183. package/src/cli/commands/{live-scan-command.ts → live-scan.ts} +21 -18
  184. package/src/cli/commands/makeauth.ts +77 -0
  185. package/src/cli/commands/map.ts +97 -0
  186. package/src/cli/commands/validate.ts +43 -0
  187. package/src/cli/index.ts +32 -473
  188. package/src/cli/types.ts +9 -0
  189. package/src/cli/utils.ts +106 -0
  190. package/src/core/live-scanner/matrix-reader.ts +2 -8
  191. package/src/core/live-scanner/scanner.ts +27 -4
  192. package/src/core/live-scanner/step-replayer.ts +92 -6
  193. package/src/core/live-scanner/types.ts +1 -0
  194. package/src/core/validator/selector-validator.ts +3 -2
  195. package/src/generators/scaffold-generator/index.ts +23 -2
  196. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/click-select-action.hbs +2 -0
  197. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/wait-for-role-with-data.hbs +1 -0
  198. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/wait-for-role.hbs +1 -0
  199. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/checked-assertion.hbs +2 -1
  200. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/column-cell-assertion.hbs +3 -0
  201. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/contain-text-assertion.hbs +2 -1
  202. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/count-assertion.hbs +2 -1
  203. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-assertion.hbs +2 -1
  204. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-filter-assertion.hbs +2 -1
  205. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-role-variable-assertion.hbs +4 -3
  206. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-variable-assertion.hbs +2 -1
  207. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/empty-assertion.hbs +2 -1
  208. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/enabled-assertion.hbs +2 -1
  209. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/focused-assertion.hbs +2 -1
  210. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/have-text-assertion.hbs +2 -1
  211. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-dialog-heading-assertion.hbs +2 -0
  212. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-filter-assertion.hbs +2 -1
  213. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-role-variable-assertion.hbs +4 -3
  214. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-variable-assertion.hbs +2 -1
  215. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/is-hidden-assertion.hbs +1 -0
  216. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/list-item-count-assertion.hbs +2 -1
  217. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/not-checked-assertion.hbs +2 -1
  218. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/page-assertion.hbs +1 -0
  219. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-assertion.hbs +2 -1
  220. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-dialog-heading-assertion.hbs +2 -0
  221. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-locator-variable-assertion.hbs +2 -1
  222. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-role-variable-assertion.hbs +4 -3
  223. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-value-assertion.hbs +2 -1
  224. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-variable-assertion.hbs +1 -0
  225. package/src/generators/test-generator/adapters/playwright/templates/steps/navigation/navigation.hbs +1 -1
  226. package/src/generators/test-generator/adapters/playwright/templates/steps/navigation/wait-for-element-with-text.hbs +1 -1
  227. package/src/generators/test-generator/patterns/assertion-patterns.ts +102 -62
  228. package/src/generators/test-generator/patterns/form-patterns.ts +38 -60
  229. package/src/generators/test-generator/patterns/index.ts +22 -4
  230. package/src/generators/test-generator/patterns/interaction-patterns.ts +47 -107
  231. package/src/generators/test-generator/patterns/legacy-patterns.ts +104 -0
  232. package/src/generators/test-generator/patterns/navigation-patterns.ts +27 -69
  233. package/src/generators/test-generator/patterns/setup-patterns.ts +23 -41
  234. package/src/generators/test-generator/patterns/types.ts +26 -9
  235. package/src/generators/test-generator/step-mapper.ts +4 -124
  236. package/src/generators/test-generator/types.ts +131 -0
  237. package/src/generators/test-generator/utils/data-resolver.ts +8 -13
  238. package/src/generators/test-generator/utils/selector-resolver.ts +15 -17
  239. package/src/orchestrator/cache-manager.ts +1 -107
  240. package/src/orchestrator/pipeline.ts +58 -433
  241. package/src/orchestrator/reporter.ts +1 -1
  242. package/src/orchestrator/screen-manager.ts +1 -1
  243. package/src/utils/feature-finder.ts +33 -0
  244. package/src/utils/screen-paths.ts +37 -0
  245. package/src/utils/selector-loader.ts +23 -0
  246. package/src/utils/selector-types.ts +17 -0
  247. package/src/utils/test-data-loader.ts +23 -0
  248. package/src/utils/yaml-io.ts +33 -0
  249. package/dist/cli/commands/auto-tag-command.d.ts +0 -8
  250. package/dist/cli/commands/auto-tag-command.d.ts.map +0 -1
  251. package/dist/cli/commands/auto-tag-command.js +0 -104
  252. package/dist/cli/commands/auto-tag-command.js.map +0 -1
  253. package/dist/cli/commands/live-scan-command.d.ts +0 -9
  254. package/dist/cli/commands/live-scan-command.d.ts.map +0 -1
  255. package/dist/cli/commands/live-scan-command.js.map +0 -1
  256. package/dist/executor/playwright/playwright-generator.d.ts +0 -33
  257. package/dist/executor/playwright/playwright-generator.d.ts.map +0 -1
  258. package/dist/executor/playwright/playwright-generator.js +0 -136
  259. package/dist/executor/playwright/playwright-generator.js.map +0 -1
  260. package/dist/executor/test-generator.d.ts.map +0 -1
  261. package/dist/executor/test-generator.js +0 -30
  262. package/dist/executor/test-generator.js.map +0 -1
  263. package/dist/generators/cli.d.ts +0 -7
  264. package/dist/generators/cli.d.ts.map +0 -1
  265. package/dist/generators/cli.js +0 -570
  266. package/dist/generators/cli.js.map +0 -1
  267. package/dist/input/cli-adapter.d.ts +0 -75
  268. package/dist/input/cli-adapter.d.ts.map +0 -1
  269. package/dist/input/cli-adapter.js +0 -218
  270. package/dist/input/cli-adapter.js.map +0 -1
  271. package/dist/input/config-adapter.d.ts +0 -25
  272. package/dist/input/config-adapter.d.ts.map +0 -1
  273. package/dist/input/config-adapter.js +0 -70
  274. package/dist/input/config-adapter.js.map +0 -1
  275. package/dist/input/input-adapter.d.ts +0 -28
  276. package/dist/input/input-adapter.d.ts.map +0 -1
  277. package/dist/input/input-adapter.js +0 -17
  278. package/dist/input/input-adapter.js.map +0 -1
  279. package/dist/input/vscode-adapter.d.ts +0 -62
  280. package/dist/input/vscode-adapter.d.ts.map +0 -1
  281. package/dist/input/vscode-adapter.js +0 -64
  282. package/dist/input/vscode-adapter.js.map +0 -1
  283. package/dist/tools/auto-tagger.d.ts +0 -107
  284. package/dist/tools/auto-tagger.d.ts.map +0 -1
  285. package/dist/tools/auto-tagger.js +0 -502
  286. package/dist/tools/auto-tagger.js.map +0 -1
  287. package/src/cli/commands/auto-tag-command.ts +0 -80
  288. package/src/executor/playwright/playwright-generator.ts +0 -125
  289. package/src/executor/test-generator.ts +0 -90
  290. package/src/generators/cli.ts +0 -640
  291. package/src/input/cli-adapter.ts +0 -233
  292. package/src/input/config-adapter.ts +0 -71
  293. package/src/input/input-adapter.ts +0 -32
  294. package/src/input/vscode-adapter.ts +0 -90
  295. package/src/tools/auto-tagger.ts +0 -572
@@ -3,7 +3,6 @@ import { StepPattern } from './types';
3
3
 
4
4
  /**
5
5
  * Setup and precondition patterns: application setup, authentication state, etc.
6
- * Uses templates for framework-agnostic code generation
7
6
  */
8
7
  export const setupPatterns: StepPattern[] = [
9
8
  {
@@ -12,14 +11,11 @@ export const setupPatterns: StepPattern[] = [
12
11
  step.text.includes('application is running') ||
13
12
  step.text.includes('application running') ||
14
13
  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
- },
14
+ resolver: (step, context) => ({
15
+ templateName: 'application-running',
16
+ data: {},
17
+ comment: `Setup: Application is running`,
18
+ }),
23
19
  priority: 5,
24
20
  },
25
21
  {
@@ -28,14 +24,11 @@ export const setupPatterns: StepPattern[] = [
28
24
  step.text.includes('user is not logged in') ||
29
25
  step.text.includes('not logged in') ||
30
26
  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
- },
27
+ resolver: (step, context) => ({
28
+ templateName: 'clear-auth',
29
+ data: {},
30
+ comment: `Clear authentication state (ensure user is logged out)`,
31
+ }),
39
32
  priority: 9,
40
33
  },
41
34
  {
@@ -44,16 +37,11 @@ export const setupPatterns: StepPattern[] = [
44
37
  (step.text.includes('user is logged in') ||
45
38
  step.text.includes('logged in as')) &&
46
39
  !step.text.includes('not logged in'),
47
- generator: (step, context) => {
48
- // Check if there's a data reference for user credentials
40
+ resolver: (step, context) => {
49
41
  const userRef = step.dataRef || 'valid_user';
50
-
51
- const code = context.templateEngine.renderStep('user-login-todo', {
52
- userRef,
53
- });
54
-
55
42
  return {
56
- code,
43
+ templateName: 'user-login-todo',
44
+ data: { userRef },
57
45
  comment: `Setup: User logged in as ${userRef}`,
58
46
  };
59
47
  },
@@ -65,14 +53,11 @@ export const setupPatterns: StepPattern[] = [
65
53
  step.text.includes('database is empty') ||
66
54
  step.text.includes('database is cleared') ||
67
55
  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
- },
56
+ resolver: (step, context) => ({
57
+ templateName: 'clear-database',
58
+ data: {},
59
+ comment: `Setup: Clear/reset database`,
60
+ }),
76
61
  priority: 7,
77
62
  },
78
63
  {
@@ -81,14 +66,11 @@ export const setupPatterns: StepPattern[] = [
81
66
  step.text.includes('clean browser state') ||
82
67
  step.text.includes('fresh browser') ||
83
68
  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
- },
69
+ resolver: (step, context) => ({
70
+ templateName: 'clear-browser-state',
71
+ data: {},
72
+ comment: `Clear browser state (cookies, storage)`,
73
+ }),
92
74
  priority: 8,
93
75
  },
94
76
  ];
@@ -9,12 +9,26 @@ import { DataResolver } from '../utils/data-resolver';
9
9
  export type PatternMatcher = RegExp | ((step: ParsedStep) => boolean);
10
10
 
11
11
  /**
12
- * Pattern generator function
12
+ * Pattern generator function (legacy — calls templateEngine directly)
13
13
  */
14
14
  export type PatternGenerator = (step: ParsedStep, context: PatternContext) => MappedStep;
15
15
 
16
16
  /**
17
- * Context passed to pattern generators
17
+ * Resolved step template data — framework-agnostic
18
+ */
19
+ export interface StepTemplateData {
20
+ templateName: string;
21
+ data: Record<string, any>;
22
+ comment?: string;
23
+ }
24
+
25
+ /**
26
+ * Pattern resolver function — returns template name + data, does NOT render
27
+ */
28
+ export type PatternResolver = (step: ParsedStep, context: PatternContext) => StepTemplateData;
29
+
30
+ /**
31
+ * Context passed to pattern generators/resolvers
18
32
  */
19
33
  export interface PatternContext {
20
34
  stepCounter: number;
@@ -23,19 +37,22 @@ export interface PatternContext {
23
37
  selectorResolver: SelectorResolver;
24
38
  dataResolver: DataResolver;
25
39
  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
40
+ baseURL?: string;
41
+ featureName?: string;
42
+ screenName?: string;
43
+ featurePath?: string;
44
+ scenarioSteps?: ParsedStep[];
31
45
  }
32
46
 
33
47
  /**
34
48
  * Step pattern definition
49
+ * Supports both `resolver` (preferred) and `generator` (legacy).
50
+ * If both are provided, `resolver` takes precedence.
35
51
  */
36
52
  export interface StepPattern {
37
53
  name: string;
38
54
  matcher: PatternMatcher;
39
- generator: PatternGenerator;
40
- priority?: number; // Higher priority = checked first (default: 0)
55
+ resolver?: PatternResolver;
56
+ generator?: PatternGenerator;
57
+ priority?: number;
41
58
  }
@@ -140,15 +140,6 @@ export class StepMapper {
140
140
  return mappedStep;
141
141
  }
142
142
 
143
- // Fallback: Try legacy patterns for backward compatibility
144
- const legacyStep = this.tryLegacyPatterns(step);
145
- if (legacyStep) {
146
- if (this.verbose) {
147
- console.log(` ✓ Legacy pattern matched: ${step.text.substring(0, 50)}...`);
148
- }
149
- return legacyStep;
150
- }
151
-
152
143
  // Fallback to AI if enabled
153
144
  if (this.useAI && this.aiMapper) {
154
145
  if (this.verbose) {
@@ -170,7 +161,10 @@ export class StepMapper {
170
161
  private createPatternContext(): PatternContext {
171
162
  return {
172
163
  stepCounter: this.stepCounter,
173
- extractScreenId: this.extractScreenId.bind(this),
164
+ extractScreenId: (selectorRef: string) => {
165
+ const match = selectorRef.match(/\[([\w-]+)\./);
166
+ return match ? match[1] : 'unknown';
167
+ },
174
168
  templateEngine: this.templateEngine,
175
169
  selectorResolver: this.selectorResolver,
176
170
  dataResolver: this.dataResolver,
@@ -183,118 +177,4 @@ export class StepMapper {
183
177
  };
184
178
  }
185
179
 
186
- /**
187
- * Extract screen ID from selector reference
188
- */
189
- private extractScreenId(selectorRef: string): string {
190
- const match = selectorRef.match(/\[([\w-]+)\./);
191
- return match ? match[1] : 'unknown';
192
- }
193
-
194
- /**
195
- * Try legacy patterns for backward compatibility
196
- * These are patterns not yet migrated to the pattern registry
197
- */
198
- private tryLegacyPatterns(step: ParsedStep): MappedStep | null {
199
- const { text, selectorRef, dataRef, value } = step;
200
-
201
- // Login pattern
202
- if (text.includes('user is logged in as') && dataRef) {
203
- return this.mapLoginStep(dataRef);
204
- }
205
-
206
- // Error message assertions
207
- if (text.includes('error message') && text.includes('should')) {
208
- return this.mapErrorMessageAssertion();
209
- }
210
-
211
- // Generic message assertions
212
- if (text.includes('message') && text.includes('should be displayed')) {
213
- return this.mapGenericMessageAssertion(text);
214
- }
215
-
216
- // Message with value assertions
217
- if (text.includes('should see message') && value) {
218
- return this.mapMessageAssertion(value, selectorRef);
219
- }
220
-
221
- // AI response assertions
222
- if (text.includes('user should see') && text.includes('AI response') && selectorRef) {
223
- return this.mapAIResponseAssertion(selectorRef);
224
- }
225
-
226
- // Message count assertions
227
- if (text.includes('messages in') && selectorRef) {
228
- return this.mapMessageCountAssertion(text, selectorRef);
229
- }
230
-
231
- // Message contains assertions
232
- if (text.includes('should contain') && text.includes('messages') && selectorRef) {
233
- return this.mapMessageCountAssertion(text, selectorRef);
234
- }
235
-
236
- return null;
237
- }
238
-
239
- // ========================================
240
- // LEGACY METHODS (to be migrated to patterns)
241
- // ========================================
242
-
243
- private mapLoginStep(dataRef: string): MappedStep {
244
- const varName = dataRef.replace(/[^a-zA-Z0-9]/g, '_') + '_' + this.stepCounter;
245
- return {
246
- code: this.templateEngine.renderStep('login', { varName, dataRef }),
247
- comment: `Login as ${dataRef}`,
248
- };
249
- }
250
-
251
- private mapErrorMessageAssertion(): MappedStep {
252
- return {
253
- code: this.templateEngine.renderStep('error-message-assertion', {}),
254
- comment: 'Assert error message is displayed',
255
- };
256
- }
257
-
258
- private mapGenericMessageAssertion(text: string): MappedStep {
259
- const messageType = text.includes('welcome') ? 'welcome' :
260
- text.includes('success') ? 'success' : 'message';
261
- return {
262
- code: this.templateEngine.renderStep('generic-message-assertion', { messageType }),
263
- comment: `Assert ${messageType} message is displayed`,
264
- };
265
- }
266
-
267
- private mapMessageAssertion(value: string, selectorRef?: string): MappedStep {
268
- const varName = (selectorRef || 'message').replace(/[^a-zA-Z0-9]/g, '_') + '_' + this.stepCounter;
269
- return {
270
- code: this.templateEngine.renderStep('message-assertion-body', { varName, value, selectorRef }),
271
- comment: `Assert message: ${value}`,
272
- };
273
- }
274
-
275
- private mapAIResponseAssertion(selectorRef: string): MappedStep {
276
- const screenId = this.extractScreenId(selectorRef);
277
- const varName = selectorRef.replace(/[^a-zA-Z0-9]/g, '_') + '_' + this.stepCounter;
278
- return {
279
- code: this.templateEngine.renderStep('ai-response-assertion-selector', { varName, selectorRef, screenId }),
280
- comment: `Assert AI response in ${selectorRef}`,
281
- };
282
- }
283
-
284
- private mapMessageCountAssertion(text: string, selectorRef: string): MappedStep {
285
- const match = text.match(/(\d+)\s+messages?/);
286
- const expectedCount = match ? parseInt(match[1]) : 1;
287
- const screenId = this.extractScreenId(selectorRef);
288
- const varName = selectorRef.replace(/[^a-zA-Z0-9]/g, '_') + '_' + this.stepCounter;
289
-
290
- return {
291
- code: this.templateEngine.renderStep('message-count-assertion', {
292
- varName,
293
- selectorRef,
294
- screenId,
295
- expectedCount,
296
- }),
297
- comment: `Assert ${expectedCount} messages in ${selectorRef}`,
298
- };
299
- }
300
180
  }
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Test Generator Interface
3
+ * Defines contract for test framework code generators
4
+ */
5
+
6
+ import { RuntimeConfig } from '../../config/config-schema';
7
+ import { ParsedFeature } from '../../core/selector-base/gherkin-parser';
8
+ import * as path from 'path';
9
+
10
+ /**
11
+ * Main Test Generator Interface
12
+ */
13
+ export interface TestGenerator {
14
+ readonly framework: string;
15
+
16
+ generate(
17
+ feature: ParsedFeature,
18
+ selectors: Record<string, any>,
19
+ testData: Record<string, any>,
20
+ config: RuntimeConfig
21
+ ): Promise<GeneratedTest>;
22
+
23
+ getFileExtension(): string;
24
+
25
+ validate(): boolean;
26
+ }
27
+
28
+ /**
29
+ * Generated Test Result (executor-level)
30
+ */
31
+ export interface GeneratedTest {
32
+ feature: string;
33
+ outputPath: string;
34
+ code: string;
35
+ stats: GenerationStats;
36
+ }
37
+
38
+ /**
39
+ * Generation Statistics
40
+ */
41
+ export interface GenerationStats {
42
+ totalScenarios: number;
43
+ totalSteps: number;
44
+ dictionaryMatched: number;
45
+ aiGenerated: number;
46
+ todoCount: number;
47
+ generationTime: number;
48
+ }
49
+
50
+ /**
51
+ * Test Generator Factory
52
+ */
53
+ export class TestGeneratorFactory {
54
+ static create(framework: string, config: RuntimeConfig): TestGenerator {
55
+ switch (framework) {
56
+ case 'playwright': {
57
+ const { CodeGenerator } = require('./code-generator');
58
+
59
+ return {
60
+ framework: 'playwright',
61
+
62
+ async generate(
63
+ feature: ParsedFeature,
64
+ selectors: Record<string, any>,
65
+ testData: Record<string, any>,
66
+ cfg: RuntimeConfig
67
+ ): Promise<GeneratedTest> {
68
+ const startTime = Date.now();
69
+
70
+ let screenName: string | undefined;
71
+ if (feature.sourceFile) {
72
+ const sourceDir = path.dirname(feature.sourceFile);
73
+ const parts = sourceDir.split(path.sep);
74
+ const screensIndex = parts.indexOf('screens');
75
+ if (screensIndex >= 0 && screensIndex < parts.length - 2) {
76
+ screenName = parts[screensIndex + 1];
77
+ }
78
+ }
79
+
80
+ const generator = new CodeGenerator({
81
+ useAI: cfg.testGenerator.enableAIFallback,
82
+ verbose: cfg.verbose,
83
+ screenName,
84
+ });
85
+
86
+ const outputDir = cfg.paths.specsDir;
87
+ const result = await generator.generateTest(feature, outputDir);
88
+ generator.writeTest(result);
89
+
90
+ const countSteps = (f: ParsedFeature) =>
91
+ f.scenarios.reduce((sum: number, s: any) => sum + (s.steps ? s.steps.length : 0), 0);
92
+ const countTodos = (code: string) => (code.match(/\/\/ TODO/g) || []).length;
93
+
94
+ const stats: GenerationStats = {
95
+ totalScenarios: feature.scenarios.length,
96
+ totalSteps: countSteps(feature),
97
+ dictionaryMatched: 0,
98
+ aiGenerated: 0,
99
+ todoCount: countTodos(result.code),
100
+ generationTime: Date.now() - startTime,
101
+ };
102
+
103
+ return {
104
+ feature: feature.name,
105
+ outputPath: result.filePath,
106
+ code: result.code,
107
+ stats,
108
+ };
109
+ },
110
+
111
+ getFileExtension() {
112
+ return '.spec.ts';
113
+ },
114
+
115
+ validate() {
116
+ return true;
117
+ },
118
+ };
119
+ }
120
+
121
+ case 'appium':
122
+ throw new Error('Appium generator not yet implemented');
123
+
124
+ case 'integration':
125
+ throw new Error('Integration test generator not yet implemented');
126
+
127
+ default:
128
+ throw new Error(`Unsupported test framework: ${framework}`);
129
+ }
130
+ }
131
+ }
@@ -1,6 +1,7 @@
1
1
  import * as fs from 'fs';
2
2
  import * as path from 'path';
3
3
  import yaml from 'yaml';
4
+ import { readYamlIfExists } from '../../../utils/yaml-io';
4
5
 
5
6
  /**
6
7
  * DataResolver - Resolves data references to actual values
@@ -102,13 +103,10 @@ export class DataResolver {
102
103
 
103
104
  // Load in reverse priority order (base first, then overrides on top)
104
105
  for (const p of [...possiblePaths].reverse()) {
105
- if (fs.existsSync(p)) {
106
- const content = fs.readFileSync(p, 'utf-8');
107
- const data = yaml.parse(content);
108
- if (data && typeof data === 'object' && Object.keys(data).length > 0) {
109
- merged = { ...merged, ...data };
110
- found = true;
111
- }
106
+ const data = readYamlIfExists(p);
107
+ if (data && typeof data === 'object' && Object.keys(data).length > 0) {
108
+ merged = { ...merged, ...data };
109
+ found = true;
112
110
  }
113
111
  }
114
112
 
@@ -131,13 +129,10 @@ export class DataResolver {
131
129
  const possiblePaths = this.getPossibleDataPaths(fileName);
132
130
 
133
131
  for (const p of possiblePaths) {
134
- if (fs.existsSync(p)) {
135
- // Check if file has actual data (not just comments/empty)
136
- const content = fs.readFileSync(p, 'utf-8');
137
- const data = yaml.parse(content);
138
-
132
+ const data = readYamlIfExists(p);
133
+ if (data !== null) {
139
134
  // Skip if file is empty or only contains null/undefined
140
- if (data === null || data === undefined || (typeof data === 'object' && Object.keys(data).length === 0)) {
135
+ if (data === undefined || (typeof data === 'object' && Object.keys(data).length === 0)) {
141
136
  continue;
142
137
  }
143
138
 
@@ -1,6 +1,7 @@
1
1
  import * as fs from 'fs';
2
2
  import * as path from 'path';
3
3
  import yaml from 'yaml';
4
+ import { readYaml, readYamlIfExists } from '../../../utils/yaml-io';
4
5
 
5
6
  /**
6
7
  * Remove Vietnamese diacritics (accents) from text
@@ -187,10 +188,12 @@ function convertJapaneseToRomaji(text: string): string {
187
188
  return result;
188
189
  }
189
190
 
191
+ import { SelectorType } from '../../../utils/selector-types';
192
+
190
193
  // New structured selector format
191
194
  interface SelectorEntry {
192
195
  locator?: string; // CSS locator (optional, empty string means use type/value)
193
- type?: 'placeholder' | 'role' | 'testid' | 'label' | 'text' | 'locator'; // Locator strategy
196
+ type?: SelectorType; // Locator strategy
194
197
  value?: string; // Natural language value for the locator (e.g., 'button', 'link' for role)
195
198
  name?: string; // Accessible name for role-based selectors (e.g., 'Login', 'Submit')
196
199
  nth?: number; // Element index (0 = no index, 1+ = append .nth())
@@ -285,7 +288,7 @@ export class SelectorResolver {
285
288
  * NOTE: textbox/textarea must precede "text" to prevent partial matching.
286
289
  */
287
290
  static extractNthFromStep(afterElement: string): number {
288
- const nthRegex = /^\s*(?:field|button|textbox|textarea|text|link|input|element|item|logo|image|img|icon|raw|table|columnheader|list|listitem|row|checkbox|radio|dropdown|select|uploader|heading|header)?\s*(\d+)\b/i;
291
+ const nthRegex = /^\s*(?:field|button|textbox|textarea|text|link|input|element|item|logo|image|img|icon|raw|table|column|columnheader|list|listitem|row|checkbox|radio|dropdown|select|uploader|heading|header)?\s*(\d+)\b/i;
289
292
  const match = nthRegex.exec(afterElement);
290
293
  return match ? parseInt(match[1], 10) : 0;
291
294
  }
@@ -683,19 +686,17 @@ export class SelectorResolver {
683
686
  // 1. Try load base file (screen-level shared selectors) - OPTIONAL
684
687
  if (this.screenName) {
685
688
  const basePath = this.findBaseSelectorPath(this.screenName);
686
- if (basePath && fs.existsSync(basePath)) {
687
- const baseContent = fs.readFileSync(basePath, 'utf-8');
688
- const baseSelectors = yaml.parse(baseContent) as SelectorFile;
689
+ if (basePath) {
690
+ const baseSelectors = readYamlIfExists<SelectorFile>(basePath);
689
691
  if (baseSelectors) {
690
692
  Object.assign(selectors, baseSelectors);
691
693
  }
692
694
  }
693
-
695
+
694
696
  // Load base override file
695
697
  const baseOverridePath = this.findOverrideSelectorPath(this.screenName);
696
- if (baseOverridePath && fs.existsSync(baseOverridePath)) {
697
- const overrideContent = fs.readFileSync(baseOverridePath, 'utf-8');
698
- const overrideSelectors = yaml.parse(overrideContent) as SelectorFile;
698
+ if (baseOverridePath) {
699
+ const overrideSelectors = readYamlIfExists<SelectorFile>(baseOverridePath);
699
700
  if (overrideSelectors) {
700
701
  Object.assign(selectors, overrideSelectors);
701
702
  }
@@ -713,18 +714,16 @@ export class SelectorResolver {
713
714
  );
714
715
  }
715
716
  } else {
716
- const featureContent = fs.readFileSync(featurePath, 'utf-8');
717
- const featureSelectors = yaml.parse(featureContent) as SelectorFile;
717
+ const featureSelectors = readYamlIfExists<SelectorFile>(featurePath);
718
718
  if (featureSelectors) {
719
719
  Object.assign(selectors, featureSelectors);
720
720
  }
721
721
  }
722
-
722
+
723
723
  // 3. Load feature override file
724
724
  const featureOverridePath = this.findOverrideSelectorPath(featureName);
725
- if (featureOverridePath && fs.existsSync(featureOverridePath)) {
726
- const overrideContent = fs.readFileSync(featureOverridePath, 'utf-8');
727
- const overrideSelectors = yaml.parse(overrideContent) as SelectorFile;
725
+ if (featureOverridePath) {
726
+ const overrideSelectors = readYamlIfExists<SelectorFile>(featureOverridePath);
728
727
  if (overrideSelectors) {
729
728
  Object.assign(selectors, overrideSelectors);
730
729
  }
@@ -944,8 +943,7 @@ export class SelectorResolver {
944
943
  );
945
944
  }
946
945
 
947
- const content = fs.readFileSync(filePath, 'utf-8');
948
- const selectorFile = yaml.parse(content) as LegacySelectorFile;
946
+ const selectorFile = readYaml<LegacySelectorFile>(filePath);
949
947
 
950
948
  this.selectorCache.set(cacheKey, selectorFile);
951
949
  return selectorFile;