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.
- package/README.md +52 -52
- package/dist/cli.e2e.test.d.ts +2 -0
- package/dist/cli.e2e.test.d.ts.map +1 -0
- package/dist/cli.e2e.test.js +73 -0
- package/dist/cli.e2e.test.js.map +1 -0
- package/dist/config.test.d.ts +2 -0
- package/dist/config.test.d.ts.map +1 -0
- package/dist/config.test.js +65 -0
- package/dist/config.test.js.map +1 -0
- package/dist/copy-template.test.d.ts +2 -0
- package/dist/copy-template.test.d.ts.map +1 -0
- package/dist/copy-template.test.js +71 -0
- package/dist/copy-template.test.js.map +1 -0
- package/dist/download-repo.test.d.ts +2 -0
- package/dist/download-repo.test.d.ts.map +1 -0
- package/dist/download-repo.test.js +14 -0
- package/dist/download-repo.test.js.map +1 -0
- package/dist/install.test.d.ts +2 -0
- package/dist/install.test.d.ts.map +1 -0
- package/dist/install.test.js +119 -0
- package/dist/install.test.js.map +1 -0
- package/dist/prepare-template-utils.d.ts.map +1 -1
- package/dist/prepare-template-utils.js +5 -0
- package/dist/prepare-template-utils.js.map +1 -1
- package/dist/prompts.test.d.ts +2 -0
- package/dist/prompts.test.d.ts.map +1 -0
- package/dist/prompts.test.js +58 -0
- package/dist/prompts.test.js.map +1 -0
- package/dist/scaffold-gitignore.d.ts +1 -0
- package/dist/scaffold-gitignore.d.ts.map +1 -1
- package/dist/scaffold-gitignore.js +3 -0
- package/dist/scaffold-gitignore.js.map +1 -1
- package/package.json +3 -2
- package/templates/default/.appraise-template-meta.json +2 -2
- package/templates/default/.env.example +2 -2
- package/templates/default/.vscode/settings.json +2 -1
- package/templates/default/README.md +53 -53
- package/templates/default/automation/mapping/locator-map.json +1 -14
- package/templates/default/automation/steps/actions/click.step.ts +58 -58
- package/templates/default/automation/steps/actions/hover.step.ts +27 -27
- package/templates/default/automation/steps/actions/input.step.ts +84 -84
- package/templates/default/automation/steps/actions/navigation.step.ts +70 -70
- package/templates/default/automation/steps/actions/random_data.step.ts +142 -142
- package/templates/default/automation/steps/actions/store.step.ts +86 -86
- package/templates/default/automation/steps/actions/wait.step.ts +90 -90
- package/templates/default/automation/steps/validations/active_state_assertion.step.ts +30 -30
- package/templates/default/automation/steps/validations/navigation_assertion.step.ts +22 -22
- package/templates/default/automation/steps/validations/text_assertion.step.ts +107 -107
- package/templates/default/automation/steps/validations/visibility_assertion.step.ts +26 -26
- package/templates/default/components.json +24 -24
- package/templates/default/cucumber.mjs +16 -16
- package/templates/default/eslint.config.mjs +16 -16
- package/templates/default/gitignore +3 -0
- package/templates/default/next-env.d.ts +6 -6
- package/templates/default/next.config.ts +11 -11
- package/templates/default/package-lock.json +146 -75
- package/templates/default/package.json +2 -1
- package/templates/default/packages/cucumber-runtime/package.json +13 -13
- package/templates/default/packages/cucumber-runtime/src/cache.util.ts +93 -93
- package/templates/default/packages/cucumber-runtime/src/cli.ts +68 -68
- package/templates/default/packages/cucumber-runtime/src/environment.util.ts +21 -21
- package/templates/default/packages/cucumber-runtime/src/executor.ts +32 -32
- package/templates/default/packages/cucumber-runtime/src/hooks.ts +25 -3
- package/templates/default/packages/cucumber-runtime/src/index.ts +17 -17
- package/templates/default/packages/cucumber-runtime/src/locator.util.ts +234 -234
- package/templates/default/packages/cucumber-runtime/src/parameter-types.ts +7 -7
- package/templates/default/packages/cucumber-runtime/src/paths.ts +66 -1
- package/templates/default/packages/cucumber-runtime/src/random-data.util.ts +35 -35
- package/templates/default/packages/cucumber-runtime/src/types.ts +13 -13
- package/templates/default/packages/cucumber-runtime/src/world.ts +44 -44
- package/templates/default/packages/cucumber-runtime/tsconfig.json +11 -11
- package/templates/default/packages/locator-picker-companion/dist/cli.d.ts +1 -0
- package/templates/default/packages/locator-picker-companion/dist/cli.js +302 -0
- package/templates/default/packages/locator-picker-companion/dist/index.d.ts +3 -0
- package/templates/default/packages/locator-picker-companion/dist/index.js +3 -0
- package/templates/default/packages/locator-picker-companion/dist/injected-picker-script.d.ts +1 -0
- package/templates/default/packages/locator-picker-companion/dist/injected-picker-script.js +615 -0
- package/templates/default/packages/locator-picker-companion/dist/launcher.d.ts +11 -0
- package/templates/default/packages/locator-picker-companion/dist/launcher.js +59 -0
- package/templates/default/packages/locator-picker-companion/dist/selector-generator.d.ts +3 -0
- package/templates/default/packages/locator-picker-companion/dist/selector-generator.js +257 -0
- package/templates/default/packages/locator-picker-companion/dist/session-file.d.ts +22 -0
- package/templates/default/packages/locator-picker-companion/dist/session-file.js +150 -0
- package/templates/default/packages/locator-picker-companion/dist/types.d.ts +31 -0
- package/templates/default/packages/locator-picker-companion/dist/types.js +1 -0
- package/templates/default/packages/locator-picker-companion/package.json +17 -0
- package/templates/default/packages/locator-picker-companion/src/cli.ts +428 -0
- package/templates/default/packages/locator-picker-companion/src/index.ts +3 -0
- package/templates/default/packages/locator-picker-companion/src/injected-picker-script.ts +771 -0
- package/templates/default/packages/locator-picker-companion/src/launcher.ts +77 -0
- package/templates/default/packages/locator-picker-companion/src/selector-generator.ts +339 -0
- package/templates/default/packages/locator-picker-companion/src/session-file.ts +226 -0
- package/templates/default/packages/locator-picker-companion/src/types.ts +42 -0
- package/templates/default/packages/locator-picker-companion/tsconfig.json +14 -0
- package/templates/default/postcss.config.mjs +8 -8
- package/templates/default/prisma/dev.db +0 -0
- package/templates/default/prisma/migrations/20251104113456_add_type_for_template_step_groups/migration.sql +16 -16
- package/templates/default/prisma/migrations/20251104170946_add_tags_to_test_suite_and_test_case/migration.sql +27 -27
- package/templates/default/prisma/migrations/20251112190024_add_cascade_delete_to_test_run_test_case/migration.sql +17 -17
- package/templates/default/prisma/migrations/20251113181100_add_test_run_log/migration.sql +12 -12
- package/templates/default/prisma/migrations/20251119191838_add_tag_type/migration.sql +28 -28
- package/templates/default/prisma/migrations/20251121164059_add_conflict_resolution/migration.sql +12 -12
- package/templates/default/prisma/migrations/20251223183400_add_report_model_to_db_schema/migration.sql +10 -10
- package/templates/default/prisma/migrations/20251223183637_add_report_test_case_entity_for_storing_test_results_for_individual_test_cases/migration.sql +10 -10
- package/templates/default/prisma/migrations/20251224083549_add_comprehensive_report_storage/migration.sql +108 -108
- package/templates/default/prisma/migrations/20251229194422_migrate_duration_to_string/migration.sql +55 -55
- package/templates/default/prisma/migrations/20251230124637_add_unique_constraint_to_test_run_name/migration.sql +27 -27
- package/templates/default/prisma/migrations/20260115094436_add_dashboard_metrics/migration.sql +59 -59
- package/templates/default/prisma/migrations/20260127172022_add_cascade_delete_to_step_parameters/migration.sql +34 -34
- package/templates/default/prisma/migrations/20260313093000_add_report_step_screenshot_path/migration.sql +1 -0
- package/templates/default/prisma/migrations/20260318120000_add_test_suite_context_to_test_run_test_case/migration.sql +20 -0
- package/templates/default/prisma/migrations/20260318173512_add_support_of_test_suite_level_runs/migration.sql +2 -0
- package/templates/default/prisma/schema.prisma +4 -0
- package/templates/default/scripts/install-playwright.ts +20 -0
- package/templates/default/scripts/protect-seeded-files.ts +38 -38
- package/templates/default/scripts/regenerate-features.ts +94 -94
- package/templates/default/scripts/setup-env.ts +19 -19
- package/templates/default/scripts/sync-all.ts +22 -66
- package/templates/default/scripts/sync-appraise-base-template.ts +57 -19
- package/templates/default/scripts/sync-environments.ts +40 -21
- package/templates/default/scripts/sync-locator-groups.ts +410 -410
- package/templates/default/scripts/sync-locators.ts +398 -398
- package/templates/default/scripts/sync-modules.ts +341 -341
- package/templates/default/scripts/sync-tags.ts +2 -3
- package/templates/default/scripts/sync-template-step-groups.ts +0 -3
- package/templates/default/scripts/sync-template-steps.ts +37 -11
- package/templates/default/scripts/sync-test-cases.ts +68 -16
- package/templates/default/scripts/sync-test-suites.ts +7 -5
- package/templates/default/src/actions/conflict/conflict.action.ts +33 -33
- package/templates/default/src/actions/dashboard/dashboard-actions.ts +240 -240
- package/templates/default/src/actions/environments/environment-actions.ts +188 -188
- package/templates/default/src/actions/locator/locator-actions.ts +490 -490
- package/templates/default/src/actions/locator-groups/locator-group-actions.ts +6 -3
- package/templates/default/src/actions/locator-picker/locator-picker-actions.ts +243 -0
- package/templates/default/src/actions/modules/module-actions.ts +135 -135
- package/templates/default/src/actions/reports/report-actions.ts +51 -49
- package/templates/default/src/actions/review/review-actions.ts +147 -147
- package/templates/default/src/actions/settings/sync-actions.ts +46 -0
- package/templates/default/src/actions/tags/tag-actions.ts +107 -107
- package/templates/default/src/actions/template-step/template-step-actions.ts +38 -4
- package/templates/default/src/actions/template-step-group/template-step-group-actions.ts +10 -3
- package/templates/default/src/actions/template-test-case/template-test-case-actions.ts +238 -238
- package/templates/default/src/actions/test-case/test-case-actions.ts +356 -356
- package/templates/default/src/actions/test-run/test-run-actions.ts +222 -129
- package/templates/default/src/actions/test-suite/test-suite-actions.ts +95 -17
- package/templates/default/src/actions/user/user-actions.ts +13 -13
- package/templates/default/src/app/(base)/environments/create/page.tsx +28 -28
- package/templates/default/src/app/(base)/environments/environment-form.tsx +219 -219
- package/templates/default/src/app/(base)/environments/environment-table-columns.tsx +96 -96
- package/templates/default/src/app/(base)/environments/environment-table.tsx +24 -24
- package/templates/default/src/app/(base)/environments/modify/[id]/page.tsx +46 -46
- package/templates/default/src/app/(base)/environments/page.tsx +59 -59
- package/templates/default/src/app/(base)/layout.tsx +10 -10
- package/templates/default/src/app/(base)/locator-groups/create/page.tsx +44 -44
- package/templates/default/src/app/(base)/locator-groups/locator-group-form.tsx +215 -215
- package/templates/default/src/app/(base)/locator-groups/locator-group-table-columns.tsx +77 -77
- package/templates/default/src/app/(base)/locator-groups/locator-group-table.tsx +28 -28
- package/templates/default/src/app/(base)/locator-groups/modify/[id]/page.tsx +46 -46
- package/templates/default/src/app/(base)/locator-groups/page.tsx +20 -8
- package/templates/default/src/app/(base)/locators/create/create-locator-workspace.tsx +542 -0
- package/templates/default/src/app/(base)/locators/create/page.tsx +32 -19
- package/templates/default/src/app/(base)/locators/locator-form.tsx +163 -163
- package/templates/default/src/app/(base)/locators/locator-table-columns.tsx +73 -73
- package/templates/default/src/app/(base)/locators/locator-table.tsx +28 -28
- package/templates/default/src/app/(base)/locators/modify/[id]/page.tsx +56 -27
- package/templates/default/src/app/(base)/locators/page.tsx +13 -13
- package/templates/default/src/app/(base)/locators/picker/page.tsx +7 -0
- package/templates/default/src/app/(base)/locators/sync-locators-button.tsx +66 -66
- package/templates/default/src/app/(base)/modules/create/page.tsx +34 -34
- package/templates/default/src/app/(base)/modules/modify/[id]/page.tsx +46 -46
- package/templates/default/src/app/(base)/modules/module-form.tsx +126 -126
- package/templates/default/src/app/(base)/modules/module-table-columns.tsx +85 -85
- package/templates/default/src/app/(base)/modules/module-table.tsx +24 -24
- package/templates/default/src/app/(base)/modules/page.tsx +59 -59
- package/templates/default/src/app/(base)/reports/[id]/page.tsx +40 -33
- package/templates/default/src/app/(base)/reports/duration-chart.tsx +33 -33
- package/templates/default/src/app/(base)/reports/feature-chart.tsx +78 -78
- package/templates/default/src/app/(base)/reports/overview-chart.tsx +49 -46
- package/templates/default/src/app/(base)/reports/page.tsx +98 -98
- package/templates/default/src/app/(base)/reports/report-metric-card.tsx +78 -16
- package/templates/default/src/app/(base)/reports/report-table-columns.tsx +189 -189
- package/templates/default/src/app/(base)/reports/report-table.tsx +72 -72
- package/templates/default/src/app/(base)/reports/report-view-table-columns.tsx +12 -1
- package/templates/default/src/app/(base)/reports/report-view-table.tsx +1 -0
- package/templates/default/src/app/(base)/reports/test-cases/page.tsx +40 -42
- package/templates/default/src/app/(base)/reports/test-cases/test-cases-metric-table-columns.tsx +115 -115
- package/templates/default/src/app/(base)/reports/test-cases/test-cases-metric-table.tsx +27 -27
- package/templates/default/src/app/(base)/reports/test-suites/page.tsx +42 -42
- package/templates/default/src/app/(base)/reports/test-suites/test-suites-metric-table-columns.tsx +79 -79
- package/templates/default/src/app/(base)/reports/test-suites/test-suites-metric-table.tsx +27 -27
- package/templates/default/src/app/(base)/reports/view-logs-button.tsx +58 -60
- package/templates/default/src/app/(base)/reviews/create/page.tsx +26 -26
- package/templates/default/src/app/(base)/reviews/created-reviews-table.tsx +15 -15
- package/templates/default/src/app/(base)/reviews/modify/[id]/page.tsx +26 -26
- package/templates/default/src/app/(base)/reviews/page.tsx +26 -26
- package/templates/default/src/app/(base)/reviews/review/[id]/page.tsx +26 -26
- package/templates/default/src/app/(base)/reviews/review-form.tsx +11 -11
- package/templates/default/src/app/(base)/reviews/review-table-by-creator-columns.tsx +9 -9
- package/templates/default/src/app/(base)/reviews/review-table-by-reviewer-columns.tsx +9 -9
- package/templates/default/src/app/(base)/reviews/reviewer-reviews-table.tsx +15 -15
- package/templates/default/src/app/(base)/settings/page.tsx +30 -0
- package/templates/default/src/app/(base)/settings/settings-sync-panel.tsx +261 -0
- package/templates/default/src/app/(base)/tags/create/page.tsx +39 -39
- package/templates/default/src/app/(base)/tags/modify/[id]/page.tsx +50 -50
- package/templates/default/src/app/(base)/tags/page.tsx +58 -58
- package/templates/default/src/app/(base)/tags/tag-form.tsx +147 -147
- package/templates/default/src/app/(base)/tags/tag-table-columns.tsx +63 -63
- package/templates/default/src/app/(base)/tags/tag-table.tsx +29 -29
- package/templates/default/src/app/(base)/template-step-groups/create/page.tsx +28 -28
- package/templates/default/src/app/(base)/template-step-groups/modify/[id]/page.tsx +45 -45
- package/templates/default/src/app/(base)/template-step-groups/page.tsx +60 -60
- package/templates/default/src/app/(base)/template-step-groups/template-step-group-form.tsx +167 -167
- package/templates/default/src/app/(base)/template-step-groups/template-step-group-table-columns.tsx +89 -89
- package/templates/default/src/app/(base)/template-step-groups/template-step-group-table.tsx +32 -32
- package/templates/default/src/app/(base)/template-steps/create/page.tsx +37 -37
- package/templates/default/src/app/(base)/template-steps/modify/[id]/page.tsx +49 -49
- package/templates/default/src/app/(base)/template-steps/page.tsx +58 -58
- package/templates/default/src/app/(base)/template-steps/paramChip.tsx +213 -213
- package/templates/default/src/app/(base)/template-steps/template-step-form.tsx +384 -384
- package/templates/default/src/app/(base)/template-steps/template-step-table-columns.tsx +158 -158
- package/templates/default/src/app/(base)/template-steps/template-step-table.tsx +24 -24
- package/templates/default/src/app/(base)/template-test-cases/create/page.tsx +56 -56
- package/templates/default/src/app/(base)/template-test-cases/modify/[id]/page.tsx +89 -89
- package/templates/default/src/app/(base)/template-test-cases/page.tsx +58 -58
- package/templates/default/src/app/(base)/template-test-cases/template-test-case-flow.tsx +84 -84
- package/templates/default/src/app/(base)/template-test-cases/template-test-case-form.tsx +262 -262
- package/templates/default/src/app/(base)/template-test-cases/template-test-case-table-columns.tsx +76 -76
- package/templates/default/src/app/(base)/template-test-cases/template-test-case-table.tsx +32 -32
- package/templates/default/src/app/(base)/test-cases/create/page.tsx +76 -76
- package/templates/default/src/app/(base)/test-cases/create-from-template/generate/[id]/page.tsx +96 -96
- package/templates/default/src/app/(base)/test-cases/create-from-template/page.tsx +38 -38
- package/templates/default/src/app/(base)/test-cases/create-from-template/template-selection-form.tsx +73 -73
- package/templates/default/src/app/(base)/test-cases/modify/[id]/page.tsx +106 -106
- package/templates/default/src/app/(base)/test-cases/page.tsx +2 -2
- package/templates/default/src/app/(base)/test-cases/test-case-flow.tsx +82 -82
- package/templates/default/src/app/(base)/test-cases/test-case-form.tsx +395 -395
- package/templates/default/src/app/(base)/test-cases/test-case-table-columns.tsx +6 -71
- package/templates/default/src/app/(base)/test-cases/test-case-table.tsx +2 -2
- package/templates/default/src/app/(base)/test-runs/[id]/page.tsx +4 -1
- package/templates/default/src/app/(base)/test-runs/create/page.tsx +11 -9
- package/templates/default/src/app/(base)/test-runs/page.tsx +60 -60
- package/templates/default/src/app/(base)/test-runs/test-run-form.tsx +37 -44
- package/templates/default/src/app/(base)/test-runs/test-run-table-columns.tsx +229 -229
- package/templates/default/src/app/(base)/test-runs/test-run-table.tsx +127 -127
- package/templates/default/src/app/(base)/test-suites/create/page.tsx +3 -2
- package/templates/default/src/app/(base)/test-suites/modify/[id]/page.tsx +2 -1
- package/templates/default/src/app/(base)/test-suites/page.tsx +57 -21
- package/templates/default/src/app/(base)/test-suites/test-suite-form.tsx +16 -17
- package/templates/default/src/app/(base)/test-suites/test-suite-table-columns.tsx +2 -1
- package/templates/default/src/app/(base)/test-suites/test-suite-table.tsx +29 -29
- package/templates/default/src/app/(dashboard-components)/app-drawer.tsx +187 -187
- package/templates/default/src/app/(dashboard-components)/data-card-grid.tsx +12 -12
- package/templates/default/src/app/(dashboard-components)/data-card.tsx +26 -26
- package/templates/default/src/app/(dashboard-components)/execution-health-panel.tsx +56 -56
- package/templates/default/src/app/(dashboard-components)/ongoing-test-runs-card.tsx +87 -87
- package/templates/default/src/app/(dashboard-components)/quick-actions-drawer.tsx +44 -44
- package/templates/default/src/app/api/reports/steps/[stepId]/screenshot/route.ts +52 -0
- package/templates/default/src/app/api/test-runs/[runId]/download/route.ts +97 -34
- package/templates/default/src/app/api/test-runs/[runId]/logs/route.ts +4 -1
- package/templates/default/src/app/api/test-runs/[runId]/trace/[testCaseId]/route.ts +146 -147
- package/templates/default/src/app/globals.css +147 -147
- package/templates/default/src/app/layout.tsx +4 -0
- package/templates/default/src/app/page.tsx +2 -0
- package/templates/default/src/assets/icons/empty-tube.tsx +23 -23
- package/templates/default/src/assets/icons/tube-plus.tsx +29 -29
- package/templates/default/src/components/base-node.tsx +21 -21
- package/templates/default/src/components/chart/pie-chart.tsx +73 -73
- package/templates/default/src/components/data-extraction/locator-inspector.tsx +460 -460
- package/templates/default/src/components/data-state/empty-state.tsx +40 -40
- package/templates/default/src/components/data-visualization/info-card.tsx +70 -70
- package/templates/default/src/components/data-visualization/info-grid.tsx +22 -22
- package/templates/default/src/components/diagram/button-edge.tsx +54 -54
- package/templates/default/src/components/diagram/dynamic-parameters.tsx +474 -474
- package/templates/default/src/components/diagram/edit-header-option.tsx +36 -36
- package/templates/default/src/components/diagram/flow-diagram.tsx +470 -470
- package/templates/default/src/components/diagram/node-form.tsx +262 -262
- package/templates/default/src/components/diagram/options-header-node.tsx +57 -57
- package/templates/default/src/components/diagram/template-step-combobox.tsx +155 -155
- package/templates/default/src/components/form/error-message.tsx +7 -7
- package/templates/default/src/components/kokonutui/smooth-tab.tsx +453 -453
- package/templates/default/src/components/loading-skeleton/data-table/data-table-skeleton.tsx +30 -30
- package/templates/default/src/components/loading-skeleton/form/button-skeleton.tsx +8 -8
- package/templates/default/src/components/loading-skeleton/form/icon-button-skeleton.tsx +8 -8
- package/templates/default/src/components/loading-skeleton/form/text-input-skeleton.tsx +8 -8
- package/templates/default/src/components/loading-skeleton/visualization/table-skeleton.tsx +14 -14
- package/templates/default/src/components/logo.tsx +15 -15
- package/templates/default/src/components/navigation/command-badge.tsx +34 -34
- package/templates/default/src/components/navigation/command-chain-input.tsx +51 -51
- package/templates/default/src/components/navigation/entity-search-command.tsx +116 -116
- package/templates/default/src/components/navigation/nav-card.tsx +31 -31
- package/templates/default/src/components/navigation/nav-command.tsx +13 -0
- package/templates/default/src/components/navigation/nav-link.tsx +60 -60
- package/templates/default/src/components/navigation/nav-menu-card-deck.tsx +112 -112
- package/templates/default/src/components/node-header.tsx +159 -159
- package/templates/default/src/components/reports/test-case-logs-modal.tsx +310 -253
- package/templates/default/src/components/table/table-actions.tsx +172 -172
- package/templates/default/src/components/test-case/test-case-columns.tsx +76 -0
- package/templates/default/src/components/test-case/test-case-picker.tsx +244 -0
- package/templates/default/src/components/test-run/download-logs-button.tsx +92 -99
- package/templates/default/src/components/test-run/log-viewer.tsx +1 -14
- package/templates/default/src/components/test-run/test-run-details.tsx +15 -2
- package/templates/default/src/components/test-run/test-run-header.tsx +149 -149
- package/templates/default/src/components/test-run/view-report-button.tsx +102 -102
- package/templates/default/src/components/test-suite/test-suite-picker.tsx +444 -0
- package/templates/default/src/components/theme/mode-toggle.tsx +54 -54
- package/templates/default/src/components/theme/theme-provider.tsx +8 -8
- package/templates/default/src/components/typography/page-header-subtitle.tsx +7 -7
- package/templates/default/src/components/typography/page-header.tsx +7 -7
- package/templates/default/src/components/ui/alert-dialog.tsx +106 -106
- package/templates/default/src/components/ui/alert.tsx +43 -43
- package/templates/default/src/components/ui/avatar.tsx +40 -40
- package/templates/default/src/components/ui/badge.tsx +29 -29
- package/templates/default/src/components/ui/button.tsx +47 -47
- package/templates/default/src/components/ui/calendar.tsx +158 -158
- package/templates/default/src/components/ui/card.tsx +43 -43
- package/templates/default/src/components/ui/checkbox.tsx +28 -28
- package/templates/default/src/components/ui/command.tsx +135 -135
- package/templates/default/src/components/ui/data-table-column-header.tsx +61 -61
- package/templates/default/src/components/ui/data-table-pagination.tsx +87 -87
- package/templates/default/src/components/ui/data-table-view-options.tsx +50 -50
- package/templates/default/src/components/ui/data-table.tsx +261 -261
- package/templates/default/src/components/ui/dialog.tsx +97 -97
- package/templates/default/src/components/ui/dropdown-menu.tsx +182 -182
- package/templates/default/src/components/ui/input.tsx +22 -22
- package/templates/default/src/components/ui/kbd.tsx +28 -28
- package/templates/default/src/components/ui/label.tsx +19 -19
- package/templates/default/src/components/ui/loading.tsx +12 -12
- package/templates/default/src/components/ui/multi-select-with-preview.tsx +116 -116
- package/templates/default/src/components/ui/multi-select.tsx +142 -142
- package/templates/default/src/components/ui/navigation-menu.tsx +120 -120
- package/templates/default/src/components/ui/popover.tsx +33 -33
- package/templates/default/src/components/ui/progress.tsx +25 -25
- package/templates/default/src/components/ui/radio-group.tsx +44 -44
- package/templates/default/src/components/ui/scroll-area.tsx +40 -40
- package/templates/default/src/components/ui/select.tsx +151 -151
- package/templates/default/src/components/ui/separator.tsx +22 -22
- package/templates/default/src/components/ui/skeleton.tsx +7 -7
- package/templates/default/src/components/ui/table.tsx +76 -76
- package/templates/default/src/components/ui/tabs.tsx +55 -55
- package/templates/default/src/components/ui/textarea.tsx +21 -21
- package/templates/default/src/components/ui/toast.tsx +113 -113
- package/templates/default/src/components/ui/toaster.tsx +26 -26
- package/templates/default/src/components/user-prompt/delete-prompt.tsx +87 -87
- package/templates/default/src/config/db-config.ts +10 -10
- package/templates/default/src/constants/form-opts/diagram/node-form.ts +30 -30
- package/templates/default/src/constants/form-opts/environment-form-opts.ts +24 -24
- package/templates/default/src/constants/form-opts/locator-form-opts.ts +20 -20
- package/templates/default/src/constants/form-opts/locator-group-form-opts.ts +28 -28
- package/templates/default/src/constants/form-opts/module-form-opts.ts +21 -21
- package/templates/default/src/constants/form-opts/review-form-opts.ts +23 -23
- package/templates/default/src/constants/form-opts/tag-form-opts.ts +42 -42
- package/templates/default/src/constants/form-opts/template-selection-form-opts.ts +16 -16
- package/templates/default/src/constants/form-opts/template-step-group-form-opts.ts +24 -24
- package/templates/default/src/constants/form-opts/template-test-case-form-opts.ts +39 -39
- package/templates/default/src/constants/form-opts/template-test-step-form-opts.ts +36 -36
- package/templates/default/src/constants/form-opts/test-case-form-opts.ts +43 -43
- package/templates/default/src/constants/form-opts/test-run-form-opts.ts +5 -3
- package/templates/default/src/constants/form-opts/test-suite-form-opts.ts +24 -24
- package/templates/default/src/hooks/use-toast.ts +187 -187
- package/templates/default/src/lib/automation/paths.ts +42 -12
- package/templates/default/src/lib/automation/projection-service.ts +2 -1
- package/templates/default/src/lib/bidirectional-sync.ts +432 -432
- package/templates/default/src/lib/database-sync.ts +2 -7
- package/templates/default/src/lib/environment-file-utils.ts +184 -184
- package/templates/default/src/lib/executor/local-executor-adapter.ts +24 -25
- package/templates/default/src/lib/executor/types.ts +2 -2
- package/templates/default/src/lib/feature-file-generator.ts +5 -66
- package/templates/default/src/lib/gherkin-parser.ts +259 -259
- package/templates/default/src/lib/locator-group-file-utils.ts +307 -307
- package/templates/default/src/lib/locator-picker/session-manager.ts +452 -0
- package/templates/default/src/lib/locator-picker/suggestions.ts +124 -0
- package/templates/default/src/lib/metrics/metric-calculator.ts +5 -0
- package/templates/default/src/lib/module-hierarchy-builder.ts +205 -205
- package/templates/default/src/lib/path-helpers/module-path.ts +71 -71
- package/templates/default/src/lib/process/task-spawner.ts +39 -2
- package/templates/default/src/lib/sync/projected-feature-utils.ts +113 -0
- package/templates/default/src/lib/sync/sync-executor.ts +130 -0
- package/templates/default/src/lib/sync/sync-pending-counts.test.ts +239 -0
- package/templates/default/src/lib/sync/sync-pending-counts.ts +1358 -0
- package/templates/default/src/lib/sync/sync-registry.ts +149 -0
- package/templates/default/src/lib/tag-utils.ts +28 -0
- package/templates/default/src/lib/template-sync-utils.d.ts +6 -6
- package/templates/default/src/lib/template-sync-utils.js +46 -46
- package/templates/default/src/lib/template-sync-utils.ts +63 -63
- package/templates/default/src/lib/test-case-utils.ts +6 -6
- package/templates/default/src/lib/test-run/log-formatter.ts +83 -83
- package/templates/default/src/lib/test-run/matching.ts +117 -0
- package/templates/default/src/lib/test-run/process-manager.ts +2 -0
- package/templates/default/src/lib/test-run/report-parser.ts +352 -316
- package/templates/default/src/lib/test-run/test-run-executor.ts +13 -15
- package/templates/default/src/lib/test-run/winston-logger.ts +64 -66
- package/templates/default/src/lib/test-suite-identifier-service.ts +76 -0
- package/templates/default/src/lib/test-suite-utils.ts +6 -0
- package/templates/default/src/lib/transformers/gherkin-converter.ts +42 -42
- package/templates/default/src/lib/transformers/key-to-icon-transformer.tsx +95 -95
- package/templates/default/src/lib/transformers/template-test-case-converter.ts +160 -160
- package/templates/default/src/lib/utils/node-param-validation.ts +81 -81
- package/templates/default/src/lib/utils/template-step-file-generator.ts +104 -104
- package/templates/default/src/lib/utils/template-step-file-manager-intelligent.ts +0 -8
- package/templates/default/src/lib/utils/template-step-file-manager.ts +166 -166
- package/templates/default/src/lib/utils.ts +31 -31
- package/templates/default/src/types/diagram/diagram.ts +34 -34
- package/templates/default/src/types/diagram/template-step.ts +11 -11
- package/templates/default/src/types/executor/browser.type.ts +1 -1
- package/templates/default/src/types/form/actionHandler.ts +6 -6
- package/templates/default/src/types/locator/locator.type.ts +11 -11
- package/templates/default/src/types/locator-picker.ts +65 -0
- package/templates/default/src/types/step/step.type.ts +1 -1
- package/templates/default/src/types/table/data-table.ts +6 -6
- package/templates/default/src/types/test-case-picker.ts +6 -0
- package/templates/default/src/types/test-suite-picker.ts +18 -0
- package/templates/default/tailwind.config.ts +62 -62
- package/templates/default/tsconfig.json +4 -1
- package/templates/default/appraisejs.config.json +0 -1
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
TestRunResult,
|
|
10
10
|
TestRunTestCaseStatus,
|
|
11
11
|
TestRunTestCaseResult,
|
|
12
|
-
TagType,
|
|
13
12
|
Tag,
|
|
14
13
|
} from '@prisma/client'
|
|
15
14
|
import { localExecutorAdapter } from '@/lib/executor/local-executor-adapter'
|
|
@@ -18,9 +17,12 @@ import { formatLogsForStorage, parseLogsFromStorage, type LogEntry } from '@/lib
|
|
|
18
17
|
import { processManager } from '@/lib/test-run/process-manager'
|
|
19
18
|
import { createTestRunLogger, closeLogger, getLogFilePath } from '@/lib/test-run/winston-logger'
|
|
20
19
|
import { promises as fs } from 'fs'
|
|
21
|
-
import path from 'path'
|
|
22
20
|
import { Prisma } from '@prisma/client'
|
|
23
21
|
import { updateTestCaseMetrics, updateMetricsForTestRun } from '@/lib/metrics/metric-calculator'
|
|
22
|
+
import { getAutomationReportRunDir, resolveStoredPath } from '@/lib/automation/paths'
|
|
23
|
+
import { ensureTestSuiteIdentifierTags } from '@/lib/test-suite-identifier-service'
|
|
24
|
+
import { getIdentifierTagByPrefix } from '@/lib/tag-utils'
|
|
25
|
+
import { findMatchingTestRunTestCase } from '@/lib/test-run/matching'
|
|
24
26
|
|
|
25
27
|
/**
|
|
26
28
|
* Check if a test run name already exists
|
|
@@ -35,6 +37,47 @@ async function checkUniqueName(name: string, excludeId?: string): Promise<boolea
|
|
|
35
37
|
return !!existing
|
|
36
38
|
}
|
|
37
39
|
|
|
40
|
+
function buildOrExpression(expressions: string[]): string | null {
|
|
41
|
+
if (expressions.length === 0) {
|
|
42
|
+
return null
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (expressions.length === 1) {
|
|
46
|
+
return expressions[0]
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return expressions.join(' or ')
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function normalizeSuiteSelection(
|
|
53
|
+
selection: z.infer<typeof testRunSchema>['testSuites'][number],
|
|
54
|
+
availableTestCaseIds: string[],
|
|
55
|
+
) {
|
|
56
|
+
if (selection.runAll) {
|
|
57
|
+
return {
|
|
58
|
+
testSuiteId: selection.testSuiteId,
|
|
59
|
+
runAll: true,
|
|
60
|
+
testCaseIds: [] as string[],
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const selectedTestCaseIds = selection.testCaseIds.filter(testCaseId => availableTestCaseIds.includes(testCaseId))
|
|
65
|
+
|
|
66
|
+
if (selectedTestCaseIds.length === availableTestCaseIds.length) {
|
|
67
|
+
return {
|
|
68
|
+
testSuiteId: selection.testSuiteId,
|
|
69
|
+
runAll: true,
|
|
70
|
+
testCaseIds: [] as string[],
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
testSuiteId: selection.testSuiteId,
|
|
76
|
+
runAll: false,
|
|
77
|
+
testCaseIds: selectedTestCaseIds,
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
38
81
|
export async function getAllTestRunsAction(filter?: string): Promise<ActionResponse> {
|
|
39
82
|
try {
|
|
40
83
|
// Build the where clause based on filter
|
|
@@ -80,6 +123,7 @@ export async function getTestRunByIdAction(id: string): Promise<ActionResponse>
|
|
|
80
123
|
testCases: {
|
|
81
124
|
include: {
|
|
82
125
|
testCase: true,
|
|
126
|
+
testSuite: true,
|
|
83
127
|
},
|
|
84
128
|
},
|
|
85
129
|
tags: true,
|
|
@@ -109,45 +153,31 @@ export async function getTestRunByIdAction(id: string): Promise<ActionResponse>
|
|
|
109
153
|
|
|
110
154
|
export async function deleteTestRunAction(id: string[]): Promise<ActionResponse> {
|
|
111
155
|
try {
|
|
112
|
-
|
|
113
|
-
// This is needed to recalculate metrics after deletion
|
|
114
|
-
const testRunTestCases = await prisma.testRunTestCase.findMany({
|
|
115
|
-
where: {
|
|
116
|
-
testRunId: { in: id },
|
|
117
|
-
},
|
|
118
|
-
select: {
|
|
119
|
-
testCaseId: true,
|
|
120
|
-
},
|
|
121
|
-
})
|
|
122
|
-
const _affectedTestCaseIds = [...new Set(testRunTestCases.map(trtc => trtc.testCaseId))]
|
|
123
|
-
|
|
124
|
-
// find all trace paths for the test runs
|
|
125
|
-
const tracePaths = await prisma.testRunTestCase.findMany({
|
|
126
|
-
where: {
|
|
127
|
-
testRunId: { in: id },
|
|
128
|
-
},
|
|
129
|
-
select: {
|
|
130
|
-
tracePath: true,
|
|
131
|
-
},
|
|
132
|
-
})
|
|
133
|
-
// delete the trace paths
|
|
134
|
-
for (const tracePath of tracePaths) {
|
|
135
|
-
if (tracePath.tracePath) {
|
|
136
|
-
await fs.unlink(tracePath.tracePath)
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// find all report paths for the test runs
|
|
141
|
-
const reportPaths = await prisma.testRun.findMany({
|
|
156
|
+
const testRuns = await prisma.testRun.findMany({
|
|
142
157
|
where: { id: { in: id } },
|
|
143
158
|
select: {
|
|
159
|
+
runId: true,
|
|
160
|
+
logPath: true,
|
|
144
161
|
reportPath: true,
|
|
162
|
+
testCases: {
|
|
163
|
+
select: {
|
|
164
|
+
tracePath: true,
|
|
165
|
+
},
|
|
166
|
+
},
|
|
145
167
|
},
|
|
146
168
|
})
|
|
147
|
-
|
|
148
|
-
for (const
|
|
149
|
-
|
|
150
|
-
|
|
169
|
+
|
|
170
|
+
for (const testRun of testRuns) {
|
|
171
|
+
await fs.rm(getAutomationReportRunDir(testRun.runId), { recursive: true, force: true })
|
|
172
|
+
|
|
173
|
+
const legacyArtifactPaths = [
|
|
174
|
+
testRun.logPath,
|
|
175
|
+
testRun.reportPath,
|
|
176
|
+
...testRun.testCases.map(testCase => testCase.tracePath),
|
|
177
|
+
].filter((artifactPath): artifactPath is string => Boolean(artifactPath))
|
|
178
|
+
|
|
179
|
+
for (const artifactPath of legacyArtifactPaths) {
|
|
180
|
+
await fs.rm(resolveStoredPath(artifactPath), { force: true }).catch(() => {})
|
|
151
181
|
}
|
|
152
182
|
}
|
|
153
183
|
|
|
@@ -161,9 +191,7 @@ export async function deleteTestRunAction(id: string[]): Promise<ActionResponse>
|
|
|
161
191
|
// deleting a test run might affect consecutive failure counts for any test case
|
|
162
192
|
// that had recent runs (e.g., if a test case had 3 consecutive failures and we
|
|
163
193
|
// delete one of those failures, it might no longer be "repeatedly failing")
|
|
164
|
-
const { recalculateMetricsForTestCases, updateDashboardMetrics } = await import(
|
|
165
|
-
'@/lib/metrics/metric-calculator'
|
|
166
|
-
)
|
|
194
|
+
const { recalculateMetricsForTestCases, updateDashboardMetrics } = await import('@/lib/metrics/metric-calculator')
|
|
167
195
|
|
|
168
196
|
// Get all test case IDs that have recent test runs (last 7 days)
|
|
169
197
|
// These are the ones that might be affected by the deletion
|
|
@@ -187,9 +215,7 @@ export async function deleteTestRunAction(id: string[]): Promise<ActionResponse>
|
|
|
187
215
|
})
|
|
188
216
|
|
|
189
217
|
// Get unique test case IDs
|
|
190
|
-
const allAffectedTestCaseIds = [
|
|
191
|
-
...new Set(allRecentTestRunTestCases.map(trtc => trtc.testCaseId)),
|
|
192
|
-
]
|
|
218
|
+
const allAffectedTestCaseIds = [...new Set(allRecentTestRunTestCases.map(trtc => trtc.testCaseId))]
|
|
193
219
|
|
|
194
220
|
// Recalculate metrics for all test cases with recent runs
|
|
195
221
|
if (allAffectedTestCaseIds.length > 0) {
|
|
@@ -216,9 +242,18 @@ export async function deleteTestRunAction(id: string[]): Promise<ActionResponse>
|
|
|
216
242
|
|
|
217
243
|
export async function getAllTestSuiteTestCasesAction(): Promise<ActionResponse> {
|
|
218
244
|
try {
|
|
245
|
+
await ensureTestSuiteIdentifierTags()
|
|
246
|
+
|
|
219
247
|
const testSuiteTestCases = await prisma.testSuite.findMany({
|
|
220
248
|
include: {
|
|
221
|
-
|
|
249
|
+
module: true,
|
|
250
|
+
tags: true,
|
|
251
|
+
testCases: {
|
|
252
|
+
include: {
|
|
253
|
+
steps: true,
|
|
254
|
+
tags: true,
|
|
255
|
+
},
|
|
256
|
+
},
|
|
222
257
|
},
|
|
223
258
|
})
|
|
224
259
|
return {
|
|
@@ -337,27 +372,29 @@ export async function createTestRunAction(
|
|
|
337
372
|
}
|
|
338
373
|
}
|
|
339
374
|
|
|
340
|
-
// Determine if we're filtering by tags or test
|
|
375
|
+
// Determine if we're filtering by tags or test suites
|
|
341
376
|
const isFilteringByTags = value.tags.length > 0
|
|
342
|
-
const
|
|
377
|
+
const isFilteringByTestSuites = value.testSuites.length > 0 && value.tags.length === 0
|
|
343
378
|
|
|
344
379
|
// Validate that at least one filtering option is provided
|
|
345
|
-
if (!isFilteringByTags && !
|
|
380
|
+
if (!isFilteringByTags && !isFilteringByTestSuites) {
|
|
346
381
|
return {
|
|
347
382
|
status: 400,
|
|
348
|
-
error: 'Either tags or test
|
|
383
|
+
error: 'Either tags or test suites must be provided to filter the test run.',
|
|
349
384
|
}
|
|
350
385
|
}
|
|
351
386
|
|
|
352
387
|
let tags: Tag[] = []
|
|
353
|
-
let
|
|
388
|
+
let tagExpression: string | null = null
|
|
389
|
+
let testRunTestCases: Array<{ testCaseId: string; testSuiteId?: string | null }> = []
|
|
354
390
|
|
|
355
391
|
if (isFilteringByTags) {
|
|
356
|
-
// Existing behavior: filter by tags
|
|
357
392
|
tags = await prisma.tag.findMany({
|
|
358
393
|
where: { id: { in: value.tags } },
|
|
359
394
|
})
|
|
360
395
|
|
|
396
|
+
tagExpression = buildOrExpression(tags.map(tag => `(${tag.tagExpression})`))
|
|
397
|
+
|
|
361
398
|
// Find test cases that have tags directly OR belong to test suites with tags
|
|
362
399
|
const tagFilteredTestCases = await prisma.testCase.findMany({
|
|
363
400
|
where: {
|
|
@@ -384,56 +421,120 @@ export async function createTestRunAction(
|
|
|
384
421
|
|
|
385
422
|
testRunTestCases = tagFilteredTestCases.map(tc => ({
|
|
386
423
|
testCaseId: tc.id,
|
|
424
|
+
testSuiteId: null,
|
|
387
425
|
}))
|
|
388
|
-
} else if (
|
|
389
|
-
|
|
390
|
-
|
|
426
|
+
} else if (isFilteringByTestSuites) {
|
|
427
|
+
await ensureTestSuiteIdentifierTags(value.testSuites.map(testSuite => testSuite.testSuiteId))
|
|
428
|
+
|
|
429
|
+
const selectedSuites = await prisma.testSuite.findMany({
|
|
391
430
|
where: {
|
|
392
|
-
id: {
|
|
431
|
+
id: {
|
|
432
|
+
in: value.testSuites.map(testSuite => testSuite.testSuiteId),
|
|
433
|
+
},
|
|
393
434
|
},
|
|
394
435
|
include: {
|
|
395
436
|
tags: true,
|
|
437
|
+
testCases: {
|
|
438
|
+
include: {
|
|
439
|
+
tags: true,
|
|
440
|
+
},
|
|
441
|
+
},
|
|
396
442
|
},
|
|
397
443
|
})
|
|
398
444
|
|
|
399
|
-
|
|
400
|
-
const identifierTags = selectedTestCases
|
|
401
|
-
.flatMap(tc => tc.tags)
|
|
402
|
-
.filter(tag => tag.type === TagType.IDENTIFIER)
|
|
403
|
-
// Remove duplicates by id
|
|
404
|
-
.filter((tag, index, self) => index === self.findIndex(t => t.id === tag.id))
|
|
405
|
-
|
|
406
|
-
// Safety check: if no identifier tags found, this would run all tests
|
|
407
|
-
// which is not what the user expects when they select specific test cases
|
|
408
|
-
if (identifierTags.length === 0) {
|
|
445
|
+
if (selectedSuites.length !== value.testSuites.length) {
|
|
409
446
|
return {
|
|
410
447
|
status: 400,
|
|
411
|
-
error: '
|
|
448
|
+
error: 'One or more selected test suites could not be found.',
|
|
412
449
|
}
|
|
413
450
|
}
|
|
414
451
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
const testCasesWithIdentifierTags = selectedTestCases.filter(tc =>
|
|
418
|
-
tc.tags.some(tag => tag.type === TagType.IDENTIFIER),
|
|
419
|
-
)
|
|
452
|
+
const selectedSuiteById = new Map(selectedSuites.map(testSuite => [testSuite.id, testSuite]))
|
|
453
|
+
const suiteClauses: string[] = []
|
|
420
454
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
455
|
+
for (const suiteSelection of value.testSuites) {
|
|
456
|
+
const selectedSuite = selectedSuiteById.get(suiteSelection.testSuiteId)
|
|
457
|
+
if (!selectedSuite) {
|
|
458
|
+
continue
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
if (selectedSuite.testCases.length === 0) {
|
|
462
|
+
continue
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
const normalizedSelection = normalizeSuiteSelection(
|
|
466
|
+
suiteSelection,
|
|
467
|
+
selectedSuite.testCases.map(testCase => testCase.id),
|
|
468
|
+
)
|
|
469
|
+
|
|
470
|
+
if (!normalizedSelection) {
|
|
471
|
+
continue
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
const suiteIdentifierTag = getIdentifierTagByPrefix(selectedSuite.tags, 'ts_')
|
|
475
|
+
if (!suiteIdentifierTag) {
|
|
476
|
+
return {
|
|
477
|
+
status: 400,
|
|
478
|
+
error: `Test suite "${selectedSuite.name}" does not have an identifier tag.`,
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
if (normalizedSelection.runAll) {
|
|
483
|
+
suiteClauses.push(`(${suiteIdentifierTag.tagExpression})`)
|
|
484
|
+
testRunTestCases.push(
|
|
485
|
+
...selectedSuite.testCases.map(testCase => ({
|
|
486
|
+
testCaseId: testCase.id,
|
|
487
|
+
testSuiteId: selectedSuite.id,
|
|
488
|
+
})),
|
|
489
|
+
)
|
|
490
|
+
continue
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
const selectedTestCases = selectedSuite.testCases.filter(testCase =>
|
|
494
|
+
normalizedSelection.testCaseIds.includes(testCase.id),
|
|
495
|
+
)
|
|
496
|
+
|
|
497
|
+
if (selectedTestCases.length === 0) {
|
|
498
|
+
return {
|
|
499
|
+
status: 400,
|
|
500
|
+
error: `Test suite "${selectedSuite.name}" requires at least one selected test case.`,
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
const missingIdentifierTestCase = selectedTestCases.find(
|
|
505
|
+
testCase => !getIdentifierTagByPrefix(testCase.tags, 'tc_'),
|
|
506
|
+
)
|
|
507
|
+
if (missingIdentifierTestCase) {
|
|
508
|
+
return {
|
|
509
|
+
status: 400,
|
|
510
|
+
error: `Test case "${missingIdentifierTestCase.title}" does not have an identifier tag.`,
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
const testCaseTagExpressions = selectedTestCases.map(testCase => {
|
|
515
|
+
const identifierTag = getIdentifierTagByPrefix(testCase.tags, 'tc_')
|
|
516
|
+
return identifierTag!.tagExpression
|
|
517
|
+
})
|
|
518
|
+
|
|
519
|
+
suiteClauses.push(
|
|
520
|
+
`(${suiteIdentifierTag.tagExpression}) and (${testCaseTagExpressions.map(tag => `(${tag})`).join(' or ')})`,
|
|
521
|
+
)
|
|
522
|
+
testRunTestCases.push(
|
|
523
|
+
...selectedTestCases.map(testCase => ({
|
|
524
|
+
testCaseId: testCase.id,
|
|
525
|
+
testSuiteId: selectedSuite.id,
|
|
526
|
+
})),
|
|
428
527
|
)
|
|
429
528
|
}
|
|
430
529
|
|
|
431
|
-
|
|
530
|
+
tagExpression = buildOrExpression(suiteClauses.map(clause => `(${clause})`))
|
|
531
|
+
}
|
|
432
532
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
533
|
+
if (!tagExpression) {
|
|
534
|
+
return {
|
|
535
|
+
status: 400,
|
|
536
|
+
error: 'No executable tests were resolved from the selected filters.',
|
|
537
|
+
}
|
|
437
538
|
}
|
|
438
539
|
|
|
439
540
|
// Create TestRun record in database with RUNNING status
|
|
@@ -451,6 +552,7 @@ export async function createTestRunAction(
|
|
|
451
552
|
testCases: {
|
|
452
553
|
create: testRunTestCases.map(tc => ({
|
|
453
554
|
testCaseId: tc.testCaseId,
|
|
555
|
+
testSuiteId: tc.testSuiteId ?? null,
|
|
454
556
|
})),
|
|
455
557
|
},
|
|
456
558
|
},
|
|
@@ -473,7 +575,7 @@ export async function createTestRunAction(
|
|
|
473
575
|
const { process: spawnedProcess, reportPath } = await localExecutorAdapter.executeTestRun({
|
|
474
576
|
testRunId: testRun.runId,
|
|
475
577
|
environment,
|
|
476
|
-
|
|
578
|
+
tagExpression,
|
|
477
579
|
testWorkersCount: value.testWorkersCount || 1,
|
|
478
580
|
browserEngine: value.browserEngine,
|
|
479
581
|
headless: true, // Default to headless
|
|
@@ -496,6 +598,8 @@ export async function createTestRunAction(
|
|
|
496
598
|
scenarioName: string
|
|
497
599
|
status: string
|
|
498
600
|
tracePath?: string
|
|
601
|
+
featureName?: string
|
|
602
|
+
scenarioTags?: string[]
|
|
499
603
|
}) => {
|
|
500
604
|
// Only process events for this test run
|
|
501
605
|
if (eventData.testRunId === testRun.runId) {
|
|
@@ -510,12 +614,13 @@ export async function createTestRunAction(
|
|
|
510
614
|
}
|
|
511
615
|
const mappedStatus = statusMap[eventData.status] || 'unknown'
|
|
512
616
|
// Update test case status in database
|
|
513
|
-
await updateTestRunTestCaseStatusAction(
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
eventData.
|
|
518
|
-
|
|
617
|
+
await updateTestRunTestCaseStatusAction(testRun.runId, {
|
|
618
|
+
scenarioName: eventData.scenarioName,
|
|
619
|
+
status: mappedStatus,
|
|
620
|
+
tracePath: eventData.tracePath,
|
|
621
|
+
featureName: eventData.featureName,
|
|
622
|
+
scenarioTags: eventData.scenarioTags,
|
|
623
|
+
})
|
|
519
624
|
}
|
|
520
625
|
}
|
|
521
626
|
|
|
@@ -754,9 +859,13 @@ export async function createTestRunAction(
|
|
|
754
859
|
*/
|
|
755
860
|
export async function updateTestRunTestCaseStatusAction(
|
|
756
861
|
testRunId: string,
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
862
|
+
scenario: {
|
|
863
|
+
scenarioName: string
|
|
864
|
+
status: 'passed' | 'failed' | 'skipped' | 'unknown'
|
|
865
|
+
tracePath?: string
|
|
866
|
+
featureName?: string
|
|
867
|
+
scenarioTags?: string[]
|
|
868
|
+
},
|
|
760
869
|
): Promise<ActionResponse> {
|
|
761
870
|
try {
|
|
762
871
|
// Find the test run by runId
|
|
@@ -765,7 +874,16 @@ export async function updateTestRunTestCaseStatusAction(
|
|
|
765
874
|
include: {
|
|
766
875
|
testCases: {
|
|
767
876
|
include: {
|
|
768
|
-
testCase:
|
|
877
|
+
testCase: {
|
|
878
|
+
include: {
|
|
879
|
+
tags: true,
|
|
880
|
+
},
|
|
881
|
+
},
|
|
882
|
+
testSuite: {
|
|
883
|
+
include: {
|
|
884
|
+
tags: true,
|
|
885
|
+
},
|
|
886
|
+
},
|
|
769
887
|
},
|
|
770
888
|
},
|
|
771
889
|
},
|
|
@@ -778,38 +896,18 @@ export async function updateTestRunTestCaseStatusAction(
|
|
|
778
896
|
}
|
|
779
897
|
}
|
|
780
898
|
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
// Try to extract title from [brackets]
|
|
786
|
-
const bracketMatch = scenarioName.match(/^\[([^\]]+)\]/)
|
|
787
|
-
if (bracketMatch) {
|
|
788
|
-
testCaseTitle = bracketMatch[1].trim()
|
|
789
|
-
} else {
|
|
790
|
-
// If no brackets, use the full scenario name (might be just the title)
|
|
791
|
-
testCaseTitle = scenarioName.trim()
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
if (!testCaseTitle) {
|
|
795
|
-
return {
|
|
796
|
-
status: 400,
|
|
797
|
-
error: 'Could not extract test case title from scenario name',
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
// Find matching test case by title
|
|
802
|
-
const matchingTestCase = testRun.testCases.find(trtc => trtc.testCase.title === testCaseTitle)
|
|
899
|
+
const matchingTestCase = findMatchingTestRunTestCase(testRun.testCases, {
|
|
900
|
+
scenarioName: scenario.scenarioName,
|
|
901
|
+
scenarioTags: scenario.scenarioTags,
|
|
902
|
+
})
|
|
803
903
|
|
|
804
904
|
if (!matchingTestCase) {
|
|
805
|
-
// This is expected when scenarios run without corresponding test cases (e.g., when filtered by tags)
|
|
806
|
-
// Return success status to indicate this was handled gracefully
|
|
807
905
|
console.log(
|
|
808
|
-
`[TestRunAction] No matching test case found for scenario: ${scenarioName}
|
|
906
|
+
`[TestRunAction] No matching test case found for scenario: ${scenario.scenarioName}. This is expected when scenarios run without corresponding test cases in this test run.`,
|
|
809
907
|
)
|
|
810
908
|
return {
|
|
811
909
|
status: 200,
|
|
812
|
-
message: `Scenario "${scenarioName}" completed but has no corresponding test case in this test run
|
|
910
|
+
message: `Scenario "${scenario.scenarioName}" completed but has no corresponding test case in this test run`,
|
|
813
911
|
}
|
|
814
912
|
}
|
|
815
913
|
|
|
@@ -817,7 +915,7 @@ export async function updateTestRunTestCaseStatusAction(
|
|
|
817
915
|
const testCaseStatus: TestRunTestCaseStatus = TestRunTestCaseStatus.COMPLETED
|
|
818
916
|
let testCaseResult: TestRunTestCaseResult
|
|
819
917
|
|
|
820
|
-
switch (status) {
|
|
918
|
+
switch (scenario.status) {
|
|
821
919
|
case 'passed':
|
|
822
920
|
testCaseResult = TestRunTestCaseResult.PASSED
|
|
823
921
|
break
|
|
@@ -837,7 +935,7 @@ export async function updateTestRunTestCaseStatusAction(
|
|
|
837
935
|
data: {
|
|
838
936
|
status: testCaseStatus,
|
|
839
937
|
result: testCaseResult,
|
|
840
|
-
tracePath: tracePath || null,
|
|
938
|
+
tracePath: scenario.tracePath || null,
|
|
841
939
|
},
|
|
842
940
|
})
|
|
843
941
|
|
|
@@ -859,7 +957,7 @@ export async function updateTestRunTestCaseStatusAction(
|
|
|
859
957
|
}
|
|
860
958
|
} catch (error) {
|
|
861
959
|
console.error(
|
|
862
|
-
`[TestRunAction] Error updating test case status for testRunId: ${testRunId}, scenario: ${scenarioName}:`,
|
|
960
|
+
`[TestRunAction] Error updating test case status for testRunId: ${testRunId}, scenario: ${scenario.scenarioName}:`,
|
|
863
961
|
error,
|
|
864
962
|
)
|
|
865
963
|
return {
|
|
@@ -973,9 +1071,11 @@ export async function spawnTraceViewerAction(testRunId: string, testCaseId: stri
|
|
|
973
1071
|
}
|
|
974
1072
|
}
|
|
975
1073
|
|
|
1074
|
+
const absoluteTracePath = resolveStoredPath(tracePath)
|
|
1075
|
+
|
|
976
1076
|
// Validate trace file exists
|
|
977
1077
|
try {
|
|
978
|
-
await fs.access(
|
|
1078
|
+
await fs.access(absoluteTracePath)
|
|
979
1079
|
} catch {
|
|
980
1080
|
return {
|
|
981
1081
|
status: 404,
|
|
@@ -983,9 +1083,6 @@ export async function spawnTraceViewerAction(testRunId: string, testCaseId: stri
|
|
|
983
1083
|
}
|
|
984
1084
|
}
|
|
985
1085
|
|
|
986
|
-
// Resolve absolute path if relative
|
|
987
|
-
const absoluteTracePath = path.isAbsolute(tracePath) ? tracePath : path.join(process.cwd(), tracePath)
|
|
988
|
-
|
|
989
1086
|
// Spawn playwright show-trace command
|
|
990
1087
|
// The process is self-closing when the user closes the trace viewer
|
|
991
1088
|
const spawnedProcess = await localExecutorAdapter.spawnTraceViewer(testCaseId, absoluteTracePath)
|
|
@@ -1177,7 +1274,3 @@ export async function checkTestRunNameUniqueAction(name: string, excludeId?: str
|
|
|
1177
1274
|
}
|
|
1178
1275
|
}
|
|
1179
1276
|
}
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|