create-appraisejs 0.3.1-alpha.0 → 0.4.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (577) hide show
  1. package/README.md +17 -17
  2. package/dist/config.d.ts.map +1 -1
  3. package/dist/config.js.map +1 -1
  4. package/dist/prepare-template-utils.d.ts.map +1 -1
  5. package/dist/prepare-template-utils.js.map +1 -1
  6. package/dist/prompts.d.ts.map +1 -1
  7. package/dist/prompts.js +2 -2
  8. package/dist/prompts.js.map +1 -1
  9. package/dist/sync-templates-utils.d.ts.map +1 -1
  10. package/dist/sync-templates-utils.js +1 -5
  11. package/dist/sync-templates-utils.js.map +1 -1
  12. package/package.json +1 -1
  13. package/templates/blank/.editorconfig +11 -0
  14. package/templates/blank/.env.example +2 -2
  15. package/templates/blank/.gitattributes +21 -0
  16. package/templates/blank/.gitconfig.appraise +14 -0
  17. package/templates/blank/.prettierrc +13 -0
  18. package/templates/blank/.vscode/settings.json +2 -0
  19. package/templates/blank/README.md +12 -12
  20. package/templates/blank/components.json +24 -24
  21. package/templates/blank/cucumber.mjs +27 -16
  22. package/templates/blank/e2e/README.md +56 -0
  23. package/templates/blank/e2e/apply-migrations.mjs +76 -0
  24. package/templates/blank/e2e/appraise-smoke.spec.ts +78 -0
  25. package/templates/blank/e2e/authoring.spec.ts +53 -0
  26. package/templates/blank/e2e/crud-configuration.spec.ts +138 -0
  27. package/templates/blank/e2e/crud-tests.spec.ts +76 -0
  28. package/templates/blank/e2e/helpers/forms.ts +186 -0
  29. package/templates/blank/e2e/helpers/navigation.ts +27 -0
  30. package/templates/blank/e2e/helpers/table.ts +45 -0
  31. package/templates/blank/e2e/helpers/test-data.ts +559 -0
  32. package/templates/blank/e2e/helpers/ui.ts +41 -0
  33. package/templates/blank/e2e/navigation.spec.ts +101 -0
  34. package/templates/blank/e2e/runs-and-reports.spec.ts +82 -0
  35. package/templates/blank/e2e/settings-sync.spec.ts +39 -0
  36. package/templates/blank/e2e/start-server.mjs +61 -0
  37. package/templates/blank/eslint.config.mjs +4 -4
  38. package/templates/blank/gitignore +0 -3
  39. package/templates/blank/next-env.d.ts +6 -6
  40. package/templates/blank/package-lock.json +60 -104
  41. package/templates/blank/package.json +11 -10
  42. package/templates/blank/packages/cucumber-runtime/package.json +14 -13
  43. package/templates/blank/packages/cucumber-runtime/src/cache.util.ts +93 -93
  44. package/templates/blank/packages/cucumber-runtime/src/cli.ts +77 -68
  45. package/templates/blank/packages/cucumber-runtime/src/environment.util.ts +21 -21
  46. package/templates/blank/packages/cucumber-runtime/src/executor.ts +32 -32
  47. package/templates/blank/packages/cucumber-runtime/src/index.ts +17 -17
  48. package/templates/blank/packages/cucumber-runtime/src/locator.util.ts +234 -234
  49. package/templates/blank/packages/cucumber-runtime/src/parameter-types.ts +7 -7
  50. package/templates/blank/packages/cucumber-runtime/src/paths.ts +22 -5
  51. package/templates/blank/packages/cucumber-runtime/src/random-data.util.ts +35 -35
  52. package/templates/blank/packages/cucumber-runtime/src/types.ts +13 -13
  53. package/templates/blank/packages/cucumber-runtime/src/world.ts +44 -44
  54. package/templates/blank/packages/cucumber-runtime/tsconfig.json +11 -11
  55. package/templates/blank/packages/locator-picker-companion/dist/cli.js +1 -1
  56. package/templates/blank/packages/locator-picker-companion/dist/index.d.ts +3 -3
  57. package/templates/blank/packages/locator-picker-companion/dist/index.js +3 -3
  58. package/templates/blank/packages/locator-picker-companion/dist/injected-picker-script.js +13 -3
  59. package/templates/blank/packages/locator-picker-companion/dist/selector-generator.d.ts +6 -3
  60. package/templates/blank/packages/locator-picker-companion/dist/selector-generator.js +233 -229
  61. package/templates/blank/packages/locator-picker-companion/package.json +2 -1
  62. package/templates/blank/packages/locator-picker-companion/src/cli.ts +1 -7
  63. package/templates/blank/packages/locator-picker-companion/src/injected-picker-script.ts +26 -5
  64. package/templates/blank/packages/locator-picker-companion/src/launcher.ts +1 -3
  65. package/templates/blank/packages/locator-picker-companion/src/session-file.ts +4 -15
  66. package/templates/blank/packages/locator-picker-companion/src/types.ts +1 -8
  67. package/templates/blank/playwright.config.ts +46 -0
  68. package/templates/blank/postcss.config.mjs +8 -8
  69. package/templates/blank/prisma/dev.db +0 -0
  70. package/templates/blank/prisma/migrations/20251104113456_add_type_for_template_step_groups/migration.sql +16 -16
  71. package/templates/blank/prisma/migrations/20251104170946_add_tags_to_test_suite_and_test_case/migration.sql +27 -27
  72. package/templates/blank/prisma/migrations/20251112190024_add_cascade_delete_to_test_run_test_case/migration.sql +17 -17
  73. package/templates/blank/prisma/migrations/20251113181100_add_test_run_log/migration.sql +12 -12
  74. package/templates/blank/prisma/migrations/20251119191838_add_tag_type/migration.sql +28 -28
  75. package/templates/blank/prisma/migrations/20251121164059_add_conflict_resolution/migration.sql +12 -12
  76. package/templates/blank/prisma/migrations/20251223183400_add_report_model_to_db_schema/migration.sql +10 -10
  77. package/templates/blank/prisma/migrations/20251223183637_add_report_test_case_entity_for_storing_test_results_for_individual_test_cases/migration.sql +10 -10
  78. package/templates/blank/prisma/migrations/20251224083549_add_comprehensive_report_storage/migration.sql +108 -108
  79. package/templates/blank/prisma/migrations/20251229194422_migrate_duration_to_string/migration.sql +55 -55
  80. package/templates/blank/prisma/migrations/20251230124637_add_unique_constraint_to_test_run_name/migration.sql +27 -27
  81. package/templates/blank/prisma/migrations/20260115094436_add_dashboard_metrics/migration.sql +59 -59
  82. package/templates/blank/prisma/migrations/20260127172022_add_cascade_delete_to_step_parameters/migration.sql +34 -34
  83. package/templates/blank/prisma/migrations/20260313093000_add_report_step_screenshot_path/migration.sql +1 -1
  84. package/templates/blank/scripts/configure-git-line-endings.mjs +91 -0
  85. package/templates/blank/scripts/install-template-step.ts +5 -1
  86. package/templates/blank/scripts/lib/step-matcher.test.ts +3 -3
  87. package/templates/blank/scripts/lib/step-matcher.ts +5 -1
  88. package/templates/blank/scripts/lib/template-step-installer.test.ts +4 -2
  89. package/templates/blank/scripts/lib/template-step-installer.ts +16 -4
  90. package/templates/blank/scripts/lib/template-step-registry.test.ts +1 -1
  91. package/templates/blank/scripts/lib/template-step-registry.ts +4 -1
  92. package/templates/blank/scripts/run-fallow-commit.mjs +4 -6
  93. package/templates/blank/scripts/setup-env.ts +0 -0
  94. package/templates/blank/scripts/sync-all.ts +7 -6
  95. package/templates/blank/scripts/sync-appraise-base-template.ts +84 -77
  96. package/templates/blank/scripts/sync-environments.ts +47 -44
  97. package/templates/blank/scripts/sync-locator-groups.ts +67 -76
  98. package/templates/blank/scripts/sync-locators.ts +50 -53
  99. package/templates/blank/scripts/sync-modules.ts +42 -42
  100. package/templates/blank/scripts/sync-tags.ts +51 -51
  101. package/templates/blank/scripts/sync-template-step-groups.ts +34 -32
  102. package/templates/blank/scripts/sync-template-steps.ts +97 -97
  103. package/templates/blank/scripts/sync-test-cases.ts +125 -84
  104. package/templates/blank/scripts/sync-test-suites.ts +85 -80
  105. package/templates/blank/src/actions/server-action-boundary.test.ts +1 -7
  106. package/templates/blank/src/actions/settings/sync-actions.ts +3 -1
  107. package/templates/blank/src/actions/tags/tag-actions.ts +1 -7
  108. package/templates/blank/src/actions/template-test-case/template-test-case-actions.ts +3 -1
  109. package/templates/blank/src/app/(base)/environments/create/page.tsx +28 -28
  110. package/templates/blank/src/app/(base)/environments/environment-form.tsx +3 -2
  111. package/templates/blank/src/app/(base)/environments/environment-helpers.ts +4 -1
  112. package/templates/blank/src/app/(base)/layout.tsx +10 -10
  113. package/templates/blank/src/app/(base)/locator-groups/locator-group-form.tsx +5 -3
  114. package/templates/blank/src/app/(base)/locator-groups/locator-group-table-columns.tsx +77 -77
  115. package/templates/blank/src/app/(base)/locator-groups/locator-group-table.tsx +28 -28
  116. package/templates/blank/src/app/(base)/locator-groups/modify/[id]/page.tsx +46 -46
  117. package/templates/blank/src/app/(base)/locator-groups/page.tsx +9 -19
  118. package/templates/blank/src/app/(base)/locators/create/create-locator-workspace-helpers.test.ts +3 -6
  119. package/templates/blank/src/app/(base)/locators/create/create-locator-workspace-response.ts +22 -5
  120. package/templates/blank/src/app/(base)/locators/create/create-locator-workspace-state.ts +5 -1
  121. package/templates/blank/src/app/(base)/locators/create/use-locator-workspace.ts +7 -2
  122. package/templates/blank/src/app/(base)/locators/locator-file-sync.ts +1 -5
  123. package/templates/blank/src/app/(base)/locators/locator-helpers.ts +2 -12
  124. package/templates/blank/src/app/(base)/locators/locator-table-columns.tsx +59 -60
  125. package/templates/blank/src/app/(base)/modules/module-form.tsx +3 -1
  126. package/templates/blank/src/app/(base)/reports/overview-chart.tsx +49 -49
  127. package/templates/blank/src/app/(base)/reports/test-cases/test-cases-metric-table-columns.tsx +114 -115
  128. package/templates/blank/src/app/(base)/reports/test-cases/test-cases-metric-table.tsx +27 -27
  129. package/templates/blank/src/app/(base)/reports/test-suites/test-suites-metric-table-columns.tsx +80 -79
  130. package/templates/blank/src/app/(base)/reports/test-suites/test-suites-metric-table.tsx +29 -27
  131. package/templates/blank/src/app/(base)/settings/settings-sync-panel-helpers.test.tsx +4 -6
  132. package/templates/blank/src/app/(base)/settings/settings-sync-panel.tsx +22 -23
  133. package/templates/blank/src/app/(base)/tags/tag-form.test.tsx +2 -10
  134. package/templates/blank/src/app/(base)/tags/tag-form.tsx +5 -3
  135. package/templates/blank/src/app/(base)/tags/tag-table-columns.tsx +63 -63
  136. package/templates/blank/src/app/(base)/tags/tag-table.tsx +29 -29
  137. package/templates/blank/src/app/(base)/template-step-groups/create/page.tsx +28 -28
  138. package/templates/blank/src/app/(base)/template-step-groups/template-step-group-form.tsx +3 -1
  139. package/templates/blank/src/app/(base)/template-step-groups/template-step-group-helpers.ts +4 -1
  140. package/templates/blank/src/app/(base)/template-steps/paramChip.tsx +6 -10
  141. package/templates/blank/src/app/(base)/template-steps/template-step-form-helpers.ts +4 -2
  142. package/templates/blank/src/app/(base)/template-steps/template-step-helpers.test.ts +19 -1
  143. package/templates/blank/src/app/(base)/template-steps/template-step-helpers.ts +1 -5
  144. package/templates/blank/src/app/(base)/template-steps/template-step-row-guards.ts +1 -5
  145. package/templates/blank/src/app/(base)/template-steps/template-step-types.ts +1 -5
  146. package/templates/blank/src/app/(base)/template-test-cases/create-template-test-case-page-data.test.ts +4 -1
  147. package/templates/blank/src/app/(base)/template-test-cases/create-template-test-case-page-data.ts +1 -2
  148. package/templates/blank/src/app/(base)/template-test-cases/modify/[id]/page.tsx +1 -0
  149. package/templates/blank/src/app/(base)/template-test-cases/template-test-case-flow.test.tsx +0 -1
  150. package/templates/blank/src/app/(base)/template-test-cases/template-test-case-form.tsx +3 -1
  151. package/templates/blank/src/app/(base)/template-test-cases/template-test-case-table-columns.tsx +76 -76
  152. package/templates/blank/src/app/(base)/template-test-cases/template-test-case-table.tsx +32 -32
  153. package/templates/blank/src/app/(base)/test-cases/create/page.tsx +1 -5
  154. package/templates/blank/src/app/(base)/test-cases/create-from-template/create-from-template-selection-helpers.ts +1 -4
  155. package/templates/blank/src/app/(base)/test-cases/create-from-template/page.test.tsx +2 -2
  156. package/templates/blank/src/app/(base)/test-cases/inline-tag-creation-dialog.tsx +1 -7
  157. package/templates/blank/src/app/(base)/test-cases/inline-test-suite-creation-dialog.tsx +1 -7
  158. package/templates/blank/src/app/(base)/test-cases/modify/[id]/page.tsx +1 -5
  159. package/templates/blank/src/app/(base)/test-cases/test-case-form.tsx +63 -78
  160. package/templates/blank/src/app/(base)/test-cases/test-case-route-helpers.test.ts +2 -7
  161. package/templates/blank/src/app/(base)/test-suites/editable-test-suite-helpers.ts +1 -6
  162. package/templates/blank/src/app/(base)/test-suites/test-suite-form.test.tsx +2 -10
  163. package/templates/blank/src/app/(dashboard-components)/data-card-grid.tsx +10 -10
  164. package/templates/blank/src/app/api/test-runs/[runId]/download/route.ts +1 -4
  165. package/templates/blank/src/app/api/test-runs/[runId]/trace/[testCaseId]/route.test.ts +18 -9
  166. package/templates/blank/src/assets/icons/empty-tube.tsx +23 -23
  167. package/templates/blank/src/assets/icons/tube-plus.tsx +29 -29
  168. package/templates/blank/src/components/data-visualization/info-card.tsx +56 -70
  169. package/templates/blank/src/components/data-visualization/info-grid.tsx +22 -22
  170. package/templates/blank/src/components/diagram/add-node-prompt-node.tsx +1 -1
  171. package/templates/blank/src/components/diagram/dynamic-parameters-helpers.ts +4 -3
  172. package/templates/blank/src/components/diagram/dynamic-parameters.test.tsx +4 -1
  173. package/templates/blank/src/components/diagram/dynamic-parameters.tsx +0 -1
  174. package/templates/blank/src/components/diagram/flow-diagram-block-dialog.test.tsx +26 -0
  175. package/templates/blank/src/components/diagram/flow-diagram-block-dialog.tsx +3 -1
  176. package/templates/blank/src/components/diagram/flow-diagram-connection-guards.ts +24 -6
  177. package/templates/blank/src/components/diagram/flow-diagram-helpers.test.ts +27 -0
  178. package/templates/blank/src/components/diagram/flow-diagram-node-search.tsx +73 -66
  179. package/templates/blank/src/components/diagram/flow-diagram-toolbar.tsx +35 -3
  180. package/templates/blank/src/components/diagram/flow-diagram-view.tsx +1 -7
  181. package/templates/blank/src/components/diagram/flow-diagram.test.tsx +225 -0
  182. package/templates/blank/src/components/diagram/flow-node-data-helpers.ts +1 -1
  183. package/templates/blank/src/components/diagram/node-form-fields-content.tsx +9 -2
  184. package/templates/blank/src/components/diagram/node-form-helpers.test.ts +3 -1
  185. package/templates/blank/src/components/diagram/node-form-helpers.ts +1 -4
  186. package/templates/blank/src/components/diagram/node-form-template-step-selection.ts +1 -4
  187. package/templates/blank/src/components/diagram/node-form.test.tsx +25 -0
  188. package/templates/blank/src/components/diagram/node-form.tsx +2 -12
  189. package/templates/blank/src/components/diagram/options-header-node.test.tsx +4 -1
  190. package/templates/blank/src/components/diagram/options-header-node.tsx +140 -130
  191. package/templates/blank/src/components/diagram/use-flow-diagram-search.ts +2 -0
  192. package/templates/blank/src/components/diagram/use-flow-diagram.ts +93 -1
  193. package/templates/blank/src/components/form/error-message.tsx +7 -7
  194. package/templates/blank/src/components/loading-skeleton/form/button-skeleton.tsx +8 -8
  195. package/templates/blank/src/components/loading-skeleton/form/text-input-skeleton.tsx +8 -8
  196. package/templates/blank/src/components/loading-skeleton/visualization/table-skeleton.tsx +14 -14
  197. package/templates/blank/src/components/navigation/entity-search-command.tsx +3 -9
  198. package/templates/blank/src/components/navigation/nav-link.tsx +60 -60
  199. package/templates/blank/src/components/test-case/test-case-form-helpers.test.ts +1 -5
  200. package/templates/blank/src/components/test-case/test-case-form-helpers.ts +1 -5
  201. package/templates/blank/src/components/test-case/test-case-picker-helpers.ts +8 -7
  202. package/templates/blank/src/components/test-case/test-case-picker.tsx +2 -6
  203. package/templates/blank/src/components/test-run/log-viewer.test.tsx +25 -0
  204. package/templates/blank/src/components/test-run/log-viewer.tsx +2 -2
  205. package/templates/blank/src/components/test-run/test-run-details-guards.ts +10 -1
  206. package/templates/blank/src/components/test-run/test-run-details.test.tsx +9 -19
  207. package/templates/blank/src/components/test-run/use-log-viewer.ts +2 -8
  208. package/templates/blank/src/components/test-run/use-test-run-header.ts +1 -4
  209. package/templates/blank/src/components/test-suite/test-suite-picker.tsx +1 -1
  210. package/templates/blank/src/components/theme/theme-provider.tsx +7 -1
  211. package/templates/blank/src/components/typography/page-header-subtitle.tsx +7 -7
  212. package/templates/blank/src/components/typography/page-header.tsx +7 -7
  213. package/templates/blank/src/components/ui/chart.tsx +2 -8
  214. package/templates/blank/src/components/ui/command.tsx +2 -5
  215. package/templates/blank/src/components/ui/data-table-column-header.tsx +3 -3
  216. package/templates/blank/src/components/ui/data-table.test.tsx +1 -8
  217. package/templates/blank/src/components/ui/dialog.tsx +1 -4
  218. package/templates/blank/src/components/ui/select.tsx +2 -2
  219. package/templates/blank/src/components/ui/separator.tsx +5 -1
  220. package/templates/blank/src/components/ui/skeleton.tsx +7 -7
  221. package/templates/blank/src/components/ui/table.tsx +1 -1
  222. package/templates/blank/src/components/ui/toaster.tsx +26 -26
  223. package/templates/blank/src/components/ui/tooltip.tsx +1 -1
  224. package/templates/blank/src/constants/form-opts/locator-group-form-opts.ts +1 -1
  225. package/templates/blank/src/lib/appraise-test-case-metadata.test.ts +78 -0
  226. package/templates/blank/src/lib/appraise-test-case-metadata.ts +220 -0
  227. package/templates/blank/src/lib/automation/automation-path-roots.test.ts +14 -0
  228. package/templates/blank/src/lib/automation/automation-path-roots.ts +10 -2
  229. package/templates/blank/src/lib/database-sync.ts +166 -15
  230. package/templates/blank/src/lib/executor/local-executor-adapter.ts +6 -2
  231. package/templates/blank/src/lib/feature-file-generator.ts +54 -10
  232. package/templates/blank/src/lib/gherkin-parser.test.ts +52 -0
  233. package/templates/blank/src/lib/gherkin-parser.ts +39 -1
  234. package/templates/blank/src/lib/locator-group-file-utils.ts +5 -1
  235. package/templates/blank/src/lib/locator-picker/session-manager.ts +1 -2
  236. package/templates/blank/src/lib/metrics/metric-calculator.test.ts +105 -6
  237. package/templates/blank/src/lib/metrics/metric-calculator.ts +39 -40
  238. package/templates/blank/src/lib/sync/projected-feature-utils.ts +5 -1
  239. package/templates/blank/src/lib/sync/sync-executor.ts +1 -4
  240. package/templates/blank/src/lib/sync/sync-pending-counts.test.ts +316 -7
  241. package/templates/blank/src/lib/sync/sync-pending-counts.ts +189 -26
  242. package/templates/blank/src/lib/template-automation-paths.ts +1 -1
  243. package/templates/blank/src/lib/template-sync-utils.d.ts +14 -7
  244. package/templates/blank/src/lib/test-case-utils.ts +6 -6
  245. package/templates/blank/src/lib/test-run/log-formatter.ts +82 -83
  246. package/templates/blank/src/lib/test-run/report-parser.ts +352 -352
  247. package/templates/blank/src/lib/transformers/gherkin-converter.ts +42 -42
  248. package/templates/blank/src/lib/transformers/key-to-icon-transformer.tsx +95 -95
  249. package/templates/blank/src/lib/utils/node-param-validation.ts +81 -81
  250. package/templates/blank/src/lib/utils/template-step-file-generator.ts +5 -3
  251. package/templates/blank/src/lib/utils/template-step-file-manager-intelligent.ts +11 -1
  252. package/templates/blank/src/services/dashboard/dashboard-service.test.ts +28 -1
  253. package/templates/blank/src/services/dashboard/dashboard-service.ts +2 -0
  254. package/templates/blank/src/services/locator/locator-service.test.ts +1 -3
  255. package/templates/blank/src/services/locator/locator-service.ts +3 -1
  256. package/templates/blank/src/services/locator/locator-sync-utils.test.ts +1 -4
  257. package/templates/blank/src/services/module/module-service.ts +1 -4
  258. package/templates/blank/src/services/report/report-service.test.ts +70 -6
  259. package/templates/blank/src/services/report/report-service.ts +52 -9
  260. package/templates/blank/src/services/shared/errors.ts +2 -4
  261. package/templates/blank/src/services/template-step/template-step-service.ts +3 -1
  262. package/templates/blank/src/services/template-step-group/template-step-group-service.ts +3 -1
  263. package/templates/blank/src/services/test-case/test-case-service.ts +0 -5
  264. package/templates/blank/src/services/test-run/test-run-service.test.ts +13 -6
  265. package/templates/blank/src/services/test-run/test-run-service.ts +53 -8
  266. package/templates/blank/src/services/test-suite/test-suite-service.test.ts +1 -5
  267. package/templates/blank/src/services/test-suite/test-suite-service.ts +2 -4
  268. package/templates/blank/src/types/form/actionHandler.ts +1 -5
  269. package/templates/blank/tsconfig.json +8 -8
  270. package/templates/starter/.editorconfig +11 -0
  271. package/templates/starter/.env.example +2 -2
  272. package/templates/starter/.gitattributes +21 -0
  273. package/templates/starter/.gitconfig.appraise +14 -0
  274. package/templates/starter/.prettierrc +13 -0
  275. package/templates/starter/.vscode/settings.json +2 -0
  276. package/templates/starter/README.md +12 -12
  277. package/templates/starter/automation/steps/actions/click.step.ts +56 -58
  278. package/templates/starter/automation/steps/actions/hover.step.ts +25 -27
  279. package/templates/starter/automation/steps/actions/input.step.ts +85 -108
  280. package/templates/starter/automation/steps/actions/navigation.step.ts +67 -70
  281. package/templates/starter/automation/steps/actions/random_data.step.ts +149 -143
  282. package/templates/starter/automation/steps/actions/store.step.ts +69 -1
  283. package/templates/starter/automation/steps/actions/wait.step.ts +84 -1
  284. package/templates/starter/automation/steps/validations/active_state_assertion.step.ts +28 -30
  285. package/templates/starter/automation/steps/validations/navigation_assertion.step.ts +20 -22
  286. package/templates/starter/automation/steps/validations/text_assertion.step.ts +67 -107
  287. package/templates/starter/automation/steps/validations/visibility_assertion.step.ts +24 -26
  288. package/templates/starter/components.json +24 -24
  289. package/templates/starter/cucumber.mjs +27 -16
  290. package/templates/starter/e2e/README.md +56 -0
  291. package/templates/starter/e2e/apply-migrations.mjs +76 -0
  292. package/templates/starter/e2e/appraise-smoke.spec.ts +78 -0
  293. package/templates/starter/e2e/authoring.spec.ts +53 -0
  294. package/templates/starter/e2e/crud-configuration.spec.ts +138 -0
  295. package/templates/starter/e2e/crud-tests.spec.ts +76 -0
  296. package/templates/starter/e2e/helpers/forms.ts +186 -0
  297. package/templates/starter/e2e/helpers/navigation.ts +27 -0
  298. package/templates/starter/e2e/helpers/table.ts +45 -0
  299. package/templates/starter/e2e/helpers/test-data.ts +559 -0
  300. package/templates/starter/e2e/helpers/ui.ts +41 -0
  301. package/templates/starter/e2e/navigation.spec.ts +101 -0
  302. package/templates/starter/e2e/runs-and-reports.spec.ts +82 -0
  303. package/templates/starter/e2e/settings-sync.spec.ts +39 -0
  304. package/templates/starter/e2e/start-server.mjs +61 -0
  305. package/templates/starter/eslint.config.mjs +4 -4
  306. package/templates/starter/gitignore +0 -3
  307. package/templates/starter/next-env.d.ts +6 -6
  308. package/templates/starter/package-lock.json +60 -104
  309. package/templates/starter/package.json +11 -10
  310. package/templates/starter/packages/cucumber-runtime/package.json +14 -13
  311. package/templates/starter/packages/cucumber-runtime/src/cache.util.ts +93 -93
  312. package/templates/starter/packages/cucumber-runtime/src/cli.ts +77 -68
  313. package/templates/starter/packages/cucumber-runtime/src/environment.util.ts +21 -21
  314. package/templates/starter/packages/cucumber-runtime/src/executor.ts +32 -32
  315. package/templates/starter/packages/cucumber-runtime/src/index.ts +17 -17
  316. package/templates/starter/packages/cucumber-runtime/src/locator.util.ts +234 -234
  317. package/templates/starter/packages/cucumber-runtime/src/parameter-types.ts +7 -7
  318. package/templates/starter/packages/cucumber-runtime/src/paths.ts +22 -5
  319. package/templates/starter/packages/cucumber-runtime/src/random-data.util.ts +35 -35
  320. package/templates/starter/packages/cucumber-runtime/src/types.ts +13 -13
  321. package/templates/starter/packages/cucumber-runtime/src/world.ts +44 -44
  322. package/templates/starter/packages/cucumber-runtime/tsconfig.json +11 -11
  323. package/templates/starter/packages/locator-picker-companion/dist/cli.js +1 -1
  324. package/templates/starter/packages/locator-picker-companion/dist/index.d.ts +3 -3
  325. package/templates/starter/packages/locator-picker-companion/dist/index.js +3 -3
  326. package/templates/starter/packages/locator-picker-companion/dist/injected-picker-script.js +13 -3
  327. package/templates/starter/packages/locator-picker-companion/dist/selector-generator.d.ts +6 -3
  328. package/templates/starter/packages/locator-picker-companion/dist/selector-generator.js +233 -229
  329. package/templates/starter/packages/locator-picker-companion/package.json +2 -1
  330. package/templates/starter/packages/locator-picker-companion/src/cli.ts +1 -7
  331. package/templates/starter/packages/locator-picker-companion/src/injected-picker-script.ts +26 -5
  332. package/templates/starter/packages/locator-picker-companion/src/launcher.ts +1 -3
  333. package/templates/starter/packages/locator-picker-companion/src/session-file.ts +4 -15
  334. package/templates/starter/packages/locator-picker-companion/src/types.ts +1 -8
  335. package/templates/starter/playwright.config.ts +46 -0
  336. package/templates/starter/postcss.config.mjs +8 -8
  337. package/templates/starter/prisma/dev.db +0 -0
  338. package/templates/starter/prisma/migrations/20251104113456_add_type_for_template_step_groups/migration.sql +16 -16
  339. package/templates/starter/prisma/migrations/20251104170946_add_tags_to_test_suite_and_test_case/migration.sql +27 -27
  340. package/templates/starter/prisma/migrations/20251112190024_add_cascade_delete_to_test_run_test_case/migration.sql +17 -17
  341. package/templates/starter/prisma/migrations/20251113181100_add_test_run_log/migration.sql +12 -12
  342. package/templates/starter/prisma/migrations/20251119191838_add_tag_type/migration.sql +28 -28
  343. package/templates/starter/prisma/migrations/20251121164059_add_conflict_resolution/migration.sql +12 -12
  344. package/templates/starter/prisma/migrations/20251223183400_add_report_model_to_db_schema/migration.sql +10 -10
  345. package/templates/starter/prisma/migrations/20251223183637_add_report_test_case_entity_for_storing_test_results_for_individual_test_cases/migration.sql +10 -10
  346. package/templates/starter/prisma/migrations/20251224083549_add_comprehensive_report_storage/migration.sql +108 -108
  347. package/templates/starter/prisma/migrations/20251229194422_migrate_duration_to_string/migration.sql +55 -55
  348. package/templates/starter/prisma/migrations/20251230124637_add_unique_constraint_to_test_run_name/migration.sql +27 -27
  349. package/templates/starter/prisma/migrations/20260115094436_add_dashboard_metrics/migration.sql +59 -59
  350. package/templates/starter/prisma/migrations/20260127172022_add_cascade_delete_to_step_parameters/migration.sql +34 -34
  351. package/templates/starter/prisma/migrations/20260313093000_add_report_step_screenshot_path/migration.sql +1 -1
  352. package/templates/starter/scripts/configure-git-line-endings.mjs +91 -0
  353. package/templates/starter/scripts/install-template-step.ts +5 -1
  354. package/templates/starter/scripts/lib/step-matcher.test.ts +3 -3
  355. package/templates/starter/scripts/lib/step-matcher.ts +5 -1
  356. package/templates/starter/scripts/lib/template-step-installer.test.ts +4 -2
  357. package/templates/starter/scripts/lib/template-step-installer.ts +16 -4
  358. package/templates/starter/scripts/lib/template-step-registry.test.ts +1 -1
  359. package/templates/starter/scripts/lib/template-step-registry.ts +4 -1
  360. package/templates/starter/scripts/run-fallow-commit.mjs +4 -6
  361. package/templates/starter/scripts/setup-env.ts +0 -0
  362. package/templates/starter/scripts/sync-all.ts +7 -6
  363. package/templates/starter/scripts/sync-appraise-base-template.ts +84 -77
  364. package/templates/starter/scripts/sync-environments.ts +47 -44
  365. package/templates/starter/scripts/sync-locator-groups.ts +67 -76
  366. package/templates/starter/scripts/sync-locators.ts +50 -53
  367. package/templates/starter/scripts/sync-modules.ts +42 -42
  368. package/templates/starter/scripts/sync-tags.ts +51 -51
  369. package/templates/starter/scripts/sync-template-step-groups.ts +34 -32
  370. package/templates/starter/scripts/sync-template-steps.ts +97 -97
  371. package/templates/starter/scripts/sync-test-cases.ts +125 -84
  372. package/templates/starter/scripts/sync-test-suites.ts +85 -80
  373. package/templates/starter/src/actions/server-action-boundary.test.ts +1 -7
  374. package/templates/starter/src/actions/settings/sync-actions.ts +3 -1
  375. package/templates/starter/src/actions/tags/tag-actions.ts +1 -7
  376. package/templates/starter/src/actions/template-test-case/template-test-case-actions.ts +3 -1
  377. package/templates/starter/src/app/(base)/environments/create/page.tsx +28 -28
  378. package/templates/starter/src/app/(base)/environments/environment-form.tsx +3 -2
  379. package/templates/starter/src/app/(base)/environments/environment-helpers.ts +4 -1
  380. package/templates/starter/src/app/(base)/layout.tsx +10 -10
  381. package/templates/starter/src/app/(base)/locator-groups/locator-group-form.tsx +5 -3
  382. package/templates/starter/src/app/(base)/locator-groups/locator-group-table-columns.tsx +77 -77
  383. package/templates/starter/src/app/(base)/locator-groups/locator-group-table.tsx +28 -28
  384. package/templates/starter/src/app/(base)/locator-groups/modify/[id]/page.tsx +46 -46
  385. package/templates/starter/src/app/(base)/locator-groups/page.tsx +9 -19
  386. package/templates/starter/src/app/(base)/locators/create/create-locator-workspace-helpers.test.ts +3 -6
  387. package/templates/starter/src/app/(base)/locators/create/create-locator-workspace-response.ts +22 -5
  388. package/templates/starter/src/app/(base)/locators/create/create-locator-workspace-state.ts +5 -1
  389. package/templates/starter/src/app/(base)/locators/create/use-locator-workspace.ts +7 -2
  390. package/templates/starter/src/app/(base)/locators/locator-file-sync.ts +1 -5
  391. package/templates/starter/src/app/(base)/locators/locator-helpers.ts +2 -12
  392. package/templates/starter/src/app/(base)/locators/locator-table-columns.tsx +59 -60
  393. package/templates/starter/src/app/(base)/modules/module-form.tsx +3 -1
  394. package/templates/starter/src/app/(base)/reports/overview-chart.tsx +49 -49
  395. package/templates/starter/src/app/(base)/reports/test-cases/test-cases-metric-table-columns.tsx +114 -115
  396. package/templates/starter/src/app/(base)/reports/test-cases/test-cases-metric-table.tsx +27 -27
  397. package/templates/starter/src/app/(base)/reports/test-suites/test-suites-metric-table-columns.tsx +80 -79
  398. package/templates/starter/src/app/(base)/reports/test-suites/test-suites-metric-table.tsx +29 -27
  399. package/templates/starter/src/app/(base)/settings/settings-sync-panel-helpers.test.tsx +4 -6
  400. package/templates/starter/src/app/(base)/settings/settings-sync-panel.tsx +22 -23
  401. package/templates/starter/src/app/(base)/tags/tag-form.test.tsx +2 -10
  402. package/templates/starter/src/app/(base)/tags/tag-form.tsx +5 -3
  403. package/templates/starter/src/app/(base)/tags/tag-table-columns.tsx +63 -63
  404. package/templates/starter/src/app/(base)/tags/tag-table.tsx +29 -29
  405. package/templates/starter/src/app/(base)/template-step-groups/create/page.tsx +28 -28
  406. package/templates/starter/src/app/(base)/template-step-groups/template-step-group-form.tsx +3 -1
  407. package/templates/starter/src/app/(base)/template-step-groups/template-step-group-helpers.ts +4 -1
  408. package/templates/starter/src/app/(base)/template-steps/paramChip.tsx +6 -10
  409. package/templates/starter/src/app/(base)/template-steps/template-step-form-helpers.ts +4 -2
  410. package/templates/starter/src/app/(base)/template-steps/template-step-helpers.test.ts +19 -1
  411. package/templates/starter/src/app/(base)/template-steps/template-step-helpers.ts +1 -5
  412. package/templates/starter/src/app/(base)/template-steps/template-step-row-guards.ts +1 -5
  413. package/templates/starter/src/app/(base)/template-steps/template-step-types.ts +1 -5
  414. package/templates/starter/src/app/(base)/template-test-cases/create-template-test-case-page-data.test.ts +4 -1
  415. package/templates/starter/src/app/(base)/template-test-cases/create-template-test-case-page-data.ts +1 -2
  416. package/templates/starter/src/app/(base)/template-test-cases/modify/[id]/page.tsx +1 -0
  417. package/templates/starter/src/app/(base)/template-test-cases/template-test-case-flow.test.tsx +0 -1
  418. package/templates/starter/src/app/(base)/template-test-cases/template-test-case-form.tsx +3 -1
  419. package/templates/starter/src/app/(base)/template-test-cases/template-test-case-table-columns.tsx +76 -76
  420. package/templates/starter/src/app/(base)/template-test-cases/template-test-case-table.tsx +32 -32
  421. package/templates/starter/src/app/(base)/test-cases/create/page.tsx +1 -5
  422. package/templates/starter/src/app/(base)/test-cases/create-from-template/create-from-template-selection-helpers.ts +1 -4
  423. package/templates/starter/src/app/(base)/test-cases/create-from-template/page.test.tsx +2 -2
  424. package/templates/starter/src/app/(base)/test-cases/inline-tag-creation-dialog.tsx +1 -7
  425. package/templates/starter/src/app/(base)/test-cases/inline-test-suite-creation-dialog.tsx +1 -7
  426. package/templates/starter/src/app/(base)/test-cases/modify/[id]/page.tsx +1 -5
  427. package/templates/starter/src/app/(base)/test-cases/test-case-form.tsx +63 -78
  428. package/templates/starter/src/app/(base)/test-cases/test-case-route-helpers.test.ts +2 -7
  429. package/templates/starter/src/app/(base)/test-suites/editable-test-suite-helpers.ts +1 -6
  430. package/templates/starter/src/app/(base)/test-suites/test-suite-form.test.tsx +2 -10
  431. package/templates/starter/src/app/(dashboard-components)/data-card-grid.tsx +10 -10
  432. package/templates/starter/src/app/api/test-runs/[runId]/download/route.ts +1 -4
  433. package/templates/starter/src/app/api/test-runs/[runId]/trace/[testCaseId]/route.test.ts +18 -9
  434. package/templates/starter/src/assets/icons/empty-tube.tsx +23 -23
  435. package/templates/starter/src/assets/icons/tube-plus.tsx +29 -29
  436. package/templates/starter/src/components/data-visualization/info-card.tsx +56 -70
  437. package/templates/starter/src/components/data-visualization/info-grid.tsx +22 -22
  438. package/templates/starter/src/components/diagram/add-node-prompt-node.tsx +1 -1
  439. package/templates/starter/src/components/diagram/dynamic-parameters-helpers.ts +4 -3
  440. package/templates/starter/src/components/diagram/dynamic-parameters.test.tsx +4 -1
  441. package/templates/starter/src/components/diagram/dynamic-parameters.tsx +0 -1
  442. package/templates/starter/src/components/diagram/flow-diagram-block-dialog.test.tsx +26 -0
  443. package/templates/starter/src/components/diagram/flow-diagram-block-dialog.tsx +3 -1
  444. package/templates/starter/src/components/diagram/flow-diagram-connection-guards.ts +24 -6
  445. package/templates/starter/src/components/diagram/flow-diagram-helpers.test.ts +27 -0
  446. package/templates/starter/src/components/diagram/flow-diagram-node-search.tsx +73 -66
  447. package/templates/starter/src/components/diagram/flow-diagram-toolbar.tsx +35 -3
  448. package/templates/starter/src/components/diagram/flow-diagram-view.tsx +1 -7
  449. package/templates/starter/src/components/diagram/flow-diagram.test.tsx +225 -0
  450. package/templates/starter/src/components/diagram/flow-node-data-helpers.ts +1 -1
  451. package/templates/starter/src/components/diagram/node-form-fields-content.tsx +9 -2
  452. package/templates/starter/src/components/diagram/node-form-helpers.test.ts +3 -1
  453. package/templates/starter/src/components/diagram/node-form-helpers.ts +1 -4
  454. package/templates/starter/src/components/diagram/node-form-template-step-selection.ts +1 -4
  455. package/templates/starter/src/components/diagram/node-form.test.tsx +25 -0
  456. package/templates/starter/src/components/diagram/node-form.tsx +2 -12
  457. package/templates/starter/src/components/diagram/options-header-node.test.tsx +4 -1
  458. package/templates/starter/src/components/diagram/options-header-node.tsx +140 -130
  459. package/templates/starter/src/components/diagram/use-flow-diagram-search.ts +2 -0
  460. package/templates/starter/src/components/diagram/use-flow-diagram.ts +93 -1
  461. package/templates/starter/src/components/form/error-message.tsx +7 -7
  462. package/templates/starter/src/components/loading-skeleton/form/button-skeleton.tsx +8 -8
  463. package/templates/starter/src/components/loading-skeleton/form/text-input-skeleton.tsx +8 -8
  464. package/templates/starter/src/components/loading-skeleton/visualization/table-skeleton.tsx +14 -14
  465. package/templates/starter/src/components/navigation/entity-search-command.tsx +3 -9
  466. package/templates/starter/src/components/navigation/nav-link.tsx +60 -60
  467. package/templates/starter/src/components/test-case/test-case-form-helpers.test.ts +1 -5
  468. package/templates/starter/src/components/test-case/test-case-form-helpers.ts +1 -5
  469. package/templates/starter/src/components/test-case/test-case-picker-helpers.ts +8 -7
  470. package/templates/starter/src/components/test-case/test-case-picker.tsx +2 -6
  471. package/templates/starter/src/components/test-run/log-viewer.test.tsx +25 -0
  472. package/templates/starter/src/components/test-run/log-viewer.tsx +2 -2
  473. package/templates/starter/src/components/test-run/test-run-details-guards.ts +10 -1
  474. package/templates/starter/src/components/test-run/test-run-details.test.tsx +9 -19
  475. package/templates/starter/src/components/test-run/use-log-viewer.ts +2 -8
  476. package/templates/starter/src/components/test-run/use-test-run-header.ts +1 -4
  477. package/templates/starter/src/components/test-suite/test-suite-picker.tsx +1 -1
  478. package/templates/starter/src/components/theme/theme-provider.tsx +7 -1
  479. package/templates/starter/src/components/typography/page-header-subtitle.tsx +7 -7
  480. package/templates/starter/src/components/typography/page-header.tsx +7 -7
  481. package/templates/starter/src/components/ui/chart.tsx +2 -8
  482. package/templates/starter/src/components/ui/command.tsx +2 -5
  483. package/templates/starter/src/components/ui/data-table-column-header.tsx +3 -3
  484. package/templates/starter/src/components/ui/data-table.test.tsx +1 -8
  485. package/templates/starter/src/components/ui/dialog.tsx +1 -4
  486. package/templates/starter/src/components/ui/select.tsx +2 -2
  487. package/templates/starter/src/components/ui/separator.tsx +5 -1
  488. package/templates/starter/src/components/ui/skeleton.tsx +7 -7
  489. package/templates/starter/src/components/ui/table.tsx +1 -1
  490. package/templates/starter/src/components/ui/toaster.tsx +26 -26
  491. package/templates/starter/src/components/ui/tooltip.tsx +1 -1
  492. package/templates/starter/src/constants/form-opts/locator-group-form-opts.ts +1 -1
  493. package/templates/starter/src/lib/appraise-test-case-metadata.test.ts +78 -0
  494. package/templates/starter/src/lib/appraise-test-case-metadata.ts +220 -0
  495. package/templates/starter/src/lib/automation/automation-path-roots.test.ts +14 -0
  496. package/templates/starter/src/lib/automation/automation-path-roots.ts +10 -2
  497. package/templates/starter/src/lib/database-sync.ts +166 -15
  498. package/templates/starter/src/lib/executor/local-executor-adapter.ts +6 -2
  499. package/templates/starter/src/lib/feature-file-generator.ts +54 -10
  500. package/templates/starter/src/lib/gherkin-parser.test.ts +52 -0
  501. package/templates/starter/src/lib/gherkin-parser.ts +39 -1
  502. package/templates/starter/src/lib/locator-group-file-utils.ts +5 -1
  503. package/templates/starter/src/lib/locator-picker/session-manager.ts +1 -2
  504. package/templates/starter/src/lib/metrics/metric-calculator.test.ts +105 -6
  505. package/templates/starter/src/lib/metrics/metric-calculator.ts +39 -40
  506. package/templates/starter/src/lib/sync/projected-feature-utils.ts +5 -1
  507. package/templates/starter/src/lib/sync/sync-executor.ts +1 -4
  508. package/templates/starter/src/lib/sync/sync-pending-counts.test.ts +316 -7
  509. package/templates/starter/src/lib/sync/sync-pending-counts.ts +189 -26
  510. package/templates/starter/src/lib/template-automation-paths.ts +1 -1
  511. package/templates/starter/src/lib/template-sync-utils.d.ts +14 -7
  512. package/templates/starter/src/lib/test-case-utils.ts +6 -6
  513. package/templates/starter/src/lib/test-run/log-formatter.ts +82 -83
  514. package/templates/starter/src/lib/test-run/report-parser.ts +352 -352
  515. package/templates/starter/src/lib/transformers/gherkin-converter.ts +42 -42
  516. package/templates/starter/src/lib/transformers/key-to-icon-transformer.tsx +95 -95
  517. package/templates/starter/src/lib/utils/node-param-validation.ts +81 -81
  518. package/templates/starter/src/lib/utils/template-step-file-generator.ts +5 -3
  519. package/templates/starter/src/lib/utils/template-step-file-manager-intelligent.ts +11 -1
  520. package/templates/starter/src/services/dashboard/dashboard-service.test.ts +28 -1
  521. package/templates/starter/src/services/dashboard/dashboard-service.ts +2 -0
  522. package/templates/starter/src/services/locator/locator-service.test.ts +1 -3
  523. package/templates/starter/src/services/locator/locator-service.ts +3 -1
  524. package/templates/starter/src/services/locator/locator-sync-utils.test.ts +1 -4
  525. package/templates/starter/src/services/module/module-service.ts +1 -4
  526. package/templates/starter/src/services/report/report-service.test.ts +70 -6
  527. package/templates/starter/src/services/report/report-service.ts +52 -9
  528. package/templates/starter/src/services/shared/errors.ts +2 -4
  529. package/templates/starter/src/services/template-step/template-step-service.ts +3 -1
  530. package/templates/starter/src/services/template-step-group/template-step-group-service.ts +3 -1
  531. package/templates/starter/src/services/test-case/test-case-service.ts +0 -5
  532. package/templates/starter/src/services/test-run/test-run-service.test.ts +13 -6
  533. package/templates/starter/src/services/test-run/test-run-service.ts +53 -8
  534. package/templates/starter/src/services/test-suite/test-suite-service.test.ts +1 -5
  535. package/templates/starter/src/services/test-suite/test-suite-service.ts +2 -4
  536. package/templates/starter/src/types/form/actionHandler.ts +1 -5
  537. package/templates/starter/tsconfig.json +8 -8
  538. package/dist/cli.e2e.test.d.ts +0 -2
  539. package/dist/cli.e2e.test.d.ts.map +0 -1
  540. package/dist/cli.e2e.test.js +0 -73
  541. package/dist/cli.e2e.test.js.map +0 -1
  542. package/dist/config.test.d.ts +0 -2
  543. package/dist/config.test.d.ts.map +0 -1
  544. package/dist/config.test.js +0 -65
  545. package/dist/config.test.js.map +0 -1
  546. package/dist/copy-template.test.d.ts +0 -2
  547. package/dist/copy-template.test.d.ts.map +0 -1
  548. package/dist/copy-template.test.js +0 -71
  549. package/dist/copy-template.test.js.map +0 -1
  550. package/dist/download-repo.test.d.ts +0 -2
  551. package/dist/download-repo.test.d.ts.map +0 -1
  552. package/dist/download-repo.test.js +0 -14
  553. package/dist/download-repo.test.js.map +0 -1
  554. package/dist/install.test.d.ts +0 -2
  555. package/dist/install.test.d.ts.map +0 -1
  556. package/dist/install.test.js +0 -119
  557. package/dist/install.test.js.map +0 -1
  558. package/dist/prompts.test.d.ts +0 -2
  559. package/dist/prompts.test.d.ts.map +0 -1
  560. package/dist/prompts.test.js +0 -58
  561. package/dist/prompts.test.js.map +0 -1
  562. package/templates/default/next-env.d.ts +0 -6
  563. package/templates/default/packages/locator-picker-companion/dist/cli.d.ts +0 -1
  564. package/templates/default/packages/locator-picker-companion/dist/cli.js +0 -302
  565. package/templates/default/packages/locator-picker-companion/dist/index.d.ts +0 -3
  566. package/templates/default/packages/locator-picker-companion/dist/index.js +0 -3
  567. package/templates/default/packages/locator-picker-companion/dist/injected-picker-script.d.ts +0 -1
  568. package/templates/default/packages/locator-picker-companion/dist/injected-picker-script.js +0 -615
  569. package/templates/default/packages/locator-picker-companion/dist/launcher.d.ts +0 -11
  570. package/templates/default/packages/locator-picker-companion/dist/launcher.js +0 -59
  571. package/templates/default/packages/locator-picker-companion/dist/selector-generator.d.ts +0 -3
  572. package/templates/default/packages/locator-picker-companion/dist/selector-generator.js +0 -257
  573. package/templates/default/packages/locator-picker-companion/dist/session-file.d.ts +0 -22
  574. package/templates/default/packages/locator-picker-companion/dist/session-file.js +0 -150
  575. package/templates/default/packages/locator-picker-companion/dist/types.d.ts +0 -31
  576. package/templates/default/packages/locator-picker-companion/dist/types.js +0 -1
  577. package/templates/default/prisma/dev.db +0 -0
