create-appraisejs 0.3.0-alpha.0 → 0.3.0-alpha.1

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 (1087) hide show
  1. package/README.md +19 -7
  2. package/dist/cli-args.d.ts +6 -0
  3. package/dist/cli-args.d.ts.map +1 -0
  4. package/dist/cli-args.js +33 -0
  5. package/dist/cli-args.js.map +1 -0
  6. package/dist/cli.d.ts +2 -1
  7. package/dist/cli.d.ts.map +1 -1
  8. package/dist/cli.js +16 -8
  9. package/dist/cli.js.map +1 -1
  10. package/dist/config.d.ts +2 -1
  11. package/dist/config.d.ts.map +1 -1
  12. package/dist/config.js +3 -3
  13. package/dist/config.js.map +1 -1
  14. package/dist/copy-template.d.ts +3 -2
  15. package/dist/copy-template.d.ts.map +1 -1
  16. package/dist/copy-template.js +6 -7
  17. package/dist/copy-template.js.map +1 -1
  18. package/dist/create-project.d.ts.map +1 -1
  19. package/dist/create-project.js +8 -8
  20. package/dist/create-project.js.map +1 -1
  21. package/dist/prepare-template-utils.d.ts +9 -1
  22. package/dist/prepare-template-utils.d.ts.map +1 -1
  23. package/dist/prepare-template-utils.js +49 -1
  24. package/dist/prepare-template-utils.js.map +1 -1
  25. package/dist/prompts.d.ts +6 -1
  26. package/dist/prompts.d.ts.map +1 -1
  27. package/dist/prompts.js +9 -2
  28. package/dist/prompts.js.map +1 -1
  29. package/dist/sync-templates-utils.d.ts.map +1 -1
  30. package/dist/sync-templates-utils.js +4 -1
  31. package/dist/sync-templates-utils.js.map +1 -1
  32. package/dist/template-catalog.d.ts +22 -0
  33. package/dist/template-catalog.d.ts.map +1 -0
  34. package/dist/template-catalog.js +50 -0
  35. package/dist/template-catalog.js.map +1 -0
  36. package/package.json +5 -3
  37. package/templates/blank/package-lock.json +15012 -0
  38. package/templates/blank/prisma/dev.db +0 -0
  39. package/templates/blank/public/favicon.svg +8 -0
  40. package/templates/blank/public/logo.svg +13 -0
  41. package/templates/blank/scripts/sync-appraise-base-template.ts +244 -0
  42. package/templates/blank/scripts/sync-template-step-groups.ts +247 -0
  43. package/templates/blank/src/app/globals.css +90 -0
  44. package/templates/blank/src/app/layout.tsx +207 -0
  45. package/templates/blank/src/components/theme/theme-provider.tsx +16 -0
  46. package/templates/blank/src/lib/template-sync-utils.js +50 -0
  47. package/templates/blank/src/lib/template-sync-utils.ts +65 -0
  48. package/templates/blank/tsconfig.json +31 -0
  49. package/templates/starter/.env.example +2 -0
  50. package/templates/starter/.vscode/settings.json +13 -0
  51. package/templates/starter/README.md +57 -0
  52. package/templates/starter/automation/config/environments/environments.json +1 -0
  53. package/templates/starter/automation/mapping/locator-map.json +1 -0
  54. package/templates/starter/components.json +24 -0
  55. package/templates/starter/cucumber.mjs +16 -0
  56. package/templates/starter/eslint.config.mjs +20 -0
  57. package/templates/starter/gitignore +56 -0
  58. package/templates/starter/next-env.d.ts +6 -0
  59. package/templates/starter/next.config.ts +20 -0
  60. package/templates/starter/package-lock.json +15012 -0
  61. package/templates/starter/package.json +139 -0
  62. package/templates/starter/packages/cucumber-runtime/package.json +13 -0
  63. package/templates/starter/packages/cucumber-runtime/src/cache.util.ts +93 -0
  64. package/templates/starter/packages/cucumber-runtime/src/cli.ts +68 -0
  65. package/templates/starter/packages/cucumber-runtime/src/environment.util.ts +21 -0
  66. package/templates/starter/packages/cucumber-runtime/src/executor.ts +32 -0
  67. package/templates/starter/packages/cucumber-runtime/src/hooks.ts +106 -0
  68. package/templates/starter/packages/cucumber-runtime/src/index.ts +17 -0
  69. package/templates/starter/packages/cucumber-runtime/src/locator.util.ts +234 -0
  70. package/templates/starter/packages/cucumber-runtime/src/parameter-types.ts +7 -0
  71. package/templates/starter/packages/cucumber-runtime/src/paths.ts +98 -0
  72. package/templates/starter/packages/cucumber-runtime/src/random-data.util.ts +35 -0
  73. package/templates/starter/packages/cucumber-runtime/src/types.ts +13 -0
  74. package/templates/starter/packages/cucumber-runtime/src/world.ts +44 -0
  75. package/templates/starter/packages/cucumber-runtime/tsconfig.json +11 -0
  76. package/templates/starter/packages/locator-picker-companion/dist/cli.d.ts +1 -0
  77. package/templates/starter/packages/locator-picker-companion/dist/cli.js +302 -0
  78. package/templates/starter/packages/locator-picker-companion/dist/index.d.ts +3 -0
  79. package/templates/starter/packages/locator-picker-companion/dist/index.js +3 -0
  80. package/templates/starter/packages/locator-picker-companion/dist/injected-picker-script.d.ts +1 -0
  81. package/templates/starter/packages/locator-picker-companion/dist/injected-picker-script.js +615 -0
  82. package/templates/starter/packages/locator-picker-companion/dist/launcher.d.ts +11 -0
  83. package/templates/starter/packages/locator-picker-companion/dist/launcher.js +59 -0
  84. package/templates/starter/packages/locator-picker-companion/dist/selector-generator.d.ts +3 -0
  85. package/templates/starter/packages/locator-picker-companion/dist/selector-generator.js +257 -0
  86. package/templates/starter/packages/locator-picker-companion/dist/session-file.d.ts +22 -0
  87. package/templates/starter/packages/locator-picker-companion/dist/session-file.js +150 -0
  88. package/templates/starter/packages/locator-picker-companion/dist/types.d.ts +31 -0
  89. package/templates/starter/packages/locator-picker-companion/dist/types.js +1 -0
  90. package/templates/starter/packages/locator-picker-companion/package.json +17 -0
  91. package/templates/starter/packages/locator-picker-companion/src/cli.ts +428 -0
  92. package/templates/starter/packages/locator-picker-companion/src/index.ts +3 -0
  93. package/templates/starter/packages/locator-picker-companion/src/injected-picker-script.ts +771 -0
  94. package/templates/starter/packages/locator-picker-companion/src/launcher.ts +77 -0
  95. package/templates/starter/packages/locator-picker-companion/src/selector-generator.ts +339 -0
  96. package/templates/starter/packages/locator-picker-companion/src/session-file.ts +226 -0
  97. package/templates/starter/packages/locator-picker-companion/src/types.ts +42 -0
  98. package/templates/starter/packages/locator-picker-companion/tsconfig.json +14 -0
  99. package/templates/starter/postcss.config.mjs +8 -0
  100. package/templates/starter/prisma/dev.db +0 -0
  101. package/templates/starter/prisma/migrations/20251026202316_migrate_back_to_sqlite/migration.sql +257 -0
  102. package/templates/starter/prisma/migrations/20251104113456_add_type_for_template_step_groups/migration.sql +16 -0
  103. package/templates/starter/prisma/migrations/20251104170946_add_tags_to_test_suite_and_test_case/migration.sql +27 -0
  104. package/templates/starter/prisma/migrations/20251112190024_add_cascade_delete_to_test_run_test_case/migration.sql +17 -0
  105. package/templates/starter/prisma/migrations/20251113181100_add_test_run_log/migration.sql +12 -0
  106. package/templates/starter/prisma/migrations/20251119191838_add_tag_type/migration.sql +28 -0
  107. package/templates/starter/prisma/migrations/20251121164059_add_conflict_resolution/migration.sql +12 -0
  108. package/templates/starter/prisma/migrations/20251130190737_add_trace_path_to_test_run_test_case/migration.sql +2 -0
  109. package/templates/starter/prisma/migrations/20251213074835_add_log_path_to_test_run/migration.sql +2 -0
  110. package/templates/starter/prisma/migrations/20251213183952_add_name_property_for_the_test_run_entities/migration.sql +30 -0
  111. package/templates/starter/prisma/migrations/20251223183400_add_report_model_to_db_schema/migration.sql +10 -0
  112. package/templates/starter/prisma/migrations/20251223183637_add_report_test_case_entity_for_storing_test_results_for_individual_test_cases/migration.sql +10 -0
  113. package/templates/starter/prisma/migrations/20251224083549_add_comprehensive_report_storage/migration.sql +108 -0
  114. package/templates/starter/prisma/migrations/20251229194422_migrate_duration_to_string/migration.sql +55 -0
  115. package/templates/starter/prisma/migrations/20251230124637_add_unique_constraint_to_test_run_name/migration.sql +27 -0
  116. package/templates/starter/prisma/migrations/20260115094436_add_dashboard_metrics/migration.sql +59 -0
  117. package/templates/starter/prisma/migrations/20260127172022_add_cascade_delete_to_step_parameters/migration.sql +34 -0
  118. package/templates/starter/prisma/migrations/20260313093000_add_report_step_screenshot_path/migration.sql +1 -0
  119. package/templates/starter/prisma/migrations/20260318120000_add_test_suite_context_to_test_run_test_case/migration.sql +20 -0
  120. package/templates/starter/prisma/migrations/20260318173512_add_support_of_test_suite_level_runs/migration.sql +2 -0
  121. package/templates/starter/prisma/migrations/migration_lock.toml +3 -0
  122. package/templates/starter/prisma/schema.prisma +558 -0
  123. package/templates/starter/public/favicon.svg +8 -0
  124. package/templates/starter/public/file.svg +1 -0
  125. package/templates/starter/public/globe.svg +1 -0
  126. package/templates/starter/public/logo.svg +13 -0
  127. package/templates/starter/public/next.svg +1 -0
  128. package/templates/starter/public/vercel.svg +1 -0
  129. package/templates/starter/public/window.svg +1 -0
  130. package/templates/starter/scripts/build-step-registry.ts +33 -0
  131. package/templates/starter/scripts/install-playwright.ts +29 -0
  132. package/templates/starter/scripts/install-template-step.ts +128 -0
  133. package/templates/starter/scripts/lib/filename-utils.test.ts +24 -0
  134. package/templates/starter/scripts/lib/filename-utils.ts +24 -0
  135. package/templates/starter/scripts/lib/jsdoc-parser.test.ts +63 -0
  136. package/templates/starter/scripts/lib/jsdoc-parser.ts +88 -0
  137. package/templates/starter/scripts/lib/step-file-parser.test.ts +71 -0
  138. package/templates/starter/scripts/lib/step-file-parser.ts +315 -0
  139. package/templates/starter/scripts/lib/step-matcher.test.ts +86 -0
  140. package/templates/starter/scripts/lib/step-matcher.ts +120 -0
  141. package/templates/starter/scripts/lib/sync-script-runner.ts +23 -0
  142. package/templates/starter/scripts/lib/sync-summary.ts +29 -0
  143. package/templates/starter/scripts/lib/tag-parsing.test.ts +20 -0
  144. package/templates/starter/scripts/lib/tag-parsing.ts +10 -0
  145. package/templates/starter/scripts/lib/template-step-installer.test.ts +225 -0
  146. package/templates/starter/scripts/lib/template-step-installer.ts +404 -0
  147. package/templates/starter/scripts/lib/template-step-registry.test.ts +118 -0
  148. package/templates/starter/scripts/lib/template-step-registry.ts +137 -0
  149. package/templates/starter/scripts/protect-seeded-files.ts +51 -0
  150. package/templates/starter/scripts/regenerate-features.ts +98 -0
  151. package/templates/starter/scripts/run-vitest.ts +59 -0
  152. package/templates/starter/scripts/setup-env.ts +26 -0
  153. package/templates/starter/scripts/sync-all.ts +287 -0
  154. package/templates/starter/scripts/sync-appraise-base-template.ts +244 -0
  155. package/templates/starter/scripts/sync-environments.ts +305 -0
  156. package/templates/starter/scripts/sync-locator-groups.ts +358 -0
  157. package/templates/starter/scripts/sync-locators.ts +348 -0
  158. package/templates/starter/scripts/sync-modules.ts +302 -0
  159. package/templates/starter/scripts/sync-tags.ts +255 -0
  160. package/templates/starter/scripts/sync-template-step-groups.ts +247 -0
  161. package/templates/starter/scripts/sync-template-steps.ts +386 -0
  162. package/templates/starter/scripts/sync-test-cases.ts +717 -0
  163. package/templates/starter/scripts/sync-test-suites.ts +369 -0
  164. package/templates/starter/src/actions/dashboard/dashboard-actions.ts +70 -0
  165. package/templates/starter/src/actions/environments/environment-actions.ts +102 -0
  166. package/templates/starter/src/actions/locator/locator-actions.ts +77 -0
  167. package/templates/starter/src/actions/locator-groups/locator-group-actions.ts +115 -0
  168. package/templates/starter/src/actions/locator-picker/locator-picker-actions.test.ts +81 -0
  169. package/templates/starter/src/actions/locator-picker/locator-picker-actions.ts +102 -0
  170. package/templates/starter/src/actions/modules/module-actions.ts +99 -0
  171. package/templates/starter/src/actions/reports/report-actions.ts +79 -0
  172. package/templates/starter/src/actions/settings/sync-actions.test.ts +58 -0
  173. package/templates/starter/src/actions/settings/sync-actions.ts +46 -0
  174. package/templates/starter/src/actions/tags/tag-actions.ts +99 -0
  175. package/templates/starter/src/actions/template-step/template-step-actions.ts +114 -0
  176. package/templates/starter/src/actions/template-step-group/template-step-group-actions.ts +129 -0
  177. package/templates/starter/src/actions/template-test-case/template-test-case-actions.ts +98 -0
  178. package/templates/starter/src/actions/test-case/test-case-actions.ts +108 -0
  179. package/templates/starter/src/actions/test-run/test-run-actions.ts +269 -0
  180. package/templates/starter/src/actions/test-suite/test-suite-actions.ts +111 -0
  181. package/templates/starter/src/app/(base)/environments/create/page.tsx +28 -0
  182. package/templates/starter/src/app/(base)/environments/environment-form.test.tsx +92 -0
  183. package/templates/starter/src/app/(base)/environments/environment-form.tsx +228 -0
  184. package/templates/starter/src/app/(base)/environments/environment-helpers.ts +58 -0
  185. package/templates/starter/src/app/(base)/environments/environment-table-columns.tsx +96 -0
  186. package/templates/starter/src/app/(base)/environments/environment-table.tsx +25 -0
  187. package/templates/starter/src/app/(base)/environments/modify/[id]/page.tsx +49 -0
  188. package/templates/starter/src/app/(base)/environments/page.tsx +59 -0
  189. package/templates/starter/src/app/(base)/layout.tsx +10 -0
  190. package/templates/starter/src/app/(base)/locator-groups/create/page.tsx +44 -0
  191. package/templates/starter/src/app/(base)/locator-groups/locator-group-form.tsx +215 -0
  192. package/templates/starter/src/app/(base)/locator-groups/locator-group-table-columns.tsx +77 -0
  193. package/templates/starter/src/app/(base)/locator-groups/locator-group-table.tsx +28 -0
  194. package/templates/starter/src/app/(base)/locator-groups/modify/[id]/page.tsx +46 -0
  195. package/templates/starter/src/app/(base)/locator-groups/page.tsx +71 -0
  196. package/templates/starter/src/app/(base)/locators/create/create-locator-workspace-helpers.test.ts +71 -0
  197. package/templates/starter/src/app/(base)/locators/create/create-locator-workspace-helpers.ts +333 -0
  198. package/templates/starter/src/app/(base)/locators/create/create-locator-workspace.test.tsx +125 -0
  199. package/templates/starter/src/app/(base)/locators/create/create-locator-workspace.tsx +324 -0
  200. package/templates/starter/src/app/(base)/locators/create/page.tsx +55 -0
  201. package/templates/starter/src/app/(base)/locators/create/use-locator-workspace.ts +183 -0
  202. package/templates/starter/src/app/(base)/locators/locator-helpers.test.ts +28 -0
  203. package/templates/starter/src/app/(base)/locators/locator-helpers.ts +59 -0
  204. package/templates/starter/src/app/(base)/locators/locator-table-columns.tsx +74 -0
  205. package/templates/starter/src/app/(base)/locators/locator-table.tsx +30 -0
  206. package/templates/starter/src/app/(base)/locators/modify/[id]/page.tsx +86 -0
  207. package/templates/starter/src/app/(base)/locators/page.tsx +62 -0
  208. package/templates/starter/src/app/(base)/locators/picker/page.tsx +7 -0
  209. package/templates/starter/src/app/(base)/locators/sync-locators-button.tsx +67 -0
  210. package/templates/starter/src/app/(base)/modules/create/page.tsx +33 -0
  211. package/templates/starter/src/app/(base)/modules/modify/[id]/page.tsx +43 -0
  212. package/templates/starter/src/app/(base)/modules/module-form.test.tsx +84 -0
  213. package/templates/starter/src/app/(base)/modules/module-form.tsx +159 -0
  214. package/templates/starter/src/app/(base)/modules/module-helpers.ts +64 -0
  215. package/templates/starter/src/app/(base)/modules/module-table-columns.tsx +81 -0
  216. package/templates/starter/src/app/(base)/modules/module-table.tsx +25 -0
  217. package/templates/starter/src/app/(base)/modules/page.tsx +59 -0
  218. package/templates/starter/src/app/(base)/reports/[id]/page.tsx +284 -0
  219. package/templates/starter/src/app/(base)/reports/duration-chart.tsx +33 -0
  220. package/templates/starter/src/app/(base)/reports/feature-chart.tsx +79 -0
  221. package/templates/starter/src/app/(base)/reports/overview-chart.tsx +49 -0
  222. package/templates/starter/src/app/(base)/reports/page.tsx +98 -0
  223. package/templates/starter/src/app/(base)/reports/report-detail-helpers.test.ts +109 -0
  224. package/templates/starter/src/app/(base)/reports/report-detail-helpers.ts +247 -0
  225. package/templates/starter/src/app/(base)/reports/report-metric-card.tsx +78 -0
  226. package/templates/starter/src/app/(base)/reports/report-table-columns.tsx +189 -0
  227. package/templates/starter/src/app/(base)/reports/report-table.tsx +72 -0
  228. package/templates/starter/src/app/(base)/reports/report-view-table-columns.tsx +142 -0
  229. package/templates/starter/src/app/(base)/reports/report-view-table.tsx +83 -0
  230. package/templates/starter/src/app/(base)/reports/test-cases/page.tsx +40 -0
  231. package/templates/starter/src/app/(base)/reports/test-cases/test-cases-metric-table-columns.tsx +115 -0
  232. package/templates/starter/src/app/(base)/reports/test-cases/test-cases-metric-table.tsx +27 -0
  233. package/templates/starter/src/app/(base)/reports/test-suites/page.tsx +42 -0
  234. package/templates/starter/src/app/(base)/reports/test-suites/test-suites-metric-table-columns.tsx +79 -0
  235. package/templates/starter/src/app/(base)/reports/test-suites/test-suites-metric-table.tsx +27 -0
  236. package/templates/starter/src/app/(base)/reports/view-logs-button.tsx +58 -0
  237. package/templates/starter/src/app/(base)/settings/page.tsx +30 -0
  238. package/templates/starter/src/app/(base)/settings/settings-sync-panel-helpers.test.tsx +40 -0
  239. package/templates/starter/src/app/(base)/settings/settings-sync-panel-helpers.tsx +110 -0
  240. package/templates/starter/src/app/(base)/settings/settings-sync-panel.test.tsx +127 -0
  241. package/templates/starter/src/app/(base)/settings/settings-sync-panel.tsx +146 -0
  242. package/templates/starter/src/app/(base)/settings/use-settings-sync.ts +66 -0
  243. package/templates/starter/src/app/(base)/tags/create/page.tsx +39 -0
  244. package/templates/starter/src/app/(base)/tags/modify/[id]/page.tsx +50 -0
  245. package/templates/starter/src/app/(base)/tags/page.tsx +58 -0
  246. package/templates/starter/src/app/(base)/tags/tag-form-helpers.ts +13 -0
  247. package/templates/starter/src/app/(base)/tags/tag-form.test.tsx +83 -0
  248. package/templates/starter/src/app/(base)/tags/tag-form.tsx +143 -0
  249. package/templates/starter/src/app/(base)/tags/tag-table-columns.tsx +63 -0
  250. package/templates/starter/src/app/(base)/tags/tag-table.tsx +29 -0
  251. package/templates/starter/src/app/(base)/template-step-groups/create/page.tsx +28 -0
  252. package/templates/starter/src/app/(base)/template-step-groups/modify/[id]/page.tsx +43 -0
  253. package/templates/starter/src/app/(base)/template-step-groups/page.tsx +60 -0
  254. package/templates/starter/src/app/(base)/template-step-groups/template-step-group-form.test.tsx +82 -0
  255. package/templates/starter/src/app/(base)/template-step-groups/template-step-group-form.tsx +181 -0
  256. package/templates/starter/src/app/(base)/template-step-groups/template-step-group-helpers.ts +54 -0
  257. package/templates/starter/src/app/(base)/template-step-groups/template-step-group-table-columns.tsx +89 -0
  258. package/templates/starter/src/app/(base)/template-step-groups/template-step-group-table.tsx +34 -0
  259. package/templates/starter/src/app/(base)/template-steps/create/page.tsx +40 -0
  260. package/templates/starter/src/app/(base)/template-steps/modify/[id]/page.tsx +54 -0
  261. package/templates/starter/src/app/(base)/template-steps/page.tsx +59 -0
  262. package/templates/starter/src/app/(base)/template-steps/paramChip.tsx +233 -0
  263. package/templates/starter/src/app/(base)/template-steps/template-step-form.test.tsx +132 -0
  264. package/templates/starter/src/app/(base)/template-steps/template-step-form.tsx +342 -0
  265. package/templates/starter/src/app/(base)/template-steps/template-step-helpers.test.ts +99 -0
  266. package/templates/starter/src/app/(base)/template-steps/template-step-helpers.ts +176 -0
  267. package/templates/starter/src/app/(base)/template-steps/template-step-table-columns.tsx +153 -0
  268. package/templates/starter/src/app/(base)/template-steps/template-step-table.tsx +26 -0
  269. package/templates/starter/src/app/(base)/template-test-cases/create/page.tsx +56 -0
  270. package/templates/starter/src/app/(base)/template-test-cases/modify/[id]/page.tsx +89 -0
  271. package/templates/starter/src/app/(base)/template-test-cases/page.tsx +58 -0
  272. package/templates/starter/src/app/(base)/template-test-cases/template-test-case-flow.test.tsx +109 -0
  273. package/templates/starter/src/app/(base)/template-test-cases/template-test-case-flow.tsx +45 -0
  274. package/templates/starter/src/app/(base)/template-test-cases/template-test-case-form.test.tsx +140 -0
  275. package/templates/starter/src/app/(base)/template-test-cases/template-test-case-form.tsx +154 -0
  276. package/templates/starter/src/app/(base)/template-test-cases/template-test-case-table-columns.tsx +76 -0
  277. package/templates/starter/src/app/(base)/template-test-cases/template-test-case-table.tsx +32 -0
  278. package/templates/starter/src/app/(base)/test-cases/create/page.tsx +90 -0
  279. package/templates/starter/src/app/(base)/test-cases/create-from-template/create-from-template-helpers.test.ts +94 -0
  280. package/templates/starter/src/app/(base)/test-cases/create-from-template/create-from-template-helpers.ts +171 -0
  281. package/templates/starter/src/app/(base)/test-cases/create-from-template/generate/[id]/page.tsx +105 -0
  282. package/templates/starter/src/app/(base)/test-cases/create-from-template/page.tsx +40 -0
  283. package/templates/starter/src/app/(base)/test-cases/create-from-template/template-selection-form.test.tsx +87 -0
  284. package/templates/starter/src/app/(base)/test-cases/create-from-template/template-selection-form.tsx +83 -0
  285. package/templates/starter/src/app/(base)/test-cases/modify/[id]/page.tsx +106 -0
  286. package/templates/starter/src/app/(base)/test-cases/page.tsx +61 -0
  287. package/templates/starter/src/app/(base)/test-cases/test-case-flow.test.tsx +108 -0
  288. package/templates/starter/src/app/(base)/test-cases/test-case-flow.tsx +43 -0
  289. package/templates/starter/src/app/(base)/test-cases/test-case-form.test.tsx +202 -0
  290. package/templates/starter/src/app/(base)/test-cases/test-case-form.tsx +263 -0
  291. package/templates/starter/src/app/(base)/test-cases/test-case-route-helpers.test.ts +95 -0
  292. package/templates/starter/src/app/(base)/test-cases/test-case-route-helpers.ts +147 -0
  293. package/templates/starter/src/app/(base)/test-cases/test-case-table-columns.tsx +25 -0
  294. package/templates/starter/src/app/(base)/test-cases/test-case-table.tsx +37 -0
  295. package/templates/starter/src/app/(base)/test-runs/[id]/page.tsx +60 -0
  296. package/templates/starter/src/app/(base)/test-runs/create/page.tsx +48 -0
  297. package/templates/starter/src/app/(base)/test-runs/page.tsx +60 -0
  298. package/templates/starter/src/app/(base)/test-runs/test-run-form-helpers.test.ts +50 -0
  299. package/templates/starter/src/app/(base)/test-runs/test-run-form-helpers.ts +168 -0
  300. package/templates/starter/src/app/(base)/test-runs/test-run-form.test.tsx +138 -0
  301. package/templates/starter/src/app/(base)/test-runs/test-run-form.tsx +356 -0
  302. package/templates/starter/src/app/(base)/test-runs/test-run-table-columns.tsx +229 -0
  303. package/templates/starter/src/app/(base)/test-runs/test-run-table.tsx +127 -0
  304. package/templates/starter/src/app/(base)/test-runs/use-test-run-name-validation.ts +74 -0
  305. package/templates/starter/src/app/(base)/test-suites/create/page.tsx +51 -0
  306. package/templates/starter/src/app/(base)/test-suites/modify/[id]/page.tsx +59 -0
  307. package/templates/starter/src/app/(base)/test-suites/page.tsx +76 -0
  308. package/templates/starter/src/app/(base)/test-suites/test-suite-form.test.tsx +127 -0
  309. package/templates/starter/src/app/(base)/test-suites/test-suite-form.tsx +249 -0
  310. package/templates/starter/src/app/(base)/test-suites/test-suite-helpers.test.ts +67 -0
  311. package/templates/starter/src/app/(base)/test-suites/test-suite-helpers.ts +215 -0
  312. package/templates/starter/src/app/(base)/test-suites/test-suite-table-columns.tsx +98 -0
  313. package/templates/starter/src/app/(base)/test-suites/test-suite-table.tsx +32 -0
  314. package/templates/starter/src/app/(dashboard-components)/app-drawer.tsx +187 -0
  315. package/templates/starter/src/app/(dashboard-components)/data-card-grid.tsx +13 -0
  316. package/templates/starter/src/app/(dashboard-components)/data-card.tsx +27 -0
  317. package/templates/starter/src/app/(dashboard-components)/execution-health-panel.tsx +57 -0
  318. package/templates/starter/src/app/(dashboard-components)/ongoing-test-runs-card.tsx +87 -0
  319. package/templates/starter/src/app/(dashboard-components)/quick-actions-drawer.tsx +45 -0
  320. package/templates/starter/src/app/api/reports/steps/[stepId]/screenshot/route.test.ts +83 -0
  321. package/templates/starter/src/app/api/reports/steps/[stepId]/screenshot/route.ts +52 -0
  322. package/templates/starter/src/app/api/test-runs/[runId]/download/route.test.ts +169 -0
  323. package/templates/starter/src/app/api/test-runs/[runId]/download/route.ts +196 -0
  324. package/templates/starter/src/app/api/test-runs/[runId]/logs/route.ts +424 -0
  325. package/templates/starter/src/app/api/test-runs/[runId]/trace/[testCaseId]/route.test.ts +135 -0
  326. package/templates/starter/src/app/api/test-runs/[runId]/trace/[testCaseId]/route.ts +146 -0
  327. package/templates/starter/src/app/favicon.ico +0 -0
  328. package/templates/starter/src/app/globals.css +90 -0
  329. package/templates/starter/src/app/layout.tsx +207 -0
  330. package/templates/starter/src/app/page.tsx +65 -0
  331. package/templates/starter/src/assets/icons/empty-tube.tsx +23 -0
  332. package/templates/starter/src/assets/icons/tube-plus.tsx +29 -0
  333. package/templates/starter/src/components/base-node.tsx +21 -0
  334. package/templates/starter/src/components/chart/pie-chart.tsx +73 -0
  335. package/templates/starter/src/components/data-extraction/locator-inspector-helpers.test.ts +32 -0
  336. package/templates/starter/src/components/data-extraction/locator-inspector-helpers.ts +183 -0
  337. package/templates/starter/src/components/data-extraction/locator-inspector.tsx +349 -0
  338. package/templates/starter/src/components/data-state/empty-state.tsx +40 -0
  339. package/templates/starter/src/components/data-visualization/info-card.tsx +70 -0
  340. package/templates/starter/src/components/data-visualization/info-grid.tsx +22 -0
  341. package/templates/starter/src/components/diagram/button-edge.tsx +54 -0
  342. package/templates/starter/src/components/diagram/dynamic-parameters-helpers.test.ts +83 -0
  343. package/templates/starter/src/components/diagram/dynamic-parameters-helpers.ts +158 -0
  344. package/templates/starter/src/components/diagram/dynamic-parameters.tsx +350 -0
  345. package/templates/starter/src/components/diagram/edit-header-option.tsx +36 -0
  346. package/templates/starter/src/components/diagram/flow-diagram-helpers.test.ts +117 -0
  347. package/templates/starter/src/components/diagram/flow-diagram-helpers.ts +251 -0
  348. package/templates/starter/src/components/diagram/flow-diagram.tsx +247 -0
  349. package/templates/starter/src/components/diagram/flow-host-helpers.test.ts +74 -0
  350. package/templates/starter/src/components/diagram/flow-host-helpers.ts +51 -0
  351. package/templates/starter/src/components/diagram/node-form-helpers.test.ts +92 -0
  352. package/templates/starter/src/components/diagram/node-form-helpers.ts +100 -0
  353. package/templates/starter/src/components/diagram/node-form.test.tsx +168 -0
  354. package/templates/starter/src/components/diagram/node-form.tsx +199 -0
  355. package/templates/starter/src/components/diagram/options-header-node.tsx +57 -0
  356. package/templates/starter/src/components/diagram/template-step-combobox.tsx +155 -0
  357. package/templates/starter/src/components/diagram/use-flow-node-order.ts +49 -0
  358. package/templates/starter/src/components/form/error-message.tsx +7 -0
  359. package/templates/starter/src/components/kokonutui/smooth-tab.tsx +453 -0
  360. package/templates/starter/src/components/loading-skeleton/data-table/data-table-skeleton.tsx +30 -0
  361. package/templates/starter/src/components/loading-skeleton/form/button-skeleton.tsx +8 -0
  362. package/templates/starter/src/components/loading-skeleton/form/icon-button-skeleton.tsx +8 -0
  363. package/templates/starter/src/components/loading-skeleton/form/text-input-skeleton.tsx +8 -0
  364. package/templates/starter/src/components/loading-skeleton/visualization/table-skeleton.tsx +14 -0
  365. package/templates/starter/src/components/logo.tsx +15 -0
  366. package/templates/starter/src/components/navigation/command-badge.tsx +34 -0
  367. package/templates/starter/src/components/navigation/command-chain-input.tsx +51 -0
  368. package/templates/starter/src/components/navigation/entity-search-command.tsx +118 -0
  369. package/templates/starter/src/components/navigation/nav-card.tsx +31 -0
  370. package/templates/starter/src/components/navigation/nav-command-helpers.ts +122 -0
  371. package/templates/starter/src/components/navigation/nav-command-search.tsx +125 -0
  372. package/templates/starter/src/components/navigation/nav-command.test.tsx +106 -0
  373. package/templates/starter/src/components/navigation/nav-command.tsx +98 -0
  374. package/templates/starter/src/components/navigation/nav-link.tsx +60 -0
  375. package/templates/starter/src/components/navigation/nav-menu-card-deck.tsx +112 -0
  376. package/templates/starter/src/components/navigation/use-nav-command.ts +58 -0
  377. package/templates/starter/src/components/node-header.tsx +159 -0
  378. package/templates/starter/src/components/reports/test-case-logs-modal.tsx +310 -0
  379. package/templates/starter/src/components/table/table-actions.tsx +174 -0
  380. package/templates/starter/src/components/test-case/test-case-columns.tsx +76 -0
  381. package/templates/starter/src/components/test-case/test-case-form-helpers.test.ts +100 -0
  382. package/templates/starter/src/components/test-case/test-case-form-helpers.ts +140 -0
  383. package/templates/starter/src/components/test-case/test-case-picker-helpers.test.ts +40 -0
  384. package/templates/starter/src/components/test-case/test-case-picker-helpers.ts +41 -0
  385. package/templates/starter/src/components/test-case/test-case-picker.test.tsx +44 -0
  386. package/templates/starter/src/components/test-case/test-case-picker.tsx +225 -0
  387. package/templates/starter/src/components/test-case/test-scenario-preview.tsx +34 -0
  388. package/templates/starter/src/components/test-run/download-logs-button.tsx +92 -0
  389. package/templates/starter/src/components/test-run/log-viewer-helpers.test.ts +37 -0
  390. package/templates/starter/src/components/test-run/log-viewer-helpers.ts +80 -0
  391. package/templates/starter/src/components/test-run/log-viewer.test.tsx +118 -0
  392. package/templates/starter/src/components/test-run/log-viewer.tsx +133 -0
  393. package/templates/starter/src/components/test-run/test-run-details-helpers.test.ts +31 -0
  394. package/templates/starter/src/components/test-run/test-run-details-helpers.ts +208 -0
  395. package/templates/starter/src/components/test-run/test-run-details.test.tsx +174 -0
  396. package/templates/starter/src/components/test-run/test-run-details.tsx +322 -0
  397. package/templates/starter/src/components/test-run/test-run-header-helpers.test.ts +31 -0
  398. package/templates/starter/src/components/test-run/test-run-header-helpers.ts +23 -0
  399. package/templates/starter/src/components/test-run/test-run-header.test.tsx +103 -0
  400. package/templates/starter/src/components/test-run/test-run-header.tsx +27 -0
  401. package/templates/starter/src/components/test-run/use-log-viewer.ts +213 -0
  402. package/templates/starter/src/components/test-run/use-test-run-details.ts +184 -0
  403. package/templates/starter/src/components/test-run/use-test-run-header.ts +89 -0
  404. package/templates/starter/src/components/test-run/view-report-button.tsx +102 -0
  405. package/templates/starter/src/components/test-suite/test-suite-picker-helpers.test.ts +68 -0
  406. package/templates/starter/src/components/test-suite/test-suite-picker-helpers.ts +76 -0
  407. package/templates/starter/src/components/test-suite/test-suite-picker.test.tsx +65 -0
  408. package/templates/starter/src/components/test-suite/test-suite-picker.tsx +376 -0
  409. package/templates/starter/src/components/theme/theme-provider.tsx +16 -0
  410. package/templates/starter/src/components/typography/page-header-subtitle.tsx +7 -0
  411. package/templates/starter/src/components/typography/page-header.tsx +7 -0
  412. package/templates/starter/src/components/ui/alert-dialog.tsx +106 -0
  413. package/templates/starter/src/components/ui/alert.tsx +43 -0
  414. package/templates/starter/src/components/ui/avatar.tsx +40 -0
  415. package/templates/starter/src/components/ui/badge.tsx +29 -0
  416. package/templates/starter/src/components/ui/button.tsx +47 -0
  417. package/templates/starter/src/components/ui/calendar.tsx +158 -0
  418. package/templates/starter/src/components/ui/card.tsx +43 -0
  419. package/templates/starter/src/components/ui/chart.tsx +369 -0
  420. package/templates/starter/src/components/ui/checkbox.tsx +28 -0
  421. package/templates/starter/src/components/ui/command.tsx +135 -0
  422. package/templates/starter/src/components/ui/data-table-column-header.tsx +61 -0
  423. package/templates/starter/src/components/ui/data-table-pagination.tsx +87 -0
  424. package/templates/starter/src/components/ui/data-table-view-options.tsx +50 -0
  425. package/templates/starter/src/components/ui/data-table.test.tsx +122 -0
  426. package/templates/starter/src/components/ui/data-table.tsx +298 -0
  427. package/templates/starter/src/components/ui/dialog.tsx +97 -0
  428. package/templates/starter/src/components/ui/dropdown-menu.tsx +182 -0
  429. package/templates/starter/src/components/ui/empty.tsx +104 -0
  430. package/templates/starter/src/components/ui/input.tsx +22 -0
  431. package/templates/starter/src/components/ui/kbd.tsx +28 -0
  432. package/templates/starter/src/components/ui/label.tsx +19 -0
  433. package/templates/starter/src/components/ui/loading.tsx +12 -0
  434. package/templates/starter/src/components/ui/multi-select-with-preview.tsx +116 -0
  435. package/templates/starter/src/components/ui/multi-select.test.tsx +45 -0
  436. package/templates/starter/src/components/ui/multi-select.tsx +158 -0
  437. package/templates/starter/src/components/ui/navigation-menu.tsx +120 -0
  438. package/templates/starter/src/components/ui/popover.tsx +33 -0
  439. package/templates/starter/src/components/ui/progress.tsx +25 -0
  440. package/templates/starter/src/components/ui/radio-group.tsx +44 -0
  441. package/templates/starter/src/components/ui/scroll-area.tsx +40 -0
  442. package/templates/starter/src/components/ui/select.tsx +151 -0
  443. package/templates/starter/src/components/ui/separator.tsx +22 -0
  444. package/templates/starter/src/components/ui/skeleton.tsx +7 -0
  445. package/templates/starter/src/components/ui/table.tsx +76 -0
  446. package/templates/starter/src/components/ui/tabs.tsx +55 -0
  447. package/templates/starter/src/components/ui/textarea.tsx +21 -0
  448. package/templates/starter/src/components/ui/toast.tsx +113 -0
  449. package/templates/starter/src/components/ui/toaster.tsx +26 -0
  450. package/templates/starter/src/components/ui/tooltip.tsx +32 -0
  451. package/templates/starter/src/components/user-prompt/delete-prompt.test.tsx +60 -0
  452. package/templates/starter/src/components/user-prompt/delete-prompt.tsx +118 -0
  453. package/templates/starter/src/config/db-config.ts +71 -0
  454. package/templates/starter/src/constants/form-opts/diagram/node-form.ts +30 -0
  455. package/templates/starter/src/constants/form-opts/environment-form-opts.ts +24 -0
  456. package/templates/starter/src/constants/form-opts/locator-group-form-opts.ts +28 -0
  457. package/templates/starter/src/constants/form-opts/module-form-opts.ts +21 -0
  458. package/templates/starter/src/constants/form-opts/tag-form-opts.ts +42 -0
  459. package/templates/starter/src/constants/form-opts/template-selection-form-opts.ts +16 -0
  460. package/templates/starter/src/constants/form-opts/template-step-group-form-opts.ts +24 -0
  461. package/templates/starter/src/constants/form-opts/template-test-case-form-opts.ts +39 -0
  462. package/templates/starter/src/constants/form-opts/template-test-step-form-opts.ts +36 -0
  463. package/templates/starter/src/constants/form-opts/test-case-form-opts.ts +43 -0
  464. package/templates/starter/src/constants/form-opts/test-run-form-opts.ts +33 -0
  465. package/templates/starter/src/constants/form-opts/test-suite-form-opts.ts +24 -0
  466. package/templates/starter/src/hooks/use-toast.ts +187 -0
  467. package/templates/starter/src/lib/automation/automation-path-roots.ts +95 -0
  468. package/templates/starter/src/lib/automation/automation-workspace.ts +147 -0
  469. package/templates/starter/src/lib/automation/paths.ts +6 -0
  470. package/templates/starter/src/lib/automation/projection-service.ts +226 -0
  471. package/templates/starter/src/lib/bidirectional-sync.ts +432 -0
  472. package/templates/starter/src/lib/database-sync.ts +526 -0
  473. package/templates/starter/src/lib/environment-file-utils.ts +181 -0
  474. package/templates/starter/src/lib/executor/local-executor-adapter.ts +97 -0
  475. package/templates/starter/src/lib/executor/types.ts +24 -0
  476. package/templates/starter/src/lib/feature-file-generator.ts +261 -0
  477. package/templates/starter/src/lib/gherkin-parser.test.ts +44 -0
  478. package/templates/starter/src/lib/gherkin-parser.ts +251 -0
  479. package/templates/starter/src/lib/locator-group-file-utils.ts +304 -0
  480. package/templates/starter/src/lib/locator-picker/session-manager.ts +431 -0
  481. package/templates/starter/src/lib/locator-picker/suggestions.ts +126 -0
  482. package/templates/starter/src/lib/metrics/metric-calculator.ts +614 -0
  483. package/templates/starter/src/lib/module-hierarchy-builder.ts +205 -0
  484. package/templates/starter/src/lib/path-helpers/module-path.ts +71 -0
  485. package/templates/starter/src/lib/process/task-spawner.ts +273 -0
  486. package/templates/starter/src/lib/sync/projected-feature-utils.ts +113 -0
  487. package/templates/starter/src/lib/sync/sync-executor.test.ts +76 -0
  488. package/templates/starter/src/lib/sync/sync-executor.ts +130 -0
  489. package/templates/starter/src/lib/sync/sync-pending-counts.test.ts +264 -0
  490. package/templates/starter/src/lib/sync/sync-pending-counts.ts +1356 -0
  491. package/templates/starter/src/lib/sync/sync-registry.ts +149 -0
  492. package/templates/starter/src/lib/tag-utils.ts +28 -0
  493. package/templates/starter/src/lib/template-sync-utils.d.ts +7 -0
  494. package/templates/starter/src/lib/template-sync-utils.d.ts.map +1 -0
  495. package/templates/starter/src/lib/template-sync-utils.js +50 -0
  496. package/templates/starter/src/lib/template-sync-utils.js.map +1 -0
  497. package/templates/starter/src/lib/template-sync-utils.ts +65 -0
  498. package/templates/starter/src/lib/test-case-utils.ts +6 -0
  499. package/templates/starter/src/lib/test-run/log-formatter.ts +83 -0
  500. package/templates/starter/src/lib/test-run/matching.ts +117 -0
  501. package/templates/starter/src/lib/test-run/process-manager.ts +115 -0
  502. package/templates/starter/src/lib/test-run/report-parser.ts +352 -0
  503. package/templates/starter/src/lib/test-run/test-run-executor.ts +13 -0
  504. package/templates/starter/src/lib/test-run/winston-logger.ts +65 -0
  505. package/templates/starter/src/lib/test-suite-identifier-service.ts +76 -0
  506. package/templates/starter/src/lib/test-suite-utils.ts +6 -0
  507. package/templates/starter/src/lib/transformers/gherkin-converter.ts +42 -0
  508. package/templates/starter/src/lib/transformers/key-to-icon-transformer.tsx +95 -0
  509. package/templates/starter/src/lib/transformers/template-test-case-converter.ts +160 -0
  510. package/templates/starter/src/lib/utils/node-param-validation.ts +81 -0
  511. package/templates/starter/src/lib/utils/template-step-file-generator.ts +128 -0
  512. package/templates/starter/src/lib/utils/template-step-file-manager-intelligent.ts +700 -0
  513. package/templates/starter/src/lib/utils/template-step-file-manager.ts +166 -0
  514. package/templates/starter/src/lib/utils.ts +31 -0
  515. package/templates/starter/src/services/dashboard/dashboard-service.test.ts +106 -0
  516. package/templates/starter/src/services/dashboard/dashboard-service.ts +173 -0
  517. package/templates/starter/src/services/environment/environment-service.test.ts +137 -0
  518. package/templates/starter/src/services/environment/environment-service.ts +96 -0
  519. package/templates/starter/src/services/locator/locator-path-utils.test.ts +14 -0
  520. package/templates/starter/src/services/locator/locator-path-utils.ts +14 -0
  521. package/templates/starter/src/services/locator/locator-service.test.ts +63 -0
  522. package/templates/starter/src/services/locator/locator-service.ts +479 -0
  523. package/templates/starter/src/services/locator/locator-sync-utils.test.ts +19 -0
  524. package/templates/starter/src/services/locator/locator-sync-utils.ts +21 -0
  525. package/templates/starter/src/services/locator-group/locator-group-service.test.ts +123 -0
  526. package/templates/starter/src/services/locator-group/locator-group-service.ts +180 -0
  527. package/templates/starter/src/services/module/module-service.test.ts +89 -0
  528. package/templates/starter/src/services/module/module-service.ts +66 -0
  529. package/templates/starter/src/services/report/report-service.test.ts +244 -0
  530. package/templates/starter/src/services/report/report-service.ts +438 -0
  531. package/templates/starter/src/services/shared/constants.ts +2 -0
  532. package/templates/starter/src/services/shared/errors.test.ts +38 -0
  533. package/templates/starter/src/services/shared/errors.ts +44 -0
  534. package/templates/starter/src/services/shared/index.ts +7 -0
  535. package/templates/starter/src/services/tag/tag-service.test.ts +22 -0
  536. package/templates/starter/src/services/tag/tag-service.ts +41 -0
  537. package/templates/starter/src/services/template-step/template-step-service.test.ts +22 -0
  538. package/templates/starter/src/services/template-step/template-step-service.ts +171 -0
  539. package/templates/starter/src/services/template-step-group/template-step-group-service.test.ts +22 -0
  540. package/templates/starter/src/services/template-step-group/template-step-group-service.ts +81 -0
  541. package/templates/starter/src/services/template-test-case/template-test-case-service.test.ts +22 -0
  542. package/templates/starter/src/services/template-test-case/template-test-case-service.ts +128 -0
  543. package/templates/starter/src/services/test-case/test-case-service.test.ts +175 -0
  544. package/templates/starter/src/services/test-case/test-case-service.ts +298 -0
  545. package/templates/starter/src/services/test-run/test-run-helpers.ts +61 -0
  546. package/templates/starter/src/services/test-run/test-run-service.test.ts +647 -0
  547. package/templates/starter/src/services/test-run/test-run-service.ts +917 -0
  548. package/templates/starter/src/services/test-suite/test-suite-service.test.ts +127 -0
  549. package/templates/starter/src/services/test-suite/test-suite-service.ts +197 -0
  550. package/templates/starter/src/types/diagram/diagram.ts +34 -0
  551. package/templates/starter/src/types/diagram/template-step.ts +11 -0
  552. package/templates/starter/src/types/executor/browser.type.ts +1 -0
  553. package/templates/starter/src/types/form/actionHandler.ts +19 -0
  554. package/templates/starter/src/types/locator/locator.type.ts +11 -0
  555. package/templates/starter/src/types/locator-picker.ts +65 -0
  556. package/templates/starter/src/types/step/step.type.ts +1 -0
  557. package/templates/starter/src/types/table/data-table.ts +6 -0
  558. package/templates/starter/src/types/test-case-picker.ts +6 -0
  559. package/templates/starter/src/types/test-suite-picker.ts +18 -0
  560. package/templates/starter/tailwind.config.ts +62 -0
  561. package/templates/starter/tsconfig.json +31 -0
  562. package/templates/default/.appraise-template-meta.json +0 -5
  563. package/templates/default/package-lock.json +0 -14957
  564. package/templates/default/prisma/dev.db +0 -0
  565. package/templates/default/public/favicon.svg +0 -11
  566. package/templates/default/public/logo.svg +0 -18
  567. package/templates/default/scripts/sync-appraise-base-template.ts +0 -244
  568. package/templates/default/scripts/sync-template-step-groups.ts +0 -248
  569. package/templates/default/src/app/globals.css +0 -147
  570. package/templates/default/src/app/layout.tsx +0 -212
  571. package/templates/default/src/components/theme/mode-toggle.tsx +0 -54
  572. package/templates/default/src/components/theme/theme-provider.tsx +0 -8
  573. package/templates/default/src/lib/template-sync-utils.js +0 -47
  574. package/templates/default/src/lib/template-sync-utils.ts +0 -63
  575. package/templates/default/tsconfig.json +0 -31
  576. /package/templates/{default → blank}/.env.example +0 -0
  577. /package/templates/{default → blank}/.vscode/settings.json +0 -0
  578. /package/templates/{default → blank}/README.md +0 -0
  579. /package/templates/{default → blank}/automation/config/environments/environments.json +0 -0
  580. /package/templates/{default → blank}/automation/mapping/locator-map.json +0 -0
  581. /package/templates/{default → blank}/components.json +0 -0
  582. /package/templates/{default → blank}/cucumber.mjs +0 -0
  583. /package/templates/{default → blank}/eslint.config.mjs +0 -0
  584. /package/templates/{default → blank}/gitignore +0 -0
  585. /package/templates/{default → blank}/next-env.d.ts +0 -0
  586. /package/templates/{default → blank}/next.config.ts +0 -0
  587. /package/templates/{default → blank}/package.json +0 -0
  588. /package/templates/{default → blank}/packages/cucumber-runtime/package.json +0 -0
  589. /package/templates/{default → blank}/packages/cucumber-runtime/src/cache.util.ts +0 -0
  590. /package/templates/{default → blank}/packages/cucumber-runtime/src/cli.ts +0 -0
  591. /package/templates/{default → blank}/packages/cucumber-runtime/src/environment.util.ts +0 -0
  592. /package/templates/{default → blank}/packages/cucumber-runtime/src/executor.ts +0 -0
  593. /package/templates/{default → blank}/packages/cucumber-runtime/src/hooks.ts +0 -0
  594. /package/templates/{default → blank}/packages/cucumber-runtime/src/index.ts +0 -0
  595. /package/templates/{default → blank}/packages/cucumber-runtime/src/locator.util.ts +0 -0
  596. /package/templates/{default → blank}/packages/cucumber-runtime/src/parameter-types.ts +0 -0
  597. /package/templates/{default → blank}/packages/cucumber-runtime/src/paths.ts +0 -0
  598. /package/templates/{default → blank}/packages/cucumber-runtime/src/random-data.util.ts +0 -0
  599. /package/templates/{default → blank}/packages/cucumber-runtime/src/types.ts +0 -0
  600. /package/templates/{default → blank}/packages/cucumber-runtime/src/world.ts +0 -0
  601. /package/templates/{default → blank}/packages/cucumber-runtime/tsconfig.json +0 -0
  602. /package/templates/{default → blank}/packages/locator-picker-companion/dist/cli.d.ts +0 -0
  603. /package/templates/{default → blank}/packages/locator-picker-companion/dist/cli.js +0 -0
  604. /package/templates/{default → blank}/packages/locator-picker-companion/dist/index.d.ts +0 -0
  605. /package/templates/{default → blank}/packages/locator-picker-companion/dist/index.js +0 -0
  606. /package/templates/{default → blank}/packages/locator-picker-companion/dist/injected-picker-script.d.ts +0 -0
  607. /package/templates/{default → blank}/packages/locator-picker-companion/dist/injected-picker-script.js +0 -0
  608. /package/templates/{default → blank}/packages/locator-picker-companion/dist/launcher.d.ts +0 -0
  609. /package/templates/{default → blank}/packages/locator-picker-companion/dist/launcher.js +0 -0
  610. /package/templates/{default → blank}/packages/locator-picker-companion/dist/selector-generator.d.ts +0 -0
  611. /package/templates/{default → blank}/packages/locator-picker-companion/dist/selector-generator.js +0 -0
  612. /package/templates/{default → blank}/packages/locator-picker-companion/dist/session-file.d.ts +0 -0
  613. /package/templates/{default → blank}/packages/locator-picker-companion/dist/session-file.js +0 -0
  614. /package/templates/{default → blank}/packages/locator-picker-companion/dist/types.d.ts +0 -0
  615. /package/templates/{default → blank}/packages/locator-picker-companion/dist/types.js +0 -0
  616. /package/templates/{default → blank}/packages/locator-picker-companion/package.json +0 -0
  617. /package/templates/{default → blank}/packages/locator-picker-companion/src/cli.ts +0 -0
  618. /package/templates/{default → blank}/packages/locator-picker-companion/src/index.ts +0 -0
  619. /package/templates/{default → blank}/packages/locator-picker-companion/src/injected-picker-script.ts +0 -0
  620. /package/templates/{default → blank}/packages/locator-picker-companion/src/launcher.ts +0 -0
  621. /package/templates/{default → blank}/packages/locator-picker-companion/src/selector-generator.ts +0 -0
  622. /package/templates/{default → blank}/packages/locator-picker-companion/src/session-file.ts +0 -0
  623. /package/templates/{default → blank}/packages/locator-picker-companion/src/types.ts +0 -0
  624. /package/templates/{default → blank}/packages/locator-picker-companion/tsconfig.json +0 -0
  625. /package/templates/{default → blank}/postcss.config.mjs +0 -0
  626. /package/templates/{default → blank}/prisma/migrations/20251026202316_migrate_back_to_sqlite/migration.sql +0 -0
  627. /package/templates/{default → blank}/prisma/migrations/20251104113456_add_type_for_template_step_groups/migration.sql +0 -0
  628. /package/templates/{default → blank}/prisma/migrations/20251104170946_add_tags_to_test_suite_and_test_case/migration.sql +0 -0
  629. /package/templates/{default → blank}/prisma/migrations/20251112190024_add_cascade_delete_to_test_run_test_case/migration.sql +0 -0
  630. /package/templates/{default → blank}/prisma/migrations/20251113181100_add_test_run_log/migration.sql +0 -0
  631. /package/templates/{default → blank}/prisma/migrations/20251119191838_add_tag_type/migration.sql +0 -0
  632. /package/templates/{default → blank}/prisma/migrations/20251121164059_add_conflict_resolution/migration.sql +0 -0
  633. /package/templates/{default → blank}/prisma/migrations/20251130190737_add_trace_path_to_test_run_test_case/migration.sql +0 -0
  634. /package/templates/{default → blank}/prisma/migrations/20251213074835_add_log_path_to_test_run/migration.sql +0 -0
  635. /package/templates/{default → blank}/prisma/migrations/20251213183952_add_name_property_for_the_test_run_entities/migration.sql +0 -0
  636. /package/templates/{default → blank}/prisma/migrations/20251223183400_add_report_model_to_db_schema/migration.sql +0 -0
  637. /package/templates/{default → blank}/prisma/migrations/20251223183637_add_report_test_case_entity_for_storing_test_results_for_individual_test_cases/migration.sql +0 -0
  638. /package/templates/{default → blank}/prisma/migrations/20251224083549_add_comprehensive_report_storage/migration.sql +0 -0
  639. /package/templates/{default → blank}/prisma/migrations/20251229194422_migrate_duration_to_string/migration.sql +0 -0
  640. /package/templates/{default → blank}/prisma/migrations/20251230124637_add_unique_constraint_to_test_run_name/migration.sql +0 -0
  641. /package/templates/{default → blank}/prisma/migrations/20260115094436_add_dashboard_metrics/migration.sql +0 -0
  642. /package/templates/{default → blank}/prisma/migrations/20260127172022_add_cascade_delete_to_step_parameters/migration.sql +0 -0
  643. /package/templates/{default → blank}/prisma/migrations/20260313093000_add_report_step_screenshot_path/migration.sql +0 -0
  644. /package/templates/{default → blank}/prisma/migrations/20260318120000_add_test_suite_context_to_test_run_test_case/migration.sql +0 -0
  645. /package/templates/{default → blank}/prisma/migrations/20260318173512_add_support_of_test_suite_level_runs/migration.sql +0 -0
  646. /package/templates/{default → blank}/prisma/migrations/migration_lock.toml +0 -0
  647. /package/templates/{default → blank}/prisma/schema.prisma +0 -0
  648. /package/templates/{default → blank}/public/file.svg +0 -0
  649. /package/templates/{default → blank}/public/globe.svg +0 -0
  650. /package/templates/{default → blank}/public/next.svg +0 -0
  651. /package/templates/{default → blank}/public/vercel.svg +0 -0
  652. /package/templates/{default → blank}/public/window.svg +0 -0
  653. /package/templates/{default → blank}/scripts/build-step-registry.ts +0 -0
  654. /package/templates/{default → blank}/scripts/install-playwright.ts +0 -0
  655. /package/templates/{default → blank}/scripts/install-template-step.ts +0 -0
  656. /package/templates/{default → blank}/scripts/lib/filename-utils.test.ts +0 -0
  657. /package/templates/{default → blank}/scripts/lib/filename-utils.ts +0 -0
  658. /package/templates/{default → blank}/scripts/lib/jsdoc-parser.test.ts +0 -0
  659. /package/templates/{default → blank}/scripts/lib/jsdoc-parser.ts +0 -0
  660. /package/templates/{default → blank}/scripts/lib/step-file-parser.test.ts +0 -0
  661. /package/templates/{default → blank}/scripts/lib/step-file-parser.ts +0 -0
  662. /package/templates/{default → blank}/scripts/lib/step-matcher.test.ts +0 -0
  663. /package/templates/{default → blank}/scripts/lib/step-matcher.ts +0 -0
  664. /package/templates/{default → blank}/scripts/lib/sync-script-runner.ts +0 -0
  665. /package/templates/{default → blank}/scripts/lib/sync-summary.ts +0 -0
  666. /package/templates/{default → blank}/scripts/lib/tag-parsing.test.ts +0 -0
  667. /package/templates/{default → blank}/scripts/lib/tag-parsing.ts +0 -0
  668. /package/templates/{default → blank}/scripts/lib/template-step-installer.test.ts +0 -0
  669. /package/templates/{default → blank}/scripts/lib/template-step-installer.ts +0 -0
  670. /package/templates/{default → blank}/scripts/lib/template-step-registry.test.ts +0 -0
  671. /package/templates/{default → blank}/scripts/lib/template-step-registry.ts +0 -0
  672. /package/templates/{default → blank}/scripts/protect-seeded-files.ts +0 -0
  673. /package/templates/{default → blank}/scripts/regenerate-features.ts +0 -0
  674. /package/templates/{default → blank}/scripts/run-vitest.ts +0 -0
  675. /package/templates/{default → blank}/scripts/setup-env.ts +0 -0
  676. /package/templates/{default → blank}/scripts/sync-all.ts +0 -0
  677. /package/templates/{default → blank}/scripts/sync-environments.ts +0 -0
  678. /package/templates/{default → blank}/scripts/sync-locator-groups.ts +0 -0
  679. /package/templates/{default → blank}/scripts/sync-locators.ts +0 -0
  680. /package/templates/{default → blank}/scripts/sync-modules.ts +0 -0
  681. /package/templates/{default → blank}/scripts/sync-tags.ts +0 -0
  682. /package/templates/{default → blank}/scripts/sync-template-steps.ts +0 -0
  683. /package/templates/{default → blank}/scripts/sync-test-cases.ts +0 -0
  684. /package/templates/{default → blank}/scripts/sync-test-suites.ts +0 -0
  685. /package/templates/{default → blank}/src/actions/dashboard/dashboard-actions.ts +0 -0
  686. /package/templates/{default → blank}/src/actions/environments/environment-actions.ts +0 -0
  687. /package/templates/{default → blank}/src/actions/locator/locator-actions.ts +0 -0
  688. /package/templates/{default → blank}/src/actions/locator-groups/locator-group-actions.ts +0 -0
  689. /package/templates/{default → blank}/src/actions/locator-picker/locator-picker-actions.test.ts +0 -0
  690. /package/templates/{default → blank}/src/actions/locator-picker/locator-picker-actions.ts +0 -0
  691. /package/templates/{default → blank}/src/actions/modules/module-actions.ts +0 -0
  692. /package/templates/{default → blank}/src/actions/reports/report-actions.ts +0 -0
  693. /package/templates/{default → blank}/src/actions/settings/sync-actions.test.ts +0 -0
  694. /package/templates/{default → blank}/src/actions/settings/sync-actions.ts +0 -0
  695. /package/templates/{default → blank}/src/actions/tags/tag-actions.ts +0 -0
  696. /package/templates/{default → blank}/src/actions/template-step/template-step-actions.ts +0 -0
  697. /package/templates/{default → blank}/src/actions/template-step-group/template-step-group-actions.ts +0 -0
  698. /package/templates/{default → blank}/src/actions/template-test-case/template-test-case-actions.ts +0 -0
  699. /package/templates/{default → blank}/src/actions/test-case/test-case-actions.ts +0 -0
  700. /package/templates/{default → blank}/src/actions/test-run/test-run-actions.ts +0 -0
  701. /package/templates/{default → blank}/src/actions/test-suite/test-suite-actions.ts +0 -0
  702. /package/templates/{default → blank}/src/app/(base)/environments/create/page.tsx +0 -0
  703. /package/templates/{default → blank}/src/app/(base)/environments/environment-form.test.tsx +0 -0
  704. /package/templates/{default → blank}/src/app/(base)/environments/environment-form.tsx +0 -0
  705. /package/templates/{default → blank}/src/app/(base)/environments/environment-helpers.ts +0 -0
  706. /package/templates/{default → blank}/src/app/(base)/environments/environment-table-columns.tsx +0 -0
  707. /package/templates/{default → blank}/src/app/(base)/environments/environment-table.tsx +0 -0
  708. /package/templates/{default → blank}/src/app/(base)/environments/modify/[id]/page.tsx +0 -0
  709. /package/templates/{default → blank}/src/app/(base)/environments/page.tsx +0 -0
  710. /package/templates/{default → blank}/src/app/(base)/layout.tsx +0 -0
  711. /package/templates/{default → blank}/src/app/(base)/locator-groups/create/page.tsx +0 -0
  712. /package/templates/{default → blank}/src/app/(base)/locator-groups/locator-group-form.tsx +0 -0
  713. /package/templates/{default → blank}/src/app/(base)/locator-groups/locator-group-table-columns.tsx +0 -0
  714. /package/templates/{default → blank}/src/app/(base)/locator-groups/locator-group-table.tsx +0 -0
  715. /package/templates/{default → blank}/src/app/(base)/locator-groups/modify/[id]/page.tsx +0 -0
  716. /package/templates/{default → blank}/src/app/(base)/locator-groups/page.tsx +0 -0
  717. /package/templates/{default → blank}/src/app/(base)/locators/create/create-locator-workspace-helpers.test.ts +0 -0
  718. /package/templates/{default → blank}/src/app/(base)/locators/create/create-locator-workspace-helpers.ts +0 -0
  719. /package/templates/{default → blank}/src/app/(base)/locators/create/create-locator-workspace.test.tsx +0 -0
  720. /package/templates/{default → blank}/src/app/(base)/locators/create/create-locator-workspace.tsx +0 -0
  721. /package/templates/{default → blank}/src/app/(base)/locators/create/page.tsx +0 -0
  722. /package/templates/{default → blank}/src/app/(base)/locators/create/use-locator-workspace.ts +0 -0
  723. /package/templates/{default → blank}/src/app/(base)/locators/locator-helpers.test.ts +0 -0
  724. /package/templates/{default → blank}/src/app/(base)/locators/locator-helpers.ts +0 -0
  725. /package/templates/{default → blank}/src/app/(base)/locators/locator-table-columns.tsx +0 -0
  726. /package/templates/{default → blank}/src/app/(base)/locators/locator-table.tsx +0 -0
  727. /package/templates/{default → blank}/src/app/(base)/locators/modify/[id]/page.tsx +0 -0
  728. /package/templates/{default → blank}/src/app/(base)/locators/page.tsx +0 -0
  729. /package/templates/{default → blank}/src/app/(base)/locators/picker/page.tsx +0 -0
  730. /package/templates/{default → blank}/src/app/(base)/locators/sync-locators-button.tsx +0 -0
  731. /package/templates/{default → blank}/src/app/(base)/modules/create/page.tsx +0 -0
  732. /package/templates/{default → blank}/src/app/(base)/modules/modify/[id]/page.tsx +0 -0
  733. /package/templates/{default → blank}/src/app/(base)/modules/module-form.test.tsx +0 -0
  734. /package/templates/{default → blank}/src/app/(base)/modules/module-form.tsx +0 -0
  735. /package/templates/{default → blank}/src/app/(base)/modules/module-helpers.ts +0 -0
  736. /package/templates/{default → blank}/src/app/(base)/modules/module-table-columns.tsx +0 -0
  737. /package/templates/{default → blank}/src/app/(base)/modules/module-table.tsx +0 -0
  738. /package/templates/{default → blank}/src/app/(base)/modules/page.tsx +0 -0
  739. /package/templates/{default → blank}/src/app/(base)/reports/[id]/page.tsx +0 -0
  740. /package/templates/{default → blank}/src/app/(base)/reports/duration-chart.tsx +0 -0
  741. /package/templates/{default → blank}/src/app/(base)/reports/feature-chart.tsx +0 -0
  742. /package/templates/{default → blank}/src/app/(base)/reports/overview-chart.tsx +0 -0
  743. /package/templates/{default → blank}/src/app/(base)/reports/page.tsx +0 -0
  744. /package/templates/{default → blank}/src/app/(base)/reports/report-detail-helpers.test.ts +0 -0
  745. /package/templates/{default → blank}/src/app/(base)/reports/report-detail-helpers.ts +0 -0
  746. /package/templates/{default → blank}/src/app/(base)/reports/report-metric-card.tsx +0 -0
  747. /package/templates/{default → blank}/src/app/(base)/reports/report-table-columns.tsx +0 -0
  748. /package/templates/{default → blank}/src/app/(base)/reports/report-table.tsx +0 -0
  749. /package/templates/{default → blank}/src/app/(base)/reports/report-view-table-columns.tsx +0 -0
  750. /package/templates/{default → blank}/src/app/(base)/reports/report-view-table.tsx +0 -0
  751. /package/templates/{default → blank}/src/app/(base)/reports/test-cases/page.tsx +0 -0
  752. /package/templates/{default → blank}/src/app/(base)/reports/test-cases/test-cases-metric-table-columns.tsx +0 -0
  753. /package/templates/{default → blank}/src/app/(base)/reports/test-cases/test-cases-metric-table.tsx +0 -0
  754. /package/templates/{default → blank}/src/app/(base)/reports/test-suites/page.tsx +0 -0
  755. /package/templates/{default → blank}/src/app/(base)/reports/test-suites/test-suites-metric-table-columns.tsx +0 -0
  756. /package/templates/{default → blank}/src/app/(base)/reports/test-suites/test-suites-metric-table.tsx +0 -0
  757. /package/templates/{default → blank}/src/app/(base)/reports/view-logs-button.tsx +0 -0
  758. /package/templates/{default → blank}/src/app/(base)/settings/page.tsx +0 -0
  759. /package/templates/{default → blank}/src/app/(base)/settings/settings-sync-panel-helpers.test.tsx +0 -0
  760. /package/templates/{default → blank}/src/app/(base)/settings/settings-sync-panel-helpers.tsx +0 -0
  761. /package/templates/{default → blank}/src/app/(base)/settings/settings-sync-panel.test.tsx +0 -0
  762. /package/templates/{default → blank}/src/app/(base)/settings/settings-sync-panel.tsx +0 -0
  763. /package/templates/{default → blank}/src/app/(base)/settings/use-settings-sync.ts +0 -0
  764. /package/templates/{default → blank}/src/app/(base)/tags/create/page.tsx +0 -0
  765. /package/templates/{default → blank}/src/app/(base)/tags/modify/[id]/page.tsx +0 -0
  766. /package/templates/{default → blank}/src/app/(base)/tags/page.tsx +0 -0
  767. /package/templates/{default → blank}/src/app/(base)/tags/tag-form-helpers.ts +0 -0
  768. /package/templates/{default → blank}/src/app/(base)/tags/tag-form.test.tsx +0 -0
  769. /package/templates/{default → blank}/src/app/(base)/tags/tag-form.tsx +0 -0
  770. /package/templates/{default → blank}/src/app/(base)/tags/tag-table-columns.tsx +0 -0
  771. /package/templates/{default → blank}/src/app/(base)/tags/tag-table.tsx +0 -0
  772. /package/templates/{default → blank}/src/app/(base)/template-step-groups/create/page.tsx +0 -0
  773. /package/templates/{default → blank}/src/app/(base)/template-step-groups/modify/[id]/page.tsx +0 -0
  774. /package/templates/{default → blank}/src/app/(base)/template-step-groups/page.tsx +0 -0
  775. /package/templates/{default → blank}/src/app/(base)/template-step-groups/template-step-group-form.test.tsx +0 -0
  776. /package/templates/{default → blank}/src/app/(base)/template-step-groups/template-step-group-form.tsx +0 -0
  777. /package/templates/{default → blank}/src/app/(base)/template-step-groups/template-step-group-helpers.ts +0 -0
  778. /package/templates/{default → blank}/src/app/(base)/template-step-groups/template-step-group-table-columns.tsx +0 -0
  779. /package/templates/{default → blank}/src/app/(base)/template-step-groups/template-step-group-table.tsx +0 -0
  780. /package/templates/{default → blank}/src/app/(base)/template-steps/create/page.tsx +0 -0
  781. /package/templates/{default → blank}/src/app/(base)/template-steps/modify/[id]/page.tsx +0 -0
  782. /package/templates/{default → blank}/src/app/(base)/template-steps/page.tsx +0 -0
  783. /package/templates/{default → blank}/src/app/(base)/template-steps/paramChip.tsx +0 -0
  784. /package/templates/{default → blank}/src/app/(base)/template-steps/template-step-form.test.tsx +0 -0
  785. /package/templates/{default → blank}/src/app/(base)/template-steps/template-step-form.tsx +0 -0
  786. /package/templates/{default → blank}/src/app/(base)/template-steps/template-step-helpers.test.ts +0 -0
  787. /package/templates/{default → blank}/src/app/(base)/template-steps/template-step-helpers.ts +0 -0
  788. /package/templates/{default → blank}/src/app/(base)/template-steps/template-step-table-columns.tsx +0 -0
  789. /package/templates/{default → blank}/src/app/(base)/template-steps/template-step-table.tsx +0 -0
  790. /package/templates/{default → blank}/src/app/(base)/template-test-cases/create/page.tsx +0 -0
  791. /package/templates/{default → blank}/src/app/(base)/template-test-cases/modify/[id]/page.tsx +0 -0
  792. /package/templates/{default → blank}/src/app/(base)/template-test-cases/page.tsx +0 -0
  793. /package/templates/{default → blank}/src/app/(base)/template-test-cases/template-test-case-flow.test.tsx +0 -0
  794. /package/templates/{default → blank}/src/app/(base)/template-test-cases/template-test-case-flow.tsx +0 -0
  795. /package/templates/{default → blank}/src/app/(base)/template-test-cases/template-test-case-form.test.tsx +0 -0
  796. /package/templates/{default → blank}/src/app/(base)/template-test-cases/template-test-case-form.tsx +0 -0
  797. /package/templates/{default → blank}/src/app/(base)/template-test-cases/template-test-case-table-columns.tsx +0 -0
  798. /package/templates/{default → blank}/src/app/(base)/template-test-cases/template-test-case-table.tsx +0 -0
  799. /package/templates/{default → blank}/src/app/(base)/test-cases/create/page.tsx +0 -0
  800. /package/templates/{default → blank}/src/app/(base)/test-cases/create-from-template/create-from-template-helpers.test.ts +0 -0
  801. /package/templates/{default → blank}/src/app/(base)/test-cases/create-from-template/create-from-template-helpers.ts +0 -0
  802. /package/templates/{default → blank}/src/app/(base)/test-cases/create-from-template/generate/[id]/page.tsx +0 -0
  803. /package/templates/{default → blank}/src/app/(base)/test-cases/create-from-template/page.tsx +0 -0
  804. /package/templates/{default → blank}/src/app/(base)/test-cases/create-from-template/template-selection-form.test.tsx +0 -0
  805. /package/templates/{default → blank}/src/app/(base)/test-cases/create-from-template/template-selection-form.tsx +0 -0
  806. /package/templates/{default → blank}/src/app/(base)/test-cases/modify/[id]/page.tsx +0 -0
  807. /package/templates/{default → blank}/src/app/(base)/test-cases/page.tsx +0 -0
  808. /package/templates/{default → blank}/src/app/(base)/test-cases/test-case-flow.test.tsx +0 -0
  809. /package/templates/{default → blank}/src/app/(base)/test-cases/test-case-flow.tsx +0 -0
  810. /package/templates/{default → blank}/src/app/(base)/test-cases/test-case-form.test.tsx +0 -0
  811. /package/templates/{default → blank}/src/app/(base)/test-cases/test-case-form.tsx +0 -0
  812. /package/templates/{default → blank}/src/app/(base)/test-cases/test-case-route-helpers.test.ts +0 -0
  813. /package/templates/{default → blank}/src/app/(base)/test-cases/test-case-route-helpers.ts +0 -0
  814. /package/templates/{default → blank}/src/app/(base)/test-cases/test-case-table-columns.tsx +0 -0
  815. /package/templates/{default → blank}/src/app/(base)/test-cases/test-case-table.tsx +0 -0
  816. /package/templates/{default → blank}/src/app/(base)/test-runs/[id]/page.tsx +0 -0
  817. /package/templates/{default → blank}/src/app/(base)/test-runs/create/page.tsx +0 -0
  818. /package/templates/{default → blank}/src/app/(base)/test-runs/page.tsx +0 -0
  819. /package/templates/{default → blank}/src/app/(base)/test-runs/test-run-form-helpers.test.ts +0 -0
  820. /package/templates/{default → blank}/src/app/(base)/test-runs/test-run-form-helpers.ts +0 -0
  821. /package/templates/{default → blank}/src/app/(base)/test-runs/test-run-form.test.tsx +0 -0
  822. /package/templates/{default → blank}/src/app/(base)/test-runs/test-run-form.tsx +0 -0
  823. /package/templates/{default → blank}/src/app/(base)/test-runs/test-run-table-columns.tsx +0 -0
  824. /package/templates/{default → blank}/src/app/(base)/test-runs/test-run-table.tsx +0 -0
  825. /package/templates/{default → blank}/src/app/(base)/test-runs/use-test-run-name-validation.ts +0 -0
  826. /package/templates/{default → blank}/src/app/(base)/test-suites/create/page.tsx +0 -0
  827. /package/templates/{default → blank}/src/app/(base)/test-suites/modify/[id]/page.tsx +0 -0
  828. /package/templates/{default → blank}/src/app/(base)/test-suites/page.tsx +0 -0
  829. /package/templates/{default → blank}/src/app/(base)/test-suites/test-suite-form.test.tsx +0 -0
  830. /package/templates/{default → blank}/src/app/(base)/test-suites/test-suite-form.tsx +0 -0
  831. /package/templates/{default → blank}/src/app/(base)/test-suites/test-suite-helpers.test.ts +0 -0
  832. /package/templates/{default → blank}/src/app/(base)/test-suites/test-suite-helpers.ts +0 -0
  833. /package/templates/{default → blank}/src/app/(base)/test-suites/test-suite-table-columns.tsx +0 -0
  834. /package/templates/{default → blank}/src/app/(base)/test-suites/test-suite-table.tsx +0 -0
  835. /package/templates/{default → blank}/src/app/(dashboard-components)/app-drawer.tsx +0 -0
  836. /package/templates/{default → blank}/src/app/(dashboard-components)/data-card-grid.tsx +0 -0
  837. /package/templates/{default → blank}/src/app/(dashboard-components)/data-card.tsx +0 -0
  838. /package/templates/{default → blank}/src/app/(dashboard-components)/execution-health-panel.tsx +0 -0
  839. /package/templates/{default → blank}/src/app/(dashboard-components)/ongoing-test-runs-card.tsx +0 -0
  840. /package/templates/{default → blank}/src/app/(dashboard-components)/quick-actions-drawer.tsx +0 -0
  841. /package/templates/{default → blank}/src/app/api/reports/steps/[stepId]/screenshot/route.test.ts +0 -0
  842. /package/templates/{default → blank}/src/app/api/reports/steps/[stepId]/screenshot/route.ts +0 -0
  843. /package/templates/{default → blank}/src/app/api/test-runs/[runId]/download/route.test.ts +0 -0
  844. /package/templates/{default → blank}/src/app/api/test-runs/[runId]/download/route.ts +0 -0
  845. /package/templates/{default → blank}/src/app/api/test-runs/[runId]/logs/route.ts +0 -0
  846. /package/templates/{default → blank}/src/app/api/test-runs/[runId]/trace/[testCaseId]/route.test.ts +0 -0
  847. /package/templates/{default → blank}/src/app/api/test-runs/[runId]/trace/[testCaseId]/route.ts +0 -0
  848. /package/templates/{default → blank}/src/app/favicon.ico +0 -0
  849. /package/templates/{default → blank}/src/app/page.tsx +0 -0
  850. /package/templates/{default → blank}/src/assets/icons/empty-tube.tsx +0 -0
  851. /package/templates/{default → blank}/src/assets/icons/tube-plus.tsx +0 -0
  852. /package/templates/{default → blank}/src/components/base-node.tsx +0 -0
  853. /package/templates/{default → blank}/src/components/chart/pie-chart.tsx +0 -0
  854. /package/templates/{default → blank}/src/components/data-extraction/locator-inspector-helpers.test.ts +0 -0
  855. /package/templates/{default → blank}/src/components/data-extraction/locator-inspector-helpers.ts +0 -0
  856. /package/templates/{default → blank}/src/components/data-extraction/locator-inspector.tsx +0 -0
  857. /package/templates/{default → blank}/src/components/data-state/empty-state.tsx +0 -0
  858. /package/templates/{default → blank}/src/components/data-visualization/info-card.tsx +0 -0
  859. /package/templates/{default → blank}/src/components/data-visualization/info-grid.tsx +0 -0
  860. /package/templates/{default → blank}/src/components/diagram/button-edge.tsx +0 -0
  861. /package/templates/{default → blank}/src/components/diagram/dynamic-parameters-helpers.test.ts +0 -0
  862. /package/templates/{default → blank}/src/components/diagram/dynamic-parameters-helpers.ts +0 -0
  863. /package/templates/{default → blank}/src/components/diagram/dynamic-parameters.tsx +0 -0
  864. /package/templates/{default → blank}/src/components/diagram/edit-header-option.tsx +0 -0
  865. /package/templates/{default → blank}/src/components/diagram/flow-diagram-helpers.test.ts +0 -0
  866. /package/templates/{default → blank}/src/components/diagram/flow-diagram-helpers.ts +0 -0
  867. /package/templates/{default → blank}/src/components/diagram/flow-diagram.tsx +0 -0
  868. /package/templates/{default → blank}/src/components/diagram/flow-host-helpers.test.ts +0 -0
  869. /package/templates/{default → blank}/src/components/diagram/flow-host-helpers.ts +0 -0
  870. /package/templates/{default → blank}/src/components/diagram/node-form-helpers.test.ts +0 -0
  871. /package/templates/{default → blank}/src/components/diagram/node-form-helpers.ts +0 -0
  872. /package/templates/{default → blank}/src/components/diagram/node-form.test.tsx +0 -0
  873. /package/templates/{default → blank}/src/components/diagram/node-form.tsx +0 -0
  874. /package/templates/{default → blank}/src/components/diagram/options-header-node.tsx +0 -0
  875. /package/templates/{default → blank}/src/components/diagram/template-step-combobox.tsx +0 -0
  876. /package/templates/{default → blank}/src/components/diagram/use-flow-node-order.ts +0 -0
  877. /package/templates/{default → blank}/src/components/form/error-message.tsx +0 -0
  878. /package/templates/{default → blank}/src/components/kokonutui/smooth-tab.tsx +0 -0
  879. /package/templates/{default → blank}/src/components/loading-skeleton/data-table/data-table-skeleton.tsx +0 -0
  880. /package/templates/{default → blank}/src/components/loading-skeleton/form/button-skeleton.tsx +0 -0
  881. /package/templates/{default → blank}/src/components/loading-skeleton/form/icon-button-skeleton.tsx +0 -0
  882. /package/templates/{default → blank}/src/components/loading-skeleton/form/text-input-skeleton.tsx +0 -0
  883. /package/templates/{default → blank}/src/components/loading-skeleton/visualization/table-skeleton.tsx +0 -0
  884. /package/templates/{default → blank}/src/components/logo.tsx +0 -0
  885. /package/templates/{default → blank}/src/components/navigation/command-badge.tsx +0 -0
  886. /package/templates/{default → blank}/src/components/navigation/command-chain-input.tsx +0 -0
  887. /package/templates/{default → blank}/src/components/navigation/entity-search-command.tsx +0 -0
  888. /package/templates/{default → blank}/src/components/navigation/nav-card.tsx +0 -0
  889. /package/templates/{default → blank}/src/components/navigation/nav-command-helpers.ts +0 -0
  890. /package/templates/{default → blank}/src/components/navigation/nav-command-search.tsx +0 -0
  891. /package/templates/{default → blank}/src/components/navigation/nav-command.test.tsx +0 -0
  892. /package/templates/{default → blank}/src/components/navigation/nav-command.tsx +0 -0
  893. /package/templates/{default → blank}/src/components/navigation/nav-link.tsx +0 -0
  894. /package/templates/{default → blank}/src/components/navigation/nav-menu-card-deck.tsx +0 -0
  895. /package/templates/{default → blank}/src/components/navigation/use-nav-command.ts +0 -0
  896. /package/templates/{default → blank}/src/components/node-header.tsx +0 -0
  897. /package/templates/{default → blank}/src/components/reports/test-case-logs-modal.tsx +0 -0
  898. /package/templates/{default → blank}/src/components/table/table-actions.tsx +0 -0
  899. /package/templates/{default → blank}/src/components/test-case/test-case-columns.tsx +0 -0
  900. /package/templates/{default → blank}/src/components/test-case/test-case-form-helpers.test.ts +0 -0
  901. /package/templates/{default → blank}/src/components/test-case/test-case-form-helpers.ts +0 -0
  902. /package/templates/{default → blank}/src/components/test-case/test-case-picker-helpers.test.ts +0 -0
  903. /package/templates/{default → blank}/src/components/test-case/test-case-picker-helpers.ts +0 -0
  904. /package/templates/{default → blank}/src/components/test-case/test-case-picker.test.tsx +0 -0
  905. /package/templates/{default → blank}/src/components/test-case/test-case-picker.tsx +0 -0
  906. /package/templates/{default → blank}/src/components/test-case/test-scenario-preview.tsx +0 -0
  907. /package/templates/{default → blank}/src/components/test-run/download-logs-button.tsx +0 -0
  908. /package/templates/{default → blank}/src/components/test-run/log-viewer-helpers.test.ts +0 -0
  909. /package/templates/{default → blank}/src/components/test-run/log-viewer-helpers.ts +0 -0
  910. /package/templates/{default → blank}/src/components/test-run/log-viewer.test.tsx +0 -0
  911. /package/templates/{default → blank}/src/components/test-run/log-viewer.tsx +0 -0
  912. /package/templates/{default → blank}/src/components/test-run/test-run-details-helpers.test.ts +0 -0
  913. /package/templates/{default → blank}/src/components/test-run/test-run-details-helpers.ts +0 -0
  914. /package/templates/{default → blank}/src/components/test-run/test-run-details.test.tsx +0 -0
  915. /package/templates/{default → blank}/src/components/test-run/test-run-details.tsx +0 -0
  916. /package/templates/{default → blank}/src/components/test-run/test-run-header-helpers.test.ts +0 -0
  917. /package/templates/{default → blank}/src/components/test-run/test-run-header-helpers.ts +0 -0
  918. /package/templates/{default → blank}/src/components/test-run/test-run-header.test.tsx +0 -0
  919. /package/templates/{default → blank}/src/components/test-run/test-run-header.tsx +0 -0
  920. /package/templates/{default → blank}/src/components/test-run/use-log-viewer.ts +0 -0
  921. /package/templates/{default → blank}/src/components/test-run/use-test-run-details.ts +0 -0
  922. /package/templates/{default → blank}/src/components/test-run/use-test-run-header.ts +0 -0
  923. /package/templates/{default → blank}/src/components/test-run/view-report-button.tsx +0 -0
  924. /package/templates/{default → blank}/src/components/test-suite/test-suite-picker-helpers.test.ts +0 -0
  925. /package/templates/{default → blank}/src/components/test-suite/test-suite-picker-helpers.ts +0 -0
  926. /package/templates/{default → blank}/src/components/test-suite/test-suite-picker.test.tsx +0 -0
  927. /package/templates/{default → blank}/src/components/test-suite/test-suite-picker.tsx +0 -0
  928. /package/templates/{default → blank}/src/components/typography/page-header-subtitle.tsx +0 -0
  929. /package/templates/{default → blank}/src/components/typography/page-header.tsx +0 -0
  930. /package/templates/{default → blank}/src/components/ui/alert-dialog.tsx +0 -0
  931. /package/templates/{default → blank}/src/components/ui/alert.tsx +0 -0
  932. /package/templates/{default → blank}/src/components/ui/avatar.tsx +0 -0
  933. /package/templates/{default → blank}/src/components/ui/badge.tsx +0 -0
  934. /package/templates/{default → blank}/src/components/ui/button.tsx +0 -0
  935. /package/templates/{default → blank}/src/components/ui/calendar.tsx +0 -0
  936. /package/templates/{default → blank}/src/components/ui/card.tsx +0 -0
  937. /package/templates/{default → blank}/src/components/ui/chart.tsx +0 -0
  938. /package/templates/{default → blank}/src/components/ui/checkbox.tsx +0 -0
  939. /package/templates/{default → blank}/src/components/ui/command.tsx +0 -0
  940. /package/templates/{default → blank}/src/components/ui/data-table-column-header.tsx +0 -0
  941. /package/templates/{default → blank}/src/components/ui/data-table-pagination.tsx +0 -0
  942. /package/templates/{default → blank}/src/components/ui/data-table-view-options.tsx +0 -0
  943. /package/templates/{default → blank}/src/components/ui/data-table.test.tsx +0 -0
  944. /package/templates/{default → blank}/src/components/ui/data-table.tsx +0 -0
  945. /package/templates/{default → blank}/src/components/ui/dialog.tsx +0 -0
  946. /package/templates/{default → blank}/src/components/ui/dropdown-menu.tsx +0 -0
  947. /package/templates/{default → blank}/src/components/ui/empty.tsx +0 -0
  948. /package/templates/{default → blank}/src/components/ui/input.tsx +0 -0
  949. /package/templates/{default → blank}/src/components/ui/kbd.tsx +0 -0
  950. /package/templates/{default → blank}/src/components/ui/label.tsx +0 -0
  951. /package/templates/{default → blank}/src/components/ui/loading.tsx +0 -0
  952. /package/templates/{default → blank}/src/components/ui/multi-select-with-preview.tsx +0 -0
  953. /package/templates/{default → blank}/src/components/ui/multi-select.test.tsx +0 -0
  954. /package/templates/{default → blank}/src/components/ui/multi-select.tsx +0 -0
  955. /package/templates/{default → blank}/src/components/ui/navigation-menu.tsx +0 -0
  956. /package/templates/{default → blank}/src/components/ui/popover.tsx +0 -0
  957. /package/templates/{default → blank}/src/components/ui/progress.tsx +0 -0
  958. /package/templates/{default → blank}/src/components/ui/radio-group.tsx +0 -0
  959. /package/templates/{default → blank}/src/components/ui/scroll-area.tsx +0 -0
  960. /package/templates/{default → blank}/src/components/ui/select.tsx +0 -0
  961. /package/templates/{default → blank}/src/components/ui/separator.tsx +0 -0
  962. /package/templates/{default → blank}/src/components/ui/skeleton.tsx +0 -0
  963. /package/templates/{default → blank}/src/components/ui/table.tsx +0 -0
  964. /package/templates/{default → blank}/src/components/ui/tabs.tsx +0 -0
  965. /package/templates/{default → blank}/src/components/ui/textarea.tsx +0 -0
  966. /package/templates/{default → blank}/src/components/ui/toast.tsx +0 -0
  967. /package/templates/{default → blank}/src/components/ui/toaster.tsx +0 -0
  968. /package/templates/{default → blank}/src/components/ui/tooltip.tsx +0 -0
  969. /package/templates/{default → blank}/src/components/user-prompt/delete-prompt.test.tsx +0 -0
  970. /package/templates/{default → blank}/src/components/user-prompt/delete-prompt.tsx +0 -0
  971. /package/templates/{default → blank}/src/config/db-config.ts +0 -0
  972. /package/templates/{default → blank}/src/constants/form-opts/diagram/node-form.ts +0 -0
  973. /package/templates/{default → blank}/src/constants/form-opts/environment-form-opts.ts +0 -0
  974. /package/templates/{default → blank}/src/constants/form-opts/locator-group-form-opts.ts +0 -0
  975. /package/templates/{default → blank}/src/constants/form-opts/module-form-opts.ts +0 -0
  976. /package/templates/{default → blank}/src/constants/form-opts/tag-form-opts.ts +0 -0
  977. /package/templates/{default → blank}/src/constants/form-opts/template-selection-form-opts.ts +0 -0
  978. /package/templates/{default → blank}/src/constants/form-opts/template-step-group-form-opts.ts +0 -0
  979. /package/templates/{default → blank}/src/constants/form-opts/template-test-case-form-opts.ts +0 -0
  980. /package/templates/{default → blank}/src/constants/form-opts/template-test-step-form-opts.ts +0 -0
  981. /package/templates/{default → blank}/src/constants/form-opts/test-case-form-opts.ts +0 -0
  982. /package/templates/{default → blank}/src/constants/form-opts/test-run-form-opts.ts +0 -0
  983. /package/templates/{default → blank}/src/constants/form-opts/test-suite-form-opts.ts +0 -0
  984. /package/templates/{default → blank}/src/hooks/use-toast.ts +0 -0
  985. /package/templates/{default → blank}/src/lib/automation/automation-path-roots.ts +0 -0
  986. /package/templates/{default → blank}/src/lib/automation/automation-workspace.ts +0 -0
  987. /package/templates/{default → blank}/src/lib/automation/paths.ts +0 -0
  988. /package/templates/{default → blank}/src/lib/automation/projection-service.ts +0 -0
  989. /package/templates/{default → blank}/src/lib/bidirectional-sync.ts +0 -0
  990. /package/templates/{default → blank}/src/lib/database-sync.ts +0 -0
  991. /package/templates/{default → blank}/src/lib/environment-file-utils.ts +0 -0
  992. /package/templates/{default → blank}/src/lib/executor/local-executor-adapter.ts +0 -0
  993. /package/templates/{default → blank}/src/lib/executor/types.ts +0 -0
  994. /package/templates/{default → blank}/src/lib/feature-file-generator.ts +0 -0
  995. /package/templates/{default → blank}/src/lib/gherkin-parser.test.ts +0 -0
  996. /package/templates/{default → blank}/src/lib/gherkin-parser.ts +0 -0
  997. /package/templates/{default → blank}/src/lib/locator-group-file-utils.ts +0 -0
  998. /package/templates/{default → blank}/src/lib/locator-picker/session-manager.ts +0 -0
  999. /package/templates/{default → blank}/src/lib/locator-picker/suggestions.ts +0 -0
  1000. /package/templates/{default → blank}/src/lib/metrics/metric-calculator.ts +0 -0
  1001. /package/templates/{default → blank}/src/lib/module-hierarchy-builder.ts +0 -0
  1002. /package/templates/{default → blank}/src/lib/path-helpers/module-path.ts +0 -0
  1003. /package/templates/{default → blank}/src/lib/process/task-spawner.ts +0 -0
  1004. /package/templates/{default → blank}/src/lib/sync/projected-feature-utils.ts +0 -0
  1005. /package/templates/{default → blank}/src/lib/sync/sync-executor.test.ts +0 -0
  1006. /package/templates/{default → blank}/src/lib/sync/sync-executor.ts +0 -0
  1007. /package/templates/{default → blank}/src/lib/sync/sync-pending-counts.test.ts +0 -0
  1008. /package/templates/{default → blank}/src/lib/sync/sync-pending-counts.ts +0 -0
  1009. /package/templates/{default → blank}/src/lib/sync/sync-registry.ts +0 -0
  1010. /package/templates/{default → blank}/src/lib/tag-utils.ts +0 -0
  1011. /package/templates/{default → blank}/src/lib/template-sync-utils.d.ts +0 -0
  1012. /package/templates/{default → blank}/src/lib/template-sync-utils.d.ts.map +0 -0
  1013. /package/templates/{default → blank}/src/lib/template-sync-utils.js.map +0 -0
  1014. /package/templates/{default → blank}/src/lib/test-case-utils.ts +0 -0
  1015. /package/templates/{default → blank}/src/lib/test-run/log-formatter.ts +0 -0
  1016. /package/templates/{default → blank}/src/lib/test-run/matching.ts +0 -0
  1017. /package/templates/{default → blank}/src/lib/test-run/process-manager.ts +0 -0
  1018. /package/templates/{default → blank}/src/lib/test-run/report-parser.ts +0 -0
  1019. /package/templates/{default → blank}/src/lib/test-run/test-run-executor.ts +0 -0
  1020. /package/templates/{default → blank}/src/lib/test-run/winston-logger.ts +0 -0
  1021. /package/templates/{default → blank}/src/lib/test-suite-identifier-service.ts +0 -0
  1022. /package/templates/{default → blank}/src/lib/test-suite-utils.ts +0 -0
  1023. /package/templates/{default → blank}/src/lib/transformers/gherkin-converter.ts +0 -0
  1024. /package/templates/{default → blank}/src/lib/transformers/key-to-icon-transformer.tsx +0 -0
  1025. /package/templates/{default → blank}/src/lib/transformers/template-test-case-converter.ts +0 -0
  1026. /package/templates/{default → blank}/src/lib/utils/node-param-validation.ts +0 -0
  1027. /package/templates/{default → blank}/src/lib/utils/template-step-file-generator.ts +0 -0
  1028. /package/templates/{default → blank}/src/lib/utils/template-step-file-manager-intelligent.ts +0 -0
  1029. /package/templates/{default → blank}/src/lib/utils/template-step-file-manager.ts +0 -0
  1030. /package/templates/{default → blank}/src/lib/utils.ts +0 -0
  1031. /package/templates/{default → blank}/src/services/dashboard/dashboard-service.test.ts +0 -0
  1032. /package/templates/{default → blank}/src/services/dashboard/dashboard-service.ts +0 -0
  1033. /package/templates/{default → blank}/src/services/environment/environment-service.test.ts +0 -0
  1034. /package/templates/{default → blank}/src/services/environment/environment-service.ts +0 -0
  1035. /package/templates/{default → blank}/src/services/locator/locator-path-utils.test.ts +0 -0
  1036. /package/templates/{default → blank}/src/services/locator/locator-path-utils.ts +0 -0
  1037. /package/templates/{default → blank}/src/services/locator/locator-service.test.ts +0 -0
  1038. /package/templates/{default → blank}/src/services/locator/locator-service.ts +0 -0
  1039. /package/templates/{default → blank}/src/services/locator/locator-sync-utils.test.ts +0 -0
  1040. /package/templates/{default → blank}/src/services/locator/locator-sync-utils.ts +0 -0
  1041. /package/templates/{default → blank}/src/services/locator-group/locator-group-service.test.ts +0 -0
  1042. /package/templates/{default → blank}/src/services/locator-group/locator-group-service.ts +0 -0
  1043. /package/templates/{default → blank}/src/services/module/module-service.test.ts +0 -0
  1044. /package/templates/{default → blank}/src/services/module/module-service.ts +0 -0
  1045. /package/templates/{default → blank}/src/services/report/report-service.test.ts +0 -0
  1046. /package/templates/{default → blank}/src/services/report/report-service.ts +0 -0
  1047. /package/templates/{default → blank}/src/services/shared/constants.ts +0 -0
  1048. /package/templates/{default → blank}/src/services/shared/errors.test.ts +0 -0
  1049. /package/templates/{default → blank}/src/services/shared/errors.ts +0 -0
  1050. /package/templates/{default → blank}/src/services/shared/index.ts +0 -0
  1051. /package/templates/{default → blank}/src/services/tag/tag-service.test.ts +0 -0
  1052. /package/templates/{default → blank}/src/services/tag/tag-service.ts +0 -0
  1053. /package/templates/{default → blank}/src/services/template-step/template-step-service.test.ts +0 -0
  1054. /package/templates/{default → blank}/src/services/template-step/template-step-service.ts +0 -0
  1055. /package/templates/{default → blank}/src/services/template-step-group/template-step-group-service.test.ts +0 -0
  1056. /package/templates/{default → blank}/src/services/template-step-group/template-step-group-service.ts +0 -0
  1057. /package/templates/{default → blank}/src/services/template-test-case/template-test-case-service.test.ts +0 -0
  1058. /package/templates/{default → blank}/src/services/template-test-case/template-test-case-service.ts +0 -0
  1059. /package/templates/{default → blank}/src/services/test-case/test-case-service.test.ts +0 -0
  1060. /package/templates/{default → blank}/src/services/test-case/test-case-service.ts +0 -0
  1061. /package/templates/{default → blank}/src/services/test-run/test-run-helpers.ts +0 -0
  1062. /package/templates/{default → blank}/src/services/test-run/test-run-service.test.ts +0 -0
  1063. /package/templates/{default → blank}/src/services/test-run/test-run-service.ts +0 -0
  1064. /package/templates/{default → blank}/src/services/test-suite/test-suite-service.test.ts +0 -0
  1065. /package/templates/{default → blank}/src/services/test-suite/test-suite-service.ts +0 -0
  1066. /package/templates/{default → blank}/src/types/diagram/diagram.ts +0 -0
  1067. /package/templates/{default → blank}/src/types/diagram/template-step.ts +0 -0
  1068. /package/templates/{default → blank}/src/types/executor/browser.type.ts +0 -0
  1069. /package/templates/{default → blank}/src/types/form/actionHandler.ts +0 -0
  1070. /package/templates/{default → blank}/src/types/locator/locator.type.ts +0 -0
  1071. /package/templates/{default → blank}/src/types/locator-picker.ts +0 -0
  1072. /package/templates/{default → blank}/src/types/step/step.type.ts +0 -0
  1073. /package/templates/{default → blank}/src/types/table/data-table.ts +0 -0
  1074. /package/templates/{default → blank}/src/types/test-case-picker.ts +0 -0
  1075. /package/templates/{default → blank}/src/types/test-suite-picker.ts +0 -0
  1076. /package/templates/{default → blank}/tailwind.config.ts +0 -0
  1077. /package/templates/{default → starter}/automation/steps/actions/click.step.ts +0 -0
  1078. /package/templates/{default → starter}/automation/steps/actions/hover.step.ts +0 -0
  1079. /package/templates/{default → starter}/automation/steps/actions/input.step.ts +0 -0
  1080. /package/templates/{default → starter}/automation/steps/actions/navigation.step.ts +0 -0
  1081. /package/templates/{default → starter}/automation/steps/actions/random_data.step.ts +0 -0
  1082. /package/templates/{default → starter}/automation/steps/actions/store.step.ts +0 -0
  1083. /package/templates/{default → starter}/automation/steps/actions/wait.step.ts +0 -0
  1084. /package/templates/{default → starter}/automation/steps/validations/active_state_assertion.step.ts +0 -0
  1085. /package/templates/{default → starter}/automation/steps/validations/navigation_assertion.step.ts +0 -0
  1086. /package/templates/{default → starter}/automation/steps/validations/text_assertion.step.ts +0 -0
  1087. /package/templates/{default → starter}/automation/steps/validations/visibility_assertion.step.ts +0 -0
