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
@@ -4,6 +4,7 @@ import prisma from '@/config/db-config'
4
4
  import { buildModulePath } from '@/lib/path-helpers/module-path'
5
5
  import { getAutomationFeaturesDir } from '@/lib/automation/automation-path-roots'
6
6
  import { ensureAutomationWorkspaceReady } from '@/lib/automation/automation-workspace'
7
+ import { buildAppraiseMetadata, getAppraiseMetadataPath } from '@/lib/appraise-test-case-metadata'
7
8
  import { generateProjectedGherkinSteps, getTestSuiteFilesystemKey } from '@/lib/sync/projected-feature-utils'
8
9
 
9
10
  async function isDirectoryEmpty(dirPath: string): Promise<boolean> {
@@ -32,6 +33,18 @@ async function removeEmptyDirectoriesUp(dirPath: string, basePath: string): Prom
32
33
  }
33
34
  }
34
35
 
36
+ async function unlinkIfExists(filePath: string): Promise<boolean> {
37
+ try {
38
+ await fs.unlink(filePath)
39
+ return true
40
+ } catch (error: unknown) {
41
+ if (error && typeof error === 'object' && 'code' in error && error.code === 'ENOENT') {
42
+ return false
43
+ }
44
+ throw error
45
+ }
46
+ }
47
+
35
48
  export async function generateFeatureFile(
36
49
  testSuiteId: string,
37
50
  testSuiteName: string,
@@ -53,6 +66,14 @@ export async function generateFeatureFile(
53
66
  order: 'asc',
54
67
  },
55
68
  },
69
+ flowBlocks: {
70
+ include: {
71
+ nodes: true,
72
+ },
73
+ orderBy: {
74
+ order: 'asc',
75
+ },
76
+ },
56
77
  tags: true,
57
78
  },
58
79
  },
@@ -73,6 +94,15 @@ export async function generateFeatureFile(
73
94
  testSuite.testCases,
74
95
  testSuite.tags,
75
96
  )
97
+ const metadataContent = JSON.stringify(
98
+ buildAppraiseMetadata({
99
+ testSuiteName,
100
+ modulePath,
101
+ testCases: testSuite.testCases,
102
+ }),
103
+ null,
104
+ 2,
105
+ )
76
106
 
77
107
  const featuresBaseDir = getAutomationFeaturesDir()
78
108
  const moduleDir = join(featuresBaseDir, modulePath.substring(1))
@@ -82,6 +112,7 @@ export async function generateFeatureFile(
82
112
  const featureFilePath = join(moduleDir, `${safeFileName}.feature`)
83
113
 
84
114
  await fs.writeFile(featureFilePath, featureContent, 'utf8')
115
+ await fs.writeFile(getAppraiseMetadataPath(featureFilePath), `${metadataContent}\n`, 'utf8')
85
116
  return featureFilePath
86
117
  } catch (error) {
87
118
  console.error('Error generating feature file:', error)
@@ -178,17 +209,12 @@ export async function deleteFeatureFile(testSuiteId: string): Promise<boolean> {
178
209
  const featuresBaseDir = getAutomationFeaturesDir()
179
210
  const moduleDir = join(featuresBaseDir, modulePath.substring(1))
180
211
  const featureFilePath = join(moduleDir, `${safeFileName}.feature`)
212
+ const metadataFilePath = getAppraiseMetadataPath(featureFilePath)
181
213
 
182
- try {
183
- await fs.unlink(featureFilePath)
184
- await removeEmptyDirectoriesUp(moduleDir, featuresBaseDir)
185
- return true
186
- } catch (error: unknown) {
187
- if (error && typeof error === 'object' && 'code' in error && error.code === 'ENOENT') {
188
- return false
189
- }
190
- throw error
191
- }
214
+ const deletedFeature = await unlinkIfExists(featureFilePath)
215
+ const deletedMetadata = await unlinkIfExists(metadataFilePath)
216
+ await removeEmptyDirectoriesUp(moduleDir, featuresBaseDir)
217
+ return deletedFeature || deletedMetadata
192
218
  } catch (error) {
193
219
  console.error('Error deleting feature file:', error)
194
220
  throw error
@@ -220,6 +246,14 @@ export async function regenerateAllFeatureFiles(): Promise<string[]> {
220
246
  order: 'asc',
221
247
  },
222
248
  },
249
+ flowBlocks: {
250
+ include: {
251
+ nodes: true,
252
+ },
253
+ orderBy: {
254
+ order: 'asc',
255
+ },
256
+ },
223
257
  tags: true,
224
258
  },
