create-appraisejs 0.1.10-alpha.8 → 0.2.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (414) hide show
  1. package/README.md +52 -52
  2. package/dist/cli.e2e.test.d.ts +2 -0
  3. package/dist/cli.e2e.test.d.ts.map +1 -0
  4. package/dist/cli.e2e.test.js +73 -0
  5. package/dist/cli.e2e.test.js.map +1 -0
  6. package/dist/config.test.d.ts +2 -0
  7. package/dist/config.test.d.ts.map +1 -0
  8. package/dist/config.test.js +65 -0
  9. package/dist/config.test.js.map +1 -0
  10. package/dist/copy-template.test.d.ts +2 -0
  11. package/dist/copy-template.test.d.ts.map +1 -0
  12. package/dist/copy-template.test.js +71 -0
  13. package/dist/copy-template.test.js.map +1 -0
  14. package/dist/download-repo.test.d.ts +2 -0
  15. package/dist/download-repo.test.d.ts.map +1 -0
  16. package/dist/download-repo.test.js +14 -0
  17. package/dist/download-repo.test.js.map +1 -0
  18. package/dist/install.test.d.ts +2 -0
  19. package/dist/install.test.d.ts.map +1 -0
  20. package/dist/install.test.js +119 -0
  21. package/dist/install.test.js.map +1 -0
  22. package/dist/prepare-template-utils.d.ts.map +1 -1
  23. package/dist/prepare-template-utils.js +5 -0
  24. package/dist/prepare-template-utils.js.map +1 -1
  25. package/dist/prompts.test.d.ts +2 -0
  26. package/dist/prompts.test.d.ts.map +1 -0
  27. package/dist/prompts.test.js +58 -0
  28. package/dist/prompts.test.js.map +1 -0
  29. package/dist/scaffold-gitignore.d.ts +1 -0
  30. package/dist/scaffold-gitignore.d.ts.map +1 -1
  31. package/dist/scaffold-gitignore.js +3 -0
  32. package/dist/scaffold-gitignore.js.map +1 -1
  33. package/package.json +3 -2
  34. package/templates/default/.appraise-template-meta.json +2 -2
  35. package/templates/default/.env.example +2 -2
  36. package/templates/default/.vscode/settings.json +2 -1
  37. package/templates/default/README.md +53 -53
  38. package/templates/default/automation/mapping/locator-map.json +1 -14
  39. package/templates/default/automation/steps/actions/click.step.ts +58 -58
  40. package/templates/default/automation/steps/actions/hover.step.ts +27 -27
  41. package/templates/default/automation/steps/actions/input.step.ts +84 -84
  42. package/templates/default/automation/steps/actions/navigation.step.ts +70 -70
  43. package/templates/default/automation/steps/actions/random_data.step.ts +142 -142
  44. package/templates/default/automation/steps/actions/store.step.ts +86 -86
  45. package/templates/default/automation/steps/actions/wait.step.ts +90 -90
  46. package/templates/default/automation/steps/validations/active_state_assertion.step.ts +30 -30
  47. package/templates/default/automation/steps/validations/navigation_assertion.step.ts +22 -22
  48. package/templates/default/automation/steps/validations/text_assertion.step.ts +107 -107
  49. package/templates/default/automation/steps/validations/visibility_assertion.step.ts +26 -26
  50. package/templates/default/components.json +24 -24
  51. package/templates/default/cucumber.mjs +16 -16
  52. package/templates/default/eslint.config.mjs +16 -16
  53. package/templates/default/gitignore +3 -0
  54. package/templates/default/next-env.d.ts +6 -6
  55. package/templates/default/next.config.ts +11 -11
  56. package/templates/default/package-lock.json +146 -75
  57. package/templates/default/package.json +2 -1
  58. package/templates/default/packages/cucumber-runtime/package.json +13 -13
  59. package/templates/default/packages/cucumber-runtime/src/cache.util.ts +93 -93
  60. package/templates/default/packages/cucumber-runtime/src/cli.ts +68 -68
  61. package/templates/default/packages/cucumber-runtime/src/environment.util.ts +21 -21
  62. package/templates/default/packages/cucumber-runtime/src/executor.ts +32 -32
  63. package/templates/default/packages/cucumber-runtime/src/hooks.ts +25 -3
  64. package/templates/default/packages/cucumber-runtime/src/index.ts +17 -17
  65. package/templates/default/packages/cucumber-runtime/src/locator.util.ts +234 -234
  66. package/templates/default/packages/cucumber-runtime/src/parameter-types.ts +7 -7
  67. package/templates/default/packages/cucumber-runtime/src/paths.ts +66 -1
  68. package/templates/default/packages/cucumber-runtime/src/random-data.util.ts +35 -35
  69. package/templates/default/packages/cucumber-runtime/src/types.ts +13 -13
  70. package/templates/default/packages/cucumber-runtime/src/world.ts +44 -44
  71. package/templates/default/packages/cucumber-runtime/tsconfig.json +11 -11
  72. package/templates/default/packages/locator-picker-companion/dist/cli.d.ts +1 -0
  73. package/templates/default/packages/locator-picker-companion/dist/cli.js +302 -0
  74. package/templates/default/packages/locator-picker-companion/dist/index.d.ts +3 -0
  75. package/templates/default/packages/locator-picker-companion/dist/index.js +3 -0
  76. package/templates/default/packages/locator-picker-companion/dist/injected-picker-script.d.ts +1 -0
  77. package/templates/default/packages/locator-picker-companion/dist/injected-picker-script.js +615 -0
  78. package/templates/default/packages/locator-picker-companion/dist/launcher.d.ts +11 -0
  79. package/templates/default/packages/locator-picker-companion/dist/launcher.js +59 -0
  80. package/templates/default/packages/locator-picker-companion/dist/selector-generator.d.ts +3 -0
  81. package/templates/default/packages/locator-picker-companion/dist/selector-generator.js +257 -0
  82. package/templates/default/packages/locator-picker-companion/dist/session-file.d.ts +22 -0
  83. package/templates/default/packages/locator-picker-companion/dist/session-file.js +150 -0
  84. package/templates/default/packages/locator-picker-companion/dist/types.d.ts +31 -0
  85. package/templates/default/packages/locator-picker-companion/dist/types.js +1 -0
  86. package/templates/default/packages/locator-picker-companion/package.json +17 -0
  87. package/templates/default/packages/locator-picker-companion/src/cli.ts +428 -0
  88. package/templates/default/packages/locator-picker-companion/src/index.ts +3 -0
  89. package/templates/default/packages/locator-picker-companion/src/injected-picker-script.ts +771 -0
  90. package/templates/default/packages/locator-picker-companion/src/launcher.ts +77 -0
  91. package/templates/default/packages/locator-picker-companion/src/selector-generator.ts +339 -0
  92. package/templates/default/packages/locator-picker-companion/src/session-file.ts +226 -0
  93. package/templates/default/packages/locator-picker-companion/src/types.ts +42 -0
  94. package/templates/default/packages/locator-picker-companion/tsconfig.json +14 -0
  95. package/templates/default/postcss.config.mjs +8 -8
  96. package/templates/default/prisma/dev.db +0 -0
  97. package/templates/default/prisma/migrations/20251104113456_add_type_for_template_step_groups/migration.sql +16 -16
  98. package/templates/default/prisma/migrations/20251104170946_add_tags_to_test_suite_and_test_case/migration.sql +27 -27
  99. package/templates/default/prisma/migrations/20251112190024_add_cascade_delete_to_test_run_test_case/migration.sql +17 -17
  100. package/templates/default/prisma/migrations/20251113181100_add_test_run_log/migration.sql +12 -12
  101. package/templates/default/prisma/migrations/20251119191838_add_tag_type/migration.sql +28 -28
  102. package/templates/default/prisma/migrations/20251121164059_add_conflict_resolution/migration.sql +12 -12
  103. package/templates/default/prisma/migrations/20251223183400_add_report_model_to_db_schema/migration.sql +10 -10
  104. package/templates/default/prisma/migrations/20251223183637_add_report_test_case_entity_for_storing_test_results_for_individual_test_cases/migration.sql +10 -10
  105. package/templates/default/prisma/migrations/20251224083549_add_comprehensive_report_storage/migration.sql +108 -108
  106. package/templates/default/prisma/migrations/20251229194422_migrate_duration_to_string/migration.sql +55 -55
  107. package/templates/default/prisma/migrations/20251230124637_add_unique_constraint_to_test_run_name/migration.sql +27 -27
  108. package/templates/default/prisma/migrations/20260115094436_add_dashboard_metrics/migration.sql +59 -59
  109. package/templates/default/prisma/migrations/20260127172022_add_cascade_delete_to_step_parameters/migration.sql +34 -34
  110. package/templates/default/prisma/migrations/20260313093000_add_report_step_screenshot_path/migration.sql +1 -0
  111. package/templates/default/prisma/migrations/20260318120000_add_test_suite_context_to_test_run_test_case/migration.sql +20 -0
  112. package/templates/default/prisma/migrations/20260318173512_add_support_of_test_suite_level_runs/migration.sql +2 -0
  113. package/templates/default/prisma/schema.prisma +4 -0
  114. package/templates/default/scripts/install-playwright.ts +20 -0
  115. package/templates/default/scripts/protect-seeded-files.ts +38 -38
  116. package/templates/default/scripts/regenerate-features.ts +94 -94
  117. package/templates/default/scripts/setup-env.ts +19 -19
  118. package/templates/default/scripts/sync-all.ts +22 -66
  119. package/templates/default/scripts/sync-appraise-base-template.ts +57 -19
  120. package/templates/default/scripts/sync-environments.ts +40 -21
  121. package/templates/default/scripts/sync-locator-groups.ts +410 -410
  122. package/templates/default/scripts/sync-locators.ts +398 -398
  123. package/templates/default/scripts/sync-modules.ts +341 -341
  124. package/templates/default/scripts/sync-tags.ts +2 -3
  125. package/templates/default/scripts/sync-template-step-groups.ts +0 -3
  126. package/templates/default/scripts/sync-template-steps.ts +37 -11
  127. package/templates/default/scripts/sync-test-cases.ts +68 -16
  128. package/templates/default/scripts/sync-test-suites.ts +7 -5
  129. package/templates/default/src/actions/conflict/conflict.action.ts +33 -33
  130. package/templates/default/src/actions/dashboard/dashboard-actions.ts +240 -240
  131. package/templates/default/src/actions/environments/environment-actions.ts +188 -188
  132. package/templates/default/src/actions/locator/locator-actions.ts +490 -490
  133. package/templates/default/src/actions/locator-groups/locator-group-actions.ts +6 -3
  134. package/templates/default/src/actions/locator-picker/locator-picker-actions.ts +243 -0
  135. package/templates/default/src/actions/modules/module-actions.ts +135 -135
  136. package/templates/default/src/actions/reports/report-actions.ts +51 -49
  137. package/templates/default/src/actions/review/review-actions.ts +147 -147
  138. package/templates/default/src/actions/settings/sync-actions.ts +46 -0
  139. package/templates/default/src/actions/tags/tag-actions.ts +107 -107
  140. package/templates/default/src/actions/template-step/template-step-actions.ts +38 -4
  141. package/templates/default/src/actions/template-step-group/template-step-group-actions.ts +10 -3
  142. package/templates/default/src/actions/template-test-case/template-test-case-actions.ts +238 -238
  143. package/templates/default/src/actions/test-case/test-case-actions.ts +356 -356
  144. package/templates/default/src/actions/test-run/test-run-actions.ts +222 -129
  145. package/templates/default/src/actions/test-suite/test-suite-actions.ts +95 -17
  146. package/templates/default/src/actions/user/user-actions.ts +13 -13
  147. package/templates/default/src/app/(base)/environments/create/page.tsx +28 -28
  148. package/templates/default/src/app/(base)/environments/environment-form.tsx +219 -219
  149. package/templates/default/src/app/(base)/environments/environment-table-columns.tsx +96 -96
  150. package/templates/default/src/app/(base)/environments/environment-table.tsx +24 -24
  151. package/templates/default/src/app/(base)/environments/modify/[id]/page.tsx +46 -46
  152. package/templates/default/src/app/(base)/environments/page.tsx +59 -59
  153. package/templates/default/src/app/(base)/layout.tsx +10 -10
  154. package/templates/default/src/app/(base)/locator-groups/create/page.tsx +44 -44
  155. package/templates/default/src/app/(base)/locator-groups/locator-group-form.tsx +215 -215
  156. package/templates/default/src/app/(base)/locator-groups/locator-group-table-columns.tsx +77 -77
  157. package/templates/default/src/app/(base)/locator-groups/locator-group-table.tsx +28 -28
  158. package/templates/default/src/app/(base)/locator-groups/modify/[id]/page.tsx +46 -46
  159. package/templates/default/src/app/(base)/locator-groups/page.tsx +20 -8
  160. package/templates/default/src/app/(base)/locators/create/create-locator-workspace.tsx +542 -0
  161. package/templates/default/src/app/(base)/locators/create/page.tsx +32 -19
  162. package/templates/default/src/app/(base)/locators/locator-form.tsx +163 -163
  163. package/templates/default/src/app/(base)/locators/locator-table-columns.tsx +73 -73
  164. package/templates/default/src/app/(base)/locators/locator-table.tsx +28 -28
  165. package/templates/default/src/app/(base)/locators/modify/[id]/page.tsx +56 -27
  166. package/templates/default/src/app/(base)/locators/page.tsx +13 -13
  167. package/templates/default/src/app/(base)/locators/picker/page.tsx +7 -0
  168. package/templates/default/src/app/(base)/locators/sync-locators-button.tsx +66 -66
  169. package/templates/default/src/app/(base)/modules/create/page.tsx +34 -34
  170. package/templates/default/src/app/(base)/modules/modify/[id]/page.tsx +46 -46
  171. package/templates/default/src/app/(base)/modules/module-form.tsx +126 -126
  172. package/templates/default/src/app/(base)/modules/module-table-columns.tsx +85 -85
  173. package/templates/default/src/app/(base)/modules/module-table.tsx +24 -24
  174. package/templates/default/src/app/(base)/modules/page.tsx +59 -59
  175. package/templates/default/src/app/(base)/reports/[id]/page.tsx +40 -33
  176. package/templates/default/src/app/(base)/reports/duration-chart.tsx +33 -33
  177. package/templates/default/src/app/(base)/reports/feature-chart.tsx +78 -78
  178. package/templates/default/src/app/(base)/reports/overview-chart.tsx +49 -46
  179. package/templates/default/src/app/(base)/reports/page.tsx +98 -98
  180. package/templates/default/src/app/(base)/reports/report-metric-card.tsx +78 -16
  181. package/templates/default/src/app/(base)/reports/report-table-columns.tsx +189 -189
  182. package/templates/default/src/app/(base)/reports/report-table.tsx +72 -72
  183. package/templates/default/src/app/(base)/reports/report-view-table-columns.tsx +12 -1
  184. package/templates/default/src/app/(base)/reports/report-view-table.tsx +1 -0
  185. package/templates/default/src/app/(base)/reports/test-cases/page.tsx +40 -42
  186. package/templates/default/src/app/(base)/reports/test-cases/test-cases-metric-table-columns.tsx +115 -115
  187. package/templates/default/src/app/(base)/reports/test-cases/test-cases-metric-table.tsx +27 -27
  188. package/templates/default/src/app/(base)/reports/test-suites/page.tsx +42 -42
  189. package/templates/default/src/app/(base)/reports/test-suites/test-suites-metric-table-columns.tsx +79 -79
  190. package/templates/default/src/app/(base)/reports/test-suites/test-suites-metric-table.tsx +27 -27
  191. package/templates/default/src/app/(base)/reports/view-logs-button.tsx +58 -60
  192. package/templates/default/src/app/(base)/reviews/create/page.tsx +26 -26
  193. package/templates/default/src/app/(base)/reviews/created-reviews-table.tsx +15 -15
  194. package/templates/default/src/app/(base)/reviews/modify/[id]/page.tsx +26 -26
  195. package/templates/default/src/app/(base)/reviews/page.tsx +26 -26
  196. package/templates/default/src/app/(base)/reviews/review/[id]/page.tsx +26 -26
  197. package/templates/default/src/app/(base)/reviews/review-form.tsx +11 -11
  198. package/templates/default/src/app/(base)/reviews/review-table-by-creator-columns.tsx +9 -9
  199. package/templates/default/src/app/(base)/reviews/review-table-by-reviewer-columns.tsx +9 -9
  200. package/templates/default/src/app/(base)/reviews/reviewer-reviews-table.tsx +15 -15
  201. package/templates/default/src/app/(base)/settings/page.tsx +30 -0
  202. package/templates/default/src/app/(base)/settings/settings-sync-panel.tsx +261 -0
  203. package/templates/default/src/app/(base)/tags/create/page.tsx +39 -39
  204. package/templates/default/src/app/(base)/tags/modify/[id]/page.tsx +50 -50
  205. package/templates/default/src/app/(base)/tags/page.tsx +58 -58
  206. package/templates/default/src/app/(base)/tags/tag-form.tsx +147 -147
  207. package/templates/default/src/app/(base)/tags/tag-table-columns.tsx +63 -63
  208. package/templates/default/src/app/(base)/tags/tag-table.tsx +29 -29
  209. package/templates/default/src/app/(base)/template-step-groups/create/page.tsx +28 -28
  210. package/templates/default/src/app/(base)/template-step-groups/modify/[id]/page.tsx +45 -45
  211. package/templates/default/src/app/(base)/template-step-groups/page.tsx +60 -60
  212. package/templates/default/src/app/(base)/template-step-groups/template-step-group-form.tsx +167 -167
  213. package/templates/default/src/app/(base)/template-step-groups/template-step-group-table-columns.tsx +89 -89
  214. package/templates/default/src/app/(base)/template-step-groups/template-step-group-table.tsx +32 -32
  215. package/templates/default/src/app/(base)/template-steps/create/page.tsx +37 -37
  216. package/templates/default/src/app/(base)/template-steps/modify/[id]/page.tsx +49 -49
  217. package/templates/default/src/app/(base)/template-steps/page.tsx +58 -58
  218. package/templates/default/src/app/(base)/template-steps/paramChip.tsx +213 -213
  219. package/templates/default/src/app/(base)/template-steps/template-step-form.tsx +384 -384
  220. package/templates/default/src/app/(base)/template-steps/template-step-table-columns.tsx +158 -158
  221. package/templates/default/src/app/(base)/template-steps/template-step-table.tsx +24 -24
  222. package/templates/default/src/app/(base)/template-test-cases/create/page.tsx +56 -56
  223. package/templates/default/src/app/(base)/template-test-cases/modify/[id]/page.tsx +89 -89
  224. package/templates/default/src/app/(base)/template-test-cases/page.tsx +58 -58
  225. package/templates/default/src/app/(base)/template-test-cases/template-test-case-flow.tsx +84 -84
  226. package/templates/default/src/app/(base)/template-test-cases/template-test-case-form.tsx +262 -262
  227. package/templates/default/src/app/(base)/template-test-cases/template-test-case-table-columns.tsx +76 -76
  228. package/templates/default/src/app/(base)/template-test-cases/template-test-case-table.tsx +32 -32
  229. package/templates/default/src/app/(base)/test-cases/create/page.tsx +76 -76
  230. package/templates/default/src/app/(base)/test-cases/create-from-template/generate/[id]/page.tsx +96 -96
  231. package/templates/default/src/app/(base)/test-cases/create-from-template/page.tsx +38 -38
  232. package/templates/default/src/app/(base)/test-cases/create-from-template/template-selection-form.tsx +73 -73
  233. package/templates/default/src/app/(base)/test-cases/modify/[id]/page.tsx +106 -106
  234. package/templates/default/src/app/(base)/test-cases/page.tsx +2 -2
  235. package/templates/default/src/app/(base)/test-cases/test-case-flow.tsx +82 -82
  236. package/templates/default/src/app/(base)/test-cases/test-case-form.tsx +395 -395
  237. package/templates/default/src/app/(base)/test-cases/test-case-table-columns.tsx +6 -71
  238. package/templates/default/src/app/(base)/test-cases/test-case-table.tsx +2 -2
  239. package/templates/default/src/app/(base)/test-runs/[id]/page.tsx +4 -1
  240. package/templates/default/src/app/(base)/test-runs/create/page.tsx +11 -9
  241. package/templates/default/src/app/(base)/test-runs/page.tsx +60 -60
  242. package/templates/default/src/app/(base)/test-runs/test-run-form.tsx +37 -44
  243. package/templates/default/src/app/(base)/test-runs/test-run-table-columns.tsx +229 -229
  244. package/templates/default/src/app/(base)/test-runs/test-run-table.tsx +127 -127
  245. package/templates/default/src/app/(base)/test-suites/create/page.tsx +3 -2
  246. package/templates/default/src/app/(base)/test-suites/modify/[id]/page.tsx +2 -1
  247. package/templates/default/src/app/(base)/test-suites/page.tsx +57 -21
  248. package/templates/default/src/app/(base)/test-suites/test-suite-form.tsx +16 -17
  249. package/templates/default/src/app/(base)/test-suites/test-suite-table-columns.tsx +2 -1
  250. package/templates/default/src/app/(base)/test-suites/test-suite-table.tsx +29 -29
  251. package/templates/default/src/app/(dashboard-components)/app-drawer.tsx +187 -187
  252. package/templates/default/src/app/(dashboard-components)/data-card-grid.tsx +12 -12
  253. package/templates/default/src/app/(dashboard-components)/data-card.tsx +26 -26
  254. package/templates/default/src/app/(dashboard-components)/execution-health-panel.tsx +56 -56
  255. package/templates/default/src/app/(dashboard-components)/ongoing-test-runs-card.tsx +87 -87
  256. package/templates/default/src/app/(dashboard-components)/quick-actions-drawer.tsx +44 -44
  257. package/templates/default/src/app/api/reports/steps/[stepId]/screenshot/route.ts +52 -0
  258. package/templates/default/src/app/api/test-runs/[runId]/download/route.ts +97 -34
  259. package/templates/default/src/app/api/test-runs/[runId]/logs/route.ts +4 -1
  260. package/templates/default/src/app/api/test-runs/[runId]/trace/[testCaseId]/route.ts +146 -147
  261. package/templates/default/src/app/globals.css +147 -147
  262. package/templates/default/src/app/layout.tsx +4 -0
  263. package/templates/default/src/app/page.tsx +2 -0
  264. package/templates/default/src/assets/icons/empty-tube.tsx +23 -23
  265. package/templates/default/src/assets/icons/tube-plus.tsx +29 -29
  266. package/templates/default/src/components/base-node.tsx +21 -21
  267. package/templates/default/src/components/chart/pie-chart.tsx +73 -73
  268. package/templates/default/src/components/data-extraction/locator-inspector.tsx +460 -460
  269. package/templates/default/src/components/data-state/empty-state.tsx +40 -40
  270. package/templates/default/src/components/data-visualization/info-card.tsx +70 -70
  271. package/templates/default/src/components/data-visualization/info-grid.tsx +22 -22
  272. package/templates/default/src/components/diagram/button-edge.tsx +54 -54
  273. package/templates/default/src/components/diagram/dynamic-parameters.tsx +474 -474
  274. package/templates/default/src/components/diagram/edit-header-option.tsx +36 -36
  275. package/templates/default/src/components/diagram/flow-diagram.tsx +470 -470
  276. package/templates/default/src/components/diagram/node-form.tsx +262 -262
  277. package/templates/default/src/components/diagram/options-header-node.tsx +57 -57
  278. package/templates/default/src/components/diagram/template-step-combobox.tsx +155 -155
  279. package/templates/default/src/components/form/error-message.tsx +7 -7
  280. package/templates/default/src/components/kokonutui/smooth-tab.tsx +453 -453
  281. package/templates/default/src/components/loading-skeleton/data-table/data-table-skeleton.tsx +30 -30
  282. package/templates/default/src/components/loading-skeleton/form/button-skeleton.tsx +8 -8
  283. package/templates/default/src/components/loading-skeleton/form/icon-button-skeleton.tsx +8 -8
  284. package/templates/default/src/components/loading-skeleton/form/text-input-skeleton.tsx +8 -8
  285. package/templates/default/src/components/loading-skeleton/visualization/table-skeleton.tsx +14 -14
  286. package/templates/default/src/components/logo.tsx +15 -15
  287. package/templates/default/src/components/navigation/command-badge.tsx +34 -34
  288. package/templates/default/src/components/navigation/command-chain-input.tsx +51 -51
  289. package/templates/default/src/components/navigation/entity-search-command.tsx +116 -116
  290. package/templates/default/src/components/navigation/nav-card.tsx +31 -31
  291. package/templates/default/src/components/navigation/nav-command.tsx +13 -0
  292. package/templates/default/src/components/navigation/nav-link.tsx +60 -60
  293. package/templates/default/src/components/navigation/nav-menu-card-deck.tsx +112 -112
  294. package/templates/default/src/components/node-header.tsx +159 -159
  295. package/templates/default/src/components/reports/test-case-logs-modal.tsx +310 -253
  296. package/templates/default/src/components/table/table-actions.tsx +172 -172
  297. package/templates/default/src/components/test-case/test-case-columns.tsx +76 -0
  298. package/templates/default/src/components/test-case/test-case-picker.tsx +244 -0
  299. package/templates/default/src/components/test-run/download-logs-button.tsx +92 -99
  300. package/templates/default/src/components/test-run/log-viewer.tsx +1 -14
  301. package/templates/default/src/components/test-run/test-run-details.tsx +15 -2
  302. package/templates/default/src/components/test-run/test-run-header.tsx +149 -149
  303. package/templates/default/src/components/test-run/view-report-button.tsx +102 -102
  304. package/templates/default/src/components/test-suite/test-suite-picker.tsx +444 -0
  305. package/templates/default/src/components/theme/mode-toggle.tsx +54 -54
  306. package/templates/default/src/components/theme/theme-provider.tsx +8 -8
  307. package/templates/default/src/components/typography/page-header-subtitle.tsx +7 -7
  308. package/templates/default/src/components/typography/page-header.tsx +7 -7
  309. package/templates/default/src/components/ui/alert-dialog.tsx +106 -106
  310. package/templates/default/src/components/ui/alert.tsx +43 -43
  311. package/templates/default/src/components/ui/avatar.tsx +40 -40
  312. package/templates/default/src/components/ui/badge.tsx +29 -29
  313. package/templates/default/src/components/ui/button.tsx +47 -47
  314. package/templates/default/src/components/ui/calendar.tsx +158 -158
  315. package/templates/default/src/components/ui/card.tsx +43 -43
  316. package/templates/default/src/components/ui/checkbox.tsx +28 -28
  317. package/templates/default/src/components/ui/command.tsx +135 -135
  318. package/templates/default/src/components/ui/data-table-column-header.tsx +61 -61
  319. package/templates/default/src/components/ui/data-table-pagination.tsx +87 -87
  320. package/templates/default/src/components/ui/data-table-view-options.tsx +50 -50
  321. package/templates/default/src/components/ui/data-table.tsx +261 -261
  322. package/templates/default/src/components/ui/dialog.tsx +97 -97
  323. package/templates/default/src/components/ui/dropdown-menu.tsx +182 -182
  324. package/templates/default/src/components/ui/input.tsx +22 -22
  325. package/templates/default/src/components/ui/kbd.tsx +28 -28
  326. package/templates/default/src/components/ui/label.tsx +19 -19
  327. package/templates/default/src/components/ui/loading.tsx +12 -12
  328. package/templates/default/src/components/ui/multi-select-with-preview.tsx +116 -116
  329. package/templates/default/src/components/ui/multi-select.tsx +142 -142
  330. package/templates/default/src/components/ui/navigation-menu.tsx +120 -120
  331. package/templates/default/src/components/ui/popover.tsx +33 -33
  332. package/templates/default/src/components/ui/progress.tsx +25 -25
  333. package/templates/default/src/components/ui/radio-group.tsx +44 -44
  334. package/templates/default/src/components/ui/scroll-area.tsx +40 -40
  335. package/templates/default/src/components/ui/select.tsx +151 -151
  336. package/templates/default/src/components/ui/separator.tsx +22 -22
  337. package/templates/default/src/components/ui/skeleton.tsx +7 -7
  338. package/templates/default/src/components/ui/table.tsx +76 -76
  339. package/templates/default/src/components/ui/tabs.tsx +55 -55
  340. package/templates/default/src/components/ui/textarea.tsx +21 -21
  341. package/templates/default/src/components/ui/toast.tsx +113 -113
  342. package/templates/default/src/components/ui/toaster.tsx +26 -26
  343. package/templates/default/src/components/user-prompt/delete-prompt.tsx +87 -87
  344. package/templates/default/src/config/db-config.ts +10 -10
  345. package/templates/default/src/constants/form-opts/diagram/node-form.ts +30 -30
  346. package/templates/default/src/constants/form-opts/environment-form-opts.ts +24 -24
  347. package/templates/default/src/constants/form-opts/locator-form-opts.ts +20 -20
  348. package/templates/default/src/constants/form-opts/locator-group-form-opts.ts +28 -28
  349. package/templates/default/src/constants/form-opts/module-form-opts.ts +21 -21
  350. package/templates/default/src/constants/form-opts/review-form-opts.ts +23 -23
  351. package/templates/default/src/constants/form-opts/tag-form-opts.ts +42 -42
  352. package/templates/default/src/constants/form-opts/template-selection-form-opts.ts +16 -16
  353. package/templates/default/src/constants/form-opts/template-step-group-form-opts.ts +24 -24
  354. package/templates/default/src/constants/form-opts/template-test-case-form-opts.ts +39 -39
  355. package/templates/default/src/constants/form-opts/template-test-step-form-opts.ts +36 -36
  356. package/templates/default/src/constants/form-opts/test-case-form-opts.ts +43 -43
  357. package/templates/default/src/constants/form-opts/test-run-form-opts.ts +5 -3
  358. package/templates/default/src/constants/form-opts/test-suite-form-opts.ts +24 -24
  359. package/templates/default/src/hooks/use-toast.ts +187 -187
  360. package/templates/default/src/lib/automation/paths.ts +42 -12
  361. package/templates/default/src/lib/automation/projection-service.ts +2 -1
  362. package/templates/default/src/lib/bidirectional-sync.ts +432 -432
  363. package/templates/default/src/lib/database-sync.ts +2 -7
  364. package/templates/default/src/lib/environment-file-utils.ts +184 -184
  365. package/templates/default/src/lib/executor/local-executor-adapter.ts +24 -25
  366. package/templates/default/src/lib/executor/types.ts +2 -2
  367. package/templates/default/src/lib/feature-file-generator.ts +5 -66
  368. package/templates/default/src/lib/gherkin-parser.ts +259 -259
  369. package/templates/default/src/lib/locator-group-file-utils.ts +307 -307
  370. package/templates/default/src/lib/locator-picker/session-manager.ts +452 -0
  371. package/templates/default/src/lib/locator-picker/suggestions.ts +124 -0
  372. package/templates/default/src/lib/metrics/metric-calculator.ts +5 -0
  373. package/templates/default/src/lib/module-hierarchy-builder.ts +205 -205
  374. package/templates/default/src/lib/path-helpers/module-path.ts +71 -71
  375. package/templates/default/src/lib/process/task-spawner.ts +39 -2
  376. package/templates/default/src/lib/sync/projected-feature-utils.ts +113 -0
  377. package/templates/default/src/lib/sync/sync-executor.ts +130 -0
  378. package/templates/default/src/lib/sync/sync-pending-counts.test.ts +239 -0
  379. package/templates/default/src/lib/sync/sync-pending-counts.ts +1358 -0
  380. package/templates/default/src/lib/sync/sync-registry.ts +149 -0
  381. package/templates/default/src/lib/tag-utils.ts +28 -0
  382. package/templates/default/src/lib/template-sync-utils.d.ts +6 -6
  383. package/templates/default/src/lib/template-sync-utils.js +46 -46
  384. package/templates/default/src/lib/template-sync-utils.ts +63 -63
  385. package/templates/default/src/lib/test-case-utils.ts +6 -6
  386. package/templates/default/src/lib/test-run/log-formatter.ts +83 -83
  387. package/templates/default/src/lib/test-run/matching.ts +117 -0
  388. package/templates/default/src/lib/test-run/process-manager.ts +2 -0
  389. package/templates/default/src/lib/test-run/report-parser.ts +352 -316
  390. package/templates/default/src/lib/test-run/test-run-executor.ts +13 -15
  391. package/templates/default/src/lib/test-run/winston-logger.ts +64 -66
  392. package/templates/default/src/lib/test-suite-identifier-service.ts +76 -0
  393. package/templates/default/src/lib/test-suite-utils.ts +6 -0
  394. package/templates/default/src/lib/transformers/gherkin-converter.ts +42 -42
  395. package/templates/default/src/lib/transformers/key-to-icon-transformer.tsx +95 -95
  396. package/templates/default/src/lib/transformers/template-test-case-converter.ts +160 -160
  397. package/templates/default/src/lib/utils/node-param-validation.ts +81 -81
  398. package/templates/default/src/lib/utils/template-step-file-generator.ts +104 -104
  399. package/templates/default/src/lib/utils/template-step-file-manager-intelligent.ts +0 -8
  400. package/templates/default/src/lib/utils/template-step-file-manager.ts +166 -166
  401. package/templates/default/src/lib/utils.ts +31 -31
  402. package/templates/default/src/types/diagram/diagram.ts +34 -34
  403. package/templates/default/src/types/diagram/template-step.ts +11 -11
  404. package/templates/default/src/types/executor/browser.type.ts +1 -1
  405. package/templates/default/src/types/form/actionHandler.ts +6 -6
  406. package/templates/default/src/types/locator/locator.type.ts +11 -11
  407. package/templates/default/src/types/locator-picker.ts +65 -0
  408. package/templates/default/src/types/step/step.type.ts +1 -1
  409. package/templates/default/src/types/table/data-table.ts +6 -6
  410. package/templates/default/src/types/test-case-picker.ts +6 -0
  411. package/templates/default/src/types/test-suite-picker.ts +18 -0
  412. package/templates/default/tailwind.config.ts +62 -62
  413. package/templates/default/tsconfig.json +4 -1
  414. package/templates/default/appraisejs.config.json +0 -1
