create-appraisejs 0.1.10-alpha.8 → 0.2.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 (414) hide show
  1. package/README.md +52 -52
  2. package/dist/cli.e2e.test.d.ts +2 -0
  3. package/dist/cli.e2e.test.d.ts.map +1 -0
  4. package/dist/cli.e2e.test.js +73 -0
  5. package/dist/cli.e2e.test.js.map +1 -0
  6. package/dist/config.test.d.ts +2 -0
  7. package/dist/config.test.d.ts.map +1 -0
  8. package/dist/config.test.js +65 -0
  9. package/dist/config.test.js.map +1 -0
  10. package/dist/copy-template.test.d.ts +2 -0
  11. package/dist/copy-template.test.d.ts.map +1 -0
  12. package/dist/copy-template.test.js +71 -0
  13. package/dist/copy-template.test.js.map +1 -0
  14. package/dist/download-repo.test.d.ts +2 -0
  15. package/dist/download-repo.test.d.ts.map +1 -0
  16. package/dist/download-repo.test.js +14 -0
  17. package/dist/download-repo.test.js.map +1 -0
  18. package/dist/install.test.d.ts +2 -0
  19. package/dist/install.test.d.ts.map +1 -0
  20. package/dist/install.test.js +119 -0
  21. package/dist/install.test.js.map +1 -0
  22. package/dist/prepare-template-utils.d.ts.map +1 -1
  23. package/dist/prepare-template-utils.js +5 -0
  24. package/dist/prepare-template-utils.js.map +1 -1
  25. package/dist/prompts.test.d.ts +2 -0
  26. package/dist/prompts.test.d.ts.map +1 -0
  27. package/dist/prompts.test.js +58 -0
  28. package/dist/prompts.test.js.map +1 -0
  29. package/dist/scaffold-gitignore.d.ts +1 -0
  30. package/dist/scaffold-gitignore.d.ts.map +1 -1
  31. package/dist/scaffold-gitignore.js +3 -0
  32. package/dist/scaffold-gitignore.js.map +1 -1
  33. package/package.json +3 -2
  34. package/templates/default/.appraise-template-meta.json +2 -2
  35. package/templates/default/.env.example +2 -2
  36. package/templates/default/.vscode/settings.json +2 -1
  37. package/templates/default/README.md +53 -53
  38. package/templates/default/automation/mapping/locator-map.json +1 -14
  39. package/templates/default/automation/steps/actions/click.step.ts +58 -58
  40. package/templates/default/automation/steps/actions/hover.step.ts +27 -27
  41. package/templates/default/automation/steps/actions/input.step.ts +84 -84
  42. package/templates/default/automation/steps/actions/navigation.step.ts +70 -70
  43. package/templates/default/automation/steps/actions/random_data.step.ts +142 -142
  44. package/templates/default/automation/steps/actions/store.step.ts +86 -86
  45. package/templates/default/automation/steps/actions/wait.step.ts +90 -90
  46. package/templates/default/automation/steps/validations/active_state_assertion.step.ts +30 -30
  47. package/templates/default/automation/steps/validations/navigation_assertion.step.ts +22 -22
  48. package/templates/default/automation/steps/validations/text_assertion.step.ts +107 -107
  49. package/templates/default/automation/steps/validations/visibility_assertion.step.ts +26 -26
  50. package/templates/default/components.json +24 -24
  51. package/templates/default/cucumber.mjs +16 -16
  52. package/templates/default/eslint.config.mjs +16 -16
  53. package/templates/default/gitignore +3 -0
  54. package/templates/default/next-env.d.ts +6 -6
  55. package/templates/default/next.config.ts +11 -11
  56. package/templates/default/package-lock.json +146 -75
  57. package/templates/default/package.json +2 -1
  58. package/templates/default/packages/cucumber-runtime/package.json +13 -13
  59. package/templates/default/packages/cucumber-runtime/src/cache.util.ts +93 -93
  60. package/templates/default/packages/cucumber-runtime/src/cli.ts +68 -68
  61. package/templates/default/packages/cucumber-runtime/src/environment.util.ts +21 -21
  62. package/templates/default/packages/cucumber-runtime/src/executor.ts +32 -32
  63. package/templates/default/packages/cucumber-runtime/src/hooks.ts +25 -3
  64. package/templates/default/packages/cucumber-runtime/src/index.ts +17 -17
  65. package/templates/default/packages/cucumber-runtime/src/locator.util.ts +234 -234
  66. package/templates/default/packages/cucumber-runtime/src/parameter-types.ts +7 -7
  67. package/templates/default/packages/cucumber-runtime/src/paths.ts +66 -1
  68. package/templates/default/packages/cucumber-runtime/src/random-data.util.ts +35 -35
  69. package/templates/default/packages/cucumber-runtime/src/types.ts +13 -13
  70. package/templates/default/packages/cucumber-runtime/src/world.ts +44 -44
  71. package/templates/default/packages/cucumber-runtime/tsconfig.json +11 -11
  72. package/templates/default/packages/locator-picker-companion/dist/cli.d.ts +1 -0
  73. package/templates/default/packages/locator-picker-companion/dist/cli.js +302 -0
  74. package/templates/default/packages/locator-picker-companion/dist/index.d.ts +3 -0
  75. package/templates/default/packages/locator-picker-companion/dist/index.js +3 -0
  76. package/templates/default/packages/locator-picker-companion/dist/injected-picker-script.d.ts +1 -0
  77. package/templates/default/packages/locator-picker-companion/dist/injected-picker-script.js +615 -0
  78. package/templates/default/packages/locator-picker-companion/dist/launcher.d.ts +11 -0
  79. package/templates/default/packages/locator-picker-companion/dist/launcher.js +59 -0
  80. package/templates/default/packages/locator-picker-companion/dist/selector-generator.d.ts +3 -0
  81. package/templates/default/packages/locator-picker-companion/dist/selector-generator.js +257 -0
  82. package/templates/default/packages/locator-picker-companion/dist/session-file.d.ts +22 -0
  83. package/templates/default/packages/locator-picker-companion/dist/session-file.js +150 -0
  84. package/templates/default/packages/locator-picker-companion/dist/types.d.ts +31 -0
  85. package/templates/default/packages/locator-picker-companion/dist/types.js +1 -0
  86. package/templates/default/packages/locator-picker-companion/package.json +17 -0
  87. package/templates/default/packages/locator-picker-companion/src/cli.ts +428 -0
  88. package/templates/default/packages/locator-picker-companion/src/index.ts +3 -0
  89. package/templates/default/packages/locator-picker-companion/src/injected-picker-script.ts +771 -0
  90. package/templates/default/packages/locator-picker-companion/src/launcher.ts +77 -0
  91. package/templates/default/packages/locator-picker-companion/src/selector-generator.ts +339 -0
  92. package/templates/default/packages/locator-picker-companion/src/session-file.ts +226 -0
  93. package/templates/default/packages/locator-picker-companion/src/types.ts +42 -0
  94. package/templates/default/packages/locator-picker-companion/tsconfig.json +14 -0
  95. package/templates/default/postcss.config.mjs +8 -8
  96. package/templates/default/prisma/dev.db +0 -0
  97. package/templates/default/prisma/migrations/20251104113456_add_type_for_template_step_groups/migration.sql +16 -16
  98. package/templates/default/prisma/migrations/20251104170946_add_tags_to_test_suite_and_test_case/migration.sql +27 -27
  99. package/templates/default/prisma/migrations/20251112190024_add_cascade_delete_to_test_run_test_case/migration.sql +17 -17
  100. package/templates/default/prisma/migrations/20251113181100_add_test_run_log/migration.sql +12 -12
  101. package/templates/default/prisma/migrations/20251119191838_add_tag_type/migration.sql +28 -28
  102. package/templates/default/prisma/migrations/20251121164059_add_conflict_resolution/migration.sql +12 -12
  103. package/templates/default/prisma/migrations/20251223183400_add_report_model_to_db_schema/migration.sql +10 -10
  104. package/templates/default/prisma/migrations/20251223183637_add_report_test_case_entity_for_storing_test_results_for_individual_test_cases/migration.sql +10 -10
  105. package/templates/default/prisma/migrations/20251224083549_add_comprehensive_report_storage/migration.sql +108 -108
  106. package/templates/default/prisma/migrations/20251229194422_migrate_duration_to_string/migration.sql +55 -55
  107. package/templates/default/prisma/migrations/20251230124637_add_unique_constraint_to_test_run_name/migration.sql +27 -27
  108. package/templates/default/prisma/migrations/20260115094436_add_dashboard_metrics/migration.sql +59 -59
  109. package/templates/default/prisma/migrations/20260127172022_add_cascade_delete_to_step_parameters/migration.sql +34 -34
  110. package/templates/default/prisma/migrations/20260313093000_add_report_step_screenshot_path/migration.sql +1 -0
  111. package/templates/default/prisma/migrations/20260318120000_add_test_suite_context_to_test_run_test_case/migration.sql +20 -0
  112. package/templates/default/prisma/migrations/20260318173512_add_support_of_test_suite_level_runs/migration.sql +2 -0
  113. package/templates/default/prisma/schema.prisma +4 -0
  114. package/templates/default/scripts/install-playwright.ts +20 -0
  115. package/templates/default/scripts/protect-seeded-files.ts +38 -38
  116. package/templates/default/scripts/regenerate-features.ts +94 -94
  117. package/templates/default/scripts/setup-env.ts +19 -19
  118. package/templates/default/scripts/sync-all.ts +22 -66
  119. package/templates/default/scripts/sync-appraise-base-template.ts +57 -19
  120. package/templates/default/scripts/sync-environments.ts +40 -21
  121. package/templates/default/scripts/sync-locator-groups.ts +410 -410
  122. package/templates/default/scripts/sync-locators.ts +398 -398
  123. package/templates/default/scripts/sync-modules.ts +341 -341
  124. package/templates/default/scripts/sync-tags.ts +2 -3
  125. package/templates/default/scripts/sync-template-step-groups.ts +0 -3
  126. package/templates/default/scripts/sync-template-steps.ts +37 -11
  127. package/templates/default/scripts/sync-test-cases.ts +68 -16
  128. package/templates/default/scripts/sync-test-suites.ts +7 -5
  129. package/templates/default/src/actions/conflict/conflict.action.ts +33 -33
  130. package/templates/default/src/actions/dashboard/dashboard-actions.ts +240 -240
  131. package/templates/default/src/actions/environments/environment-actions.ts +188 -188
  132. package/templates/default/src/actions/locator/locator-actions.ts +490 -490
  133. package/templates/default/src/actions/locator-groups/locator-group-actions.ts +6 -3
  134. package/templates/default/src/actions/locator-picker/locator-picker-actions.ts +243 -0
  135. package/templates/default/src/actions/modules/module-actions.ts +135 -135
  136. package/templates/default/src/actions/reports/report-actions.ts +51 -49
  137. package/templates/default/src/actions/review/review-actions.ts +147 -147
  138. package/templates/default/src/actions/settings/sync-actions.ts +46 -0
  139. package/templates/default/src/actions/tags/tag-actions.ts +107 -107
  140. package/templates/default/src/actions/template-step/template-step-actions.ts +38 -4
  141. package/templates/default/src/actions/template-step-group/template-step-group-actions.ts +10 -3
  142. package/templates/default/src/actions/template-test-case/template-test-case-actions.ts +238 -238
  143. package/templates/default/src/actions/test-case/test-case-actions.ts +356 -356
  144. package/templates/default/src/actions/test-run/test-run-actions.ts +222 -129
  145. package/templates/default/src/actions/test-suite/test-suite-actions.ts +95 -17
  146. package/templates/default/src/actions/user/user-actions.ts +13 -13
  147. package/templates/default/src/app/(base)/environments/create/page.tsx +28 -28
  148. package/templates/default/src/app/(base)/environments/environment-form.tsx +219 -219
  149. package/templates/default/src/app/(base)/environments/environment-table-columns.tsx +96 -96
  150. package/templates/default/src/app/(base)/environments/environment-table.tsx +24 -24
  151. package/templates/default/src/app/(base)/environments/modify/[id]/page.tsx +46 -46
  152. package/templates/default/src/app/(base)/environments/page.tsx +59 -59
  153. package/templates/default/src/app/(base)/layout.tsx +10 -10
  154. package/templates/default/src/app/(base)/locator-groups/create/page.tsx +44 -44
  155. package/templates/default/src/app/(base)/locator-groups/locator-group-form.tsx +215 -215
  156. package/templates/default/src/app/(base)/locator-groups/locator-group-table-columns.tsx +77 -77
  157. package/templates/default/src/app/(base)/locator-groups/locator-group-table.tsx +28 -28
  158. package/templates/default/src/app/(base)/locator-groups/modify/[id]/page.tsx +46 -46
  159. package/templates/default/src/app/(base)/locator-groups/page.tsx +20 -8
  160. package/templates/default/src/app/(base)/locators/create/create-locator-workspace.tsx +542 -0
  161. package/templates/default/src/app/(base)/locators/create/page.tsx +32 -19
  162. package/templates/default/src/app/(base)/locators/locator-form.tsx +163 -163
  163. package/templates/default/src/app/(base)/locators/locator-table-columns.tsx +73 -73
  164. package/templates/default/src/app/(base)/locators/locator-table.tsx +28 -28
  165. package/templates/default/src/app/(base)/locators/modify/[id]/page.tsx +56 -27
  166. package/templates/default/src/app/(base)/locators/page.tsx +13 -13
  167. package/templates/default/src/app/(base)/locators/picker/page.tsx +7 -0
  168. package/templates/default/src/app/(base)/locators/sync-locators-button.tsx +66 -66
  169. package/templates/default/src/app/(base)/modules/create/page.tsx +34 -34
  170. package/templates/default/src/app/(base)/modules/modify/[id]/page.tsx +46 -46
  171. package/templates/default/src/app/(base)/modules/module-form.tsx +126 -126
  172. package/templates/default/src/app/(base)/modules/module-table-columns.tsx +85 -85
  173. package/templates/default/src/app/(base)/modules/module-table.tsx +24 -24
  174. package/templates/default/src/app/(base)/modules/page.tsx +59 -59
  175. package/templates/default/src/app/(base)/reports/[id]/page.tsx +40 -33
  176. package/templates/default/src/app/(base)/reports/duration-chart.tsx +33 -33
  177. package/templates/default/src/app/(base)/reports/feature-chart.tsx +78 -78
  178. package/templates/default/src/app/(base)/reports/overview-chart.tsx +49 -46
  179. package/templates/default/src/app/(base)/reports/page.tsx +98 -98
  180. package/templates/default/src/app/(base)/reports/report-metric-card.tsx +78 -16
  181. package/templates/default/src/app/(base)/reports/report-table-columns.tsx +189 -189
  182. package/templates/default/src/app/(base)/reports/report-table.tsx +72 -72
  183. package/templates/default/src/app/(base)/reports/report-view-table-columns.tsx +12 -1
  184. package/templates/default/src/app/(base)/reports/report-view-table.tsx +1 -0
  185. package/templates/default/src/app/(base)/reports/test-cases/page.tsx +40 -42
  186. package/templates/default/src/app/(base)/reports/test-cases/test-cases-metric-table-columns.tsx +115 -115
  187. package/templates/default/src/app/(base)/reports/test-cases/test-cases-metric-table.tsx +27 -27
  188. package/templates/default/src/app/(base)/reports/test-suites/page.tsx +42 -42
  189. package/templates/default/src/app/(base)/reports/test-suites/test-suites-metric-table-columns.tsx +79 -79
  190. package/templates/default/src/app/(base)/reports/test-suites/test-suites-metric-table.tsx +27 -27
  191. package/templates/default/src/app/(base)/reports/view-logs-button.tsx +58 -60
  192. package/templates/default/src/app/(base)/reviews/create/page.tsx +26 -26
  193. package/templates/default/src/app/(base)/reviews/created-reviews-table.tsx +15 -15
  194. package/templates/default/src/app/(base)/reviews/modify/[id]/page.tsx +26 -26
  195. package/templates/default/src/app/(base)/reviews/page.tsx +26 -26
  196. package/templates/default/src/app/(base)/reviews/review/[id]/page.tsx +26 -26
  197. package/templates/default/src/app/(base)/reviews/review-form.tsx +11 -11
  198. package/templates/default/src/app/(base)/reviews/review-table-by-creator-columns.tsx +9 -9
  199. package/templates/default/src/app/(base)/reviews/review-table-by-reviewer-columns.tsx +9 -9
  200. package/templates/default/src/app/(base)/reviews/reviewer-reviews-table.tsx +15 -15
  201. package/templates/default/src/app/(base)/settings/page.tsx +30 -0
  202. package/templates/default/src/app/(base)/settings/settings-sync-panel.tsx +261 -0
  203. package/templates/default/src/app/(base)/tags/create/page.tsx +39 -39
  204. package/templates/default/src/app/(base)/tags/modify/[id]/page.tsx +50 -50
  205. package/templates/default/src/app/(base)/tags/page.tsx +58 -58
  206. package/templates/default/src/app/(base)/tags/tag-form.tsx +147 -147
  207. package/templates/default/src/app/(base)/tags/tag-table-columns.tsx +63 -63
  208. package/templates/default/src/app/(base)/tags/tag-table.tsx +29 -29
  209. package/templates/default/src/app/(base)/template-step-groups/create/page.tsx +28 -28
  210. package/templates/default/src/app/(base)/template-step-groups/modify/[id]/page.tsx +45 -45
  211. package/templates/default/src/app/(base)/template-step-groups/page.tsx +60 -60
  212. package/templates/default/src/app/(base)/template-step-groups/template-step-group-form.tsx +167 -167
  213. package/templates/default/src/app/(base)/template-step-groups/template-step-group-table-columns.tsx +89 -89
  214. package/templates/default/src/app/(base)/template-step-groups/template-step-group-table.tsx +32 -32
  215. package/templates/default/src/app/(base)/template-steps/create/page.tsx +37 -37
  216. package/templates/default/src/app/(base)/template-steps/modify/[id]/page.tsx +49 -49
  217. package/templates/default/src/app/(base)/template-steps/page.tsx +58 -58
  218. package/templates/default/src/app/(base)/template-steps/paramChip.tsx +213 -213
  219. package/templates/default/src/app/(base)/template-steps/template-step-form.tsx +384 -384
  220. package/templates/default/src/app/(base)/template-steps/template-step-table-columns.tsx +158 -158
  221. package/templates/default/src/app/(base)/template-steps/template-step-table.tsx +24 -24
  222. package/templates/default/src/app/(base)/template-test-cases/create/page.tsx +56 -56
  223. package/templates/default/src/app/(base)/template-test-cases/modify/[id]/page.tsx +89 -89
  224. package/templates/default/src/app/(base)/template-test-cases/page.tsx +58 -58
  225. package/templates/default/src/app/(base)/template-test-cases/template-test-case-flow.tsx +84 -84
  226. package/templates/default/src/app/(base)/template-test-cases/template-test-case-form.tsx +262 -262
  227. package/templates/default/src/app/(base)/template-test-cases/template-test-case-table-columns.tsx +76 -76
  228. package/templates/default/src/app/(base)/template-test-cases/template-test-case-table.tsx +32 -32
  229. package/templates/default/src/app/(base)/test-cases/create/page.tsx +76 -76
  230. package/templates/default/src/app/(base)/test-cases/create-from-template/generate/[id]/page.tsx +96 -96
  231. package/templates/default/src/app/(base)/test-cases/create-from-template/page.tsx +38 -38
  232. package/templates/default/src/app/(base)/test-cases/create-from-template/template-selection-form.tsx +73 -73
  233. package/templates/default/src/app/(base)/test-cases/modify/[id]/page.tsx +106 -106
  234. package/templates/default/src/app/(base)/test-cases/page.tsx +2 -2
  235. package/templates/default/src/app/(base)/test-cases/test-case-flow.tsx +82 -82
  236. package/templates/default/src/app/(base)/test-cases/test-case-form.tsx +395 -395
  237. package/templates/default/src/app/(base)/test-cases/test-case-table-columns.tsx +6 -71
  238. package/templates/default/src/app/(base)/test-cases/test-case-table.tsx +2 -2
  239. package/templates/default/src/app/(base)/test-runs/[id]/page.tsx +4 -1
  240. package/templates/default/src/app/(base)/test-runs/create/page.tsx +11 -9
  241. package/templates/default/src/app/(base)/test-runs/page.tsx +60 -60
  242. package/templates/default/src/app/(base)/test-runs/test-run-form.tsx +37 -44
  243. package/templates/default/src/app/(base)/test-runs/test-run-table-columns.tsx +229 -229
  244. package/templates/default/src/app/(base)/test-runs/test-run-table.tsx +127 -127
  245. package/templates/default/src/app/(base)/test-suites/create/page.tsx +3 -2
  246. package/templates/default/src/app/(base)/test-suites/modify/[id]/page.tsx +2 -1
  247. package/templates/default/src/app/(base)/test-suites/page.tsx +57 -21
  248. package/templates/default/src/app/(base)/test-suites/test-suite-form.tsx +16 -17
  249. package/templates/default/src/app/(base)/test-suites/test-suite-table-columns.tsx +2 -1
  250. package/templates/default/src/app/(base)/test-suites/test-suite-table.tsx +29 -29
  251. package/templates/default/src/app/(dashboard-components)/app-drawer.tsx +187 -187
  252. package/templates/default/src/app/(dashboard-components)/data-card-grid.tsx +12 -12
  253. package/templates/default/src/app/(dashboard-components)/data-card.tsx +26 -26
  254. package/templates/default/src/app/(dashboard-components)/execution-health-panel.tsx +56 -56
  255. package/templates/default/src/app/(dashboard-components)/ongoing-test-runs-card.tsx +87 -87
  256. package/templates/default/src/app/(dashboard-components)/quick-actions-drawer.tsx +44 -44
  257. package/templates/default/src/app/api/reports/steps/[stepId]/screenshot/route.ts +52 -0
  258. package/templates/default/src/app/api/test-runs/[runId]/download/route.ts +97 -34
  259. package/templates/default/src/app/api/test-runs/[runId]/logs/route.ts +4 -1
  260. package/templates/default/src/app/api/test-runs/[runId]/trace/[testCaseId]/route.ts +146 -147
  261. package/templates/default/src/app/globals.css +147 -147
  262. package/templates/default/src/app/layout.tsx +4 -0
  263. package/templates/default/src/app/page.tsx +2 -0
  264. package/templates/default/src/assets/icons/empty-tube.tsx +23 -23
  265. package/templates/default/src/assets/icons/tube-plus.tsx +29 -29
  266. package/templates/default/src/components/base-node.tsx +21 -21
  267. package/templates/default/src/components/chart/pie-chart.tsx +73 -73
  268. package/templates/default/src/components/data-extraction/locator-inspector.tsx +460 -460
  269. package/templates/default/src/components/data-state/empty-state.tsx +40 -40
  270. package/templates/default/src/components/data-visualization/info-card.tsx +70 -70
  271. package/templates/default/src/components/data-visualization/info-grid.tsx +22 -22
  272. package/templates/default/src/components/diagram/button-edge.tsx +54 -54
  273. package/templates/default/src/components/diagram/dynamic-parameters.tsx +474 -474
  274. package/templates/default/src/components/diagram/edit-header-option.tsx +36 -36
  275. package/templates/default/src/components/diagram/flow-diagram.tsx +470 -470
  276. package/templates/default/src/components/diagram/node-form.tsx +262 -262
  277. package/templates/default/src/components/diagram/options-header-node.tsx +57 -57
  278. package/templates/default/src/components/diagram/template-step-combobox.tsx +155 -155
  279. package/templates/default/src/components/form/error-message.tsx +7 -7
  280. package/templates/default/src/components/kokonutui/smooth-tab.tsx +453 -453
  281. package/templates/default/src/components/loading-skeleton/data-table/data-table-skeleton.tsx +30 -30
  282. package/templates/default/src/components/loading-skeleton/form/button-skeleton.tsx +8 -8
  283. package/templates/default/src/components/loading-skeleton/form/icon-button-skeleton.tsx +8 -8
  284. package/templates/default/src/components/loading-skeleton/form/text-input-skeleton.tsx +8 -8
  285. package/templates/default/src/components/loading-skeleton/visualization/table-skeleton.tsx +14 -14
  286. package/templates/default/src/components/logo.tsx +15 -15
  287. package/templates/default/src/components/navigation/command-badge.tsx +34 -34
  288. package/templates/default/src/components/navigation/command-chain-input.tsx +51 -51
  289. package/templates/default/src/components/navigation/entity-search-command.tsx +116 -116
  290. package/templates/default/src/components/navigation/nav-card.tsx +31 -31
  291. package/templates/default/src/components/navigation/nav-command.tsx +13 -0
  292. package/templates/default/src/components/navigation/nav-link.tsx +60 -60
  293. package/templates/default/src/components/navigation/nav-menu-card-deck.tsx +112 -112
  294. package/templates/default/src/components/node-header.tsx +159 -159
  295. package/templates/default/src/components/reports/test-case-logs-modal.tsx +310 -253
  296. package/templates/default/src/components/table/table-actions.tsx +172 -172
  297. package/templates/default/src/components/test-case/test-case-columns.tsx +76 -0
  298. package/templates/default/src/components/test-case/test-case-picker.tsx +244 -0
  299. package/templates/default/src/components/test-run/download-logs-button.tsx +92 -99
  300. package/templates/default/src/components/test-run/log-viewer.tsx +1 -14
  301. package/templates/default/src/components/test-run/test-run-details.tsx +15 -2
  302. package/templates/default/src/components/test-run/test-run-header.tsx +149 -149
  303. package/templates/default/src/components/test-run/view-report-button.tsx +102 -102
  304. package/templates/default/src/components/test-suite/test-suite-picker.tsx +444 -0
  305. package/templates/default/src/components/theme/mode-toggle.tsx +54 -54
  306. package/templates/default/src/components/theme/theme-provider.tsx +8 -8
  307. package/templates/default/src/components/typography/page-header-subtitle.tsx +7 -7
  308. package/templates/default/src/components/typography/page-header.tsx +7 -7
  309. package/templates/default/src/components/ui/alert-dialog.tsx +106 -106
  310. package/templates/default/src/components/ui/alert.tsx +43 -43
  311. package/templates/default/src/components/ui/avatar.tsx +40 -40
  312. package/templates/default/src/components/ui/badge.tsx +29 -29
  313. package/templates/default/src/components/ui/button.tsx +47 -47
  314. package/templates/default/src/components/ui/calendar.tsx +158 -158
  315. package/templates/default/src/components/ui/card.tsx +43 -43
  316. package/templates/default/src/components/ui/checkbox.tsx +28 -28
  317. package/templates/default/src/components/ui/command.tsx +135 -135
  318. package/templates/default/src/components/ui/data-table-column-header.tsx +61 -61
  319. package/templates/default/src/components/ui/data-table-pagination.tsx +87 -87
  320. package/templates/default/src/components/ui/data-table-view-options.tsx +50 -50
  321. package/templates/default/src/components/ui/data-table.tsx +261 -261
  322. package/templates/default/src/components/ui/dialog.tsx +97 -97
  323. package/templates/default/src/components/ui/dropdown-menu.tsx +182 -182
  324. package/templates/default/src/components/ui/input.tsx +22 -22
  325. package/templates/default/src/components/ui/kbd.tsx +28 -28
  326. package/templates/default/src/components/ui/label.tsx +19 -19
  327. package/templates/default/src/components/ui/loading.tsx +12 -12
  328. package/templates/default/src/components/ui/multi-select-with-preview.tsx +116 -116
  329. package/templates/default/src/components/ui/multi-select.tsx +142 -142
  330. package/templates/default/src/components/ui/navigation-menu.tsx +120 -120
  331. package/templates/default/src/components/ui/popover.tsx +33 -33
  332. package/templates/default/src/components/ui/progress.tsx +25 -25
  333. package/templates/default/src/components/ui/radio-group.tsx +44 -44
  334. package/templates/default/src/components/ui/scroll-area.tsx +40 -40
  335. package/templates/default/src/components/ui/select.tsx +151 -151
  336. package/templates/default/src/components/ui/separator.tsx +22 -22
  337. package/templates/default/src/components/ui/skeleton.tsx +7 -7
  338. package/templates/default/src/components/ui/table.tsx +76 -76
  339. package/templates/default/src/components/ui/tabs.tsx +55 -55
  340. package/templates/default/src/components/ui/textarea.tsx +21 -21
  341. package/templates/default/src/components/ui/toast.tsx +113 -113
  342. package/templates/default/src/components/ui/toaster.tsx +26 -26
  343. package/templates/default/src/components/user-prompt/delete-prompt.tsx +87 -87
  344. package/templates/default/src/config/db-config.ts +10 -10
  345. package/templates/default/src/constants/form-opts/diagram/node-form.ts +30 -30
  346. package/templates/default/src/constants/form-opts/environment-form-opts.ts +24 -24
  347. package/templates/default/src/constants/form-opts/locator-form-opts.ts +20 -20
  348. package/templates/default/src/constants/form-opts/locator-group-form-opts.ts +28 -28
  349. package/templates/default/src/constants/form-opts/module-form-opts.ts +21 -21
  350. package/templates/default/src/constants/form-opts/review-form-opts.ts +23 -23
  351. package/templates/default/src/constants/form-opts/tag-form-opts.ts +42 -42
  352. package/templates/default/src/constants/form-opts/template-selection-form-opts.ts +16 -16
  353. package/templates/default/src/constants/form-opts/template-step-group-form-opts.ts +24 -24
  354. package/templates/default/src/constants/form-opts/template-test-case-form-opts.ts +39 -39
  355. package/templates/default/src/constants/form-opts/template-test-step-form-opts.ts +36 -36
  356. package/templates/default/src/constants/form-opts/test-case-form-opts.ts +43 -43
  357. package/templates/default/src/constants/form-opts/test-run-form-opts.ts +5 -3
  358. package/templates/default/src/constants/form-opts/test-suite-form-opts.ts +24 -24
  359. package/templates/default/src/hooks/use-toast.ts +187 -187
  360. package/templates/default/src/lib/automation/paths.ts +42 -12
  361. package/templates/default/src/lib/automation/projection-service.ts +2 -1
  362. package/templates/default/src/lib/bidirectional-sync.ts +432 -432
  363. package/templates/default/src/lib/database-sync.ts +2 -7
  364. package/templates/default/src/lib/environment-file-utils.ts +184 -184
  365. package/templates/default/src/lib/executor/local-executor-adapter.ts +24 -25
  366. package/templates/default/src/lib/executor/types.ts +2 -2
  367. package/templates/default/src/lib/feature-file-generator.ts +5 -66
  368. package/templates/default/src/lib/gherkin-parser.ts +259 -259
  369. package/templates/default/src/lib/locator-group-file-utils.ts +307 -307
  370. package/templates/default/src/lib/locator-picker/session-manager.ts +452 -0
  371. package/templates/default/src/lib/locator-picker/suggestions.ts +124 -0
  372. package/templates/default/src/lib/metrics/metric-calculator.ts +5 -0
  373. package/templates/default/src/lib/module-hierarchy-builder.ts +205 -205
  374. package/templates/default/src/lib/path-helpers/module-path.ts +71 -71
  375. package/templates/default/src/lib/process/task-spawner.ts +39 -2
  376. package/templates/default/src/lib/sync/projected-feature-utils.ts +113 -0
  377. package/templates/default/src/lib/sync/sync-executor.ts +130 -0
  378. package/templates/default/src/lib/sync/sync-pending-counts.test.ts +239 -0
  379. package/templates/default/src/lib/sync/sync-pending-counts.ts +1358 -0
  380. package/templates/default/src/lib/sync/sync-registry.ts +149 -0
  381. package/templates/default/src/lib/tag-utils.ts +28 -0
  382. package/templates/default/src/lib/template-sync-utils.d.ts +6 -6
  383. package/templates/default/src/lib/template-sync-utils.js +46 -46
  384. package/templates/default/src/lib/template-sync-utils.ts +63 -63
  385. package/templates/default/src/lib/test-case-utils.ts +6 -6
  386. package/templates/default/src/lib/test-run/log-formatter.ts +83 -83
  387. package/templates/default/src/lib/test-run/matching.ts +117 -0
  388. package/templates/default/src/lib/test-run/process-manager.ts +2 -0
  389. package/templates/default/src/lib/test-run/report-parser.ts +352 -316
  390. package/templates/default/src/lib/test-run/test-run-executor.ts +13 -15
  391. package/templates/default/src/lib/test-run/winston-logger.ts +64 -66
  392. package/templates/default/src/lib/test-suite-identifier-service.ts +76 -0
  393. package/templates/default/src/lib/test-suite-utils.ts +6 -0
  394. package/templates/default/src/lib/transformers/gherkin-converter.ts +42 -42
  395. package/templates/default/src/lib/transformers/key-to-icon-transformer.tsx +95 -95
  396. package/templates/default/src/lib/transformers/template-test-case-converter.ts +160 -160
  397. package/templates/default/src/lib/utils/node-param-validation.ts +81 -81
  398. package/templates/default/src/lib/utils/template-step-file-generator.ts +104 -104
  399. package/templates/default/src/lib/utils/template-step-file-manager-intelligent.ts +0 -8
  400. package/templates/default/src/lib/utils/template-step-file-manager.ts +166 -166
  401. package/templates/default/src/lib/utils.ts +31 -31
  402. package/templates/default/src/types/diagram/diagram.ts +34 -34
  403. package/templates/default/src/types/diagram/template-step.ts +11 -11
  404. package/templates/default/src/types/executor/browser.type.ts +1 -1
  405. package/templates/default/src/types/form/actionHandler.ts +6 -6
  406. package/templates/default/src/types/locator/locator.type.ts +11 -11
  407. package/templates/default/src/types/locator-picker.ts +65 -0
  408. package/templates/default/src/types/step/step.type.ts +1 -1
  409. package/templates/default/src/types/table/data-table.ts +6 -6
  410. package/templates/default/src/types/test-case-picker.ts +6 -0
  411. package/templates/default/src/types/test-suite-picker.ts +18 -0
  412. package/templates/default/tailwind.config.ts +62 -62
  413. package/templates/default/tsconfig.json +4 -1
  414. package/templates/default/appraisejs.config.json +0 -1
