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
|
@@ -1,87 +1,87 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import { Button } from '@/components/ui/button'
|
|
4
|
-
import { Card, CardContent, CardTitle, CardHeader } from '@/components/ui/card'
|
|
5
|
-
import { ExternalLink } from 'lucide-react'
|
|
6
|
-
import { useRouter } from 'next/navigation'
|
|
7
|
-
import { useEffect, useState, useRef } from 'react'
|
|
8
|
-
import { getRunningTestRunsCountAction } from '@/actions/dashboard/dashboard-actions'
|
|
9
|
-
|
|
10
|
-
interface OngoingTestRunsCardProps {
|
|
11
|
-
initialCount: number
|
|
12
|
-
link: string
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export default function OngoingTestRunsCard({ initialCount, link }: OngoingTestRunsCardProps) {
|
|
16
|
-
const router = useRouter()
|
|
17
|
-
const [count, setCount] = useState(initialCount)
|
|
18
|
-
const pollingRef = useRef<NodeJS.Timeout | null>(null)
|
|
19
|
-
|
|
20
|
-
// Poll for count updates while there are ongoing test runs
|
|
21
|
-
useEffect(() => {
|
|
22
|
-
// Clear any existing polling interval
|
|
23
|
-
if (pollingRef.current) {
|
|
24
|
-
clearInterval(pollingRef.current)
|
|
25
|
-
pollingRef.current = null
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// If no ongoing test runs, don't poll
|
|
29
|
-
if (count === 0) {
|
|
30
|
-
return
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
pollingRef.current = setInterval(async () => {
|
|
34
|
-
try {
|
|
35
|
-
const { data, error } = await getRunningTestRunsCountAction()
|
|
36
|
-
if (error) {
|
|
37
|
-
console.error('Error polling running test runs count:', error)
|
|
38
|
-
return
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const newCount = data as number
|
|
42
|
-
setCount(newCount)
|
|
43
|
-
|
|
44
|
-
// If count reaches 0, stop polling
|
|
45
|
-
if (newCount === 0 && pollingRef.current) {
|
|
46
|
-
clearInterval(pollingRef.current)
|
|
47
|
-
pollingRef.current = null
|
|
48
|
-
}
|
|
49
|
-
} catch (error) {
|
|
50
|
-
console.error('Error polling running test runs count:', error)
|
|
51
|
-
}
|
|
52
|
-
}, 2000) // Poll every 2 seconds
|
|
53
|
-
|
|
54
|
-
return () => {
|
|
55
|
-
if (pollingRef.current) {
|
|
56
|
-
clearInterval(pollingRef.current)
|
|
57
|
-
pollingRef.current = null
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}, [count])
|
|
61
|
-
|
|
62
|
-
return (
|
|
63
|
-
<Card className="h-fit border-gray-600/10 bg-gray-600/10 min-w-40">
|
|
64
|
-
<CardHeader className="flex items-center justify-between flex-row p-2">
|
|
65
|
-
<CardTitle className={`text-xs font-normal ${count > 0 ? 'text-primary' : 'text-gray-400'}`}>
|
|
66
|
-
Ongoing Test Runs
|
|
67
|
-
</CardTitle>
|
|
68
|
-
<div className="flex items-center gap-2">
|
|
69
|
-
<Button
|
|
70
|
-
variant="outline"
|
|
71
|
-
className="text-primary hover:text-primary/80 px-2 py-1 bg-inherit border-gray-600/15 hover:bg-emerald-400/10"
|
|
72
|
-
disabled={count === 0}
|
|
73
|
-
onClick={() => router.push(link)}
|
|
74
|
-
size="sm"
|
|
75
|
-
>
|
|
76
|
-
<ExternalLink className="h-4 w-4" />
|
|
77
|
-
</Button>
|
|
78
|
-
</div>
|
|
79
|
-
</CardHeader>
|
|
80
|
-
<CardContent className="h-full px-2 py-1">
|
|
81
|
-
<div className={`text-2xl h-full flex items-center font-bold ${count > 0 ? 'text-primary' : 'text-gray-400'}`}>
|
|
82
|
-
{count}
|
|
83
|
-
</div>
|
|
84
|
-
</CardContent>
|
|
85
|
-
</Card>
|
|
86
|
-
)
|
|
87
|
-
}
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { Button } from '@/components/ui/button'
|
|
4
|
+
import { Card, CardContent, CardTitle, CardHeader } from '@/components/ui/card'
|
|
5
|
+
import { ExternalLink } from 'lucide-react'
|
|
6
|
+
import { useRouter } from 'next/navigation'
|
|
7
|
+
import { useEffect, useState, useRef } from 'react'
|
|
8
|
+
import { getRunningTestRunsCountAction } from '@/actions/dashboard/dashboard-actions'
|
|
9
|
+
|
|
10
|
+
interface OngoingTestRunsCardProps {
|
|
11
|
+
initialCount: number
|
|
12
|
+
link: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default function OngoingTestRunsCard({ initialCount, link }: OngoingTestRunsCardProps) {
|
|
16
|
+
const router = useRouter()
|
|
17
|
+
const [count, setCount] = useState(initialCount)
|
|
18
|
+
const pollingRef = useRef<NodeJS.Timeout | null>(null)
|
|
19
|
+
|
|
20
|
+
// Poll for count updates while there are ongoing test runs
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
// Clear any existing polling interval
|
|
23
|
+
if (pollingRef.current) {
|
|
24
|
+
clearInterval(pollingRef.current)
|
|
25
|
+
pollingRef.current = null
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// If no ongoing test runs, don't poll
|
|
29
|
+
if (count === 0) {
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
pollingRef.current = setInterval(async () => {
|
|
34
|
+
try {
|
|
35
|
+
const { data, error } = await getRunningTestRunsCountAction()
|
|
36
|
+
if (error) {
|
|
37
|
+
console.error('Error polling running test runs count:', error)
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const newCount = data as number
|
|
42
|
+
setCount(newCount)
|
|
43
|
+
|
|
44
|
+
// If count reaches 0, stop polling
|
|
45
|
+
if (newCount === 0 && pollingRef.current) {
|
|
46
|
+
clearInterval(pollingRef.current)
|
|
47
|
+
pollingRef.current = null
|
|
48
|
+
}
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.error('Error polling running test runs count:', error)
|
|
51
|
+
}
|
|
52
|
+
}, 2000) // Poll every 2 seconds
|
|
53
|
+
|
|
54
|
+
return () => {
|
|
55
|
+
if (pollingRef.current) {
|
|
56
|
+
clearInterval(pollingRef.current)
|
|
57
|
+
pollingRef.current = null
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}, [count])
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<Card className="h-fit border-gray-600/10 bg-gray-600/10 min-w-40">
|
|
64
|
+
<CardHeader className="flex items-center justify-between flex-row p-2">
|
|
65
|
+
<CardTitle className={`text-xs font-normal ${count > 0 ? 'text-primary' : 'text-gray-400'}`}>
|
|
66
|
+
Ongoing Test Runs
|
|
67
|
+
</CardTitle>
|
|
68
|
+
<div className="flex items-center gap-2">
|
|
69
|
+
<Button
|
|
70
|
+
variant="outline"
|
|
71
|
+
className="text-primary hover:text-primary/80 px-2 py-1 bg-inherit border-gray-600/15 hover:bg-emerald-400/10"
|
|
72
|
+
disabled={count === 0}
|
|
73
|
+
onClick={() => router.push(link)}
|
|
74
|
+
size="sm"
|
|
75
|
+
>
|
|
76
|
+
<ExternalLink className="h-4 w-4" />
|
|
77
|
+
</Button>
|
|
78
|
+
</div>
|
|
79
|
+
</CardHeader>
|
|
80
|
+
<CardContent className="h-full px-2 py-1">
|
|
81
|
+
<div className={`text-2xl h-full flex items-center font-bold ${count > 0 ? 'text-primary' : 'text-gray-400'}`}>
|
|
82
|
+
{count}
|
|
83
|
+
</div>
|
|
84
|
+
</CardContent>
|
|
85
|
+
</Card>
|
|
86
|
+
)
|
|
87
|
+
}
|
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
import { Button } from "@/components/ui/button";
|
|
3
|
-
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
|
4
|
-
import { Blocks, FileCheck, LayoutTemplate, ListChecks, TestTubeDiagonal, TestTubes } from "lucide-react";
|
|
5
|
-
import { useRouter } from "next/navigation";
|
|
6
|
-
|
|
7
|
-
export default function QuickActionsDrawer() {
|
|
8
|
-
const router = useRouter()
|
|
9
|
-
return (
|
|
10
|
-
<Card id="container" className="w-fit border-gray-600/10 bg-gray-600/10 h-fit">
|
|
11
|
-
<CardHeader id="header">
|
|
12
|
-
<CardTitle className="text-primary">Quick Actions</CardTitle>
|
|
13
|
-
<CardDescription>Quickly create new entities to get started</CardDescription>
|
|
14
|
-
</CardHeader>
|
|
15
|
-
<CardContent id="content">
|
|
16
|
-
<div className="grid grid-cols-5 gap-4">
|
|
17
|
-
<Button variant="outline" className="flex flex-col items-center gap-2 h-fit [&_svg]:!h-6 [&_svg]:!w-6 bg-emerald-500/10 hover:bg-emerald-500/25 text-emerald-500 hover:text-emerald-400 border-none" onClick={() => router.push('/test-suites/create')}>
|
|
18
|
-
<TestTubes />
|
|
19
|
-
<span className="text-xs font-medium">Create Suite</span>
|
|
20
|
-
</Button>
|
|
21
|
-
<Button variant="outline" className="flex flex-col items-center gap-2 h-fit [&_svg]:!h-6 [&_svg]:!w-6 bg-emerald-500/10 hover:bg-emerald-500/25 text-emerald-500 hover:text-emerald-400 border-none" onClick={() => router.push('/test-cases/create')}>
|
|
22
|
-
<TestTubeDiagonal />
|
|
23
|
-
<span className="text-xs font-medium">Create Test</span>
|
|
24
|
-
</Button>
|
|
25
|
-
<Button variant="outline" className="flex flex-col items-center gap-2 h-fit [&_svg]:!h-6 [&_svg]:!w-6 bg-emerald-500/10 hover:bg-emerald-500/25 text-emerald-500 hover:text-emerald-400 border-none" onClick={() => router.push('/template-steps/create')}>
|
|
26
|
-
<LayoutTemplate />
|
|
27
|
-
<span className="text-xs font-medium">Create Step</span>
|
|
28
|
-
</Button>
|
|
29
|
-
<Button variant="outline" className="flex flex-col items-center gap-2 h-fit [&_svg]:!h-6 [&_svg]:!w-6 bg-emerald-500/10 hover:bg-emerald-500/25 text-emerald-500 hover:text-emerald-400 border-none" onClick={() => router.push('/test-runs/create')}>
|
|
30
|
-
<ListChecks />
|
|
31
|
-
<span className="text-xs font-medium">Create Run</span>
|
|
32
|
-
</Button>
|
|
33
|
-
<Button variant="outline" className="flex flex-col items-center gap-2 h-fit [&_svg]:!h-6 [&_svg]:!w-6 bg-emerald-500/10 hover:bg-emerald-500/25 text-emerald-500 hover:text-emerald-400 border-none" onClick={() => router.push('/template-test-cases/create')}>
|
|
34
|
-
<Blocks />
|
|
35
|
-
<span className="text-xs font-medium">Create Template</span>
|
|
36
|
-
</Button>
|
|
37
|
-
<Button variant="outline" className="flex flex-col items-center gap-2 h-fit [&_svg]:!h-6 [&_svg]:!w-6 bg-emerald-500/10 hover:bg-emerald-500/25 text-emerald-500 hover:text-emerald-400 border-none" onClick={() => router.push('/reports')}>
|
|
38
|
-
<FileCheck />
|
|
39
|
-
<span className="text-xs font-medium">View Reports</span>
|
|
40
|
-
</Button>
|
|
41
|
-
</div>
|
|
42
|
-
</CardContent>
|
|
43
|
-
</Card>
|
|
44
|
-
)
|
|
1
|
+
'use client'
|
|
2
|
+
import { Button } from "@/components/ui/button";
|
|
3
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
|
4
|
+
import { Blocks, FileCheck, LayoutTemplate, ListChecks, TestTubeDiagonal, TestTubes } from "lucide-react";
|
|
5
|
+
import { useRouter } from "next/navigation";
|
|
6
|
+
|
|
7
|
+
export default function QuickActionsDrawer() {
|
|
8
|
+
const router = useRouter()
|
|
9
|
+
return (
|
|
10
|
+
<Card id="container" className="w-fit border-gray-600/10 bg-gray-600/10 h-fit">
|
|
11
|
+
<CardHeader id="header">
|
|
12
|
+
<CardTitle className="text-primary">Quick Actions</CardTitle>
|
|
13
|
+
<CardDescription>Quickly create new entities to get started</CardDescription>
|
|
14
|
+
</CardHeader>
|
|
15
|
+
<CardContent id="content">
|
|
16
|
+
<div className="grid grid-cols-5 gap-4">
|
|
17
|
+
<Button variant="outline" className="flex flex-col items-center gap-2 h-fit [&_svg]:!h-6 [&_svg]:!w-6 bg-emerald-500/10 hover:bg-emerald-500/25 text-emerald-500 hover:text-emerald-400 border-none" onClick={() => router.push('/test-suites/create')}>
|
|
18
|
+
<TestTubes />
|
|
19
|
+
<span className="text-xs font-medium">Create Suite</span>
|
|
20
|
+
</Button>
|
|
21
|
+
<Button variant="outline" className="flex flex-col items-center gap-2 h-fit [&_svg]:!h-6 [&_svg]:!w-6 bg-emerald-500/10 hover:bg-emerald-500/25 text-emerald-500 hover:text-emerald-400 border-none" onClick={() => router.push('/test-cases/create')}>
|
|
22
|
+
<TestTubeDiagonal />
|
|
23
|
+
<span className="text-xs font-medium">Create Test</span>
|
|
24
|
+
</Button>
|
|
25
|
+
<Button variant="outline" className="flex flex-col items-center gap-2 h-fit [&_svg]:!h-6 [&_svg]:!w-6 bg-emerald-500/10 hover:bg-emerald-500/25 text-emerald-500 hover:text-emerald-400 border-none" onClick={() => router.push('/template-steps/create')}>
|
|
26
|
+
<LayoutTemplate />
|
|
27
|
+
<span className="text-xs font-medium">Create Step</span>
|
|
28
|
+
</Button>
|
|
29
|
+
<Button variant="outline" className="flex flex-col items-center gap-2 h-fit [&_svg]:!h-6 [&_svg]:!w-6 bg-emerald-500/10 hover:bg-emerald-500/25 text-emerald-500 hover:text-emerald-400 border-none" onClick={() => router.push('/test-runs/create')}>
|
|
30
|
+
<ListChecks />
|
|
31
|
+
<span className="text-xs font-medium">Create Run</span>
|
|
32
|
+
</Button>
|
|
33
|
+
<Button variant="outline" className="flex flex-col items-center gap-2 h-fit [&_svg]:!h-6 [&_svg]:!w-6 bg-emerald-500/10 hover:bg-emerald-500/25 text-emerald-500 hover:text-emerald-400 border-none" onClick={() => router.push('/template-test-cases/create')}>
|
|
34
|
+
<Blocks />
|
|
35
|
+
<span className="text-xs font-medium">Create Template</span>
|
|
36
|
+
</Button>
|
|
37
|
+
<Button variant="outline" className="flex flex-col items-center gap-2 h-fit [&_svg]:!h-6 [&_svg]:!w-6 bg-emerald-500/10 hover:bg-emerald-500/25 text-emerald-500 hover:text-emerald-400 border-none" onClick={() => router.push('/reports')}>
|
|
38
|
+
<FileCheck />
|
|
39
|
+
<span className="text-xs font-medium">View Reports</span>
|
|
40
|
+
</Button>
|
|
41
|
+
</div>
|
|
42
|
+
</CardContent>
|
|
43
|
+
</Card>
|
|
44
|
+
)
|
|
45
45
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server'
|
|
2
|
+
import { promises as fs, createReadStream } from 'fs'
|
|
3
|
+
import { Readable } from 'stream'
|
|
4
|
+
import prisma from '@/config/db-config'
|
|
5
|
+
import { resolveStoredPath } from '@/lib/automation/paths'
|
|
6
|
+
|
|
7
|
+
export const runtime = 'nodejs'
|
|
8
|
+
|
|
9
|
+
export async function GET(_request: Request, { params }: { params: Promise<{ stepId: string }> }) {
|
|
10
|
+
const { stepId } = await params
|
|
11
|
+
|
|
12
|
+
try {
|
|
13
|
+
const step = await prisma.reportStep.findUnique({
|
|
14
|
+
where: { id: stepId },
|
|
15
|
+
select: {
|
|
16
|
+
screenshotPath: true,
|
|
17
|
+
},
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
if (!step) {
|
|
21
|
+
return NextResponse.json({ error: 'Report step not found' }, { status: 404 })
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (!step.screenshotPath) {
|
|
25
|
+
return NextResponse.json({ error: 'Screenshot not available for this step' }, { status: 404 })
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const screenshotPath = resolveStoredPath(step.screenshotPath)
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
await fs.access(screenshotPath)
|
|
32
|
+
} catch {
|
|
33
|
+
return NextResponse.json({ error: 'Screenshot file not found' }, { status: 404 })
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return new NextResponse(Readable.toWeb(createReadStream(screenshotPath)) as ReadableStream, {
|
|
37
|
+
headers: {
|
|
38
|
+
'Content-Type': 'image/png',
|
|
39
|
+
'Cache-Control': 'private, max-age=60',
|
|
40
|
+
},
|
|
41
|
+
})
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.error(`[ReportScreenshot] Failed to serve screenshot for step ${stepId}:`, error)
|
|
44
|
+
return NextResponse.json(
|
|
45
|
+
{
|
|
46
|
+
error: 'Failed to load screenshot',
|
|
47
|
+
details: error instanceof Error ? error.message : 'Unknown error',
|
|
48
|
+
},
|
|
49
|
+
{ status: 500 },
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -3,31 +3,83 @@ import prisma from '@/config/db-config'
|
|
|
3
3
|
import archiver from 'archiver'
|
|
4
4
|
import { promises as fs } from 'fs'
|
|
5
5
|
import path from 'path'
|
|
6
|
+
import { getAutomationReportRunDir, resolveStoredPath } from '@/lib/automation/paths'
|
|
6
7
|
|
|
7
8
|
// Ensure this route runs in Node.js runtime (not Edge) for file system access
|
|
8
9
|
export const runtime = 'nodejs'
|
|
9
10
|
|
|
11
|
+
async function collectRunArtifactFiles(
|
|
12
|
+
dir: string,
|
|
13
|
+
baseDir = dir,
|
|
14
|
+
): Promise<Array<{ absolutePath: string; archivePath: string }>> {
|
|
15
|
+
try {
|
|
16
|
+
const entries = await fs.readdir(dir, { withFileTypes: true })
|
|
17
|
+
const files: Array<{ absolutePath: string; archivePath: string }> = []
|
|
18
|
+
|
|
19
|
+
for (const entry of entries) {
|
|
20
|
+
const absolutePath = path.join(dir, entry.name)
|
|
21
|
+
if (entry.isDirectory()) {
|
|
22
|
+
files.push(...(await collectRunArtifactFiles(absolutePath, baseDir)))
|
|
23
|
+
continue
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
files.push({
|
|
27
|
+
absolutePath,
|
|
28
|
+
archivePath: path.relative(baseDir, absolutePath).replace(/\\/g, '/'),
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return files
|
|
33
|
+
} catch {
|
|
34
|
+
return []
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function addStoredArtifactFile(
|
|
39
|
+
archive: ReturnType<typeof archiver>,
|
|
40
|
+
storedPath: string,
|
|
41
|
+
archivePath: string,
|
|
42
|
+
warningLabel: string,
|
|
43
|
+
): Promise<boolean> {
|
|
44
|
+
try {
|
|
45
|
+
const resolvedPath = resolveStoredPath(storedPath)
|
|
46
|
+
await fs.access(resolvedPath)
|
|
47
|
+
archive.file(resolvedPath, { name: archivePath })
|
|
48
|
+
return true
|
|
49
|
+
} catch {
|
|
50
|
+
console.warn(`[Download] ${warningLabel} not found at path: ${storedPath}`)
|
|
51
|
+
return false
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function isPathWithinDirectory(targetPath: string, directoryPath: string): boolean {
|
|
56
|
+
const relativePath = path.relative(directoryPath, targetPath)
|
|
57
|
+
return relativePath !== '' && !relativePath.startsWith('..') && !path.isAbsolute(relativePath)
|
|
58
|
+
}
|
|
59
|
+
|
|
10
60
|
/**
|
|
11
|
-
* GET handler for downloading test run
|
|
61
|
+
* GET handler for downloading a test run's stored artifacts as a zip file
|
|
12
62
|
*
|
|
13
63
|
* This endpoint:
|
|
14
64
|
* - Verifies the test run exists
|
|
15
|
-
* - Collects the
|
|
16
|
-
* -
|
|
65
|
+
* - Collects the run folder artifacts when present
|
|
66
|
+
* - Falls back to legacy log/trace paths for older runs
|
|
17
67
|
* - Creates a zip file containing all files
|
|
18
68
|
* - Returns the zip file as a downloadable response
|
|
19
69
|
*/
|
|
20
|
-
export async function GET(
|
|
70
|
+
export async function GET(_request: NextRequest, { params }: { params: Promise<{ runId: string }> }) {
|
|
21
71
|
const { runId } = await params
|
|
72
|
+
const runArtifactDir = getAutomationReportRunDir(runId)
|
|
22
73
|
|
|
23
74
|
try {
|
|
24
75
|
// Verify test run exists
|
|
25
76
|
const testRun = await prisma.testRun.findUnique({
|
|
26
77
|
where: { runId },
|
|
27
|
-
|
|
78
|
+
select: {
|
|
79
|
+
logPath: true,
|
|
80
|
+
reportPath: true,
|
|
28
81
|
testCases: {
|
|
29
82
|
select: {
|
|
30
|
-
id: true,
|
|
31
83
|
tracePath: true,
|
|
32
84
|
},
|
|
33
85
|
},
|
|
@@ -43,47 +95,59 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
|
|
|
43
95
|
zlib: { level: 9 }, // Maximum compression
|
|
44
96
|
})
|
|
45
97
|
|
|
46
|
-
|
|
47
|
-
let hasFiles =
|
|
98
|
+
const runArtifactFiles = await collectRunArtifactFiles(runArtifactDir)
|
|
99
|
+
let hasFiles = runArtifactFiles.length > 0
|
|
100
|
+
const archivedPaths = new Set<string>(runArtifactFiles.map(artifactFile => artifactFile.archivePath))
|
|
101
|
+
|
|
102
|
+
for (const artifactFile of runArtifactFiles) {
|
|
103
|
+
archive.file(artifactFile.absolutePath, { name: artifactFile.archivePath })
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (testRun.reportPath) {
|
|
107
|
+
const resolvedReportPath = resolveStoredPath(testRun.reportPath)
|
|
108
|
+
if (!isPathWithinDirectory(resolvedReportPath, runArtifactDir) && !archivedPaths.has('cucumber.json')) {
|
|
109
|
+
const didAddReportFile = await addStoredArtifactFile(archive, testRun.reportPath, 'cucumber.json', 'Report file')
|
|
110
|
+
hasFiles = didAddReportFile || hasFiles
|
|
111
|
+
if (didAddReportFile) {
|
|
112
|
+
archivedPaths.add('cucumber.json')
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
48
116
|
|
|
49
|
-
// Add log file if it exists
|
|
50
117
|
if (testRun.logPath) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
archive
|
|
55
|
-
hasFiles =
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
118
|
+
const resolvedLogPath = resolveStoredPath(testRun.logPath)
|
|
119
|
+
const archivePath = `logs/${path.basename(testRun.logPath)}`
|
|
120
|
+
if (!isPathWithinDirectory(resolvedLogPath, runArtifactDir) && !archivedPaths.has(archivePath)) {
|
|
121
|
+
const didAddLogFile = await addStoredArtifactFile(archive, testRun.logPath, archivePath, 'Log file')
|
|
122
|
+
hasFiles = didAddLogFile || hasFiles
|
|
123
|
+
if (didAddLogFile) {
|
|
124
|
+
archivedPaths.add(archivePath)
|
|
125
|
+
}
|
|
59
126
|
}
|
|
60
127
|
}
|
|
61
128
|
|
|
62
|
-
|
|
63
|
-
const traceFiles = testRun.testCases.filter(tc => tc.tracePath).map(tc => tc.tracePath!)
|
|
129
|
+
const traceFiles = testRun.testCases.flatMap(({ tracePath }) => (tracePath ? [tracePath] : []))
|
|
64
130
|
for (const tracePath of traceFiles) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
131
|
+
const resolvedTracePath = resolveStoredPath(tracePath)
|
|
132
|
+
const archivePath = `traces/${path.basename(tracePath)}`
|
|
133
|
+
|
|
134
|
+
if (!isPathWithinDirectory(resolvedTracePath, runArtifactDir) && !archivedPaths.has(archivePath)) {
|
|
135
|
+
const didAddTraceFile = await addStoredArtifactFile(archive, tracePath, archivePath, 'Trace file')
|
|
136
|
+
hasFiles = didAddTraceFile || hasFiles
|
|
137
|
+
if (didAddTraceFile) {
|
|
138
|
+
archivedPaths.add(archivePath)
|
|
139
|
+
}
|
|
73
140
|
}
|
|
74
141
|
}
|
|
75
142
|
|
|
76
143
|
// If no files to add, return an error
|
|
77
144
|
if (!hasFiles) {
|
|
78
|
-
return NextResponse.json(
|
|
79
|
-
{ error: 'No log or trace files available for this test run' },
|
|
80
|
-
{ status: 404 },
|
|
81
|
-
)
|
|
145
|
+
return NextResponse.json({ error: 'No run artifacts available for this test run' }, { status: 404 })
|
|
82
146
|
}
|
|
83
147
|
|
|
84
148
|
// Create a readable stream to collect the archive data
|
|
85
149
|
const chunks: Buffer[] = []
|
|
86
|
-
|
|
150
|
+
|
|
87
151
|
// Set up event handlers before finalizing
|
|
88
152
|
const archivePromise = new Promise<Buffer>((resolve, reject) => {
|
|
89
153
|
archive.on('data', (chunk: Buffer) => {
|
|
@@ -95,7 +159,7 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
|
|
|
95
159
|
resolve(zipBuffer)
|
|
96
160
|
})
|
|
97
161
|
|
|
98
|
-
archive.on('error',
|
|
162
|
+
archive.on('error', err => {
|
|
99
163
|
reject(err)
|
|
100
164
|
})
|
|
101
165
|
})
|
|
@@ -130,4 +194,3 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
|
|
|
130
194
|
)
|
|
131
195
|
}
|
|
132
196
|
}
|
|
133
|
-
|
|
@@ -312,6 +312,8 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
|
|
|
312
312
|
scenarioName: string
|
|
313
313
|
status: string
|
|
314
314
|
tracePath?: string
|
|
315
|
+
featureName?: string
|
|
316
|
+
scenarioTags?: string[]
|
|
315
317
|
}) => {
|
|
316
318
|
// Early return if error occurred to prevent infinite loops
|
|
317
319
|
if (errorOccurred) return
|
|
@@ -325,7 +327,9 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
|
|
|
325
327
|
sendSSE(
|
|
326
328
|
'scenario::end',
|
|
327
329
|
JSON.stringify({
|
|
330
|
+
featureName: eventData.featureName,
|
|
328
331
|
scenarioName: eventData.scenarioName,
|
|
332
|
+
scenarioTags: eventData.scenarioTags,
|
|
329
333
|
status: eventData.status,
|
|
330
334
|
tracePath: eventData.tracePath,
|
|
331
335
|
}),
|
|
@@ -418,4 +422,3 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
|
|
|
418
422
|
},
|
|
419
423
|
})
|
|
420
424
|
}
|
|
421
|
-
|