@@ -7,6 +7,7 @@
7
7
  "dev": "next dev",
8
8
  "init": "DISABLE_DEVTOOLS=1 NEXT_PUBLIC_DISABLE_DEVTOOLS=1 next dev",
9
9
  "build:cucumber-runtime": "tsc -p packages/cucumber-runtime/tsconfig.json",
10
+ "build:locator-picker-companion": "tsc -p packages/locator-picker-companion/tsconfig.json",
10
11
  "build": "npm run build:local",
11
12
  "start": "next start",
12
13
  "lint": "eslint .",
@@ -29,7 +30,7 @@
29
30
  "sync-all": "npx tsx scripts/sync-all.ts",
30
31
  "sync-template": "npx tsx scripts/sync-appraise-base-template.ts",
31
32
  "test": "cucumber-js",
32
- "build:local": "npm run generate-db-client && npm run build:cucumber-runtime && next build",
33
+ "build:local": "npm run generate-db-client && npm run build:cucumber-runtime && npm run build:locator-picker-companion && next build",
33
34
  "generate-db-client": "npx prisma generate --schema prisma/schema.prisma",
34
35
  "setup:db": "npm run setup-env && npm run generate-db-client && npm run migrate-db && npm run sync-all",
35
36
  "setup:full": "npm run install-dependencies && npm run setup:db && npm run build:local && npm run protect-seeded-files",