@@ -10,11 +10,7 @@
10
10
  */
11
11
 
12
12
  import prisma from '../src/config/db-config'
13
- import {
14
- scanFeatureFiles,
15
- extractModulePathFromFilePath,
16
- ParsedStep,
17
- } from '../src/lib/gherkin-parser'
13
+ import { scanFeatureFiles, extractModulePathFromFilePath, ParsedStep } from '../src/lib/gherkin-parser'
18
14
  import { buildModuleHierarchy, findModuleByPath } from '../src/lib/module-hierarchy-builder'
19
15
  import { StepParameterType, TagType } from '@prisma/client'
20
16
  import { ensureAutomationWorkspaceReady, getAutomationFeaturesDir } from '../src/lib/automation/paths'
@@ -25,11 +21,7 @@ import {
25
21
  } from '../src/lib/sync/projected-feature-utils'
26
22
  import { extractTestSuiteNameFromFilename } from './lib/filename-utils'
27
23
  import { splitTagLine } from './lib/tag-parsing'
28
- import {
29
- determineStepTypeAndIcon,
30
- findMatchingTemplateStep,
31
- sameResolvedParameters,
32
- } from './lib/step-matcher'
24
+ import { determineStepTypeAndIcon, findMatchingTemplateStep, sameResolvedParameters } from './lib/step-matcher'
33
25
  import { printSyncSummary } from './lib/sync-summary'