@@ -0,0 +1,1356 @@
1
+ import { promises as fs } from 'fs'
2
+ import { join } from 'path'
3
+ import { glob } from 'glob'
4
+ import prettier from 'prettier'
5
+ import { parse } from '@babel/parser'
6
+ import * as t from '@babel/types'
7
+ import _traverse from '@babel/traverse'
8
+ import type { NodePath } from '@babel/traverse'
9
+ import {
10
+ StepParameterType,
11
+ TagType,
12
+ TemplateStepGroupType,
13
+ TemplateStepIcon,
14
+ TemplateStepType,
15
+ } from '@prisma/client'
16
+ import prisma from '@/config/db-config'
17
+ import { getAutomationEnvironmentsDir, getAutomationFeaturesDir } from '@/lib/automation/automation-path-roots'
18
+ import { ensureAutomationWorkspaceReady } from '@/lib/automation/automation-workspace'
19
+ import { extractModulePathFromFilePath, scanFeatureFiles, type ParsedFeature, type ParsedStep } from '@/lib/gherkin-parser'
20
+ import { getAllModulesWithPaths } from '@/lib/module-hierarchy-builder'
21
+ import { SYNC_ALL_REQUEST_ID, syncScriptDefinitions, type SyncRequestId, type SyncScriptId } from '@/lib/sync/sync-registry'
22
+ import { getTagTypeFromName } from '@/lib/tag-utils'
23
+ import { extractModulePathFromAutomationFile, getAutomationLocatorMapPath } from '@/lib/template-sync-utils'
24
+ import {
25
+ determineProjectedStepIcon,
26
+ getTestSuiteSyncIdentity,
27
+ normalizeProjectedDbTestCaseSteps,
28
+ } from '@/lib/sync/projected-feature-utils'
29
+
30
+ const traverse = (_traverse as { default?: typeof _traverse }).default ?? _traverse
31
+
32
+ export type SyncPendingCounts = Record<SyncRequestId, number>
33
+
34
+ type EnvironmentConfig = {
35
+ baseUrl: string
36
+ apiBaseUrl: string
37
+ email: string
38
+ password: string
39
+ }
40
+
41
+ type EnvironmentData = {
42
+ name: string
43
+ baseUrl: string
44
+ apiBaseUrl: string | null
45
+ username: string | null
46
+ password: string | null
47
+ }
48
+
49
+ type LocatorMapEntry = {
50
+ name: string
51
+ path: string
52
+ }
53
+
54
+ type LocatorGroupFromFs = {
55
+ name: string
56
+ route: string
57
+ modulePath: string
58
+ }
59
+
60
+ type LocatorFileData = {
61
+ groupName: string
62
+ modulePath: string
63
+ locators: Record<string, string>
64
+ }
65
+
66
+ type StepGroupJSDoc = {
67
+ name: string
68
+ description: string | null
69
+ type: TemplateStepGroupType
70
+ }
71
+
72
+ type StepJSDoc = {
73
+ name: string
74
+ description: string | null
75
+ icon: TemplateStepIcon
76
+ }
77
+
78
+ type StepParameter = {
79
+ name: string
80
+ type: StepParameterType
81
+ order: number
82
+ }
83
+
84
+ type ParsedTemplateStep = {
85
+ jsdoc: StepJSDoc
86
+ signature: string
87
+ functionDefinition: string
88
+ normalizedFunctionDefinition: string
89
+ parameters: StepParameter[]
90
+ keyword: 'When' | 'Then' | 'Given'
91
+ }
92
+
93
+ type ParsedStepFile = {
94
+ group: StepGroupJSDoc
95
+ steps: ParsedTemplateStep[]
96
+ }
97
+
98
+ type TemplateStepFromFs = {
99
+ step: ParsedTemplateStep
100
+ groupName: string
101
+ groupType: TemplateStepGroupType
102
+ }
103
+
104
+ type TestSuiteFromFs = {
105
+ name: string
106
+ description: string | null
107
+ modulePath: string
108
+ tags: string[]
109
+ }
110
+
111
+ type TestCaseFromFs = {
112
+ identifierTag: string
113
+ title: string
114
+ description: string
115
+ testSuiteName: string
116
+ modulePath: string
117
+ filterTags: string[]
118
+ steps: ParsedStep[]
119
+ }
120
+
121
+ type ParameterMatch = {
122
+ name: string
123
+ value: string
124
+ order: number
125
+ type: StepParameterType
126
+ }
127
+
128
+ type FilesystemSnapshot = {
129
+ environments: EnvironmentData[]
130
+ modulePaths: Set<string>
131
+ locatorGroups: LocatorGroupFromFs[]
132
+ locatorFiles: LocatorFileData[]
133
+ tagObjects: Array<{ name: string; tagExpression: string; type: TagType }>
134
+ templateStepGroups: StepGroupJSDoc[]
135
+ templateSteps: TemplateStepFromFs[]
136
+ testSuites: TestSuiteFromFs[]
137
+ testCases: TestCaseFromFs[]
138
+ }
139
+
140
+ function normalizeEnvironmentName(name: string): string {
141
+ if (!name || name.trim() === '') {
142
+ return name
143
+ }
144
+
145
+ return name
146
+ .trim()
147
+ .replace(/[_\s]+/g, ' ')
148
+ .split(' ')
149
+ .filter(Boolean)
150
+ .map(segment => segment.charAt(0).toUpperCase() + segment.slice(1).toLowerCase())
151
+ .join(' ')
152
+ }
153
+
154
+ function getEnvironmentIdentityKey(name: string): string {
155
+ return name
156
+ .trim()
157
+ .replace(/[_\s]+/g, ' ')
158
+ .toLowerCase()
159
+ }
160
+
161
+ async function normalizeFunctionDefinition(functionDefinition: string | null | undefined): Promise<string> {
162
+ const source = functionDefinition?.trim()
163
+ if (!source) {
164
+ return ''
165
+ }
166
+
167
+ try {
168
+ return (
169
+ await prettier.format(source, {
170
+ parser: 'typescript',
171
+ semi: true,
172
+ singleQuote: true,
173
+ trailingComma: 'es5',
174
+ printWidth: 80,
175
+ tabWidth: 2,
176
+ })
177
+ ).trim()
178
+ } catch {
179
+ return source
180
+ }
181
+ }
182
+
183
+ async function readEnvironmentsFromFile(): Promise<EnvironmentData[]> {
184
+ const filePath = join(getAutomationEnvironmentsDir(), 'environments.json')
185
+
186
+ try {
187
+ const fileContent = await fs.readFile(filePath, 'utf-8')
188
+ const jsonContent = JSON.parse(fileContent) as Record<string, EnvironmentConfig>
189
+
190
+ return Object.entries(jsonContent).map(([key, config]) => ({
191
+ name: normalizeEnvironmentName(key),
192
+ baseUrl: config.baseUrl.trim(),
193
+ apiBaseUrl: config.apiBaseUrl?.trim() ? config.apiBaseUrl.trim() : null,
194
+ username: config.email?.trim() ? config.email.trim() : null,
195
+ password: config.password?.trim() ? config.password.trim() : null,
196
+ }))
197
+ } catch (error) {
198
+ console.error('Unable to read environments for sync counts:', error)
199
+ return []
200
+ }
201
+ }
202
+
203
+ function splitTagLine(tagLine: string): string[] {
204
+ return tagLine
205
+ .split(/\s+/)
206
+ .filter(tag => tag.trim().startsWith('@'))
207
+ .map(tag => tag.trim())
208
+ }
209
+
210
+ function normalizeTagExpression(tagExpression: string): string {
211
+ return tagExpression.startsWith('@') ? tagExpression : `@${tagExpression}`
212
+ }
213
+
214
+ function extractUniqueTags(parsedFeatures: ParsedFeature[]): Set<string> {
215
+ const uniqueTags = new Set<string>()
216
+
217
+ for (const feature of parsedFeatures) {
218
+ for (const tagLine of feature.tags) {
219
+ for (const tag of splitTagLine(tagLine)) {
220
+ uniqueTags.add(tag)
221
+ }
222
+ }
223
+
224
+ for (const scenario of feature.scenarios) {
225
+ for (const tagLine of scenario.tags) {
226
+ for (const tag of splitTagLine(tagLine)) {
227
+ uniqueTags.add(tag)
228
+ }
229
+ }
230
+ }
231
+ }
232
+
233
+ return uniqueTags
234
+ }
235
+
236
+ function buildTagObjects(tagExpressions: Set<string>): Array<{ name: string; tagExpression: string; type: TagType }> {
237
+ return Array.from(tagExpressions).map(tagExpression => {
238
+ const name = tagExpression.startsWith('@') ? tagExpression.substring(1) : tagExpression
239
+ return {
240
+ name,
241
+ tagExpression,
242
+ type: getTagTypeFromName(name),
243
+ }
244
+ })
245
+ }
246
+
247
+ function buildModuleTreePaths(modulePaths: Iterable<string>): Set<string> {
248
+ const tree = new Set<string>()
249
+
250
+ for (const modulePath of modulePaths) {
251
+ if (modulePath === '/') {
252
+ tree.add('/')
253
+ continue
254
+ }
255
+
256
+ const parts = modulePath.split('/').filter(Boolean)
257
+ let currentPath = ''
258
+
259
+ for (const part of parts) {
260
+ currentPath += `/${part}`
261
+ tree.add(currentPath)
262
+ }
263
+ }
264
+
265
+ return tree
266
+ }
267
+
268
+ async function scanLocatorFiles(baseDir: string): Promise<string[]> {
269
+ const files = await glob('automation/locators/**/*.json', { cwd: baseDir })
270
+ return files.map(file => join(baseDir, file))
271
+ }
272
+
273
+ async function readLocatorMap(baseDir: string): Promise<LocatorMapEntry[]> {
274
+ try {
275
+ const fileContent = await fs.readFile(getAutomationLocatorMapPath(baseDir), 'utf-8')
276
+ const locatorMap = JSON.parse(fileContent) as LocatorMapEntry[]
277
+ return Array.isArray(locatorMap) ? locatorMap : []
278
+ } catch {
279
+ return []
280
+ }
281
+ }
282
+
283
+ function extractLocatorGroupName(filePath: string): string {
284
+ const fileName = filePath.split(/[/\\]/).pop() ?? ''
285
+ return fileName.replace(/\.json$/, '')
286
+ }
287
+
288
+ async function readLocatorFile(filePath: string): Promise<Record<string, string>> {
289
+ try {
290
+ const fileContent = await fs.readFile(filePath, 'utf-8')
291
+ const content = JSON.parse(fileContent) as Record<string, string>
292
+ return typeof content === 'object' && content !== null ? content : {}
293
+ } catch (error) {
294
+ console.error(`Unable to read locator file ${filePath}:`, error)
295
+ return {}
296
+ }
297
+ }
298
+
299
+ function parseGroupJSDoc(content: string): StepGroupJSDoc | null {
300
+ const lines = content.split('\n')
301
+ let startLine = 0
302
+
303
+ while (startLine < lines.length) {
304
+ const line = lines[startLine].trim()
305
+ if (line === '' || line.startsWith('import ')) {
306
+ startLine++
307
+ continue
308
+ }
309
+ break
310
+ }
311
+
312
+ if (startLine >= lines.length || !lines[startLine].trim().startsWith('/**')) {
313
+ return null
314
+ }
315
+
316
+ let hasType = false
317
+ let endLine = -1
318
+ let name: string | null = null
319
+ let description: string | null = null
320
+ let type: string | null = null
321
+
322
+ const maxLines = Math.min(lines.length, startLine + 50)
323
+ for (let i = startLine; i < maxLines; i++) {
324
+ const line = lines[i].trim()
325
+
326
+ if (line.includes('*/')) {
327
+ const beforeClose = line.split('*/')[0].trim()
328
+
329
+ if (beforeClose.startsWith('* @name') || beforeClose.startsWith('*@name')) {
330
+ const match = beforeClose.match(/@name\s+(.+)/)
331
+ if (match) name = match[1].trim()
332
+ } else if (beforeClose.startsWith('* @description') || beforeClose.startsWith('*@description')) {
333
+ const match = beforeClose.match(/@description\s+(.+)/)
334
+ if (match) description = match[1].trim() || null
335
+ } else if (beforeClose.startsWith('* @type') || beforeClose.startsWith('*@type')) {
336
+ const match = beforeClose.match(/@type\s+(.+)/)
337
+ if (match) {
338
+ hasType = true
339
+ type = match[1].trim()
340
+ }
341
+ }
342
+
343
+ endLine = i
344
+ break
345
+ }
346
+
347
+ if (line.startsWith('* @name') || line.startsWith('*@name')) {
348
+ const match = line.match(/@name\s+(.+)/)
349
+ if (match) name = match[1].trim()
350
+ } else if (line.startsWith('* @description') || line.startsWith('*@description')) {
351
+ const match = line.match(/@description\s+(.+)/)
352
+ if (match) description = match[1].trim() || null
353
+ } else if (line.startsWith('* @type') || line.startsWith('*@type')) {
354
+ const match = line.match(/@type\s+(.+)/)
355
+ if (match) {
356
+ hasType = true
357
+ type = match[1].trim()
358
+ }
359
+ }
360
+ }
361
+
362
+ if (!hasType || endLine < 0 || !name || !type) {
363
+ return null
364
+ }
365
+
366
+ const normalizedType = type.toUpperCase()
367
+ if (normalizedType !== 'ACTION' && normalizedType !== 'VALIDATION') {
368
+ return null
369
+ }
370
+
371
+ return {
372
+ name: name.trim(),
373
+ description: description ? description.trim() : null,
374
+ type: normalizedType as TemplateStepGroupType,
375
+ }
376
+ }
377
+
378
+ function parseStepJSDoc(content: string, startLine: number): StepJSDoc | null {
379
+ const lines = content.split('\n')
380
+ let jsdocStart = -1
381
+
382
+ for (let i = startLine - 1; i >= 0 && i >= startLine - 20; i--) {
383
+ const line = lines[i]?.trim()
384
+ if (line?.includes('*/')) {
385
+ jsdocStart = i
386
+ for (let j = i - 1; j >= 0 && j >= i - 10; j--) {
387
+ const previousLine = lines[j]?.trim()
388
+ if (previousLine?.startsWith('/**')) {
389
+ jsdocStart = j
390
+ break
391
+ }
392
+ }
393
+ break
394
+ }
395
+
396
+ if (line?.startsWith('/**')) {
397
+ jsdocStart = i
398
+ break
399
+ }
400
+ }
401
+
402
+ if (jsdocStart === -1) {
403
+ return null
404
+ }
405
+
406
+ let name: string | null = null
407
+ let description: string | null = null
408
+ let icon: string | null = null
409
+ let foundJSDoc = false
410
+
411
+ for (let i = jsdocStart; i < Math.min(lines.length, jsdocStart + 20); i++) {
412
+ const line = lines[i]?.trim()
413
+
414
+ if (line?.startsWith('/**')) {
415
+ foundJSDoc = true
416
+ continue
417
+ }
418
+
419
+ if (line?.includes('*/')) {
420
+ const beforeClose = line.split('*/')[0].trim()
421
+ if (beforeClose.startsWith('* @name') || beforeClose.startsWith('*@name')) {
422
+ const match = beforeClose.match(/@name\s+(.+)/)
423
+ if (match) name = match[1].trim()
424
+ } else if (beforeClose.startsWith('* @description') || beforeClose.startsWith('*@description')) {
425
+ const match = beforeClose.match(/@description\s+(.+)/)
426
+ if (match) description = match[1].trim() || null
427
+ } else if (beforeClose.startsWith('* @icon') || beforeClose.startsWith('*@icon')) {
428
+ const match = beforeClose.match(/@icon\s+(.+)/)
429
+ if (match) icon = match[1].trim()
430
+ }
431
+ break
432
+ }
433
+
434
+ if (!foundJSDoc) {
435
+ continue
436
+ }
437
+
438
+ if (line?.startsWith('* @name') || line?.startsWith('*@name')) {
439
+ const match = line.match(/@name\s+(.+)/)
440
+ if (match) name = match[1].trim()
441
+ } else if (line?.startsWith('* @description') || line?.startsWith('*@description')) {
442
+ const match = line.match(/@description\s+(.+)/)
443
+ if (match) description = match[1].trim() || null
444
+ } else if (line?.startsWith('* @icon') || line?.startsWith('*@icon')) {
445
+ const match = line.match(/@icon\s+(.+)/)
446
+ if (match) icon = match[1].trim()
447
+ }
448
+ }
449
+
450
+ if (!name || !icon) {
451
+ return null
452
+ }
453
+
454
+ const iconUpper = icon.toUpperCase()
455
+ const validIcons = Object.values(TemplateStepIcon)
456
+ if (!validIcons.includes(iconUpper as TemplateStepIcon)) {
457
+ return null
458
+ }
459
+
460
+ return {
461
+ name: name.trim(),
462
+ description: description ? description.trim() : null,
463
+ icon: iconUpper as TemplateStepIcon,
464
+ }
465
+ }
466
+
467
+ function mapTypeToParameterType(typeName: string): StepParameterType {
468
+ const normalized = typeName.trim()
469
+
470
+ if (normalized === 'SelectorName') return StepParameterType.LOCATOR
471
+ if (normalized === 'string') return StepParameterType.STRING
472
+ if (normalized === 'number' || normalized === 'int') return StepParameterType.NUMBER
473
+ if (normalized === 'boolean') return StepParameterType.BOOLEAN
474
+ if (normalized === 'Date') return StepParameterType.DATE
475
+
476
+ throw new Error(`Unsupported parameter type: ${typeName}`)
477
+ }
478
+
479
+ function extractFunctionDefinition(callExpression: t.CallExpression, sourceCode: string): string {
480
+ const start = callExpression.start
481
+ const end = callExpression.end
482
+
483
+ if (start == null || end == null) {
484
+ throw new Error('Cannot extract function definition.')
485
+ }
486
+
487
+ let code = sourceCode.slice(start, end).trim()
488
+ const trailingSource = sourceCode.slice(end, end + 10).trim()
489
+ if (trailingSource.startsWith(';')) {
490
+ code += ';'
491
+ }
492
+
493
+ return code
494
+ }
495
+
496
+ function parseStepFile(content: string): ParsedStepFile | null {
497
+ const group = parseGroupJSDoc(content)
498
+ if (!group) {
499
+ return null
500
+ }
501
+
502
+ const ast = parse(content, {
503
+ sourceType: 'module',
504
+ plugins: ['typescript', 'decorators-legacy'],
505
+ })
506
+
507
+ const steps: ParsedTemplateStep[] = []
508
+
509
+ traverse(ast, {
510
+ CallExpression(path: NodePath<t.CallExpression>) {
511
+ const node = path.node
512
+ const callee = node.callee
513
+ let keyword: 'When' | 'Then' | 'Given' | null = null
514
+
515
+ if (t.isIdentifier(callee) && (callee.name === 'When' || callee.name === 'Then' || callee.name === 'Given')) {
516
+ keyword = callee.name as 'When' | 'Then' | 'Given'
517
+ }
518
+
519
+ if (!keyword || node.arguments.length < 2) {
520
+ return
521
+ }
522
+
523
+ const patternArg = node.arguments[0]
524
+ const functionArg = node.arguments[1]
525
+
526
+ if (!t.isStringLiteral(patternArg) || !t.isFunction(functionArg)) {
527
+ return
528
+ }
529
+
530
+ const lineNumber = node.loc?.start?.line
531
+ if (lineNumber == null) {
532
+ return
533
+ }
534
+
535
+ const jsdoc = parseStepJSDoc(content, lineNumber - 1)
536
+ if (!jsdoc) {
537
+ return
538
+ }
539
+
540
+ const parameters: StepParameter[] = []
541
+ let order = 0
542
+
543
+ for (const parameter of functionArg.params) {
544
+ if (t.isIdentifier(parameter) && parameter.name === 'this') {
545
+ continue
546
+ }
547
+
548
+ if (t.isObjectPattern(parameter)) {
549
+ continue
550
+ }
551
+
552
+ if (!t.isIdentifier(parameter) || !parameter.typeAnnotation || !t.isTSTypeAnnotation(parameter.typeAnnotation)) {
553
+ continue
554
+ }
555
+
556
+ const annotation = parameter.typeAnnotation.typeAnnotation
557
+ let typeName: string | null = null
558
+
559
+ if (t.isTSTypeReference(annotation) && t.isIdentifier(annotation.typeName)) {
560
+ typeName = annotation.typeName.name
561
+ } else if (t.isTSStringKeyword(annotation)) {
562
+ typeName = 'string'
563
+ } else if (t.isTSNumberKeyword(annotation)) {
564
+ typeName = 'number'
565
+ } else if (t.isTSBooleanKeyword(annotation)) {
566
+ typeName = 'boolean'
567
+ }
568
+
569
+ if (!typeName) {
570
+ continue
571
+ }
572
+
573
+ try {
574
+ parameters.push({
575
+ name: parameter.name,
576
+ type: mapTypeToParameterType(typeName),
577
+ order: order++,
578
+ })
579
+ } catch {
580
+ return
581
+ }
582
+ }
583
+
584
+ steps.push({
585
+ jsdoc,
586
+ signature: patternArg.value,
587
+ functionDefinition: extractFunctionDefinition(node, content),
588
+ normalizedFunctionDefinition: '',
589
+ parameters,
590
+ keyword,
591
+ })
592
+ },
593
+ })
594
+
595
+ return { group, steps }
596
+ }
597
+
598
+ async function scanStepFiles(baseDir: string): Promise<string[]> {
599
+ const actionFiles = await glob('automation/steps/actions/**/*.step.ts', { cwd: baseDir })
600
+ const validationFiles = await glob('automation/steps/validations/**/*.step.ts', { cwd: baseDir })
601
+ return [...actionFiles, ...validationFiles]
602
+ }
603
+
604
+ function extractTestSuiteNameFromFilename(filePath: string): string {
605
+ const fileName = filePath.split(/[/\\]/).pop() ?? ''
606
+ return fileName.replace(/\.feature$/, '')
607
+ }
608
+
609
+ function extractFeatureLevelTags(parsedFeature: ParsedFeature): string[] {
610
+ return parsedFeature.tags.flatMap(splitTagLine)
611
+ }
612
+
613
+ function parseScenarioTitle(scenarioName: string, scenarioDescription?: string): { title: string; description: string } {
614
+ if (scenarioDescription) {
615
+ return {
616
+ title: scenarioDescription.trim(),
617
+ description: scenarioName.trim(),
618
+ }
619
+ }
620
+
621
+ return {
622
+ title: scenarioName.trim(),
623
+ description: '',
624
+ }
625
+ }
626
+
627
+ function signatureToRegex(signature: string): RegExp {
628
+ let pattern = signature.replace(/[.*+?^${}()|[\]\\]/g, match => {
629
+ if (match === '{' || match === '}') return match
630
+ return `\\${match}`
631
+ })
632
+
633
+ pattern = pattern.replace(/\{string\}/g, '"([^"]+)"')
634
+ pattern = pattern.replace(/\{int\}/g, '(\\d+)')
635
+ pattern = pattern.replace(/\{boolean\}/g, '(true|false)')
636
+ pattern = pattern.replace(/\{number\}/g, '(\\d+(?:\\.\\d+)?)')
637
+
638
+ return new RegExp(`^${pattern}$`, 'i')
639
+ }
640
+
641
+ function extractParametersFromGherkinStep(
642
+ gherkinText: string,
643
+ signature: string,
644
+ templateStepParameters: Array<{ name: string; order: number; type: StepParameterType }>,
645
+ ): ParameterMatch[] | null {
646
+ const match = gherkinText.match(signatureToRegex(signature))
647
+ if (!match) {
648
+ return null
649
+ }
650
+
651
+ return match.slice(1).flatMap((value, index) => {
652
+ const parameter = templateStepParameters[index]
653
+ if (!parameter || value == null) {
654
+ return []
655
+ }
656
+
657
+ return [
658
+ {
659
+ name: parameter.name,
660
+ value,
661
+ order: parameter.order,
662
+ type: parameter.type,
663
+ },
664
+ ]
665
+ })
666
+ }
667
+
668
+ function matchGherkinStepToTemplateStep(
669
+ gherkinStep: ParsedStep,
670
+ templateSteps: Array<{
671
+ signature: string
672
+ parameters: Array<{ name: string; order: number; type: StepParameterType }>
673
+ }>,
674
+ ): { signature: string; parameters: ParameterMatch[] } | null {
675
+ for (const templateStep of templateSteps) {
676
+ const parameters = extractParametersFromGherkinStep(gherkinStep.text, templateStep.signature, templateStep.parameters)
677
+ if (parameters) {
678
+ return {
679
+ signature: templateStep.signature,
680
+ parameters,
681
+ }
682
+ }
683
+ }
684
+
685
+ return null
686
+ }
687
+
688
+ function groupRecordsByKey<T>(records: T[], getKey: (record: T) => string | null | undefined): Map<string, T[]> {
689
+ const recordsByKey = new Map<string, T[]>()
690
+
691
+ for (const record of records) {
692
+ const key = getKey(record)
693
+ if (!key) {
694
+ continue
695
+ }
696
+
697
+ const existing = recordsByKey.get(key)
698
+ if (existing) {
699
+ existing.push(record)
700
+ continue
701
+ }
702
+
703
+ recordsByKey.set(key, [record])
704
+ }
705
+
706
+ return recordsByKey
707
+ }
708
+
709
+ function sameStringSet(left: string[], right: string[]): boolean {
710
+ const sortedLeft = [...left].sort()
711
+ const sortedRight = [...right].sort()
712
+
713
+ return JSON.stringify(sortedLeft) === JSON.stringify(sortedRight)
714
+ }
715
+
716
+ function sameStepParameters(
717
+ left: Array<{ name: string; order: number; type: StepParameterType }>,
718
+ right: Array<{ name: string; order: number; type: StepParameterType }>,
719
+ ): boolean {
720
+ if (left.length !== right.length) {
721
+ return false
722
+ }
723
+
724
+ return left.every((parameter, index) => {
725
+ const other = right[index]
726
+ return (
727
+ parameter.name === other?.name &&
728
+ parameter.order === other?.order &&
729
+ parameter.type === other?.type
730
+ )
731
+ })
732
+ }
733
+
734
+ function sameResolvedParameters(
735
+ left: Array<{ name: string; value: string; order: number; type: StepParameterType }>,
736
+ right: Array<{ name: string; value: string; order: number; type: StepParameterType }>,
737
+ ): boolean {
738
+ if (left.length !== right.length) {
739
+ return false
740
+ }
741
+
742
+ return left.every((parameter, index) => {
743
+ const other = right[index]
744
+ return (
745
+ parameter.name === other?.name &&
746
+ parameter.value === other?.value &&
747
+ parameter.order === other?.order &&
748
+ parameter.type === other?.type
749
+ )
750
+ })
751
+ }
752
+
753
+ async function buildFilesystemSnapshot(baseDir: string): Promise<FilesystemSnapshot> {
754
+ const featuresDir = getAutomationFeaturesDir()
755
+ const [environments, parsedFeatures, locatorFiles, locatorMap, stepFiles] = await Promise.all([
756
+ readEnvironmentsFromFile(),
757
+ scanFeatureFiles(featuresDir),
758
+ scanLocatorFiles(baseDir),
759
+ readLocatorMap(baseDir),
760
+ scanStepFiles(baseDir),
761
+ ])
762
+
763
+ const locatorRouteMap = new Map(locatorMap.map(entry => [entry.name, entry.path]))
764
+ const locatorGroups: LocatorGroupFromFs[] = []
765
+ const locatorFileData: LocatorFileData[] = []
766
+ const directModulePaths = new Set<string>()
767
+
768
+ for (const filePath of locatorFiles) {
769
+ const modulePath = extractModulePathFromAutomationFile(filePath, baseDir, 'locators')
770
+ const groupName = extractLocatorGroupName(filePath)
771
+ const locators = await readLocatorFile(filePath)
772
+
773
+ locatorGroups.push({
774
+ name: groupName,
775
+ route: locatorRouteMap.get(groupName) ?? `/${groupName}`,
776
+ modulePath,
777
+ })
778
+ locatorFileData.push({
779
+ groupName,
780
+ modulePath,
781
+ locators,
782
+ })
783
+ directModulePaths.add(modulePath)
784
+ }
785
+
786
+ for (const feature of parsedFeatures) {
787
+ directModulePaths.add(extractModulePathFromFilePath(feature.filePath, featuresDir))
788
+ }
789
+
790
+ const tagObjects = buildTagObjects(extractUniqueTags(parsedFeatures))
791
+
792
+ const templateStepGroups: StepGroupJSDoc[] = []
793
+ const templateSteps: TemplateStepFromFs[] = []
794
+
795
+ for (const file of stepFiles) {
796
+ try {
797
+ const filePath = join(baseDir, file)
798
+ const content = await fs.readFile(filePath, 'utf-8')
799
+ const parsed = parseStepFile(content)
800
+ if (!parsed) {
801
+ continue
802
+ }
803
+
804
+ await Promise.all(
805
+ parsed.steps.map(async step => {
806
+ step.normalizedFunctionDefinition = await normalizeFunctionDefinition(step.functionDefinition)
807
+ }),
808
+ )
809
+
810
+ templateStepGroups.push(parsed.group)
811
+ for (const step of parsed.steps) {
812
+ templateSteps.push({
813
+ step,
814
+ groupName: parsed.group.name,
815
+ groupType: parsed.group.type,
816
+ })
817
+ }
818
+ } catch (error) {
819
+ console.error(`Unable to parse step file ${file} for sync counts:`, error)
820
+ }
821
+ }
822
+
823
+ const testSuites: TestSuiteFromFs[] = parsedFeatures.map(feature => ({
824
+ name: extractTestSuiteNameFromFilename(feature.filePath),
825
+ description: feature.featureDescription ?? feature.featureName ?? null,
826
+ modulePath: extractModulePathFromFilePath(feature.filePath, featuresDir),
827
+ tags: extractFeatureLevelTags(feature),
828
+ }))
829
+
830
+ const testCases: TestCaseFromFs[] = []
831
+ for (const feature of parsedFeatures) {
832
+ const modulePath = extractModulePathFromFilePath(feature.filePath, featuresDir)
833
+ const testSuiteName = extractTestSuiteNameFromFilename(feature.filePath)
834
+
835
+ for (const scenario of feature.scenarios) {
836
+ const flattenedTags = scenario.tags.flatMap(splitTagLine)
837
+ const identifierTag = flattenedTags.find(tag => tag.replace(/^@/, '').startsWith('tc_'))
838
+ if (!identifierTag) {
839
+ continue
840
+ }
841
+
842
+ const { title, description } = parseScenarioTitle(scenario.name, scenario.description)
843
+ testCases.push({
844
+ identifierTag: normalizeTagExpression(identifierTag),
845
+ title,
846
+ description,
847
+ testSuiteName,
848
+ modulePath,
849
+ filterTags: flattenedTags.filter(tag => normalizeTagExpression(tag) !== normalizeTagExpression(identifierTag)),
850
+ steps: scenario.steps,
851
+ })
852
+ }
853
+ }
854
+
855
+ return {
856
+ environments,
857
+ modulePaths: buildModuleTreePaths(directModulePaths),
858
+ locatorGroups,
859
+ locatorFiles: locatorFileData,
860
+ tagObjects,
861
+ templateStepGroups,
862
+ templateSteps,
863
+ testSuites,
864
+ testCases,
865
+ }
866
+ }
867
+
868
+ export function countModuleMismatches(
869
+ filesystemPaths: Set<string>,
870
+ dbModules: Array<{ id: string; name: string; path: string; parentId: string | null }>,
871
+ ): number {
872
+ const dbPaths = new Set<string>()
873
+ let rootExists = false
874
+
875
+ for (const dbModule of dbModules) {
876
+ if (dbModule.name === 'root' && dbModule.parentId === null) {
877
+ rootExists = true
878
+ continue
879
+ }
880
+
881
+ dbPaths.add(dbModule.path)
882
+ }
883
+
884
+ let count = 0
885
+ for (const modulePath of filesystemPaths) {
886
+ if (modulePath === '/') {
887
+ if (!rootExists) count++
888
+ continue
889
+ }
890
+
891
+ if (!dbPaths.has(modulePath)) {
892
+ count++
893
+ }
894
+ }
895
+
896
+ return count
897
+ }
898
+
899
+ function countEnvironmentMismatches(
900
+ filesystemEnvironments: EnvironmentData[],
901
+ dbEnvironments: Array<{ name: string }>,
902
+ ): number {
903
+ const fsByNormalizedName = new Map(
904
+ filesystemEnvironments.map(environment => [getEnvironmentIdentityKey(environment.name), environment]),
905
+ )
906
+ const dbByNormalizedName = new Map<string, { name: string }>()
907
+
908
+ for (const environment of dbEnvironments) {
909
+ const normalizedName = getEnvironmentIdentityKey(environment.name)
910
+ if (!dbByNormalizedName.has(normalizedName)) {
911
+ dbByNormalizedName.set(normalizedName, environment)
912
+ }
913
+ }
914
+
915
+ let count = 0
916
+ for (const environment of filesystemEnvironments) {
917
+ const existing = dbByNormalizedName.get(getEnvironmentIdentityKey(environment.name))
918
+ if (!existing) {
919
+ count++
920
+ }
921
+ }
922
+
923
+ for (const environment of dbEnvironments) {
924
+ if (!fsByNormalizedName.has(getEnvironmentIdentityKey(environment.name))) {
925
+ count++
926
+ }
927
+ }
928
+
929
+ return count
930
+ }
931
+
932
+ export function countTagMismatches(
933
+ filesystemTags: Array<{ name: string; tagExpression: string; type: TagType }>,
934
+ dbTags: Array<{ name: string; type: TagType }>,
935
+ ): number {
936
+ const dbByName = groupRecordsByKey(dbTags, tag => tag.name)
937
+
938
+ let count = 0
939
+ for (const tag of filesystemTags) {
940
+ const hasMatch = (dbByName.get(tag.name) ?? []).some(existing => existing.type === tag.type)
941
+ if (!hasMatch) {
942
+ count++
943
+ }
944
+ }
945
+
946
+ return count
947
+ }
948
+
949
+ export function countTemplateStepGroupMismatches(
950
+ filesystemGroups: StepGroupJSDoc[],
951
+ dbGroups: Array<{ name: string; description: string | null; type: TemplateStepGroupType }>,
952
+ ): number {
953
+ const dbByName = groupRecordsByKey(dbGroups, group => group.name)
954
+ let count = 0
955
+
956
+ for (const group of filesystemGroups) {
957
+ const hasMatch = (dbByName.get(group.name) ?? []).some(existing => {
958
+ return (existing.description ?? null) === (group.description ?? null) && existing.type === group.type
959
+ })
960
+
961
+ if (!hasMatch) {
962
+ count++
963
+ }
964
+ }
965
+
966
+ return count
967
+ }
968
+
969
+ export function countTemplateStepMismatches(
970
+ filesystemSteps: TemplateStepFromFs[],
971
+ dbSteps: Array<{
972
+ signature: string
973
+ name: string
974
+ description: string | null
975
+ functionDefinition: string | null
976
+ icon: TemplateStepIcon
977
+ type: TemplateStepType
978
+ templateStepGroup: { name: string }
979
+ parameters: Array<{ name: string; order: number; type: StepParameterType }>
980
+ }>,
981
+ ): number {
982
+ const dbBySignature = groupRecordsByKey(dbSteps, step => step.signature)
983
+ let count = 0
984
+
985
+ for (const item of filesystemSteps) {
986
+ const expectedType =
987
+ item.groupType === TemplateStepGroupType.ACTION ? TemplateStepType.ACTION : TemplateStepType.ASSERTION
988
+
989
+ const hasMatch = (dbBySignature.get(item.step.signature) ?? []).some(existing => {
990
+ return (
991
+ existing.name === item.step.jsdoc.name &&
992
+ (existing.description ?? '') === (item.step.jsdoc.description ?? '') &&
993
+ (existing.functionDefinition ?? '') === item.step.normalizedFunctionDefinition &&
994
+ existing.icon === item.step.jsdoc.icon &&
995
+ existing.type === expectedType &&
996
+ existing.templateStepGroup.name === item.groupName &&
997
+ sameStepParameters(existing.parameters, item.step.parameters)
998
+ )
999
+ })
1000
+
1001
+ if (!hasMatch) {
1002
+ count++
1003
+ }
1004
+ }
1005
+
1006
+ return count
1007
+ }
1008
+
1009
+ function countLocatorGroupMismatches(
1010
+ filesystemGroups: LocatorGroupFromFs[],
1011
+ dbGroups: Array<{ name: string; route: string; moduleId: string }>,
1012
+ modulePathMap: Map<string, string>,
1013
+ ): number {
1014
+ const fsByName = new Map(filesystemGroups.map(group => [group.name, group]))
1015
+ const dbByName = new Map(dbGroups.map(group => [group.name, group]))
1016
+ let count = 0
1017
+
1018
+ for (const group of filesystemGroups) {
1019
+ const existing = dbByName.get(group.name)
1020
+ if (!existing) {
1021
+ count++
1022
+ continue
1023
+ }
1024
+
1025
+ const existingModulePath = modulePathMap.get(existing.moduleId) ?? '/'
1026
+ if (existing.route !== group.route || existingModulePath !== group.modulePath) {
1027
+ count++
1028
+ }
1029
+ }
1030
+
1031
+ for (const group of dbGroups) {
1032
+ if (!fsByName.has(group.name)) {
1033
+ count++
1034
+ }
1035
+ }
1036
+
1037
+ return count
1038
+ }
1039
+
1040
+ function countLocatorMismatches(
1041
+ filesystemLocatorFiles: LocatorFileData[],
1042
+ dbGroups: Array<{
1043
+ name: string
1044
+ locators: Array<{ name: string; value: string }>
1045
+ }>,
1046
+ ): number {
1047
+ const dbGroupsByName = new Map(dbGroups.map(group => [group.name, group]))
1048
+ let count = 0
1049
+
1050
+ for (const file of filesystemLocatorFiles) {
1051
+ const dbGroup = dbGroupsByName.get(file.groupName)
1052
+ const fileLocators = Object.entries(file.locators)
1053
+
1054
+ if (!dbGroup) {
1055
+ count += fileLocators.length
1056
+ continue
1057
+ }
1058
+
1059
+ const dbLocators = new Map(dbGroup.locators.map(locator => [locator.name, locator.value]))
1060
+ const fileLocatorNames = new Set<string>()
1061
+
1062
+ for (const [name, value] of fileLocators) {
1063
+ fileLocatorNames.add(name)
1064
+ if (!dbLocators.has(name) || dbLocators.get(name) !== value) {
1065
+ count++
1066
+ }
1067
+ }
1068
+
1069
+ for (const locator of dbGroup.locators) {
1070
+ if (!fileLocatorNames.has(locator.name)) {
1071
+ count++
1072
+ }
1073
+ }
1074
+ }
1075
+
1076
+ return count
1077
+ }
1078
+
1079
+ export function countTestSuiteMismatches(
1080
+ filesystemSuites: TestSuiteFromFs[],
1081
+ dbSuites: Array<{
1082
+ name: string
1083
+ description: string | null
1084
+ moduleId: string
1085
+ tags: Array<{ tagExpression: string }>
1086
+ }>,
1087
+ modulePathMap: Map<string, string>,
1088
+ ): number {
1089
+ const dbByKey = groupRecordsByKey(dbSuites, suite =>
1090
+ getTestSuiteSyncIdentity(suite.name, modulePathMap.get(suite.moduleId) ?? '/'),
1091
+ )
1092
+ let count = 0
1093
+
1094
+ for (const suite of filesystemSuites) {
1095
+ const suiteKey = getTestSuiteSyncIdentity(suite.name, suite.modulePath)
1096
+ const fsTagExpressions = suite.tags.map(normalizeTagExpression)
1097
+ const hasMatch = (dbByKey.get(suiteKey) ?? []).some(existing => {
1098
+ const dbTagExpressions = existing.tags.map(tag => normalizeTagExpression(tag.tagExpression))
1099
+ const expectedDescription = existing.description ?? existing.name
1100
+ return expectedDescription === (suite.description ?? null) && sameStringSet(dbTagExpressions, fsTagExpressions)
1101
+ })
1102
+
1103
+ if (!hasMatch) {
1104
+ count++
1105
+ }
1106
+ }
1107
+
1108
+ return count
1109
+ }
1110
+
1111
+ function hasProjectedTestCaseStepMismatch(
1112
+ stepsFromFs: ParsedStep[],
1113
+ dbSteps: Array<{
1114
+ order: number
1115
+ gherkinStep: string
1116
+ label: string
1117
+ icon: TemplateStepIcon
1118
+ TemplateStep: { signature: string } | null
1119
+ parameters: Array<{ name: string; value: string; order: number; type: StepParameterType }>
1120
+ }>,
1121
+ dbTemplateSteps: Array<{
1122
+ signature: string
1123
+ parameters: Array<{ name: string; order: number; type: StepParameterType }>
1124
+ }>,
1125
+ ): boolean {
1126
+ const projectedDbSteps = normalizeProjectedDbTestCaseSteps(dbSteps)
1127
+ const dbStepsByOrder = new Map(projectedDbSteps.map(step => [step.order, step]))
1128
+
1129
+ for (const step of stepsFromFs) {
1130
+ const existing = dbStepsByOrder.get(step.order)
1131
+ const matchedTemplateStep = matchGherkinStepToTemplateStep(step, dbTemplateSteps)
1132
+
1133
+ if (!existing || !matchedTemplateStep) {
1134
+ return true
1135
+ }
1136
+
1137
+ const expectedIcon = determineProjectedStepIcon(step.keyword)
1138
+ const expectedGherkinStep = `${step.keyword} ${step.text}`
1139
+
1140
+ if (
1141
+ existing.gherkinStep !== expectedGherkinStep ||
1142
+ existing.label !== step.text ||
1143
+ existing.icon !== expectedIcon ||
1144
+ existing.templateStepSignature !== matchedTemplateStep.signature ||
1145
+ !sameResolvedParameters(existing.parameters, matchedTemplateStep.parameters)
1146
+ ) {
1147
+ return true
1148
+ }
1149
+ }
1150
+
1151
+ const fsOrders = new Set(stepsFromFs.map(step => step.order))
1152
+ return projectedDbSteps.some(step => !fsOrders.has(step.order))
1153
+ }
1154
+
1155
+ export function countTestCaseMismatches(
1156
+ filesystemTestCases: TestCaseFromFs[],
1157
+ dbTestCases: Array<{
1158
+ title: string
1159
+ description: string
1160
+ tags: Array<{ tagExpression: string; type: TagType }>
1161
+ TestSuite: Array<{ name: string; moduleId: string }>
1162
+ steps: Array<{
1163
+ order: number
1164
+ gherkinStep: string
1165
+ label: string
1166
+ icon: TemplateStepIcon
1167
+ TemplateStep: { signature: string } | null
1168
+ parameters: Array<{ name: string; value: string; order: number; type: StepParameterType }>
1169
+ }>
1170
+ }>,
1171
+ modulePathMap: Map<string, string>,
1172
+ dbTemplateSteps: Array<{
1173
+ signature: string
1174
+ parameters: Array<{ name: string; order: number; type: StepParameterType }>
1175
+ }>,
1176
+ ): number {
1177
+ const dbByIdentifier = new Map<string, Array<(typeof dbTestCases)[number]>>()
1178
+ let count = 0
1179
+
1180
+ for (const testCase of dbTestCases) {
1181
+ const identifierTag = testCase.tags.find(tag => tag.type === TagType.IDENTIFIER)
1182
+ if (!identifierTag) {
1183
+ continue
1184
+ }
1185
+
1186
+ const normalizedIdentifier = normalizeTagExpression(identifierTag.tagExpression)
1187
+ const existing = dbByIdentifier.get(normalizedIdentifier)
1188
+ if (existing) {
1189
+ existing.push(testCase)
1190
+ continue
1191
+ }
1192
+
1193
+ dbByIdentifier.set(normalizedIdentifier, [testCase])
1194
+ }
1195
+
1196
+ for (const testCase of filesystemTestCases) {
1197
+ const expectedSuiteIdentity = getTestSuiteSyncIdentity(testCase.testSuiteName, testCase.modulePath)
1198
+ const normalizedFilterTags = testCase.filterTags.map(normalizeTagExpression)
1199
+ const hasMatch = (dbByIdentifier.get(testCase.identifierTag) ?? []).some(existing => {
1200
+ const existingFilterTags = existing.tags
1201
+ .filter(tag => tag.type === TagType.FILTER)
1202
+ .map(tag => normalizeTagExpression(tag.tagExpression))
1203
+ const isLinkedToExpectedSuite = existing.TestSuite.some(
1204
+ suite => getTestSuiteSyncIdentity(suite.name, modulePathMap.get(suite.moduleId) ?? '/') === expectedSuiteIdentity,
1205
+ )
1206
+
1207
+ return (
1208
+ existing.title === testCase.title &&
1209
+ existing.description === testCase.description &&
1210
+ isLinkedToExpectedSuite &&
1211
+ sameStringSet(existingFilterTags, normalizedFilterTags) &&
1212
+ !hasProjectedTestCaseStepMismatch(testCase.steps, existing.steps, dbTemplateSteps)
1213
+ )
1214
+ })
1215
+
1216
+ if (!hasMatch) {
1217
+ count++
1218
+ }
1219
+ }
1220
+
1221
+ return count
1222
+ }
1223
+
1224
+ function emptyCounts(): SyncPendingCounts {
1225
+ const counts = Object.fromEntries(syncScriptDefinitions.map(definition => [definition.id, 0])) as Record<SyncScriptId, number>
1226
+ return {
1227
+ ...counts,
1228
+ [SYNC_ALL_REQUEST_ID]: 0,
1229
+ }
1230
+ }
1231
+
1232
+ export async function getSyncPendingCounts(): Promise<SyncPendingCounts> {
1233
+ try {
1234
+ await ensureAutomationWorkspaceReady()
1235
+
1236
+ const baseDir = process.cwd()
1237
+ const filesystem = await buildFilesystemSnapshot(baseDir)
1238
+ const [
1239
+ dbModules,
1240
+ dbEnvironments,
1241
+ dbTags,
1242
+ dbTemplateStepGroups,
1243
+ dbTemplateSteps,
1244
+ dbLocatorGroups,
1245
+ dbTestSuites,
1246
+ dbTestCases,
1247
+ ] = await Promise.all([
1248
+ getAllModulesWithPaths(),
1249
+ prisma.environment.findMany({ select: { name: true } }),
1250
+ prisma.tag.findMany({ select: { name: true, type: true } }),
1251
+ prisma.templateStepGroup.findMany({ select: { name: true, description: true, type: true } }),
1252
+ prisma.templateStep.findMany({
1253
+ select: {
1254
+ signature: true,
1255
+ name: true,
1256
+ description: true,
1257
+ functionDefinition: true,
1258
+ icon: true,
1259
+ type: true,
1260
+ parameters: {
1261
+ select: { name: true, order: true, type: true },
1262
+ orderBy: { order: 'asc' },
1263
+ },
1264
+ templateStepGroup: {
1265
+ select: { name: true },
1266
+ },
1267
+ },
1268
+ }),
1269
+ prisma.locatorGroup.findMany({
1270
+ select: {
1271
+ name: true,
1272
+ route: true,
1273
+ moduleId: true,
1274
+ locators: {
1275
+ select: { name: true, value: true },
1276
+ },
1277
+ },
1278
+ }),
1279
+ prisma.testSuite.findMany({
1280
+ select: {
1281
+ name: true,
1282
+ description: true,
1283
+ moduleId: true,
1284
+ tags: {
1285
+ select: { tagExpression: true },
1286
+ },
1287
+ },
1288
+ }),
1289
+ prisma.testCase.findMany({
1290
+ select: {
1291
+ title: true,
1292
+ description: true,
1293
+ tags: {
1294
+ select: { tagExpression: true, type: true },
1295
+ },
1296
+ TestSuite: {
1297
+ select: { name: true, moduleId: true },
1298
+ },
1299
+ steps: {
1300
+ orderBy: { order: 'asc' },
1301
+ select: {
1302
+ order: true,
1303
+ gherkinStep: true,
1304
+ label: true,
1305
+ icon: true,
1306
+ TemplateStep: {
1307
+ select: { signature: true },
1308
+ },
1309
+ parameters: {
1310
+ select: { name: true, value: true, order: true, type: true },
1311
+ orderBy: { order: 'asc' },
1312
+ },
1313
+ },
1314
+ },
1315
+ },
1316
+ }),
1317
+ ])
1318
+
1319
+ const normalizedDbTemplateSteps = await Promise.all(
1320
+ dbTemplateSteps.map(async step => ({
1321
+ ...step,
1322
+ functionDefinition: await normalizeFunctionDefinition(step.functionDefinition),
1323
+ })),
1324
+ )
1325
+
1326
+ const modulePathMap = new Map(dbModules.map(module => [module.id, module.name === 'root' && module.parentId === null ? '/' : module.path]))
1327
+
1328
+ const counts: Record<SyncScriptId, number> = {
1329
+ 'sync-modules': countModuleMismatches(filesystem.modulePaths, dbModules),
1330
+ 'sync-environments': countEnvironmentMismatches(filesystem.environments, dbEnvironments),
1331
+ 'sync-tags': countTagMismatches(filesystem.tagObjects, dbTags),
1332
+ 'sync-template-step-groups': countTemplateStepGroupMismatches(filesystem.templateStepGroups, dbTemplateStepGroups),
1333
+ 'sync-template-steps': countTemplateStepMismatches(filesystem.templateSteps, normalizedDbTemplateSteps),
1334
+ 'sync-locator-groups': countLocatorGroupMismatches(filesystem.locatorGroups, dbLocatorGroups, modulePathMap),
1335
+ 'sync-locators': countLocatorMismatches(filesystem.locatorFiles, dbLocatorGroups),
1336
+ 'sync-test-suites': countTestSuiteMismatches(filesystem.testSuites, dbTestSuites, modulePathMap),
1337
+ 'sync-test-cases': countTestCaseMismatches(
1338
+ filesystem.testCases,
1339
+ dbTestCases,
1340
+ modulePathMap,
1341
+ normalizedDbTemplateSteps.map(step => ({
1342
+ signature: step.signature,
1343
+ parameters: step.parameters,
1344
+ })),
1345
+ ),
1346
+ }
1347
+
1348
+ return {
1349
+ ...counts,
1350
+ [SYNC_ALL_REQUEST_ID]: Object.values(counts).reduce((sum, count) => sum + count, 0),
1351
+ }
1352
+ } catch (error) {
1353
+ console.error('Unable to compute sync pending counts:', error)
1354
+ return emptyCounts()
1355
+ }
1356
+ }