@@ -1,13 +1,13 @@
1
- {
2
- "name": "@appraise/cucumber-runtime",
3
- "private": true,
4
- "type": "module",
5
- "main": "./dist/index.js",
6
- "types": "./dist/index.d.ts",
7
- "exports": {
8
- ".": "./dist/index.js"
9
- },
10
- "scripts": {
11
- "build": "tsc -p tsconfig.json"
12
- }
13
- }
1
+ {
2
+ "name": "@appraise/cucumber-runtime",
3
+ "private": true,
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": "./dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc -p tsconfig.json"
12
+ }
13
+ }
@@ -1,93 +1,93 @@
1
- import { readFileSync } from 'fs'
2
- import { globSync } from 'glob'
3
- import * as path from 'path'
4
- import { LocatorCollection, LocatorMap } from './types.js'
5
- import { getAutomationLocatorMapPath, getAutomationLocatorsDir } from './paths.js'
6
-
7
- function toGlobPath(targetPath: string): string {
8
- return targetPath.split(path.sep).join('/')
9
- }
10
-
11
- export class LocatorCache {
12
- private static instance: LocatorCache
13
- private data: Record<string, LocatorCollection> = {}
14
- private filePaths: Record<string, string> = {}
15
- private loadedFiles: Set<string> = new Set()
16
-
17
- private constructor() {
18
- globSync(`${toGlobPath(getAutomationLocatorsDir())}/**/*.json`).forEach(file => {
19
- const fileName = path.basename(file, path.extname(file))
20
- this.filePaths[fileName ?? file] = file
21
- })
22
- }
23
-
24
- public static getInstance(): LocatorCache {
25
- if (!LocatorCache.instance) {
26
- LocatorCache.instance = new LocatorCache()
27
- }
28
- return LocatorCache.instance
29
- }
30
-
31
- public get(key: string): LocatorCollection | null {
32
- if (!this.loadedFiles.has(key) && this.filePaths[key]) {
33
- try {
34
- const filePath = this.filePaths[key]
35
- const data = JSON.parse(readFileSync(filePath, 'utf8'))
36
- this.data[key] = data as LocatorCollection
37
- this.loadedFiles.add(key)
38
- } catch (error) {
39
- console.error(`Error loading locator file for key "${key}":`, error)
40
- return null
41
- }
42
- }
43
-
44
- return this.data[key] ? { ...this.data[key] } : null
45
- }
46
-
47
- public preloadAll(): void {
48
- Object.keys(this.filePaths).forEach(key => {
49
- if (!this.loadedFiles.has(key)) {
50
- this.get(key)
51
- }
52
- })
53
- }
54
-
55
- public getAvailableKeys(): string[] {
56
- return Object.keys(this.filePaths)
57
- }
58
-
59
- public isLoaded(key: string): boolean {
60
- return this.loadedFiles.has(key)
61
- }
62
- }
63
-
64
- export class LocatorMapCache {
65
- private static instance: LocatorMapCache
66
- private data: LocatorMap[] = []
67
-
68
- private constructor() {
69
- this.data = JSON.parse(readFileSync(getAutomationLocatorMapPath(), 'utf8'))
70
- }
71
-
72
- public static getInstance(): LocatorMapCache {
73
- if (!LocatorMapCache.instance) {
74
- LocatorMapCache.instance = new LocatorMapCache()
75
- }
76
- return LocatorMapCache.instance
77
- }
78
-
79
- public get(key: string): LocatorMap {
80
- try {
81
- return this.data.find(map => map.path === key) as LocatorMap
82
- } catch {
83
- return {
84
- name: '',
85
- path: '',
86
- }
87
- }
88
- }
89
-
90
- public getAll(): LocatorMap[] {
91
- return this.data
92
- }
93
- }
1
+ import { readFileSync } from 'fs'
2
+ import { globSync } from 'glob'
3
+ import * as path from 'path'
4
+ import { LocatorCollection, LocatorMap } from './types.js'
5
+ import { getAutomationLocatorMapPath, getAutomationLocatorsDir } from './paths.js'
6
+
7
+ function toGlobPath(targetPath: string): string {
8
+ return targetPath.split(path.sep).join('/')
9
+ }
10
+
11
+ export class LocatorCache {
12
+ private static instance: LocatorCache
13
+ private data: Record<string, LocatorCollection> = {}
14
+ private filePaths: Record<string, string> = {}
15
+ private loadedFiles: Set<string> = new Set()
16
+
17
+ private constructor() {
18
+ globSync(`${toGlobPath(getAutomationLocatorsDir())}/**/*.json`).forEach(file => {
19
+ const fileName = path.basename(file, path.extname(file))
20
+ this.filePaths[fileName ?? file] = file
21
+ })
22
+ }
23
+
24
+ public static getInstance(): LocatorCache {
25
+ if (!LocatorCache.instance) {
26
+ LocatorCache.instance = new LocatorCache()
27
+ }
28
+ return LocatorCache.instance
29
+ }
30
+
31
+ public get(key: string): LocatorCollection | null {
32
+ if (!this.loadedFiles.has(key) && this.filePaths[key]) {
33
+ try {
34
+ const filePath = this.filePaths[key]
35
+ const data = JSON.parse(readFileSync(filePath, 'utf8'))
36
+ this.data[key] = data as LocatorCollection
37
+ this.loadedFiles.add(key)
38
+ } catch (error) {
39
+ console.error(`Error loading locator file for key "${key}":`, error)
40
+ return null
41
+ }
42
+ }
43
+
44
+ return this.data[key] ? { ...this.data[key] } : null
45
+ }
46
+
47
+ public preloadAll(): void {
48
+ Object.keys(this.filePaths).forEach(key => {
49
+ if (!this.loadedFiles.has(key)) {
50
+ this.get(key)
51
+ }
52
+ })
53
+ }
54
+
55
+ public getAvailableKeys(): string[] {
56
+ return Object.keys(this.filePaths)
57
+ }
58
+
59
+ public isLoaded(key: string): boolean {
60
+ return this.loadedFiles.has(key)
61
+ }
62
+ }
63
+
64
+ export class LocatorMapCache {
65
+ private static instance: LocatorMapCache
66
+ private data: LocatorMap[] = []
67
+
68
+ private constructor() {
69
+ this.data = JSON.parse(readFileSync(getAutomationLocatorMapPath(), 'utf8'))
70
+ }
71
+
72
+ public static getInstance(): LocatorMapCache {
73
+ if (!LocatorMapCache.instance) {
74
+ LocatorMapCache.instance = new LocatorMapCache()
75
+ }
76
+ return LocatorMapCache.instance
77
+ }
78
+
79
+ public get(key: string): LocatorMap {
80
+ try {
81
+ return this.data.find(map => map.path === key) as LocatorMap
82
+ } catch {
83
+ return {
84
+ name: '',
85
+ path: '',
86
+ }
87
+ }
88
+ }
89
+
90
+ public getAll(): LocatorMap[] {
91
+ return this.data
92
+ }
93
+ }
@@ -1,68 +1,68 @@
1
- import { Command, Option, OptionValues } from 'commander'
2
- import parseTagExpression from '@cucumber/tag-expressions'
3
- import { getAllEnvironments } from './environment.util.js'
4
- import { BrowserName } from './types.js'
5
-
6
- export interface CliOptions extends OptionValues {
7
- environment: string
8
- tags: string
9
- parallel: number
10
- browser: BrowserName
11
- headless: 'true' | 'false'
12
- }
13
-
14
- const BROWSER_CHOICES = ['chromium', 'firefox', 'webkit'] as const
15
- const HEADLESS_CHOICES = ['true', 'false'] as const
16
- const DEFAULT_PARALLEL_WORKERS = 1
17
- const DEFAULT_BROWSER: BrowserName = 'chromium'
18
- const DEFAULT_HEADLESS = 'true'
19
-
20
- const program = new Command()
21
-
22
- let environmentNames: string[] = []
23
- try {
24
- environmentNames = Object.keys(getAllEnvironments())
25
- } catch (error) {
26
- console.error('Failed to load environments:', error instanceof Error ? error.message : 'Unknown error')
27
- process.exit(1)
28
- }
29
-
30
- function parsePositiveInt(value: string): number {
31
- const parsed = Number(value)
32
- if (!Number.isInteger(parsed) || parsed <= 0) {
33
- throw new Error(`--parallel must be a positive integer, got "${value}"`)
34
- }
35
- return parsed
36
- }
37
-
38
- function validateCucumberTagExpression(value: string): string {
39
- try {
40
- parseTagExpression(value)
41
- return value
42
- } catch (error) {
43
- throw new Error(`Invalid tag expression: ${error instanceof Error ? error.message : 'Unknown error'}`)
44
- }
45
- }
46
-
47
- program
48
- .name('cucumber-runtime')
49
- .description('CLI for running Appraise cucumber automation')
50
- .version('1.0.0')
51
- .addOption(
52
- new Option('-e, --environment <environment>', 'The environment to run the tests on')
53
- .choices(environmentNames)
54
- .makeOptionMandatory(),
55
- )
56
- .addOption(
57
- new Option('-t, --tags <tags>', 'The tags to run the tests on')
58
- .argParser(validateCucumberTagExpression)
59
- .makeOptionMandatory(),
60
- )
61
- .option('-p, --parallel <parallel>', 'The number of parallel workers to run', parsePositiveInt, DEFAULT_PARALLEL_WORKERS)
62
- .addOption(new Option('-b, --browser <browser>', 'The browser to run').choices(BROWSER_CHOICES).default(DEFAULT_BROWSER))
63
- .addOption(new Option('--headless <headless>', 'Whether to run headless').choices(HEADLESS_CHOICES).default(DEFAULT_HEADLESS))
64
-
65
- export function startCli(): CliOptions {
66
- program.parse()
67
- return program.opts() as CliOptions
68
- }
1
+ import { Command, Option, OptionValues } from 'commander'
2
+ import parseTagExpression from '@cucumber/tag-expressions'
3
+ import { getAllEnvironments } from './environment.util.js'
4
+ import { BrowserName } from './types.js'
5
+
6
+ export interface CliOptions extends OptionValues {
7
+ environment: string
8
+ tags: string
9
+ parallel: number
10
+ browser: BrowserName
11
+ headless: 'true' | 'false'
12
+ }
13
+
14
+ const BROWSER_CHOICES = ['chromium', 'firefox', 'webkit'] as const
15
+ const HEADLESS_CHOICES = ['true', 'false'] as const
16
+ const DEFAULT_PARALLEL_WORKERS = 1
17
+ const DEFAULT_BROWSER: BrowserName = 'chromium'
18
+ const DEFAULT_HEADLESS = 'true'
19
+
20
+ const program = new Command()
21
+
22
+ let environmentNames: string[] = []
23
+ try {
24
+ environmentNames = Object.keys(getAllEnvironments())
25
+ } catch (error) {
26
+ console.error('Failed to load environments:', error instanceof Error ? error.message : 'Unknown error')
27
+ process.exit(1)
28
+ }
29
+
30
+ function parsePositiveInt(value: string): number {
31
+ const parsed = Number(value)
32
+ if (!Number.isInteger(parsed) || parsed <= 0) {
33
+ throw new Error(`--parallel must be a positive integer, got "${value}"`)
34
+ }
35
+ return parsed
36
+ }
37
+
38
+ function validateCucumberTagExpression(value: string): string {
39
+ try {
40
+ parseTagExpression(value)
41
+ return value
42
+ } catch (error) {
43
+ throw new Error(`Invalid tag expression: ${error instanceof Error ? error.message : 'Unknown error'}`)
44
+ }
45
+ }
46
+
47
+ program
48
+ .name('cucumber-runtime')
49
+ .description('CLI for running Appraise cucumber automation')
50
+ .version('1.0.0')
51
+ .addOption(
52
+ new Option('-e, --environment <environment>', 'The environment to run the tests on')
53
+ .choices(environmentNames)
54
+ .makeOptionMandatory(),
55
+ )
56
+ .addOption(
57
+ new Option('-t, --tags <tags>', 'The tags to run the tests on')
58
+ .argParser(validateCucumberTagExpression)
59
+ .makeOptionMandatory(),
60
+ )
61
+ .option('-p, --parallel <parallel>', 'The number of parallel workers to run', parsePositiveInt, DEFAULT_PARALLEL_WORKERS)
62
+ .addOption(new Option('-b, --browser <browser>', 'The browser to run').choices(BROWSER_CHOICES).default(DEFAULT_BROWSER))
63
+ .addOption(new Option('--headless <headless>', 'Whether to run headless').choices(HEADLESS_CHOICES).default(DEFAULT_HEADLESS))
64
+
65
+ export function startCli(): CliOptions {
66
+ program.parse()
67
+ return program.opts() as CliOptions
68
+ }
@@ -1,21 +1,21 @@
1
- import { readFileSync } from 'fs'
2
- import { getAutomationEnvironmentsFilePath } from './paths.js'
3
-
4
- interface EnvironmentConfig {
5
- baseUrl: string
6
- apiBaseUrl: string
7
- email: string
8
- password: string
9
- }
10
-
11
- export function getEnvironment(environment: string): EnvironmentConfig {
12
- const environmentConfig: Record<string, EnvironmentConfig> = JSON.parse(
13
- readFileSync(getAutomationEnvironmentsFilePath(), 'utf8'),
14
- )
15
-
16
- return environmentConfig[environment.toLowerCase()] as EnvironmentConfig
17
- }
18
-
19
- export function getAllEnvironments(): Record<string, EnvironmentConfig> {
20
- return JSON.parse(readFileSync(getAutomationEnvironmentsFilePath(), 'utf8'))
21
- }
1
+ import { readFileSync } from 'fs'
2
+ import { getAutomationEnvironmentsFilePath } from './paths.js'
3
+
4
+ interface EnvironmentConfig {
5
+ baseUrl: string
6
+ apiBaseUrl: string
7
+ email: string
8
+ password: string
9
+ }
10
+
11
+ export function getEnvironment(environment: string): EnvironmentConfig {
12
+ const environmentConfig: Record<string, EnvironmentConfig> = JSON.parse(
13
+ readFileSync(getAutomationEnvironmentsFilePath(), 'utf8'),
14
+ )
15
+
16
+ return environmentConfig[environment.toLowerCase()] as EnvironmentConfig
17
+ }
18
+
19
+ export function getAllEnvironments(): Record<string, EnvironmentConfig> {
20
+ return JSON.parse(readFileSync(getAutomationEnvironmentsFilePath(), 'utf8'))
21
+ }
@@ -1,32 +1,32 @@
1
- import { execa } from 'execa'
2
- import { config } from 'dotenv'
3
- import { startCli } from './cli.js'
4
-
5
- async function bootstrap(): Promise<void> {
6
- config()
7
-
8
- try {
9
- const { environment, tags, parallel, browser, headless } = startCli()
10
-
11
- process.env.ENVIRONMENT = environment
12
- process.env.HEADLESS = headless
13
- process.env.BROWSER = browser
14
-
15
- const cucumberArgs: string[] = ['cucumber-js', '-t', tags]
16
- if (parallel > 1) {
17
- cucumberArgs.push('--parallel', parallel.toString())
18
- }
19
-
20
- const subprocess = execa('npx', cucumberArgs, {
21
- stdio: 'inherit',
22
- })
23
-
24
- const result = await subprocess
25
- process.exit(result.exitCode ?? 0)
26
- } catch (error) {
27
- console.error(error instanceof Error ? error.message : 'Unknown error')
28
- process.exit(1)
29
- }
30
- }
31
-
32
- bootstrap()
1
+ import { execa } from 'execa'
2
+ import { config } from 'dotenv'
3
+ import { startCli } from './cli.js'
4
+
5
+ async function bootstrap(): Promise<void> {
6
+ config()
7
+
8
+ try {
9
+ const { environment, tags, parallel, browser, headless } = startCli()
10
+
11
+ process.env.ENVIRONMENT = environment
12
+ process.env.HEADLESS = headless
13
+ process.env.BROWSER = browser
14
+
15
+ const cucumberArgs: string[] = ['cucumber-js', '-t', tags]
16
+ if (parallel > 1) {
17
+ cucumberArgs.push('--parallel', parallel.toString())
18
+ }
19
+
20
+ const subprocess = execa('npx', cucumberArgs, {
21
+ stdio: 'inherit',
22
+ })
23
+
24
+ const result = await subprocess
25
+ process.exit(result.exitCode ?? 0)
26
+ } catch (error) {
27
+ console.error(error instanceof Error ? error.message : 'Unknown error')
28
+ process.exit(1)
29
+ }
30
+ }
31
+
32
+ bootstrap()
@@ -2,12 +2,13 @@ import { After, AfterAll, AfterStep, Before, BeforeAll, setDefaultTimeout } from
2
2
  import { config } from 'dotenv'