@@ -13,6 +13,7 @@ import { join } from 'path'
13
13
  import prisma from '../src/config/db-config'
14
14
  import { scanFeatureFiles, ParsedFeature } from '../src/lib/gherkin-parser'
15
15
  import { TagType } from '@prisma/client'
16
+ import { getTagTypeFromName } from '../src/lib/tag-utils'
16
17
 
17
18
  interface TagData {
18
19
  name: string // Without @ prefix, for DB storage
@@ -90,8 +91,7 @@ function buildTagObjects(tagExpressions: Set<string>): TagData[] {
90
91
  // Strip @ prefix for name field
91
92
  const name = tagExpression.startsWith('@') ? tagExpression.substring(1) : tagExpression
92
93
 
93
- // Determine type: IDENTIFIER if starts with tc_, otherwise FILTER
94
- const type = name.startsWith('tc_') ? TagType.IDENTIFIER : TagType.FILTER
94
+ const type = getTagTypeFromName(name)
95
95
 
96
96
  tagObjects.push({
97
97
  name,
@@ -289,4 +289,3 @@ async function main() {
289
289
  }
290
290
 
291
291
  main()
292
-
@@ -151,7 +151,6 @@ function parseGroupJSDoc(content: string): StepGroupJSDoc | null {
151
151
  * Scans step definition files in actions and validations directories
152
152
  */
153
153
  async function scanStepFiles(baseDir: string): Promise<string[]> {
154
- const _stepsDir = join(baseDir, 'src', 'tests', 'steps')
155
154
  const stepFiles: string[] = []
156
155
 
157
156
  try {
@@ -405,5 +404,3 @@ async function main() {
405
404
  }
406
405
 
407
406
  main()
408
-
409
-
@@ -16,6 +16,7 @@ import { parse } from '@babel/parser'
16
16
  import * as t from '@babel/types'
17
17
  import _traverse from '@babel/traverse'
18
18
  import type { NodePath } from '@babel/traverse'
19
+ import prettier from 'prettier'
19
20
 
20
21
  // Handle both ESM and CJS exports
21
22
  const traverse = (_traverse as { default?: typeof _traverse }).default ?? _traverse
@@ -66,6 +67,33 @@ interface SyncResult {
66
67
  deletedSteps: Array<{ name: string; signature: string; group: string }>
67
68
  }
68
69
 
70
+ function normalizeOptionalText(value: string | null | undefined): string | null {
71
+ const normalized = value?.trim()
72
+ return normalized ? normalized : null
73
+ }
74
+
75
+ async function normalizeFunctionDefinition(functionDefinition: string | null | undefined): Promise<string> {
76
+ const source = functionDefinition?.trim()
77
+ if (!source) {
78
+ return ''
79
+ }
80
+
81
+ try {
82
+ return (
83
+ await prettier.format(source, {
84
+ parser: 'typescript',
85
+ semi: true,
86
+ singleQuote: true,
87
+ trailingComma: 'es5',
88
+ printWidth: 80,
89
+ tabWidth: 2,
90
+ })
91
+ ).trim()
92
+ } catch {
93
+ return source
94
+ }
95
+ }
96
+
69
97
  /**
70
98
  * Parses JSDoc comment to extract step group metadata
71
99
  * Reused from template-step-group-sync.ts
@@ -325,7 +353,6 @@ function extractFunctionDefinition(callExpr: t.CallExpression, keyword: string,
325
353
  * Parses a step definition file to extract steps
326
354
  */
327
355
  function parseStepFile(content: string, filePath: string): StepData | null {
328
- // Parse group JSDoc
329
356
  const group = parseGroupJSDoc(content)
330
357
  if (!group) {
331
358
  return null
@@ -482,7 +509,6 @@ async function scanStepFiles(baseDir: string): Promise<string[]> {
482
509
  */
483
510
  async function syncStepsToDatabase(
484
511
  allSteps: Array<{ step: ParsedStep; groupName: string; filePath: string }>,
485
- _baseDir: string,
486
512
  ): Promise<SyncResult> {
487
513
  const result: SyncResult = {
488
514
  stepsScanned: 0,
@@ -520,6 +546,8 @@ async function syncStepsToDatabase(
520
546
  // Determine step type from group type
521
547
  const stepType: TemplateStepType =
522
548
  stepGroup.type === TemplateStepGroupType.ACTION ? TemplateStepType.ACTION : TemplateStepType.ASSERTION
549
+ const description = normalizeOptionalText(step.jsdoc.description)
550
+ const functionDefinition = await normalizeFunctionDefinition(step.functionDefinition)
523
551
 
524
552
  // Check if step exists by signature
525
553
  const existingStep = await prisma.templateStep.findFirst({
@@ -535,9 +563,9 @@ async function syncStepsToDatabase(
535
563
  // Check if update is needed
536
564
  const needsUpdate =
537
565
  existingStep.name !== step.jsdoc.name ||
538
- existingStep.description !== (step.jsdoc.description || '') ||
566
+ (existingStep.description ?? null) !== description ||
539
567
  existingStep.signature !== step.signature ||
540
- existingStep.functionDefinition !== step.functionDefinition ||
568
+ (existingStep.functionDefinition ?? '') !== functionDefinition ||
541
569
  existingStep.icon !== step.jsdoc.icon ||
542
570
  existingStep.type !== stepType ||
543
571
  existingStep.templateStepGroupId !== stepGroup.id
@@ -548,9 +576,9 @@ async function syncStepsToDatabase(
548
576
  where: { id: existingStep.id },
549
577
  data: {
550
578
  name: step.jsdoc.name,
551
- description: step.jsdoc.description || '',
579
+ description,
552
580
  signature: step.signature,
553
- functionDefinition: step.functionDefinition,
581
+ functionDefinition,
554
582
  icon: step.jsdoc.icon,
555
583
  type: stepType,
556
584
  templateStepGroupId: stepGroup.id,
@@ -579,9 +607,9 @@ async function syncStepsToDatabase(
579
607
  await prisma.templateStep.create({
580
608
  data: {
581
609
  name: step.jsdoc.name,
582
- description: step.jsdoc.description || '',
610
+ description,
583
611
  signature: step.signature,
584
- functionDefinition: step.functionDefinition,
612
+ functionDefinition,
585
613
  icon: step.jsdoc.icon,
586
614
  type: stepType,
587
615
  templateStepGroupId: stepGroup.id,
@@ -790,7 +818,7 @@ async function main() {
790
818
 
791
819
  // Sync to database
792
820
  console.log('\n✅ Syncing template steps to database...')
793
- const result = await syncStepsToDatabase(allSteps, baseDir)
821
+ const result = await syncStepsToDatabase(allSteps)
794
822
 
795
823
  // Add parsing errors to result
796
824
  result.errors.push(...errors)
@@ -813,5 +841,3 @@ async function main() {
813
841
  }
814
842
 
815
843
  main()
816
-
817
-
@@ -18,6 +18,11 @@ import {
18
18
  import { buildModuleHierarchy, findModuleByPath } from '../src/lib/module-hierarchy-builder'
19
19
  import { TemplateStepType, TemplateStepIcon, StepParameterType, TagType } from '@prisma/client'
20
20
  import { ensureAutomationWorkspaceReady, getAutomationFeaturesDir } from '../src/lib/automation/paths'
21
+ import {
22
+ determineProjectedStepIcon,
23
+ getTestSuiteFilesystemKey,
24
+ normalizeProjectedDbTestCaseSteps,
25
+ } from '../src/lib/sync/projected-feature-utils'
21
26
 
22
27
  interface TestCaseFromFS {
23
28
  identifierTag: string // @tc_... tag
@@ -39,6 +44,7 @@ interface ParameterMatch {
39
44
 
40
45
  interface TemplateStepMatch {
41
46
  templateStepId: string
47
+ signature: string
42
48
  parameters: ParameterMatch[]
43
49
  }
44
50
 
@@ -259,6 +265,7 @@ async function matchGherkinStepToTemplateStep(gherkinStep: ParsedStep): Promise<
259
265
  if (parameters !== null) {
260
266
  return {
261
267
  templateStepId: templateStep.id,
268
+ signature: templateStep.signature,
262
269
  parameters,
263
270
  }
264
271
  }
@@ -291,6 +298,22 @@ function determineStepTypeAndIcon(keyword: string): { type: TemplateStepType; ic
291
298
  }
292
299
  }
293
300
 
301
+ function sameResolvedParameters(left: ParameterMatch[], right: ParameterMatch[]): boolean {
302
+ if (left.length !== right.length) {
303
+ return false
304
+ }
305
+
306
+ return left.every((parameter, index) => {
307
+ const other = right[index]
308
+ return (
309
+ parameter.name === other?.name &&
310
+ parameter.value === other?.value &&
311
+ parameter.order === other?.order &&
312
+ parameter.type === other?.type
313
+ )
314
+ })
315
+ }
316
+
294
317
  /**
295
318
  * Finds or creates a tag by tag expression
296
319
  * If the tag exists but has a different type, updates it to the correct type
@@ -341,12 +364,18 @@ async function syncTestCaseSteps(testCaseId: string, steps: ParsedStep[], result
341
364
  where: { testCaseId },
342
365
  orderBy: { order: 'asc' },
343
366
  include: {
367
+ TemplateStep: {
368
+ select: {
369
+ signature: true,
370
+ },
371
+ },
344
372
  parameters: true,
345
373
  },
346
374
  })
347
375
 
348
376
  // Create a map of existing steps by order
349
377
  const existingStepsMap = new Map(existingSteps.map(step => [step.order, step]))
378
+ const projectedExistingStepsMap = new Map(normalizeProjectedDbTestCaseSteps(existingSteps).map(step => [step.order, step]))
350
379
 
351
380
  // Process each step from filesystem
352
381
  for (const step of steps) {
@@ -365,11 +394,22 @@ async function syncTestCaseSteps(testCaseId: string, steps: ParsedStep[], result
365
394
  const gherkinStep = `${step.keyword} ${step.text}`
366
395
 
367
396
  if (existingStep) {
397
+ const projectedExistingStep = projectedExistingStepsMap.get(step.order)
398
+ const matchesProjectedState =
399
+ projectedExistingStep != null &&
400
+ projectedExistingStep.gherkinStep === gherkinStep &&
401
+ projectedExistingStep.label === step.text &&
402
+ projectedExistingStep.icon === determineProjectedStepIcon(step.keyword) &&
403
+ projectedExistingStep.templateStepSignature === match.signature &&
404
+ sameResolvedParameters(projectedExistingStep.parameters, match.parameters)
405
+
368
406
  // Update existing step if needed
369
407
  const needsUpdate =
370
- existingStep.gherkinStep !== gherkinStep ||
371
- existingStep.templateStepId !== match.templateStepId ||
372
- existingStep.label !== step.text
408
+ !matchesProjectedState &&
409
+ (existingStep.gherkinStep !== gherkinStep ||
410
+ existingStep.templateStepId !== match.templateStepId ||
411
+ existingStep.label !== step.text ||
412
+ existingStep.icon !== icon)
373
413
 
374
414
  if (needsUpdate) {
375
415
  await prisma.testCaseStep.update({
@@ -451,6 +491,7 @@ async function syncTestCasesToDatabase(testCasesFromFS: TestCaseFromFS[], result
451
491
 
452
492
  // Track test cases from filesystem (by identifier tag)
453
493
  const fsTestCaseTags = new Set<string>()
494
+ const suitesByModuleId = new Map<string, Array<{ id: string; name: string }>>()
454
495
 
455
496
  for (const testCase of testCasesFromFS) {
456
497
  try {
@@ -465,12 +506,23 @@ async function syncTestCasesToDatabase(testCasesFromFS: TestCaseFromFS[], result
465
506
  }
466
507
 
467
508
  // Find test suite
468
- const testSuite = await prisma.testSuite.findFirst({
469
- where: {
470
- name: testCase.testSuiteName,
471
- moduleId: moduleId,
472
- },
473
- })
509
+ let moduleSuites = suitesByModuleId.get(moduleId)
510
+ if (!moduleSuites) {
511
+ moduleSuites = await prisma.testSuite.findMany({
512
+ where: {
513
+ moduleId: moduleId,
514
+ },
515
+ select: {
516
+ id: true,
517
+ name: true,
518
+ },
519
+ })
520
+ suitesByModuleId.set(moduleId, moduleSuites)
521
+ }
522
+
523
+ const testSuite = moduleSuites.find(
524
+ suite => getTestSuiteFilesystemKey(suite.name) === getTestSuiteFilesystemKey(testCase.testSuiteName),
525
+ )
474
526
 
475
527
  if (!testSuite) {
476
528
  result.errors.push(`Test suite '${testCase.testSuiteName}' not found in module '${testCase.modulePath}'`)
@@ -509,8 +561,11 @@ async function syncTestCasesToDatabase(testCasesFromFS: TestCaseFromFS[], result
509
561
 
510
562
  if (identifierTag && identifierTag.testCases.length > 0) {
511
563
  // Test case exists - update it
564
+ const matchedExistingTestCaseSummary =
565
+ identifierTag.testCases.find(existingCase => existingCase.TestSuite.some(suite => suite.id === testSuite.id)) ??
566
+ identifierTag.testCases[0]
512
567
  const existingTestCase = await prisma.testCase.findUnique({
513
- where: { id: identifierTag.testCases[0].id },
568
+ where: { id: matchedExistingTestCaseSummary.id },
514
569
  include: {
515
570
  tags: true,
516
571
  TestSuite: true,
@@ -531,16 +586,15 @@ async function syncTestCasesToDatabase(testCasesFromFS: TestCaseFromFS[], result
531
586
 
532
587
  const newFilterTagIds = filterTagIds.sort()
533
588
  const tagsChanged = JSON.stringify(currentFilterTagIds) !== JSON.stringify(newFilterTagIds)
589
+ const isAssociated = existingTestCase.TestSuite.some(ts => ts.id === testSuite.id)
534
590
 
535
591
  const needsUpdate =
536
592
  existingTestCase.title !== testCase.title ||
537
593
  existingTestCase.description !== testCase.description ||
538
- tagsChanged
594
+ tagsChanged ||
595
+ !isAssociated
539
596
 
540
597
  if (needsUpdate) {
541
- // Check if test case is already associated with this test suite
542
- const isAssociated = existingTestCase.TestSuite.some(ts => ts.id === testSuite.id)
543
-
544
598
  await prisma.testCase.update({
545
599
  where: { id: existingTestCase.id },
546
600
  data: {
@@ -904,5 +958,3 @@ async function main() {
904
958
 
905
959
  main()
906
960
 
907
-
908
-
@@ -13,6 +13,7 @@ import prisma from '../src/config/db-config'
13
13
  import { scanFeatureFiles, extractModulePathFromFilePath, ParsedFeature } from '../src/lib/gherkin-parser'
14
14
  import { buildModuleHierarchy, findModuleByPath, getAllModulesWithPaths } from '../src/lib/module-hierarchy-builder'
15
15
  import { ensureAutomationWorkspaceReady, getAutomationFeaturesDir } from '../src/lib/automation/paths'
16
+ import { getTestSuiteSyncIdentity, getTestSuiteFilesystemKey } from '../src/lib/sync/projected-feature-utils'
16
17
 
17
18
  interface TestSuiteFromFS {
18
19
  name: string // From filename (without .feature extension)
@@ -142,7 +143,7 @@ async function syncTestSuitesToDatabase(
142
143
 
143
144
  for (const testSuite of testSuitesFromFS) {
144
145
  try {
145
- const key = `${testSuite.name}::${testSuite.modulePath}`
146
+ const key = getTestSuiteSyncIdentity(testSuite.name, testSuite.modulePath)
146
147
  fsTestSuiteKeys.add(key)
147
148
 
148
149
  // Ensure module exists
@@ -154,15 +155,17 @@ async function syncTestSuitesToDatabase(
154
155
  }
155
156
 
156
157
  // Find existing test suite by name and moduleId
157
- const existingTestSuite = await prisma.testSuite.findFirst({
158
+ const existingTestSuites = await prisma.testSuite.findMany({
158
159
  where: {
159
- name: testSuite.name,
160
160
  moduleId: moduleId,
161
161
  },
162
162
  include: {
163
163
  tags: true,
164
164
  },
165
165
  })
166
+ const existingTestSuite = existingTestSuites.find(
167
+ candidate => getTestSuiteFilesystemKey(candidate.name) === getTestSuiteFilesystemKey(testSuite.name),
168
+ )
166
169
 
167
170
  // Find tag IDs
168
171
  const tagIds = await findTagIdsByExpressions(testSuite.tags)
@@ -271,7 +274,7 @@ async function syncTestSuitesToDatabase(
271
274
  for (const dbTestSuite of allDbTestSuites) {
272
275
  try {
273
276
  const modulePath = modulePathMap.get(dbTestSuite.moduleId) || '/'
274
- const key = `${dbTestSuite.name}::${modulePath}`
277
+ const key = getTestSuiteSyncIdentity(dbTestSuite.name, modulePath)
275
278
 
276
279
  if (!fsTestSuiteKeys.has(key)) {
277
280
  // Check if test suite has test cases (for logging)
@@ -411,4 +414,3 @@ async function main() {
411
414
  main()
412
415
 
413
416
 
414
-
@@ -1,33 +1,33 @@
1
- 'use server'
2
-
3
- import { ActionResponse } from '@/types/form/actionHandler'
4
- import prisma from '@/config/db-config'
5
- import { revalidatePath } from 'next/cache'
6
-
7
- export async function resolveConflictsAction(conflictIds: string[]): Promise<ActionResponse> {
8
- try {
9
- const updatedConflicts = await prisma.conflictResolution.updateMany({
10
- where: { entityId: { in: conflictIds } },
11
- data: { resolved: true },
12
- })
13
-
14
- revalidatePath('/locators')
15
-
16
- if (updatedConflicts.count === 0) {
17
- return {
18
- status: 404,
19
- error: 'No conflicts found',
20
- }
21
- }
22
- return {
23
- status: 200,
24
- data: updatedConflicts.count,
25
- message: 'Conflicts resolved successfully',
26
- }
27
- } catch (error) {
28
- return {
29
- status: 500,
30
- error: `Server error occurred: ${error}`,
31
- }
32
- }
33
- }
1
+ 'use server'
2
+
3
+ import { ActionResponse } from '@/types/form/actionHandler'
4
+ import prisma from '@/config/db-config'
5
+ import { revalidatePath } from 'next/cache'
6
+
7
+ export async function resolveConflictsAction(conflictIds: string[]): Promise<ActionResponse> {
8
+ try {
9
+ const updatedConflicts = await prisma.conflictResolution.updateMany({
10
+ where: { entityId: { in: conflictIds } },
11
+ data: { resolved: true },
12
+ })
13
+
14
+ revalidatePath('/locators')
15
+
16
+ if (updatedConflicts.count === 0) {
17
+ return {
18
+ status: 404,
19
+ error: 'No conflicts found',
20
+ }
21
+ }
22
+ return {
23
+ status: 200,
24
+ data: updatedConflicts.count,
25
+ message: 'Conflicts resolved successfully',
26
+ }
27
+ } catch (error) {
28
+ return {
29
+ status: 500,
30
+ error: `Server error occurred: ${error}`,
31
+ }
32
+ }
33
+ }