225
259
  },
@@ -239,6 +273,15 @@ export async function regenerateAllFeatureFiles(): Promise<string[]> {
239
273
  testSuite.testCases,
240
274
  testSuite.tags,
241
275
  )
276
+ const metadataContent = JSON.stringify(
277
+ buildAppraiseMetadata({
278
+ testSuiteName: testSuite.name,
279
+ modulePath,
280
+ testCases: testSuite.testCases,
281
+ }),
282
+ null,
283
+ 2,
284
+ )
242
285
 
243
286
  const moduleDir = join(featuresBaseDir, modulePath.substring(1))
244
287
  await fs.mkdir(moduleDir, { recursive: true })
@@ -247,6 +290,7 @@ export async function regenerateAllFeatureFiles(): Promise<string[]> {
247
290
  const featureFilePath = join(moduleDir, `${safeFileName}.feature`)
248
291
 
249
292
  await fs.writeFile(featureFilePath, featureContent, 'utf8')
293
+ await fs.writeFile(getAppraiseMetadataPath(featureFilePath), `${metadataContent}\n`, 'utf8')
250
294
  generatedFiles.push(featureFilePath)
251
295
  } catch (error) {
252
296
  console.error(`Error generating feature file for test suite ${testSuite.name}:`, error)
@@ -3,6 +3,7 @@ import { join } from 'path'
3
3
  import { tmpdir } from 'os'
4
4
  import { expect, test } from 'vitest'
5
5
 
6
+ import { getAppraiseMetadataPath } from '@/lib/appraise-test-case-metadata'
6
7
  import { parseFeatureFile } from '@/lib/gherkin-parser'
7
8
 
8
9
  async function withTempFeatureFile(content: string): Promise<string> {
@@ -42,3 +43,54 @@ Scenario: buys item
42
43
  expect(parsed).not.toBeNull()
43
44
  expect(parsed?.featureDescription).toBe('Checkout flow')
44
45
  })
46
+
47
+ test('attaches adjacent Appraise metadata to matching scenarios', async () => {
48
+ const filePath = await withTempFeatureFile(`
49
+ Feature: Checkout flow
50
+
51
+ @tc_checkout_buy @smoke
52
+ Scenario: [Legacy description] Legacy title
53
+ Given user adds item to cart
54
+ `)
55
+ await fs.writeFile(
56
+ getAppraiseMetadataPath(filePath),
57
+ JSON.stringify({
58
+ version: 1,
59
+ testSuite: { name: 'checkout-flow', modulePath: '/checkout' },
60
+ testCases: [
61
+ {
62
+ identifierTag: '@tc_checkout_buy',
63
+ title: 'Buys item',
64
+ description: 'Happy path',
65
+ nodes: [{ nodeId: 'node-cart', order: 1, label: 'Add item' }],
66
+ flowBlocks: [{ id: 'block-cart', name: 'Cart', order: 0, nodeIds: ['node-cart'] }],
67
+ },
68
+ ],
69
+ }),
70
+ 'utf8',
71
+ )
72
+
73
+ const parsed = await parseFeatureFile(filePath)
74
+
75
+ expect(parsed?.scenarios[0]?.appraiseMetadata).toMatchObject({
76
+ title: 'Buys item',
77
+ description: 'Happy path',
78
+ nodes: [{ nodeId: 'node-cart', order: 1, label: 'Add item' }],
79
+ })
80
+ })
81
+
82
+ test('falls back to feature-only parsing when sidecar is malformed', async () => {
83
+ const filePath = await withTempFeatureFile(`
84
+ Feature: Checkout flow
85
+
86
+ @tc_checkout_buy
87
+ Scenario: buys item
88
+ Given user adds item to cart
89
+ `)
90
+ await fs.writeFile(getAppraiseMetadataPath(filePath), '{', 'utf8')
91
+
92
+ const parsed = await parseFeatureFile(filePath)
93
+
94
+ expect(parsed?.scenarios[0]?.appraiseMetadata).toBeUndefined()
95
+ expect(parsed?.metadataWarnings).toHaveLength(1)
96
+ })
@@ -1,5 +1,11 @@
1
1
  import { promises as fs } from 'fs'
