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
@@ -10,58 +10,13 @@
10
10
 
11
11
  import { execa } from 'execa'
12
12
  import { join } from 'path'
13
-
14
- /**
15
- * Sync script configuration with execution order and dependencies
16
- * Order is critical - scripts must run after their dependencies
17
- */
18
- const SYNC_SCRIPTS = [
19
- {
20
- name: 'sync-modules',
21
- description: 'Sync module hierarchy',
22
- dependencies: [], // No dependencies - base entity
23
- },
24
- {
25
- name: 'sync-environments',
26
- description: 'Sync environments',
27
- dependencies: [], // No dependencies - standalone
28
- },
29
- {
30
- name: 'sync-tags',
31
- description: 'Sync tags',
32
- dependencies: [], // No dependencies - standalone
33
- },
34
- {
35
- name: 'sync-template-step-groups',
36
- description: 'Sync template step groups',
37
- dependencies: [], // No dependencies - base for template steps
38
- },
39
- {
40
- name: 'sync-template-steps',
41
- description: 'Sync template steps',
42
- dependencies: ['sync-template-step-groups'], // Depends on template-step-groups
43
- },
44
- {
45
- name: 'sync-locator-groups',
46
- description: 'Sync locator groups',
47
- dependencies: ['sync-modules'], // Depends on modules
48
- },
49
- {
50
- name: 'sync-locators',
51
- description: 'Sync locators',
52
- dependencies: ['sync-locator-groups'], // Depends on locator-groups
53
- },
54
- {
55
- name: 'sync-test-suites',
56
- description: 'Sync test suites',
57
- dependencies: ['sync-modules', 'sync-tags'], // Depends on modules and tags
58
- },
59
- {
60
- name: 'sync-test-cases',
61
- description: 'Sync test cases',
62
- dependencies: ['sync-test-suites', 'sync-template-steps', 'sync-tags'], // Depends on test-suites, template-steps, and tags
63
- },
64
- ] as const
13
+ import {
14
+ getSyncScriptDefinition,
15
+ resolveRequestedSyncExecutionOrder,
16
+ SYNC_ALL_REQUEST_ID,
17
+ type SyncScriptId,
18
+ } from '../src/lib/sync/sync-registry'
19
+ const SYNC_SCRIPT_IDS = resolveRequestedSyncExecutionOrder(SYNC_ALL_REQUEST_ID)
65
20
 