3
3
  import { promises as fs } from 'fs'
4
4
  import { chromium, firefox, webkit, ChromiumBrowser, FirefoxBrowser, WebKitBrowser } from 'playwright'
5
- import { getAutomationTraceDir } from './paths.js'
5
+ import { getAutomationScreenshotDir, getAutomationTraceDir, toProjectRelativePath } from './paths.js'
6
6
  import { BrowserName } from './types.js'
7
7
  import { CustomWorld } from './world.js'
8
8
 
9
9
  config()
10
10
 
11
+ const SCREENSHOT_ATTACHMENT_MEDIA_TYPE = 'application/vnd.appraisejs.report-step-screenshot+json'
11
12
  let browser: ChromiumBrowser | FirefoxBrowser | WebKitBrowser
12
13
  let currentScenarioStatus = 'unknown'
13
14
 
@@ -45,6 +46,24 @@ AfterStep(async function (this: CustomWorld, result) {
45
46
  const status = result.result?.status
46
47
  if (status === 'FAILED') {
47
48
  currentScenarioStatus = 'failed'
49
+
50
+ if (result.pickleStep?.text) {
51
+ try {
52
+ const screenshotDir = getAutomationScreenshotDir()
53
+ await fs.mkdir(screenshotDir, { recursive: true })
54
+
55
+ const screenshotPath = `${screenshotDir}/${crypto.randomUUID()}.png`
56
+ await this.page.screenshot({ path: screenshotPath, fullPage: true })
57
+ await this.attach(
58
+ JSON.stringify({ screenshotPath: toProjectRelativePath(screenshotPath) }),
59
+ SCREENSHOT_ATTACHMENT_MEDIA_TYPE,
60
+ )
61
+ } catch (error) {
62
+ console.warn(
63
+ `[CucumberRuntime] Failed to capture screenshot for step "${result.pickleStep.text}": ${error instanceof Error ? error.message : 'Unknown error'}`,
64
+ )
65
+ }
66
+ }
48
67
  } else if (status === 'SKIPPED' && currentScenarioStatus !== 'failed') {
49
68
  currentScenarioStatus = 'skipped'
50
69
  } else if (status === 'PASSED' && currentScenarioStatus === 'unknown') {
@@ -57,14 +76,17 @@ After(async function (this: CustomWorld, scenario) {
57
76
  if (scenario.result?.status === 'FAILED') {
58
77
  const traceDir = getAutomationTraceDir()
59
78
  await fs.mkdir(traceDir, { recursive: true })
60
- tracePath = `${traceDir}/${crypto.randomUUID()}.zip`
61
- await this.context.tracing.stop({ path: tracePath })
79
+ const absoluteTracePath = `${traceDir}/${crypto.randomUUID()}.zip`
80
+ tracePath = toProjectRelativePath(absoluteTracePath)
81
+ await this.context.tracing.stop({ path: absoluteTracePath })
62
82
  }
63
83
 
64
84
  const eventJson = JSON.stringify({
65
85
  event: 'scenario::end',
66
86
  data: {
87
+ featureName: scenario.gherkinDocument?.feature?.name,
67
88
  scenarioName: scenario.pickle.name,
89
+ scenarioTags: scenario.pickle.tags?.map(tag => tag.name) ?? [],
68
90
  status: currentScenarioStatus,
69
91
  tracePath,
70
92
  },
@@ -1,17 +1,17 @@
1
- export {
2
- After,
3
- AfterAll,
4
- AfterStep,
5
- Before,
6
- BeforeAll,
7
- Given,
8
- Then,
9
- When,
10
- defineParameterType,
11
- setDefaultTimeout,
12
- } from '@cucumber/cucumber'
13
- export { CustomWorld, expect } from './world.js'
14
- export { getEnvironment, getAllEnvironments } from './environment.util.js'
15
- export { resolveLocator, retry, waitForRouteSettled } from './locator.util.js'
16
- export { generateRandomData, RandomDataType } from './random-data.util.js'
17
- export type { BrowserName, Locator, LocatorCollection, LocatorMap, Selector, SelectorName } from './types.js'
1
+ export {
2
+ After,
3
+ AfterAll,
4
+ AfterStep,
5
+ Before,
6
+ BeforeAll,
7
+ Given,
8
+ Then,
9
+ When,
10
+ defineParameterType,
11
+ setDefaultTimeout,
12
+ } from '@cucumber/cucumber'
13
+ export { CustomWorld, expect } from './world.js'
14
+ export { getEnvironment, getAllEnvironments } from './environment.util.js'
15
+ export { resolveLocator, retry, waitForRouteSettled } from './locator.util.js'
16
+ export { generateRandomData, RandomDataType } from './random-data.util.js'
17
+ export type { BrowserName, Locator, LocatorCollection, LocatorMap, Selector, SelectorName } from './types.js'