2
2
  import { join } from 'path'
3
+ import {
4
+ getAppraiseMetadataPath,
5
+ getMetadataByIdentifier,
6
+ readAppraiseMetadataFile,
7
+ type AppraiseTestCaseMetadataEntry,
8
+ } from '@/lib/appraise-test-case-metadata'
3
9
  import { getFeatureModulePath } from '@/lib/path-helpers/feature-path'
4
10
 
5
11
  /**
@@ -11,6 +17,7 @@ export interface ParsedFeature {
11
17
  featureDescription?: string
12
18
  tags: string[]
13
19
  scenarios: ParsedScenario[]
20
+ metadataWarnings: string[]
14
21
  }
15
22
 
16
23
  /**
@@ -21,6 +28,7 @@ export interface ParsedScenario {
21
28
  description?: string
22
29
  tags: string[]
23
30
  steps: ParsedStep[]
31
+ appraiseMetadata?: AppraiseTestCaseMetadataEntry
24
32
  }
25
33
 
26
34
  /**
@@ -30,6 +38,7 @@ export interface ParsedStep {
30
38
  keyword: string
31
39
  text: string
32
40
  order: number
41
+ appraiseNode?: AppraiseTestCaseMetadataEntry['nodes'][number]
33
42
  }
34
43
 
35
44
  const STEP_KEYWORDS = ['Given', 'When', 'Then', 'And', 'But'] as const
@@ -103,6 +112,23 @@ function parseFeatureLine(line: string) {
103
112
  return line.replace('Feature:', '').trim()
104
113
  }
105
114
 
115
+ function normalizeTagExpression(tagExpression: string): string {
116
+ return tagExpression.startsWith('@') ? tagExpression : `@${tagExpression}`
117
+ }
118
+
119
+ function getScenarioIdentifierTag(scenario: ParsedScenario): string | null {
120
+ for (const tagLine of scenario.tags) {
121
+ const tags = tagLine.split(/\s+/).filter(tag => tag.trim().startsWith('@'))
122
+ const identifierTag = tags.find(tag => normalizeTagExpression(tag).replace(/^@/, '').startsWith('tc_'))
123
+
124
+ if (identifierTag) {
125
+ return normalizeTagExpression(identifierTag)
126
+ }
127
+ }
128
+
129
+ return null
130
+ }
131
+
106
132
  function startScenario(lines: string[], index: number): ParsedScenario {
107
133
  const { name, description } = parseScenarioHeader(lines[index])
108
134
 
@@ -170,10 +196,21 @@ function parseGherkinLines(lines: string[]) {
170
196
  */