34
26
  import { runSyncScript } from './lib/sync-script-runner'
35
27
 
@@ -41,6 +33,9 @@ interface TestCaseFromFS {
41
33
  modulePath: string // From folder structure
42
34
  filterTags: string[] // Scenario tags excluding @tc_...
43
35
  steps: ParsedStep[] // From scenario steps
36
+ hasAppraiseMetadata: boolean
37
+ nodes: Array<{ nodeId: string; order: number; label: string }>
38
+ flowBlocks: Array<{ id: string; name: string; order: number; nodeIds: string[] }>
44
39
  filePath: string // Feature file path
45
40
  }
46
41
 
@@ -109,7 +104,8 @@ async function scanTestCasesFromFilesystem(featuresDir: string): Promise<TestCas
109
104
 
110
105
  for (const scenario of parsedFeature.scenarios) {
111
106
  // Find identifier tag (@tc_...)
112
- const identifierTag = scenario.tags.find(tag => {
107
+ const flattenedTags = scenario.tags.flatMap(splitTagLine)
108
+ const identifierTag = flattenedTags.find(tag => {
113
109
  const tagName = tag.startsWith('@') ? tag.substring(1) : tag
114
110
  return tagName.startsWith('tc_')
115
111
  })
@@ -122,20 +118,27 @@ async function scanTestCasesFromFilesystem(featuresDir: string): Promise<TestCas
122
118
  }
123
119
 
124
120
  // Extract filter tags (all tags except identifier tag)
125
- const filterTags = scenario.tags.filter(tag => tag !== identifierTag).flatMap(tag => splitTagLine(tag))
121
+ const filterTags = flattenedTags.filter(tag => tag !== identifierTag)
126
122
 
127
123
  // Parse title and description from scenario name
128
124
  // Note: gherkin parser swaps them, so we pass both
129
- const { title, description } = parseScenarioTitle(scenario.name, scenario.description)
125
+ const parsedTitle = parseScenarioTitle(scenario.name, scenario.description)
126
+ const nodesByOrder = new Map((scenario.appraiseMetadata?.nodes ?? []).map(node => [node.order, node]))
130
127
 
131
128
  testCases.push({
132
129
  identifierTag: identifierTag.startsWith('@') ? identifierTag : `@${identifierTag}`,
133
- title,
134
- description,
130
+ title: scenario.appraiseMetadata?.title ?? parsedTitle.title,
131
+ description: scenario.appraiseMetadata?.description ?? parsedTitle.description,
135
132
  testSuiteName,
136
133
  modulePath,
137
134
  filterTags,
138
- steps: scenario.steps,
135
+ steps: scenario.steps.map(step => ({
136
+ ...step,
137
+ appraiseNode: nodesByOrder.get(step.order),
138
+ })),
139
+ hasAppraiseMetadata: scenario.appraiseMetadata != null,
140
+ nodes: scenario.appraiseMetadata?.nodes ?? [],
141
+ flowBlocks: scenario.appraiseMetadata?.flowBlocks ?? [],
139
142
  filePath: parsedFeature.filePath,
140
143
  })
141
144
  }
@@ -187,10 +190,7 @@ async function findOrCreateTag(tagExpression: string, type: TagType): Promise<st
187
190
  }