66
21
  interface DatabaseChanges {
67
22
  scanned: number
@@ -138,13 +93,14 @@ function parseDatabaseChanges(stdout: string): DatabaseChanges | undefined {
138
93
  /**
139
94
  * Executes a single sync script and captures the result
140
95
  */
141
- async function executeSyncScript(scriptName: string): Promise<ScriptResult> {
142
- const scriptPath = join(process.cwd(), 'scripts', `${scriptName}.ts`)
96
+ async function executeSyncScript(scriptId: SyncScriptId): Promise<ScriptResult> {
97
+ const definition = getSyncScriptDefinition(scriptId)
98
+ const scriptPath = join(process.cwd(), 'scripts', definition.scriptFile)
143
99
  const startTime = Date.now()
144
100
 
145
101
  try {
146
- console.log(`\n🔄 Running ${scriptName}...`)
147
- const result = await execa('npx', ['tsx', scriptPath], {
102
+ console.log(`\n🔄 Running ${scriptId}...`)
103
+ const result = await execa(process.execPath, ['--import', 'tsx', scriptPath], {
148
104
  cwd: process.cwd(),
149
105
  stdio: 'pipe',
150
106
  reject: false, // Don't throw on non-zero exit codes
@@ -155,17 +111,17 @@ async function executeSyncScript(scriptName: string): Promise<ScriptResult> {
155
111
  const dbChanges = parseDatabaseChanges(result.stdout)
156
112
 
157
113
  if (success) {
158
- console.log(` ✅ ${scriptName} completed successfully (${duration}ms)`)
114
+ console.log(` ✅ ${scriptId} completed successfully (${duration}ms)`)
159
115
  } else {
160
- console.log(` ❌ ${scriptName} failed with exit code ${result.exitCode} (${duration}ms)`)
116
+ console.log(` ❌ ${scriptId} failed with exit code ${result.exitCode} (${duration}ms)`)
161
117
  if (result.stderr) {
162
118
  console.log(` Error output: ${result.stderr.substring(0, 200)}...`)
163
119
  }
164
120
  }
165
121
 
166
122
  return {
167
- name: scriptName,
168
- description: SYNC_SCRIPTS.find(s => s.name === scriptName)?.description || scriptName,
123
+ name: scriptId,
124
+ description: definition.description,
169
125
  success,
170
126
  exitCode: result.exitCode ?? null,
171
127
  duration,
@@ -175,12 +131,12 @@ async function executeSyncScript(scriptName: string): Promise<ScriptResult> {
175
131
  }
176
132
  } catch (error) {
177
133
  const duration = Date.now() - startTime
178
- console.log(` ❌ ${scriptName} threw an error (${duration}ms)`)
134
+ console.log(` ❌ ${scriptId} threw an error (${duration}ms)`)
179
135
  console.error(` Error: ${error}`)
180
136
 
181
137
  return {
182
- name: scriptName,
183
- description: SYNC_SCRIPTS.find(s => s.name === scriptName)?.description || scriptName,
138
+ name: scriptId,
139
+ description: definition.description,
184
140
  success: false,
185
141
  exitCode: null,
186
142
  duration,
@@ -301,8 +257,8 @@ async function main(): Promise<void> {
301
257
  console.log('Execution will continue even if individual scripts fail.\n')
302
258
 
303
259
  // Execute each script in order
304
- for (const script of SYNC_SCRIPTS) {
305
- const result = await executeSyncScript(script.name)
260
+ for (const scriptId of SYNC_SCRIPT_IDS) {
261
+ const result = await executeSyncScript(scriptId)
306
262
  results.push(result)
307
263
 
308
264
  // Continue execution even if script failed (as per user requirement)
@@ -315,7 +271,7 @@ async function main(): Promise<void> {
315
271
  const totalDbChanges = aggregateDatabaseChanges(results)
316
272
 
317
273
  const summary: SyncSummary = {
318
- totalScripts: SYNC_SCRIPTS.length,
274
+ totalScripts: SYNC_SCRIPT_IDS.length,
319
275
  successfulScripts,
320
276
  failedScripts,
321
277
  totalDuration,
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
3
  * Sync the default template from the base app (repo root).
4
- * Copies src/, automation/, prisma/, public/, scripts/, the cucumber runtime package,
4
+ * Copies src/, automation/, prisma/, public/, scripts/, selected internal packages,
5
5
  * and root config files into templates/default/ while preserving template-only files.
6
6
  *
7
7
  * Usage: npx tsx scripts/sync-appraise-base-template.ts
@@ -20,18 +20,23 @@ function shouldExclude(relativePath: string): boolean {
20
20
  return shouldExcludeTemplatePath(relativePath)
21
21
  }
22
22
 
23
- function copyDirWithFilter(src: string, dest: string, base = src): void {
23
+ function copyDirWithFilter(
24
+ src: string,
25
+ dest: string,
26
+ options: { base?: string; shouldExcludePath?: (relativePath: string) => boolean } = {},
27
+ ): void {
24
28
  if (!existsSync(src)) return
25
29
 
30
+ const { base = src, shouldExcludePath = shouldExclude } = options
26
31
  mkdirSync(dest, { recursive: true })
27
32
  for (const entry of readdirSync(src, { withFileTypes: true })) {
28
33
  const srcPath = join(src, entry.name)
29
34
  const relativePath = srcPath.slice(base.length + 1).replace(/\\/g, '/')
30
- if (shouldExclude(relativePath)) continue
35
+ if (shouldExcludePath(relativePath)) continue
31
36
 
32
37
  const destPath = join(dest, entry.name)
33
38
  if (entry.isDirectory()) {
34
- copyDirWithFilter(srcPath, destPath, base)
39
+ copyDirWithFilter(srcPath, destPath, { base, shouldExcludePath })
35
40
  continue
36
41
  }
37
42
 
@@ -51,6 +56,12 @@ function resetAutomationReports(templateRoot: string): void {
51
56
  mkdirSync(join(reportsRoot, 'traces'), { recursive: true })
52
57
  }
53
58
 
59
+ function resetAutomationLocatorMap(templateRoot: string): void {
60
+ const locatorMapPath = join(templateRoot, 'automation', 'mapping', 'locator-map.json')
61
+ mkdirSync(dirname(locatorMapPath), { recursive: true })
62
+ writeFileSync(locatorMapPath, '[]\n')
63
+ }
64
+
54
65
  function syncLegacyEnvironmentConfig(): void {
55
66
  const legacyEnvironmentsDir = join(repoRoot, 'src', 'tests', 'config', 'environments')
56
67
  const targetEnvironmentsDir = join(target, 'automation', 'config', 'environments')
@@ -65,22 +76,46 @@ function syncLegacyEnvironmentConfig(): void {
65
76
  console.log('Backfilled automation/config/environments from legacy src/tests config.')
66
77
  }
67
78
 
68
- function syncCucumberRuntimePackage(): void {
69
- const runtimeTarget = join(target, 'packages', 'cucumber-runtime')
70
- rmSync(runtimeTarget, { recursive: true, force: true })
71
- mkdirSync(runtimeTarget, { recursive: true })
79
+ type InternalPackageSyncConfig = {
80
+ name: string
81
+ directories: string[]
82
+ }
83
+
84
+ const INTERNAL_PACKAGES: InternalPackageSyncConfig[] = [
85
+ { name: 'cucumber-runtime', directories: ['src'] },
86
+ { name: 'locator-picker-companion', directories: ['src', 'dist'] },
87
+ ]
88
+
89
+ function syncInternalPackage({ name, directories }: InternalPackageSyncConfig): void {
90
+ const packageRoot = join(repoRoot, 'packages', name)
91
+ const packageTarget = join(target, 'packages', name)
92
+
93
+ rmSync(packageTarget, { recursive: true, force: true })
94
+ mkdirSync(packageTarget, { recursive: true })
95
+
96
+ copyFile(join(packageRoot, 'package.json'), join(packageTarget, 'package.json'))
97
+ copyFile(join(packageRoot, 'tsconfig.json'), join(packageTarget, 'tsconfig.json'))
72
98
 
73
- copyFile(join(repoRoot, 'packages', 'cucumber-runtime', 'package.json'), join(runtimeTarget, 'package.json'))
74
- copyFile(join(repoRoot, 'packages', 'cucumber-runtime', 'tsconfig.json'), join(runtimeTarget, 'tsconfig.json'))
75
- copyDirWithFilter(join(repoRoot, 'packages', 'cucumber-runtime', 'src'), join(runtimeTarget, 'src'))
99
+ const shouldExcludeInternalPackagePath = (relativePath: string): boolean => {
100
+ if (relativePath === 'dist' || relativePath.startsWith('dist/')) {
101
+ return false
102
+ }
103
+
104
+ return shouldExclude(relativePath)
105
+ }
106
+
107
+ for (const directory of directories) {
108
+ copyDirWithFilter(join(packageRoot, directory), join(packageTarget, directory), {
109
+ base: packageRoot,
110
+ shouldExcludePath: shouldExcludeInternalPackagePath,
111
+ })
112
+ }
76
113
  }
77
114
 
78
115
  const readmePath = join(target, 'README.md')
79
116
  const appraisejsConfigPath = join(target, 'appraisejs.config.json')
80
117
  const savedReadme = existsSync(readmePath) ? readFileSync(readmePath, 'utf8') : null
81
- const savedAppraisejsConfig = existsSync(appraisejsConfigPath)
82
- ? readFileSync(appraisejsConfigPath, 'utf8')
83
- : null
118
+ const savedAppraisejsConfig = existsSync(appraisejsConfigPath) ? readFileSync(appraisejsConfigPath, 'utf8') : null
84
119
 
85
120
  rmSync(target, { recursive: true, force: true })
86
121
  mkdirSync(target, { recursive: true })
@@ -92,9 +127,12 @@ console.log('Copying automation/...')
92
127
  copyDirWithFilter(join(repoRoot, 'automation'), join(target, 'automation'))
93
128
  syncLegacyEnvironmentConfig()
94
129
  resetAutomationReports(target)
130
+ resetAutomationLocatorMap(target)
95
131
 
96
- console.log('Copying cucumber runtime package...')
97
- syncCucumberRuntimePackage()
132
+ for (const internalPackage of INTERNAL_PACKAGES) {
133
+ console.log(`Copying internal package ${internalPackage.name}...`)
134
+ syncInternalPackage(internalPackage)
135
+ }
98
136
 
99
137
  console.log('Copying prisma/...')
100
138
  copyDirWithFilter(join(repoRoot, 'prisma'), join(target, 'prisma'))
@@ -149,13 +187,13 @@ const rootPkg = JSON.parse(readFileSync(join(repoRoot, 'package.json'), 'utf8'))
149
187
  rootPkg.scripts = {
150
188
  ...rootPkg.scripts,
151
189
  build: 'npm run build:local',
152
- 'build:local': 'npm run generate-db-client && npm run build:cucumber-runtime && next build',
190
+ 'build:local':
191
+ 'npm run generate-db-client && npm run build:cucumber-runtime && npm run build:locator-picker-companion && next build',
153
192
  start: 'next start',
154
193
  'generate-db-client': 'npx prisma generate --schema prisma/schema.prisma',
155
194
  'migrate-db': 'npx prisma migrate deploy',
156
195
  'install-playwright': 'npx playwright install',
157
- setup:
158
- 'npm run install-dependencies && npm run setup:db && npm run build:local && npm run protect-seeded-files',
196
+ setup: 'npm run install-dependencies && npm run setup:db && npm run build:local && npm run protect-seeded-files',
159
197
  'setup:db': 'npm run setup-env && npm run generate-db-client && npm run migrate-db && npm run sync-all',
160
198
  'setup:full':
161
199
  'npm run install-dependencies && npm run setup:db && npm run build:local && npm run protect-seeded-files',
@@ -69,15 +69,25 @@ async function readEnvironmentsFromFile(): Promise<Record<string, EnvironmentCon
69
69
  }
70
70
  }
71
71
 
72
- /**
73
- * Normalizes environment name to title case for consistent comparison
74
- * e.g., "staging" -> "Staging", "STAGING" -> "Staging", "Staging" -> "Staging"
75
- */
76
72
  function normalizeEnvironmentName(name: string): string {
77
73
  if (!name || name.trim() === '') {
78
74
  return name
79
75
  }
80
- return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase()
76
+
77
+ return name
78
+ .trim()
79
+ .replace(/[_\s]+/g, ' ')
80
+ .split(' ')
81
+ .filter(Boolean)
82
+ .map(segment => segment.charAt(0).toUpperCase() + segment.slice(1).toLowerCase())
83
+ .join(' ')
84
+ }
85
+
86
+ function getEnvironmentIdentityKey(name: string): string {
87
+ return name
88
+ .trim()
89
+ .replace(/[_\s]+/g, ' ')
90
+ .toLowerCase()
81
91
  }
82
92
 
83
93
  /**
@@ -135,19 +145,20 @@ async function syncEnvironmentsToDatabase(environments: EnvironmentData[]): Prom
135
145
  }
136
146
 
137
147
  // Get set of normalized environment names from JSON file (for case-insensitive comparison)
138
- const jsonEnvironmentNamesNormalized = new Set(
139
- environments.map(env => normalizeEnvironmentName(env.name))
140
- )
148
+ const jsonEnvironmentNamesNormalized = new Set(environments.map(env => getEnvironmentIdentityKey(env.name)))
141
149
 
142
150
  // Get all environments from database
143
151
  const allDbEnvironments = await prisma.environment.findMany({
144
- select: { id: true, name: true },
152
+ select: { id: true, name: true, baseUrl: true, apiBaseUrl: true, username: true, password: true },
145
153
  })
146
154
 
147
155
  // Create a case-insensitive map: normalized name -> actual DB name
148
- const dbEnvironmentsByNormalizedName = new Map<string, { id: string; name: string }>()
156
+ const dbEnvironmentsByNormalizedName = new Map<
157
+ string,
158
+ { id: string; name: string; baseUrl: string; apiBaseUrl: string | null; username: string | null; password: string | null }
159
+ >()
149
160
  for (const dbEnv of allDbEnvironments) {
150
- const normalizedName = normalizeEnvironmentName(dbEnv.name)
161
+ const normalizedName = getEnvironmentIdentityKey(dbEnv.name)
151
162
  // If we find a duplicate normalized name, keep the first one
152
163
  if (!dbEnvironmentsByNormalizedName.has(normalizedName)) {
153
164
  dbEnvironmentsByNormalizedName.set(normalizedName, dbEnv)
@@ -156,7 +167,7 @@ async function syncEnvironmentsToDatabase(environments: EnvironmentData[]): Prom
156
167
 
157
168
  // Delete environments from DB that are not in JSON file (case-insensitive comparison)
158
169
  for (const dbEnv of allDbEnvironments) {
159
- const normalizedDbName = normalizeEnvironmentName(dbEnv.name)
170
+ const normalizedDbName = getEnvironmentIdentityKey(dbEnv.name)
160
171
  if (!jsonEnvironmentNamesNormalized.has(normalizedDbName)) {
161
172
  try {
162
173
  // Check if environment has test runs (foreign key constraint prevents deletion)
@@ -187,23 +198,32 @@ async function syncEnvironmentsToDatabase(environments: EnvironmentData[]): Prom
187
198
  // Create or update environments from JSON file
188
199
  for (const env of environments) {
189
200
  try {
190
- const normalizedName = normalizeEnvironmentName(env.name)
201
+ const normalizedName = getEnvironmentIdentityKey(env.name)
191
202
  // Check if environment already exists by normalized name (case-insensitive)
192
203
  const existingDbEnv = dbEnvironmentsByNormalizedName.get(normalizedName)
193
204
 
194
205
  if (existingDbEnv) {
195
- // Environment exists, check if name needs to be updated to normalized form
196
- if (existingDbEnv.name !== env.name) {
197
- // Update the name to normalized form
206
+ const needsUpdate =
207
+ existingDbEnv.baseUrl !== env.baseUrl ||
208
+ (existingDbEnv.apiBaseUrl ?? null) !== env.apiBaseUrl ||
209
+ (existingDbEnv.username ?? null) !== env.username ||
210
+ (existingDbEnv.password ?? null) !== env.password
211
+
212
+ if (needsUpdate) {
198
213
  await prisma.environment.update({
199
214
  where: { id: existingDbEnv.id },
200
- data: { name: env.name },
215
+ data: {
216
+ baseUrl: env.baseUrl,
217
+ apiBaseUrl: env.apiBaseUrl,
218
+ username: env.username,
219
+ password: env.password,
220
+ },
201
221
  })
202
- console.log(` 🔄 Updated environment name from '${existingDbEnv.name}' to '${env.name}'`)
222
+ console.log(` 🔄 Updated environment '${existingDbEnv.name}'`)
203
223
  }
204
224
  result.environmentsExisting++
205
- result.existingEnvironments.push(env.name)
206
- console.log(` ✓ Environment '${env.name}' already exists`)
225
+ result.existingEnvironments.push(existingDbEnv.name)
226
+ console.log(` ✓ Environment '${existingDbEnv.name}' already exists`)
207
227
  } else {
208
228
  // Create the environment
209
229
  await prisma.environment.create({
@@ -323,4 +343,3 @@ main()
323
343
 
324
344
 
325
345
 
326
-