171
197
  export async function parseFeatureFile(filePath: string): Promise<ParsedFeature | null> {
172
198
  try {
173
- const content = await fs.readFile(filePath, 'utf-8')
199
+ const [content, metadataResult] = await Promise.all([
200
+ fs.readFile(filePath, 'utf-8'),
201
+ readAppraiseMetadataFile(getAppraiseMetadataPath(filePath)),
202
+ ])
174
203
  const lines = normalizeGherkinLines(content)
175
204
  const featureTags = getFeatureTags(lines)
176
205
  const { featureName, featureDescription, scenarios } = parseGherkinLines(lines)
206
+ const metadataByIdentifier = getMetadataByIdentifier(metadataResult.metadata)
207
+
208
+ for (const scenario of scenarios) {
209
+ const identifierTag = getScenarioIdentifierTag(scenario)
210
+ if (identifierTag) {
211
+ scenario.appraiseMetadata = metadataByIdentifier.get(identifierTag)
212
+ }
213
+ }
177
214
 
178
215
  if (!featureName) {
179
216
  console.warn(`No feature found in file: ${filePath}`)
@@ -186,6 +223,7 @@ export async function parseFeatureFile(filePath: string): Promise<ParsedFeature
186
223
  featureDescription: featureDescription || undefined,
187
224
  tags: featureTags,
188
225
  scenarios,
226
+ metadataWarnings: metadataResult.warnings,
189
227
  }
190
228
  } catch (error) {
191
229
  console.error(`Error parsing feature file ${filePath}:`, error)
@@ -144,7 +144,11 @@ async function cleanupEmptyDirectories(filePath: string): Promise<void> {
144
144
  let currentDir = path.dirname(filePath)
145
145
  const locatorsRoot = getAutomationLocatorsDir()
146
146
 
147
- while (currentDir.startsWith(locatorsRoot) && currentDir !== locatorsRoot && currentDir !== path.dirname(currentDir)) {
147
+ while (
148
+ currentDir.startsWith(locatorsRoot) &&
149
+ currentDir !== locatorsRoot &&
150
+ currentDir !== path.dirname(currentDir)
151
+ ) {
148
152
  try {
149
153
  const files = await fs.readdir(currentDir)
150
154
  if (files.length === 0) {
@@ -143,8 +143,7 @@ async function cleanupLingeringCompanionSessions(currentSessionId?: string): Pro
143
143
  const isTerminal = isTerminalStatus(session.status)
144
144
  const shouldTerminate = Boolean(session.companionPid)
145
145
  const shouldCloseStaleSession = !session.companionPid && !isTerminal && ageMs > ACTIVE_SESSION_STALE_MS
146
- const shouldPruneSessionFile =
147
- (isTerminal && ageMs > TERMINAL_SESSION_RETENTION_MS) || shouldCloseStaleSession
146
+ const shouldPruneSessionFile = (isTerminal && ageMs > TERMINAL_SESSION_RETENTION_MS) || shouldCloseStaleSession
148
147
 
149
148
  if (shouldTerminate && session.companionPid) {
150
149
  await shutdownCompanionProcess(session.companionPid).catch(() => undefined)
@@ -1,10 +1,26 @@
1
1
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
2
2
  import { TestRunTestCaseResult, TestRunTestCaseStatus } from '@prisma/client'
3
3
 
4
- const { mockTestRunTestCaseFindMany, mockTestRunTestCaseFindFirst, mockTestCaseMetricsUpsert } = vi.hoisted(() => ({
4
+ const {
5
+ mockTestRunTestCaseFindMany,
6
+ mockTestRunTestCaseFindFirst,
7
+ mockTestCaseMetricsUpsert,
8
+ mockTestCaseCount,
9
+ mockTestSuiteCount,
10
+ mockTestRunCount,
11
+ mockDashboardMetricsFindFirst,
12
+ mockDashboardMetricsUpdate,
13
+ mockDashboardMetricsCreate,
14
+ } = vi.hoisted(() => ({
5
15
  mockTestRunTestCaseFindMany: vi.fn(),
6
16
  mockTestRunTestCaseFindFirst: vi.fn(),
7
17
  mockTestCaseMetricsUpsert: vi.fn(),
18
+ mockTestCaseCount: vi.fn(),
19
+ mockTestSuiteCount: vi.fn(),
20
+ mockTestRunCount: vi.fn(),
21
+ mockDashboardMetricsFindFirst: vi.fn(),
22
+ mockDashboardMetricsUpdate: vi.fn(),
23
+ mockDashboardMetricsCreate: vi.fn(),
8
24
  }))
9
25
 
10
26
  vi.mock('@/config/db-config', () => ({
@@ -18,23 +34,29 @@ vi.mock('@/config/db-config', () => ({
18
34
  upsert: mockTestCaseMetricsUpsert,
19
35
  count: vi.fn(),
20
36
  },
37
+ testCase: {
38
+ count: mockTestCaseCount,
39
+ },
21
40
  testSuiteMetrics: {
22
41
  upsert: vi.fn(),
23
42
  count: vi.fn(),
24
43
  },
44
+ testSuite: {
45
+ count: mockTestSuiteCount,
46
+ },
25
47
  testRun: {
26
- count: vi.fn(),
48
+ count: mockTestRunCount,
27
49
  findUnique: vi.fn(),
28
50
  },
29
51
  dashboardMetrics: {
30
- findFirst: vi.fn(),
31
- update: vi.fn(),
32
- create: vi.fn(),
52
+ findFirst: mockDashboardMetricsFindFirst,
53
+ update: mockDashboardMetricsUpdate,
54
+ create: mockDashboardMetricsCreate,
33
55
  },
34
56
  },
35
57
  }))
36
58
 
37
- import { recalculateTestCaseMetrics } from './metric-calculator'
59
+ import { recalculateTestCaseMetrics, updateDashboardMetrics } from './metric-calculator'
38
60
 
39
61
  function completedCase(result: TestRunTestCaseResult, completedAt: Date) {
40
62
  return {
@@ -154,3 +176,80 @@ describe('recalculateTestCaseMetrics', () => {
154
176
  })
155
177
  })
156
178
  })
179
+
180
+ describe('updateDashboardMetrics', () => {
181
+ beforeEach(() => {
182
+ vi.useFakeTimers()
183
+ vi.setSystemTime(new Date('2026-05-12T00:00:00.000Z'))
184
+ vi.clearAllMocks()
185
+ mockTestRunCount.mockResolvedValue(4)
186
+ mockTestCaseCount.mockResolvedValueOnce(2).mockResolvedValueOnce(1)
187
+ mockTestSuiteCount.mockResolvedValue(3)
188
+ mockDashboardMetricsFindFirst.mockResolvedValue({ id: 'dashboard-metrics-1' })
189
+ mockDashboardMetricsUpdate.mockResolvedValue({})
190
+ mockDashboardMetricsCreate.mockResolvedValue({})
191
+ })
192
+
193
+ afterEach(() => {
194
+ vi.useRealTimers()
195
+ })
196
+
197
+ it('counts attention metrics from live entities instead of orphaned metric rows', async () => {
198
+ await updateDashboardMetrics()
199
+
200
+ expect(mockTestCaseCount).toHaveBeenNthCalledWith(1, {
201
+ where: {
202
+ metrics: {
203
+ is: {
204
+ isRepeatedlyFailing: true,
205
+ },
206
+ },
207
+ },
208
+ })
209
+ expect(mockTestCaseCount).toHaveBeenNthCalledWith(2, {
210
+ where: {
211
+ metrics: {
212
+ is: {
213
+ isFlaky: true,
214
+ },
215
+ },
216
+ },
217
+ })
218
+ expect(mockTestSuiteCount).toHaveBeenCalledWith({
219
+ where: {
220
+ OR: [
221
+ {
222
+ metrics: {
223
+ is: null,
224
+ },
225
+ },
226
+ {
227
+ metrics: {
228
+ is: {
229
+ lastExecutedAt: null,
230
+ },
231
+ },
232
+ },
233
+ {
234
+ metrics: {
235
+ is: {
236
+ lastExecutedAt: {
237
+ lt: new Date('2026-05-05T00:00:00.000Z'),
238
+ },
239
+ },
240
+ },
241
+ },
242
+ ],
243
+ },
244
+ })
245
+ expect(mockDashboardMetricsUpdate).toHaveBeenCalledWith({
246
+ where: { id: 'dashboard-metrics-1' },
247
+ data: expect.objectContaining({
248
+ failedRecentRunsCount: 4,
249
+ repeatedlyFailingTestsCount: 2,
250
+ flakyTestsCount: 1,
251
+ suitesNotExecutedRecentlyCount: 3,
252
+ }),
253
+ })
254
+ })
255
+ })
@@ -57,9 +57,7 @@ function getRecentPeriodDate(): Date {
57
57
 
58
58
  function summarizeRecentTestCaseRuns(recentTestRunTestCases: CompletedTestRunTestCase[]): TestCaseMetricSummary {
59
59
  const totalRecentRuns = recentTestRunTestCases.length
60
- const failedRecentRuns = recentTestRunTestCases.filter(
61
- trtc => trtc.result === TestRunTestCaseResult.FAILED,
62
- ).length
60
+ const failedRecentRuns = recentTestRunTestCases.filter(trtc => trtc.result === TestRunTestCaseResult.FAILED).length
63
61
  const failureRate = totalRecentRuns > 0 ? failedRecentRuns / totalRecentRuns : 0
64
62
  const consecutiveFailures = countConsecutiveFailures(recentTestRunTestCases)
65
63
 
@@ -138,14 +136,8 @@ export async function updateTestCaseMetrics(
138
136
 
139
137
  const recentTestRunTestCases = await findRecentCompletedTestRunTestCases(testCaseId, recentPeriodDate)
140
138
 
141
- const {
142
- totalRecentRuns,
143
- failedRecentRuns,
144
- failureRate,
145
- isFlaky,
146
- consecutiveFailures,
147
- isRepeatedlyFailing,
148
- } = summarizeRecentTestCaseRuns(recentTestRunTestCases)
139
+ const { totalRecentRuns, failedRecentRuns, failureRate, isFlaky, consecutiveFailures, isRepeatedlyFailing } =
140
+ summarizeRecentTestCaseRuns(recentTestRunTestCases)
149
141
 
150
142
  // Determine which date fields to update
151
143
  const updateData: {
@@ -194,10 +186,7 @@ export async function updateTestCaseMetrics(
194
186
  * @param testSuiteId - The test suite ID
195
187
  * @param executedAt - When the test suite was executed
196
188
  */
197
- export async function updateTestSuiteMetrics(
198
- testSuiteId: string,
199
- executedAt: Date,
200
- ): Promise<void> {
189
+ export async function updateTestSuiteMetrics(testSuiteId: string, executedAt: Date): Promise<void> {
201
190
  try {
202
191
  await prisma.testSuiteMetrics.upsert({
203
192
  where: { testSuiteId },
@@ -220,10 +209,7 @@ export async function updateTestSuiteMetrics(
220
209
  * @param testRunId - The test run ID
221
210
  * @param executedAt - When the test run was executed
222
211
  */
223
- async function updateTestSuitesForTestRun(
224
- testRunId: string,
225
- executedAt: Date,
226
- ): Promise<void> {
212
+ async function updateTestSuitesForTestRun(testRunId: string, executedAt: Date): Promise<void> {
227
213
  try {
228
214
  // Get all test cases in the test run
229
215
  const testRunTestCases = await prisma.testRunTestCase.findMany({
@@ -290,31 +276,52 @@ export async function updateDashboardMetrics(): Promise<void> {
290
276
  },
291
277
  })
292
278
 
293
- // Count repeatedly failing tests
294
- const repeatedlyFailingTestsCount = await prisma.testCaseMetrics.count({
279
+ // Count repeatedly failing live tests
280
+ const repeatedlyFailingTestsCount = await prisma.testCase.count({
295
281
  where: {
296
- isRepeatedlyFailing: true,
282
+ metrics: {
283
+ is: {
284
+ isRepeatedlyFailing: true,
285
+ },
286
+ },
297
287
  },
298
288
  })
299
289
 
300
- // Count flaky tests
301
- const flakyTestsCount = await prisma.testCaseMetrics.count({
290
+ // Count flaky live tests
291
+ const flakyTestsCount = await prisma.testCase.count({
302
292
  where: {
303
- isFlaky: true,
293
+ metrics: {
294
+ is: {
295
+ isFlaky: true,
296
+ },
297
+ },
304
298
  },
305
299
  })
306
300
 
307
- // Count suites not executed recently
308
- const suitesNotExecutedRecentlyCount = await prisma.testSuiteMetrics.count({
301
+ // Count live suites with no execution metrics or stale execution metrics
302
+ const suitesNotExecutedRecentlyCount = await prisma.testSuite.count({
309
303
  where: {
310
304
  OR: [
311
305
  {
312
- lastExecutedAt: {
313
- lt: recentPeriodDate,
306
+ metrics: {
307
+ is: null,
314
308
  },
315
309
  },
316
310
  {
317
- lastExecutedAt: null,
311
+ metrics: {
312
+ is: {
313
+ lastExecutedAt: null,
314
+ },
315
+ },
316
+ },
317
+ {
318
+ metrics: {
319
+ is: {
320
+ lastExecutedAt: {
321
+ lt: recentPeriodDate,
322
+ },
323
+ },
324
+ },
318
325
  },
319
326
  ],
320
327
  },
@@ -364,11 +371,7 @@ export async function recalculateTestCaseMetrics(testCaseId: string): Promise<vo
364
371
  const recentTestRunTestCases = await findRecentCompletedTestRunTestCases(testCaseId, recentPeriodDate)
365
372
 
366
373
  const metricSummary = summarizeRecentTestCaseRuns(recentTestRunTestCases)
367
- const recalculatedDates = await resolveRecalculatedMetricDates(
368
- testCaseId,
369
- recentPeriodDate,
370
- recentTestRunTestCases,
371
- )
374
+ const recalculatedDates = await resolveRecalculatedMetricDates(testCaseId, recentPeriodDate, recentTestRunTestCases)
372
375
  const updateData = buildRecalculatedMetricUpdateData(metricSummary, recalculatedDates)
373
376
 
374
377
  // Upsert the metrics
@@ -572,11 +575,7 @@ export async function updateMetricsForTestRun(testRunId: string): Promise<void>
572
575
  // Update metrics for all test cases in the run
573
576
  for (const testRunTestCase of testRun.testCases) {
574
577
  if (testRunTestCase.status === TestRunTestCaseStatus.COMPLETED) {
575
- await updateTestCaseMetrics(
576
- testRunTestCase.testCaseId,
577
- testRunTestCase.result,
578
- executedAt,
579
- )
578
+ await updateTestCaseMetrics(testRunTestCase.testCaseId, testRunTestCase.result, executedAt)
580
579
  }
581
580
  }
582
581
 
@@ -7,6 +7,8 @@ type StoredProjectedStep = {
7
7
  }
8
8
 
9
9
  type StoredProjectedDbStep = StoredProjectedStep & {
10
+ flowNodeId: string | null
11
+ label: string
10
12
  TemplateStep: { signature: string } | null
11
13
  parameters: Array<{ name: string; value: string; order: number; type: StepParameterType }>
12
14
  }
@@ -16,6 +18,7 @@ export type ProjectedDbTestCaseStep = {
16
18
  keyword: string
17
19
  text: string
18
20
  gherkinStep: string
21
+ flowNodeId: string | null
19
22
  label: string
20
23
  icon: TemplateStepIcon
21
24
  templateStepSignature: string | null
@@ -64,7 +67,8 @@ export function normalizeProjectedDbTestCaseSteps(steps: StoredProjectedDbStep[]
64
67
  keyword,
65
68
  text,
66
69
  gherkinStep,
67
- label: text,
70
+ flowNodeId: step.flowNodeId,
71
+ label: step.label,
68
72
  icon: determineProjectedStepIcon(keyword),
69
73
  templateStepSignature: step.TemplateStep?.signature ?? null,
70
74
  parameters: step.parameters,
@@ -64,10 +64,7 @@ function parseSyncFailureCause(result: ScriptExecutionOutput | { error: unknown
64
64
  return result.error instanceof Error ? result.error.message : String(result.error)
65
65
  }
66
66
 
67
- return selectMostRelevantLine([
68
- ...normalizeOutputLines(result.stderr),
69
- ...normalizeOutputLines(result.stdout),
70
- ])
67
+ return selectMostRelevantLine([...normalizeOutputLines(result.stderr), ...normalizeOutputLines(result.stdout)])
71
68
  }
72
69
 
73
70
  async function executeSyncScript(scriptId: SyncScriptId): Promise<ScriptExecutionOutput> {