188
191
  }
189
192
 
190
- async function deleteTestCaseWithCascade(
191
- testCaseId: string,
192
- identifierTagId?: string,
193
- ): Promise<void> {
193
+ async function deleteTestCaseWithCascade(testCaseId: string, identifierTagId?: string): Promise<void> {
194
194
  // Keep deletes in dependency order to satisfy RESTRICT constraints and
195
195
  // mirror domain-level delete behavior in a single transactional boundary.
196
196
  await prisma.$transaction(async tx => {
@@ -263,7 +263,9 @@ async function syncTestCaseSteps(
263
263
 
264
264
  // Order is the stable identity within a scenario for synchronization.
265
265
  const existingStepsMap = new Map(existingSteps.map(step => [step.order, step]))
266
- const projectedExistingStepsMap = new Map(normalizeProjectedDbTestCaseSteps(existingSteps).map(step => [step.order, step]))
266
+ const projectedExistingStepsMap = new Map(
267
+ normalizeProjectedDbTestCaseSteps(existingSteps).map(step => [step.order, step]),
268
+ )
267
269
 
268
270
  // Process each step from filesystem
269
271
  for (const step of steps) {
@@ -280,13 +282,15 @@ async function syncTestCaseSteps(
280
282
  const existingStep = existingStepsMap.get(step.order)
281
283
  const { icon } = determineStepTypeAndIcon(step.keyword)
282
284
  const gherkinStep = `${step.keyword} ${step.text}`
285
+ const label = step.appraiseNode?.label ?? step.text
283
286
 
284
287
  if (existingStep) {
288
+ const expectedFlowNodeId = step.appraiseNode?.nodeId ?? existingStep.flowNodeId
285
289
  const projectedExistingStep = projectedExistingStepsMap.get(step.order)
286
290
  const matchesProjectedState =
287
291
  projectedExistingStep != null &&
288
292
  projectedExistingStep.gherkinStep === gherkinStep &&
289
- projectedExistingStep.label === step.text &&
293
+ projectedExistingStep.label === label &&
290
294
  projectedExistingStep.icon === determineProjectedStepIcon(step.keyword) &&
291
295
  projectedExistingStep.templateStepSignature === match.signature &&
292
296
  sameResolvedParameters(projectedExistingStep.parameters, match.parameters)
@@ -297,7 +301,8 @@ async function syncTestCaseSteps(
297
301
  !matchesProjectedState &&
298
302
  (existingStep.gherkinStep !== gherkinStep ||
299
303
  existingStep.templateStepId !== match.templateStepId ||
300
- existingStep.label !== step.text ||
304
+ existingStep.flowNodeId !== expectedFlowNodeId ||
305
+ existingStep.label !== label ||
301
306
  existingStep.icon !== icon)
302
307
 
303
308
  if (needsUpdate) {
@@ -305,7 +310,8 @@ async function syncTestCaseSteps(
305
310
  where: { id: existingStep.id },
306
311
  data: {
307
312
  gherkinStep,
308
- label: step.text,
313
+ flowNodeId: expectedFlowNodeId,
314
+ label,
309
315
  templateStepId: match.templateStepId,
310
316
  icon,
311
317
  },
@@ -335,7 +341,8 @@ async function syncTestCaseSteps(
335
341
  testCaseId,
336
342
  order: step.order,
337
343
  gherkinStep,
338
- label: step.text,
344
+ flowNodeId: step.appraiseNode?.nodeId,
345
+ label,
339
346
  icon,
340
347
  templateStepId: match.templateStepId,
341
348
  },
@@ -372,6 +379,38 @@ async function syncTestCaseSteps(
372
379
  }
373
380
  }
374
381
 
382
+ async function syncTestCaseFlowBlocks(testCaseId: string, testCase: TestCaseFromFS): Promise<void> {
383
+ if (!testCase.hasAppraiseMetadata) {
384
+ return
385
+ }
386
+
387
+ const validNodeIds = new Set(testCase.nodes.map(node => node.nodeId))
388
+
389
+ await prisma.testCaseFlowBlock.deleteMany({
390
+ where: { testCaseId },
391
+ })
392
+
393
+ if (testCase.flowBlocks.length === 0) {
394
+ return
395
+ }
396
+
397
+ await prisma.testCase.update({
398
+ where: { id: testCaseId },
399
+ data: {
400
+ flowBlocks: {
401
+ create: testCase.flowBlocks.map(block => ({
402
+ id: block.id,
403
+ name: block.name,
404
+ order: block.order,
405
+ nodes: {
406
+ create: block.nodeIds.filter(nodeId => validNodeIds.has(nodeId)).map(nodeId => ({ flowNodeId: nodeId })),
407
+ },
408
+ })),
409
+ },
410
+ },
411
+ })
412
+ }
413
+
375
414
  type TemplateStepForMatch = Array<{
376
415
  id: string
377
416
  signature: string
@@ -509,6 +548,7 @@ async function upsertTestCase(
509
548
  }
510
549
 
511
550
  await syncTestCaseSteps(existingTestCase.id, testCase.steps, templateSteps, result)
551
+ await syncTestCaseFlowBlocks(existingTestCase.id, testCase)
512
552
  return
513
553
  }
514
554
 
@@ -554,6 +594,7 @@ async function upsertTestCase(
554
594
  console.log(` āž• Created test case '${testCase.title}' (${testCase.identifierTag})`)
555
595
 
556
596
  await syncTestCaseSteps(newTestCase.id, testCase.steps, templateSteps, result)
597
+ await syncTestCaseFlowBlocks(newTestCase.id, testCase)
557
598
  }
558
599
 
559
600
  async function deleteOrphanedTestCases(fsTestCaseTags: Set<string>, result: SyncResult): Promise<void> {
@@ -647,71 +688,71 @@ async function syncTestCasesToDatabase(testCasesFromFS: TestCaseFromFS[], result
647
688
  * Generates and displays sync summary
648
689
  */
649
690
  async function main(): Promise<SyncResult | void> {
650
- console.log('šŸ”„ Starting test cases sync...')
651
- console.log('This will scan feature files and sync test cases to database.')
652
- console.log('Filesystem is the source of truth - test cases in DB but not in FS will be deleted.\n')
691
+ console.log('šŸ”„ Starting test cases sync...')
692
+ console.log('This will scan feature files and sync test cases to database.')
693
+ console.log('Filesystem is the source of truth - test cases in DB but not in FS will be deleted.\n')
653
694
 
654
- await ensureAutomationWorkspaceReady()
655
- const featuresDir = getAutomationFeaturesDir()
695
+ await ensureAutomationWorkspaceReady()
696
+ const featuresDir = getAutomationFeaturesDir()
656
697
 
657
- // Scan test cases from filesystem
658
- const testCasesFromFS = await scanTestCasesFromFilesystem(featuresDir)
698
+ // Scan test cases from filesystem
699
+ const testCasesFromFS = await scanTestCasesFromFilesystem(featuresDir)
659
700
 
660
- if (testCasesFromFS.length === 0) {
661
- console.log('\nāš ļø No test cases found in feature files. Nothing to sync.')
662
- return
663
- }
701
+ if (testCasesFromFS.length === 0) {
702
+ console.log('\nāš ļø No test cases found in feature files. Nothing to sync.')
703
+ return
704
+ }
664
705
 
665
- console.log(`\nšŸ“‹ Found ${testCasesFromFS.length} test case(s) from feature files:`)
666
- for (const tc of testCasesFromFS) {
667
- console.log(` - ${tc.title} (${tc.identifierTag}) in ${tc.testSuiteName}`)
668
- }
706
+ console.log(`\nšŸ“‹ Found ${testCasesFromFS.length} test case(s) from feature files:`)
707
+ for (const tc of testCasesFromFS) {
708
+ console.log(` - ${tc.title} (${tc.identifierTag}) in ${tc.testSuiteName}`)
709
+ }
669
710
 
670
- // Initialize result
671
- const result: SyncResult = {
672
- testCasesScanned: testCasesFromFS.length,
673
- testCasesExisting: 0,
674
- testCasesCreated: 0,
675
- testCasesUpdated: 0,
676
- testCasesDeleted: 0,
677
- errors: [],
678
- warnings: [],
679
- createdTestCases: [],
680
- updatedTestCases: [],
681
- deletedTestCases: [],
682
- }
711
+ // Initialize result
712
+ const result: SyncResult = {
713
+ testCasesScanned: testCasesFromFS.length,
714
+ testCasesExisting: 0,
715
+ testCasesCreated: 0,
716
+ testCasesUpdated: 0,
717
+ testCasesDeleted: 0,
718
+ errors: [],
719
+ warnings: [],
720
+ createdTestCases: [],
721
+ updatedTestCases: [],
722
+ deletedTestCases: [],
723
+ }
683
724
 
684
- // Sync to database
685
- await syncTestCasesToDatabase(testCasesFromFS, result)
686
-
687
- printSyncSummary(
688
- [
689
- { label: 'šŸ“ Test cases scanned', value: result.testCasesScanned },
690
- { label: 'āœ… Test cases existing', value: result.testCasesExisting },
691
- { label: 'āž• Test cases created', value: result.testCasesCreated },
692
- { label: 'šŸ”„ Test cases updated', value: result.testCasesUpdated },
693
- { label: 'šŸ—‘ļø Test cases deleted', value: result.testCasesDeleted },
694
- { label: 'āš ļø Warnings', value: result.warnings.length },
695
- { label: 'āŒ Errors', value: result.errors.length },
696
- ],
697
- [
698
- {
699
- title: 'Created test cases',
700
- items: result.createdTestCases.map(tc => `${tc.title} (${tc.identifierTag})`),
701
- },
702
- {
703
- title: 'Updated test cases',
704
- items: result.updatedTestCases.map(tc => `${tc.title} (${tc.identifierTag})`),
705
- },
706
- {
707
- title: 'Deleted test cases',
708
- items: result.deletedTestCases.map(tc => `${tc.title} (${tc.identifierTag})`),
709
- },
710
- { title: 'Warnings', items: result.warnings },
711
- { title: 'Errors', items: result.errors },
712
- ],
713
- )
714
- return result
725
+ // Sync to database
726
+ await syncTestCasesToDatabase(testCasesFromFS, result)
727
+
728
+ printSyncSummary(
729
+ [
730
+ { label: 'šŸ“ Test cases scanned', value: result.testCasesScanned },
731
+ { label: 'āœ… Test cases existing', value: result.testCasesExisting },
732
+ { label: 'āž• Test cases created', value: result.testCasesCreated },
733
+ { label: 'šŸ”„ Test cases updated', value: result.testCasesUpdated },
734
+ { label: 'šŸ—‘ļø Test cases deleted', value: result.testCasesDeleted },
735
+ { label: 'āš ļø Warnings', value: result.warnings.length },
736
+ { label: 'āŒ Errors', value: result.errors.length },
737
+ ],
738
+ [
739
+ {
740
+ title: 'Created test cases',
741
+ items: result.createdTestCases.map(tc => `${tc.title} (${tc.identifierTag})`),
742
+ },
743
+ {
744
+ title: 'Updated test cases',
745
+ items: result.updatedTestCases.map(tc => `${tc.title} (${tc.identifierTag})`),
746
+ },
747
+ {
748
+ title: 'Deleted test cases',
749
+ items: result.deletedTestCases.map(tc => `${tc.title} (${tc.identifierTag})`),
750
+ },
751
+ { title: 'Warnings', items: result.warnings },
752
+ { title: 'Errors', items: result.errors },
753
+ ],
754
+ )
755
+ return result
715
756
  }
716
757
 
717
758
  runSyncScript(main)
@@ -49,14 +49,14 @@ type DbTestSuiteWithModule = Prisma.TestSuiteGetPayload<{ include: { module: tru
49
49
  */
50
50
  function extractFeatureLevelTags(parsedFeature: ParsedFeature): string[] {
51
51
  const tags: string[] = []
52
-
52
+
53
53
  for (const tagLine of parsedFeature.tags) {
54
54
  if (tagLine.startsWith('@')) {
55
55
  const splitTags = splitTagLine(tagLine)
56
56
  tags.push(...splitTags)
57
57
  }
58
58
  }
59
-
59
+
60
60
  return tags
61
61
  }
62
62
 
@@ -65,17 +65,17 @@ function extractFeatureLevelTags(parsedFeature: ParsedFeature): string[] {
65
65
  */
66
66
  async function scanTestSuitesFromFilesystem(featuresDir: string): Promise<TestSuiteFromFS[]> {
67
67
  const testSuites: TestSuiteFromFS[] = []
68
-
68
+
69
69
  console.log('šŸ“ Scanning feature files...')
70
70
  const parsedFeatures = await scanFeatureFiles(featuresDir)
71
71
  console.log(` Found ${parsedFeatures.length} feature file(s)`)
72
-
72
+
73
73
  for (const parsedFeature of parsedFeatures) {
74
74
  try {
75
75
  const testSuiteName = extractTestSuiteNameFromFilename(parsedFeature.filePath)
76
76
  const modulePath = extractModulePathFromFilePath(parsedFeature.filePath, featuresDir)
77
77
  const tags = extractFeatureLevelTags(parsedFeature)
78
-
78
+
79
79
  testSuites.push({
80
80
  name: testSuiteName,
81
81
  description: parsedFeature.featureDescription || null,
@@ -87,7 +87,7 @@ async function scanTestSuitesFromFilesystem(featuresDir: string): Promise<TestSu
87
87
  console.error(` āŒ Error processing feature file '${parsedFeature.filePath}': ${error}`)
88
88
  }
89
89
  }
90
-
90
+
91
91
  return testSuites
92
92
  }
93
93
 
@@ -97,13 +97,13 @@ async function scanTestSuitesFromFilesystem(featuresDir: string): Promise<TestSu
97
97
  */
98
98
  async function findTagIdsByExpressions(tagExpressions: string[]): Promise<string[]> {
99
99
  const tagIds: string[] = []
100
-
100
+
101
101
  for (const tagExpression of tagExpressions) {
102
102
  try {
103
103
  const tag = await prisma.tag.findFirst({
104
104
  where: { tagExpression },
105
105
  })
106
-
106
+
107
107
  if (tag) {
108
108
  tagIds.push(tag.id)
109
109
  } else {
@@ -113,7 +113,7 @@ async function findTagIdsByExpressions(tagExpressions: string[]): Promise<string
113
113
  console.error(` āŒ Error finding tag '${tagExpression}': ${error}`)
114
114
  }
115
115
  }
116
-
116
+
117
117
  return tagIds
118
118
  }
119
119
 
@@ -128,7 +128,10 @@ async function resolveModuleId(modulePath: string) {
128
128
  return moduleId
129
129
  }
130
130
 
131
- async function findExistingTestSuite(testSuite: TestSuiteFromFS, moduleId: string): Promise<ExistingTestSuite | undefined> {
131
+ async function findExistingTestSuite(
132
+ testSuite: TestSuiteFromFS,
133
+ moduleId: string,
134
+ ): Promise<ExistingTestSuite | undefined> {
132
135
  const existingTestSuites = await prisma.testSuite.findMany({
133
136
  where: {
134
137
  moduleId,
@@ -150,7 +153,12 @@ function getSortedTagIds(existingTestSuite: ExistingTestSuite, tagIds: string[])
150
153
  }
151
154
  }
152
155
 
153
- function testSuiteNeedsUpdate(existingTestSuite: ExistingTestSuite, testSuite: TestSuiteFromFS, moduleId: string, tagIds: string[]) {
156
+ function testSuiteNeedsUpdate(
157
+ existingTestSuite: ExistingTestSuite,
158
+ testSuite: TestSuiteFromFS,
159
+ moduleId: string,
160
+ tagIds: string[],
161
+ ) {
154
162
  const { currentTagIds, newTagIds } = getSortedTagIds(existingTestSuite, tagIds)
155
163
 
156
164
  return (
@@ -346,15 +354,12 @@ async function deleteOrphanedTestSuites(fsTestSuiteKeys: Set<string>, result: Sy
346
354
  /**
347
355
  * Syncs test suites from filesystem to database
348
356
  */
349
- async function syncTestSuitesToDatabase(
350
- testSuitesFromFS: TestSuiteFromFS[],
351
- result: SyncResult,
352
- ): Promise<void> {
357
+ async function syncTestSuitesToDatabase(testSuitesFromFS: TestSuiteFromFS[], result: SyncResult): Promise<void> {
353
358
  console.log('\nāœ… Syncing test suites to database...')
354
-
359
+
355
360
  // Track test suites from filesystem (by name + modulePath)
356
361
  const fsTestSuiteKeys = new Set<string>()
357
-
362
+
358
363
  for (const testSuite of testSuitesFromFS) {
359
364
  try {
360
365
  await syncFilesystemTestSuite(testSuite, fsTestSuiteKeys, result)
@@ -372,69 +377,69 @@ async function syncTestSuitesToDatabase(
372
377
  * Generates and displays sync summary
373
378
  */
374
379
  async function main(): Promise<SyncResult | void> {
375
- console.log('šŸ”„ Starting test suites sync...')
376
- console.log('This will scan feature files and sync test suites to database.')
377
- console.log('Filesystem is the source of truth - test suites in DB but not in FS will be deleted.')
378
- console.log('Note: Test cases are not synced by this script (they will be handled separately).\n')
379
-
380
- await ensureAutomationWorkspaceReady()
381
- const featuresDir = getAutomationFeaturesDir()
382
-
383
- // Scan test suites from filesystem
384
- const testSuitesFromFS = await scanTestSuitesFromFilesystem(featuresDir)
385
-
386
- if (testSuitesFromFS.length === 0) {
387
- console.log('\nāš ļø No feature files found. Nothing to sync.')
388
- return
389
- }
390
-
391
- console.log(`\nšŸ“‹ Found ${testSuitesFromFS.length} test suite(s) from feature files:`)
392
- for (const ts of testSuitesFromFS) {
393
- console.log(` - ${ts.name} (${ts.modulePath})`)
394
- }
395
-
396
- // Initialize result
397
- const result: SyncResult = {
398
- testSuitesScanned: testSuitesFromFS.length,
399
- testSuitesExisting: 0,
400
- testSuitesCreated: 0,
401
- testSuitesUpdated: 0,
402
- testSuitesDeleted: 0,
403
- errors: [],
404
- createdTestSuites: [],
405
- updatedTestSuites: [],
406
- deletedTestSuites: [],
407
- }
408
-
409
- // Sync to database
410
- await syncTestSuitesToDatabase(testSuitesFromFS, result)
411
-
412
- printSyncSummary(
413
- [
414
- { label: 'šŸ“ Test suites scanned', value: result.testSuitesScanned },
415
- { label: 'āœ… Test suites existing', value: result.testSuitesExisting },
416
- { label: 'āž• Test suites created', value: result.testSuitesCreated },
417
- { label: 'šŸ”„ Test suites updated', value: result.testSuitesUpdated },
418
- { label: 'šŸ—‘ļø Test suites deleted', value: result.testSuitesDeleted },
419
- { label: 'āŒ Errors', value: result.errors.length },
420
- ],
421
- [
422
- {
423
- title: 'Created test suites',
424
- items: result.createdTestSuites.map(ts => `${ts.name} (${ts.modulePath})`),
425
- },
426
- {
427
- title: 'Updated test suites',
428
- items: result.updatedTestSuites.map(ts => `${ts.name} (${ts.modulePath})`),
429
- },
430
- {
431
- title: 'Deleted test suites',
432
- items: result.deletedTestSuites.map(ts => `${ts.name} (${ts.modulePath})`),
433
- },
434
- { title: 'Errors', items: result.errors },
435
- ],
436
- )
437
- return result
380
+ console.log('šŸ”„ Starting test suites sync...')
381
+ console.log('This will scan feature files and sync test suites to database.')
382
+ console.log('Filesystem is the source of truth - test suites in DB but not in FS will be deleted.')
383
+ console.log('Note: Test cases are not synced by this script (they will be handled separately).\n')
384
+
385
+ await ensureAutomationWorkspaceReady()
386
+ const featuresDir = getAutomationFeaturesDir()
387
+
388
+ // Scan test suites from filesystem
389
+ const testSuitesFromFS = await scanTestSuitesFromFilesystem(featuresDir)
390
+
391
+ if (testSuitesFromFS.length === 0) {
392
+ console.log('\nāš ļø No feature files found. Nothing to sync.')
393
+ return
394
+ }
395
+
396
+ console.log(`\nšŸ“‹ Found ${testSuitesFromFS.length} test suite(s) from feature files:`)
397
+ for (const ts of testSuitesFromFS) {
398
+ console.log(` - ${ts.name} (${ts.modulePath})`)
399
+ }
400
+
401
+ // Initialize result
402
+ const result: SyncResult = {
403
+ testSuitesScanned: testSuitesFromFS.length,
404
+ testSuitesExisting: 0,
405
+ testSuitesCreated: 0,
406
+ testSuitesUpdated: 0,
407
+ testSuitesDeleted: 0,
408
+ errors: [],
409
+ createdTestSuites: [],
410
+ updatedTestSuites: [],
411
+ deletedTestSuites: [],
412
+ }
413
+
414
+ // Sync to database
415
+ await syncTestSuitesToDatabase(testSuitesFromFS, result)
416
+
417
+ printSyncSummary(
418
+ [
419
+ { label: 'šŸ“ Test suites scanned', value: result.testSuitesScanned },
420
+ { label: 'āœ… Test suites existing', value: result.testSuitesExisting },
421
+ { label: 'āž• Test suites created', value: result.testSuitesCreated },
422
+ { label: 'šŸ”„ Test suites updated', value: result.testSuitesUpdated },
423
+ { label: 'šŸ—‘ļø Test suites deleted', value: result.testSuitesDeleted },
424
+ { label: 'āŒ Errors', value: result.errors.length },
425
+ ],
426
+ [
427
+ {
428
+ title: 'Created test suites',
429
+ items: result.createdTestSuites.map(ts => `${ts.name} (${ts.modulePath})`),
430
+ },
431
+ {
432
+ title: 'Updated test suites',
433
+ items: result.updatedTestSuites.map(ts => `${ts.name} (${ts.modulePath})`),
434
+ },
435
+ {
436
+ title: 'Deleted test suites',
437
+ items: result.deletedTestSuites.map(ts => `${ts.name} (${ts.modulePath})`),
438
+ },
439
+ { title: 'Errors', items: result.errors },
440
+ ],
441
+ )
442
+ return result
438
443
  }
439
444
 
440
445
  runSyncScript(main)
@@ -22,13 +22,7 @@ import {
22
22
  listEnvironments,
23
23
  updateEnvironment,
24
24
  } from '@/services/environment/environment-service'
25
- import {
26
- createTag,
27
- deleteTags,
28
- getTagByIdOrThrow,
29
- listFilterTags,
30
- updateTag,
31
- } from '@/services/tag/tag-service'
25
+ import { createTag, deleteTags, getTagByIdOrThrow, listFilterTags, updateTag } from '@/services/tag/tag-service'
32
26
  import {
33
27
  checkLocatorGroupNameUnique,
34
28
  createLocatorGroup,
@@ -5,7 +5,9 @@ import { runRequestedSync, type SyncExecutionResult } from '@/lib/sync/sync-exec
5
5
  import { getSyncPendingCounts, type SyncPendingCounts } from '@/lib/sync/sync-pending-counts'
6
6
  import { isSyncRequestId } from '@/lib/sync/sync-registry'
7
7
 
8
- export async function runSyncAction(requestedScriptId: string): Promise<SyncExecutionResult | InvalidSyncExecutionResult> {
8
+ export async function runSyncAction(
9
+ requestedScriptId: string,
10
+ ): Promise<SyncExecutionResult | InvalidSyncExecutionResult> {
9
11
  if (!isSyncRequestId(requestedScriptId)) {
10
12
  return {
11
13
  requestedScriptId,
@@ -1,13 +1,7 @@
1
1
  'use server'
2
2
 
3
3
  import { tagSchema } from '@/constants/form-opts/tag-form-opts'
4
- import {
5
- createTag,
6
- deleteTags,
7
- getTagByIdOrThrow,
8
- listFilterTags,
9
- updateTag,
10
- } from '@/services/tag/tag-service'
4
+ import { createTag, deleteTags, getTagByIdOrThrow, listFilterTags, updateTag } from '@/services/tag/tag-service'
11
5
  import { ServiceError, serviceErrorToActionResponse, unknownErrorToActionResponse } from '@/services/shared/errors'
12
6
  import { ActionResponse } from '@/types/form/actionHandler'
13
7
  import { revalidatePath } from 'next/cache'
@@ -40,7 +40,9 @@ export async function deleteTemplateTestCaseAction(id: string[]): Promise<Action
40
40
  }
41
41
  }
42
42
 
43
- export async function createTemplateTestCaseAction(value: z.infer<typeof templateTestCaseSchema>): Promise<ActionResponse> {
43
+ export async function createTemplateTestCaseAction(
44
+ value: z.infer<typeof templateTestCaseSchema>,
45
+ ): Promise<ActionResponse> {
44
46
  try {
45
47
  templateTestCaseSchema.parse(value)
46
48
  const newTemplateTestCase = await createTemplateTestCase(value)