create-appraisejs 0.2.0-alpha.6 → 0.3.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -1
- package/package.json +1 -1
- package/templates/default/.appraise-template-meta.json +2 -2
- package/templates/default/.env.example +2 -2
- package/templates/default/README.md +57 -53
- 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/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 +110 -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 +20 -16
- package/templates/default/next-env.d.ts +6 -6
- package/templates/default/next.config.ts +20 -11
- package/templates/default/package-lock.json +1775 -74
- package/templates/default/package.json +8 -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/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/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/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 -1
- package/templates/default/scripts/build-step-registry.ts +33 -0
- package/templates/default/scripts/install-playwright.ts +17 -8
- package/templates/default/scripts/install-template-step.ts +128 -0
- package/templates/default/scripts/lib/filename-utils.test.ts +24 -0
- package/templates/default/scripts/lib/filename-utils.ts +24 -0
- package/templates/default/scripts/lib/jsdoc-parser.test.ts +63 -0
- package/templates/default/scripts/lib/jsdoc-parser.ts +88 -0
- package/templates/default/scripts/lib/step-file-parser.test.ts +71 -0
- package/templates/default/scripts/lib/step-file-parser.ts +315 -0
- package/templates/default/scripts/lib/step-matcher.test.ts +86 -0
- package/templates/default/scripts/lib/step-matcher.ts +120 -0
- package/templates/default/scripts/lib/sync-script-runner.ts +23 -0
- package/templates/default/scripts/lib/sync-summary.ts +29 -0
- package/templates/default/scripts/lib/tag-parsing.test.ts +20 -0
- package/templates/default/scripts/lib/tag-parsing.ts +10 -0
- package/templates/default/scripts/lib/template-step-installer.test.ts +225 -0
- package/templates/default/scripts/lib/template-step-installer.ts +404 -0
- package/templates/default/scripts/lib/template-step-registry.test.ts +118 -0
- package/templates/default/scripts/lib/template-step-registry.ts +137 -0
- package/templates/default/scripts/protect-seeded-files.ts +51 -38
- package/templates/default/scripts/regenerate-features.ts +98 -94
- package/templates/default/scripts/run-vitest.ts +59 -0
- package/templates/default/scripts/setup-env.ts +26 -19
- package/templates/default/scripts/sync-all.ts +44 -54
- package/templates/default/scripts/sync-appraise-base-template.ts +44 -16
- package/templates/default/scripts/sync-environments.ts +22 -66
- package/templates/default/scripts/sync-locator-groups.ts +358 -410
- package/templates/default/scripts/sync-locators.ts +348 -398
- package/templates/default/scripts/sync-modules.ts +302 -341
- package/templates/default/scripts/sync-tags.ts +29 -65
- package/templates/default/scripts/sync-template-step-groups.ts +24 -182
- package/templates/default/scripts/sync-template-steps.ts +36 -493
- package/templates/default/scripts/sync-test-cases.ts +296 -539
- package/templates/default/scripts/sync-test-suites.ts +32 -79
- package/templates/default/src/actions/dashboard/dashboard-actions.ts +70 -241
- package/templates/default/src/actions/environments/environment-actions.ts +102 -188
- package/templates/default/src/actions/locator/locator-actions.ts +77 -490
- package/templates/default/src/actions/locator-groups/locator-group-actions.ts +34 -212
- package/templates/default/src/actions/locator-picker/locator-picker-actions.test.ts +81 -0
- package/templates/default/src/actions/locator-picker/locator-picker-actions.ts +20 -161
- package/templates/default/src/actions/modules/module-actions.ts +99 -135
- package/templates/default/src/actions/reports/report-actions.ts +28 -565
- package/templates/default/src/actions/settings/sync-actions.test.ts +58 -0
- package/templates/default/src/actions/tags/tag-actions.ts +99 -107
- package/templates/default/src/actions/template-step/template-step-actions.ts +33 -194
- package/templates/default/src/actions/template-step-group/template-step-group-actions.ts +35 -92
- package/templates/default/src/actions/template-test-case/template-test-case-actions.ts +98 -238
- package/templates/default/src/actions/test-case/test-case-actions.ts +108 -356
- package/templates/default/src/actions/test-run/test-run-actions.ts +74 -1081
- package/templates/default/src/actions/test-suite/test-suite-actions.ts +35 -202
- package/templates/default/src/app/(base)/environments/create/page.tsx +28 -28
- package/templates/default/src/app/(base)/environments/environment-form.test.tsx +92 -0
- package/templates/default/src/app/(base)/environments/environment-form.tsx +228 -219
- package/templates/default/src/app/(base)/environments/environment-helpers.ts +58 -0
- package/templates/default/src/app/(base)/environments/environment-table-columns.tsx +96 -96
- package/templates/default/src/app/(base)/environments/environment-table.tsx +25 -24
- package/templates/default/src/app/(base)/environments/modify/[id]/page.tsx +49 -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)/locators/create/create-locator-workspace-helpers.test.ts +71 -0
- package/templates/default/src/app/(base)/locators/create/create-locator-workspace-helpers.ts +333 -0
- package/templates/default/src/app/(base)/locators/create/create-locator-workspace.test.tsx +125 -0
- package/templates/default/src/app/(base)/locators/create/create-locator-workspace.tsx +56 -274
- package/templates/default/src/app/(base)/locators/create/page.tsx +8 -4
- package/templates/default/src/app/(base)/locators/create/use-locator-workspace.ts +183 -0
- package/templates/default/src/app/(base)/locators/locator-helpers.test.ts +28 -0
- package/templates/default/src/app/(base)/locators/locator-helpers.ts +59 -0
- package/templates/default/src/app/(base)/locators/locator-table-columns.tsx +74 -73
- package/templates/default/src/app/(base)/locators/locator-table.tsx +30 -28
- package/templates/default/src/app/(base)/locators/modify/[id]/page.tsx +20 -8
- package/templates/default/src/app/(base)/locators/page.tsx +3 -6
- package/templates/default/src/app/(base)/locators/sync-locators-button.tsx +67 -66
- package/templates/default/src/app/(base)/modules/create/page.tsx +33 -34
- package/templates/default/src/app/(base)/modules/modify/[id]/page.tsx +43 -46
- package/templates/default/src/app/(base)/modules/module-form.test.tsx +84 -0
- package/templates/default/src/app/(base)/modules/module-form.tsx +159 -126
- package/templates/default/src/app/(base)/modules/module-helpers.ts +64 -0
- package/templates/default/src/app/(base)/modules/module-table-columns.tsx +81 -85
- package/templates/default/src/app/(base)/modules/module-table.tsx +25 -24
- package/templates/default/src/app/(base)/modules/page.tsx +59 -59
- package/templates/default/src/app/(base)/reports/[id]/page.tsx +20 -260
- package/templates/default/src/app/(base)/reports/duration-chart.tsx +33 -33
- package/templates/default/src/app/(base)/reports/feature-chart.tsx +79 -78
- package/templates/default/src/app/(base)/reports/overview-chart.tsx +49 -49
- package/templates/default/src/app/(base)/reports/page.tsx +98 -98
- package/templates/default/src/app/(base)/reports/report-detail-helpers.test.ts +109 -0
- package/templates/default/src/app/(base)/reports/report-detail-helpers.ts +247 -0
- package/templates/default/src/app/(base)/reports/report-metric-card.tsx +78 -78
- 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/test-cases/page.tsx +40 -40
- 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 -58
- package/templates/default/src/app/(base)/settings/settings-sync-panel-helpers.test.tsx +40 -0
- package/templates/default/src/app/(base)/settings/settings-sync-panel-helpers.tsx +110 -0
- package/templates/default/src/app/(base)/settings/settings-sync-panel.test.tsx +127 -0
- package/templates/default/src/app/(base)/settings/settings-sync-panel.tsx +19 -134
- package/templates/default/src/app/(base)/settings/use-settings-sync.ts +66 -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-helpers.ts +13 -0
- package/templates/default/src/app/(base)/tags/tag-form.test.tsx +83 -0
- package/templates/default/src/app/(base)/tags/tag-form.tsx +143 -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 +43 -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.test.tsx +82 -0
- package/templates/default/src/app/(base)/template-step-groups/template-step-group-form.tsx +181 -167
- package/templates/default/src/app/(base)/template-step-groups/template-step-group-helpers.ts +54 -0
- 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 +34 -32
- package/templates/default/src/app/(base)/template-steps/create/page.tsx +40 -37
- package/templates/default/src/app/(base)/template-steps/modify/[id]/page.tsx +54 -49
- package/templates/default/src/app/(base)/template-steps/page.tsx +59 -58
- package/templates/default/src/app/(base)/template-steps/paramChip.tsx +233 -213
- package/templates/default/src/app/(base)/template-steps/template-step-form.test.tsx +132 -0
- package/templates/default/src/app/(base)/template-steps/template-step-form.tsx +342 -384
- package/templates/default/src/app/(base)/template-steps/template-step-helpers.test.ts +99 -0
- package/templates/default/src/app/(base)/template-steps/template-step-helpers.ts +176 -0
- package/templates/default/src/app/(base)/template-steps/template-step-table-columns.tsx +153 -158
- package/templates/default/src/app/(base)/template-steps/template-step-table.tsx +26 -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.test.tsx +109 -0
- package/templates/default/src/app/(base)/template-test-cases/template-test-case-flow.tsx +45 -84
- package/templates/default/src/app/(base)/template-test-cases/template-test-case-form.test.tsx +140 -0
- package/templates/default/src/app/(base)/template-test-cases/template-test-case-form.tsx +154 -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 +90 -76
- package/templates/default/src/app/(base)/test-cases/create-from-template/create-from-template-helpers.test.ts +94 -0
- package/templates/default/src/app/(base)/test-cases/create-from-template/create-from-template-helpers.ts +171 -0
- package/templates/default/src/app/(base)/test-cases/create-from-template/generate/[id]/page.tsx +105 -96
- package/templates/default/src/app/(base)/test-cases/create-from-template/page.tsx +40 -38
- package/templates/default/src/app/(base)/test-cases/create-from-template/template-selection-form.test.tsx +87 -0
- package/templates/default/src/app/(base)/test-cases/create-from-template/template-selection-form.tsx +83 -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 +3 -2
- package/templates/default/src/app/(base)/test-cases/test-case-flow.test.tsx +108 -0
- package/templates/default/src/app/(base)/test-cases/test-case-flow.tsx +43 -82
- package/templates/default/src/app/(base)/test-cases/test-case-form.test.tsx +202 -0
- package/templates/default/src/app/(base)/test-cases/test-case-form.tsx +263 -395
- package/templates/default/src/app/(base)/test-cases/test-case-route-helpers.test.ts +95 -0
- package/templates/default/src/app/(base)/test-cases/test-case-route-helpers.ts +147 -0
- package/templates/default/src/app/(base)/test-cases/test-case-table.tsx +4 -2
- package/templates/default/src/app/(base)/test-runs/[id]/page.tsx +11 -10
- package/templates/default/src/app/(base)/test-runs/create/page.tsx +4 -5
- package/templates/default/src/app/(base)/test-runs/page.tsx +60 -60
- package/templates/default/src/app/(base)/test-runs/test-run-form-helpers.test.ts +50 -0
- package/templates/default/src/app/(base)/test-runs/test-run-form-helpers.ts +168 -0
- package/templates/default/src/app/(base)/test-runs/test-run-form.test.tsx +138 -0
- package/templates/default/src/app/(base)/test-runs/test-run-form.tsx +111 -256
- 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-runs/use-test-run-name-validation.ts +74 -0
- package/templates/default/src/app/(base)/test-suites/create/page.tsx +17 -12
- package/templates/default/src/app/(base)/test-suites/modify/[id]/page.tsx +22 -19
- package/templates/default/src/app/(base)/test-suites/page.tsx +14 -56
- package/templates/default/src/app/(base)/test-suites/test-suite-form.test.tsx +127 -0
- package/templates/default/src/app/(base)/test-suites/test-suite-form.tsx +45 -64
- package/templates/default/src/app/(base)/test-suites/test-suite-helpers.test.ts +67 -0
- package/templates/default/src/app/(base)/test-suites/test-suite-helpers.ts +215 -0
- package/templates/default/src/app/(base)/test-suites/test-suite-table.tsx +32 -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.test.ts +83 -0
- package/templates/default/src/app/api/reports/steps/[stepId]/screenshot/route.ts +52 -52
- package/templates/default/src/app/api/test-runs/[runId]/download/route.test.ts +169 -0
- package/templates/default/src/app/api/test-runs/[runId]/download/route.ts +1 -1
- package/templates/default/src/app/api/test-runs/[runId]/trace/[testCaseId]/route.test.ts +135 -0
- package/templates/default/src/app/api/test-runs/[runId]/trace/[testCaseId]/route.ts +146 -146
- package/templates/default/src/app/globals.css +147 -147
- package/templates/default/src/app/page.tsx +1 -1
- 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-helpers.test.ts +32 -0
- package/templates/default/src/components/data-extraction/locator-inspector-helpers.ts +183 -0
- package/templates/default/src/components/data-extraction/locator-inspector.tsx +349 -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-helpers.test.ts +83 -0
- package/templates/default/src/components/diagram/dynamic-parameters-helpers.ts +158 -0
- package/templates/default/src/components/diagram/dynamic-parameters.tsx +350 -474
- package/templates/default/src/components/diagram/edit-header-option.tsx +36 -36
- package/templates/default/src/components/diagram/flow-diagram-helpers.test.ts +117 -0
- package/templates/default/src/components/diagram/flow-diagram-helpers.ts +251 -0
- package/templates/default/src/components/diagram/flow-diagram.tsx +247 -470
- package/templates/default/src/components/diagram/flow-host-helpers.test.ts +74 -0
- package/templates/default/src/components/diagram/flow-host-helpers.ts +51 -0
- package/templates/default/src/components/diagram/node-form-helpers.test.ts +92 -0
- package/templates/default/src/components/diagram/node-form-helpers.ts +100 -0
- package/templates/default/src/components/diagram/node-form.test.tsx +168 -0
- package/templates/default/src/components/diagram/node-form.tsx +199 -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/diagram/use-flow-node-order.ts +49 -0
- 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/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 +118 -116
- package/templates/default/src/components/navigation/nav-card.tsx +31 -31
- package/templates/default/src/components/navigation/nav-command-helpers.ts +122 -0
- package/templates/default/src/components/navigation/nav-command-search.tsx +125 -0
- package/templates/default/src/components/navigation/nav-command.test.tsx +106 -0
- package/templates/default/src/components/navigation/nav-command.tsx +49 -472
- 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/navigation/use-nav-command.ts +58 -0
- package/templates/default/src/components/node-header.tsx +159 -159
- package/templates/default/src/components/reports/test-case-logs-modal.tsx +310 -310
- package/templates/default/src/components/table/table-actions.tsx +174 -172
- package/templates/default/src/components/test-case/test-case-form-helpers.test.ts +100 -0
- package/templates/default/src/components/test-case/test-case-form-helpers.ts +140 -0
- package/templates/default/src/components/test-case/test-case-picker-helpers.test.ts +40 -0
- package/templates/default/src/components/test-case/test-case-picker-helpers.ts +41 -0
- package/templates/default/src/components/test-case/test-case-picker.test.tsx +44 -0
- package/templates/default/src/components/test-case/test-case-picker.tsx +16 -35
- package/templates/default/src/components/test-case/test-scenario-preview.tsx +34 -0
- package/templates/default/src/components/test-run/download-logs-button.tsx +92 -92
- package/templates/default/src/components/test-run/log-viewer-helpers.test.ts +37 -0
- package/templates/default/src/components/test-run/log-viewer-helpers.ts +80 -0
- package/templates/default/src/components/test-run/log-viewer.test.tsx +118 -0
- package/templates/default/src/components/test-run/log-viewer.tsx +51 -350
- package/templates/default/src/components/test-run/test-run-details-helpers.test.ts +31 -0
- package/templates/default/src/components/test-run/test-run-details-helpers.ts +208 -0
- package/templates/default/src/components/test-run/test-run-details.test.tsx +174 -0
- package/templates/default/src/components/test-run/test-run-details.tsx +155 -457
- package/templates/default/src/components/test-run/test-run-header-helpers.test.ts +31 -0
- package/templates/default/src/components/test-run/test-run-header-helpers.ts +23 -0
- package/templates/default/src/components/test-run/test-run-header.test.tsx +103 -0
- package/templates/default/src/components/test-run/test-run-header.tsx +27 -149
- package/templates/default/src/components/test-run/use-log-viewer.ts +213 -0
- package/templates/default/src/components/test-run/use-test-run-details.ts +184 -0
- package/templates/default/src/components/test-run/use-test-run-header.ts +89 -0
- package/templates/default/src/components/test-run/view-report-button.tsx +102 -102
- package/templates/default/src/components/test-suite/test-suite-picker-helpers.test.ts +68 -0
- package/templates/default/src/components/test-suite/test-suite-picker-helpers.ts +76 -0
- package/templates/default/src/components/test-suite/test-suite-picker.test.tsx +65 -0
- package/templates/default/src/components/test-suite/test-suite-picker.tsx +4 -72
- 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.test.tsx +122 -0
- package/templates/default/src/components/ui/data-table.tsx +298 -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.test.tsx +45 -0
- package/templates/default/src/components/ui/multi-select.tsx +158 -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.test.tsx +60 -0
- package/templates/default/src/components/user-prompt/delete-prompt.tsx +118 -87
- 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-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/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-suite-form-opts.ts +24 -24
- package/templates/default/src/hooks/use-toast.ts +187 -187
- package/templates/default/src/lib/automation/automation-path-roots.ts +95 -0
- package/templates/default/src/lib/automation/automation-workspace.ts +147 -0
- package/templates/default/src/lib/automation/paths.ts +6 -211
- package/templates/default/src/lib/bidirectional-sync.ts +432 -432
- package/templates/default/src/lib/environment-file-utils.ts +2 -1
- package/templates/default/src/lib/executor/local-executor-adapter.ts +2 -5
- package/templates/default/src/lib/feature-file-generator.ts +2 -1
- package/templates/default/src/lib/gherkin-parser.ts +0 -2
- package/templates/default/src/lib/locator-group-file-utils.ts +304 -307
- package/templates/default/src/lib/locator-picker/session-manager.ts +0 -21
- package/templates/default/src/lib/locator-picker/suggestions.ts +13 -11
- package/templates/default/src/lib/metrics/metric-calculator.ts +2 -6
- 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/sync/sync-executor.test.ts +76 -0
- package/templates/default/src/lib/sync/sync-pending-counts.test.ts +227 -226
- package/templates/default/src/lib/sync/sync-pending-counts.ts +2 -5
- 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/report-parser.ts +352 -352
- package/templates/default/src/lib/test-run/test-run-executor.ts +13 -13
- package/templates/default/src/lib/test-run/winston-logger.ts +65 -64
- 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 +2 -2
- 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/services/dashboard/dashboard-service.test.ts +106 -0
- package/templates/default/src/services/dashboard/dashboard-service.ts +173 -0
- package/templates/default/src/services/environment/environment-service.test.ts +137 -0
- package/templates/default/src/services/environment/environment-service.ts +96 -0
- package/templates/default/src/services/locator/locator-path-utils.test.ts +14 -0
- package/templates/default/src/services/locator/locator-path-utils.ts +14 -0
- package/templates/default/src/services/locator/locator-service.test.ts +63 -0
- package/templates/default/src/services/locator/locator-service.ts +479 -0
- package/templates/default/src/services/locator/locator-sync-utils.test.ts +19 -0
- package/templates/default/src/services/locator/locator-sync-utils.ts +21 -0
- package/templates/default/src/services/locator-group/locator-group-service.test.ts +123 -0
- package/templates/default/src/services/locator-group/locator-group-service.ts +180 -0
- package/templates/default/src/services/module/module-service.test.ts +89 -0
- package/templates/default/src/services/module/module-service.ts +66 -0
- package/templates/default/src/services/report/report-service.test.ts +244 -0
- package/templates/default/src/services/report/report-service.ts +438 -0
- package/templates/default/src/services/shared/constants.ts +2 -0
- package/templates/default/src/services/shared/errors.test.ts +38 -0
- package/templates/default/src/services/shared/errors.ts +44 -0
- package/templates/default/src/services/shared/index.ts +7 -0
- package/templates/default/src/services/tag/tag-service.test.ts +22 -0
- package/templates/default/src/services/tag/tag-service.ts +41 -0
- package/templates/default/src/services/template-step/template-step-service.test.ts +22 -0
- package/templates/default/src/services/template-step/template-step-service.ts +171 -0
- package/templates/default/src/services/template-step-group/template-step-group-service.test.ts +22 -0
- package/templates/default/src/services/template-step-group/template-step-group-service.ts +81 -0
- package/templates/default/src/services/template-test-case/template-test-case-service.test.ts +22 -0
- package/templates/default/src/services/template-test-case/template-test-case-service.ts +128 -0
- package/templates/default/src/services/test-case/test-case-service.test.ts +175 -0
- package/templates/default/src/services/test-case/test-case-service.ts +298 -0
- package/templates/default/src/services/test-run/test-run-helpers.ts +61 -0
- package/templates/default/src/services/test-run/test-run-service.test.ts +647 -0
- package/templates/default/src/services/test-run/test-run-service.ts +917 -0
- package/templates/default/src/services/test-suite/test-suite-service.test.ts +127 -0
- package/templates/default/src/services/test-suite/test-suite-service.ts +197 -0
- 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 +19 -6
- package/templates/default/src/types/locator/locator.type.ts +11 -11
- 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/tailwind.config.ts +62 -62
- package/templates/default/tsconfig.json +1 -1
- package/dist/cli.e2e.test.d.ts +0 -2
- package/dist/cli.e2e.test.d.ts.map +0 -1
- package/dist/cli.e2e.test.js +0 -73
- package/dist/cli.e2e.test.js.map +0 -1
- package/dist/config.test.d.ts +0 -2
- package/dist/config.test.d.ts.map +0 -1
- package/dist/config.test.js +0 -65
- package/dist/config.test.js.map +0 -1
- package/dist/copy-template.test.d.ts +0 -2
- package/dist/copy-template.test.d.ts.map +0 -1
- package/dist/copy-template.test.js +0 -71
- package/dist/copy-template.test.js.map +0 -1
- package/dist/download-repo.test.d.ts +0 -2
- package/dist/download-repo.test.d.ts.map +0 -1
- package/dist/download-repo.test.js +0 -14
- package/dist/download-repo.test.js.map +0 -1
- package/dist/install.test.d.ts +0 -2
- package/dist/install.test.d.ts.map +0 -1
- package/dist/install.test.js +0 -119
- package/dist/install.test.js.map +0 -1
- package/dist/prompts.test.d.ts +0 -2
- package/dist/prompts.test.d.ts.map +0 -1
- package/dist/prompts.test.js +0 -58
- package/dist/prompts.test.js.map +0 -1
- package/templates/default/src/actions/conflict/conflict.action.ts +0 -33
- package/templates/default/src/actions/review/review-actions.ts +0 -147
- package/templates/default/src/actions/user/user-actions.ts +0 -13
- package/templates/default/src/app/(base)/locators/locator-form.tsx +0 -163
- package/templates/default/src/app/(base)/reviews/create/page.tsx +0 -26
- package/templates/default/src/app/(base)/reviews/created-reviews-table.tsx +0 -15
- package/templates/default/src/app/(base)/reviews/modify/[id]/page.tsx +0 -26
- package/templates/default/src/app/(base)/reviews/page.tsx +0 -26
- package/templates/default/src/app/(base)/reviews/review/[id]/page.tsx +0 -26
- package/templates/default/src/app/(base)/reviews/review-form.tsx +0 -11
- package/templates/default/src/app/(base)/reviews/review-table-by-creator-columns.tsx +0 -9
- package/templates/default/src/app/(base)/reviews/review-table-by-reviewer-columns.tsx +0 -9
- package/templates/default/src/app/(base)/reviews/reviewer-reviews-table.tsx +0 -15
- package/templates/default/src/constants/form-opts/locator-form-opts.ts +0 -20
- package/templates/default/src/constants/form-opts/review-form-opts.ts +0 -23
|
@@ -1,28 +1,67 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
3
|
import { Button } from '@/components/ui/button'
|
|
4
|
+
import ErrorMessage from '@/components/form/error-message'
|
|
4
5
|
import TestSuitePicker from '@/components/test-suite/test-suite-picker'
|
|
5
6
|
import { Input } from '@/components/ui/input'
|
|
6
7
|
import { Label } from '@/components/ui/label'
|
|
7
8
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
|
|
8
9
|
import { MultiSelect } from '@/components/ui/multi-select'
|
|
9
|
-
import { formOpts, TestRun } from '@/constants/form-opts/test-run-form-opts'
|
|
10
|
+
import { formOpts, type TestRun } from '@/constants/form-opts/test-run-form-opts'
|
|
10
11
|
import { toast } from '@/hooks/use-toast'
|
|
11
|
-
import { ActionResponse } from '@/types/form/actionHandler'
|
|
12
12
|
import { BrowserEngine, Environment, Tag } from '@prisma/client'
|
|
13
13
|
import { useForm } from '@tanstack/react-form'
|
|
14
14
|
import { useRouter } from 'next/navigation'
|
|
15
|
-
import {
|
|
16
|
-
import { z } from 'zod'
|
|
15
|
+
import { useRef, useState } from 'react'
|
|
17
16
|
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'
|
|
18
17
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
|
19
|
-
import { checkTestRunNameUniqueAction } from '@/actions/test-run/test-run-actions'
|
|
20
18
|
import { Info, Play } from 'lucide-react'
|
|
21
|
-
import { TestSuitePickerRow } from '@/types/test-suite-picker'
|
|
19
|
+
import type { TestSuitePickerRow } from '@/types/test-suite-picker'
|
|
20
|
+
import {
|
|
21
|
+
buildTestRunSubmitValue,
|
|
22
|
+
getActionErrorMessage,
|
|
23
|
+
getBrowserEngineOptions,
|
|
24
|
+
getFieldErrorMessage,
|
|
25
|
+
getInitialTestSelectionType,
|
|
26
|
+
getTestRunSuccessPath,
|
|
27
|
+
testRunFieldValidators,
|
|
28
|
+
testRunQuickTips,
|
|
29
|
+
testSelectionTypes,
|
|
30
|
+
type TestRunFormSubmitAction,
|
|
31
|
+
type TestSelectionType,
|
|
32
|
+
validateTagSelections,
|
|
33
|
+
validateTestSuiteSelections,
|
|
34
|
+
} from './test-run-form-helpers'
|
|
35
|
+
import { useTestRunNameValidation } from './use-test-run-name-validation'
|
|
22
36
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
37
|
+
type TestRunFormProps = {
|
|
38
|
+
defaultValues?: TestRun
|
|
39
|
+
successTitle: string
|
|
40
|
+
successMessage: string
|
|
41
|
+
testSuites: TestSuitePickerRow[]
|
|
42
|
+
environments: Environment[]
|
|
43
|
+
tags: Tag[]
|
|
44
|
+
id?: string
|
|
45
|
+
onSubmitAction: TestRunFormSubmitAction
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
type TestRunFieldErrorsProps = {
|
|
49
|
+
errors: unknown[]
|
|
50
|
+
isTouched: boolean
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function TestRunFieldErrors({ errors, isTouched }: TestRunFieldErrorsProps) {
|
|
54
|
+
if (!isTouched) {
|
|
55
|
+
return null
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<div className="flex flex-col gap-1" aria-live="polite">
|
|
60
|
+
{errors.map((error, index) => (
|
|
61
|
+
<ErrorMessage key={`${String(error)}-${index}`} message={getFieldErrorMessage(error)} visible={true} />
|
|
62
|
+
))}
|
|
63
|
+
</div>
|
|
64
|
+
)
|
|
26
65
|
}
|
|
27
66
|
|
|
28
67
|
const TestRunForm = ({
|
|
@@ -34,125 +73,58 @@ const TestRunForm = ({
|
|
|
34
73
|
tags,
|
|
35
74
|
id,
|
|
36
75
|
onSubmitAction,
|
|
37
|
-
}: {
|
|
38
|
-
defaultValues?: TestRun
|
|
39
|
-
successTitle: string
|
|
40
|
-
successMessage: string
|
|
41
|
-
testSuites: TestSuitePickerRow[]
|
|
42
|
-
environments: Environment[]
|
|
43
|
-
tags: Tag[]
|
|
44
|
-
id?: string
|
|
45
|
-
onSubmitAction: (_prev: unknown, value: TestRun, id?: string) => Promise<ActionResponse>
|
|
46
|
-
}) => {
|
|
76
|
+
}: TestRunFormProps) => {
|
|
47
77
|
const router = useRouter()
|
|
78
|
+
const { debouncedNameValidation } = useTestRunNameValidation(id)
|
|
48
79
|
const [testSelectionType, setTestSelectionType] = useState<TestSelectionType>(() =>
|
|
49
|
-
defaultValues
|
|
80
|
+
getInitialTestSelectionType(defaultValues),
|
|
50
81
|
)
|
|
51
82
|
const testSelectionTypeRef = useRef<TestSelectionType>(testSelectionType)
|
|
52
|
-
const debounceTimeoutRef = useRef<NodeJS.Timeout | null>(null)
|
|
53
|
-
|
|
54
|
-
// Keep ref in sync with state
|
|
55
|
-
useEffect(() => {
|
|
56
|
-
testSelectionTypeRef.current = testSelectionType
|
|
57
|
-
}, [testSelectionType])
|
|
58
|
-
|
|
59
|
-
// Debounced function to check name uniqueness
|
|
60
|
-
// Returns: { isValid: boolean, error?: string }
|
|
61
|
-
// isValid: false only if name is confirmed to be duplicate
|
|
62
|
-
// error: error message to display (only returned when isValid is false to block submission)
|
|
63
|
-
const checkNameUniqueness = useCallback(
|
|
64
|
-
async (name: string): Promise<{ isValid: boolean; error?: string }> => {
|
|
65
|
-
if (!name || name.length < 1) return { isValid: true }
|
|
66
|
-
|
|
67
|
-
try {
|
|
68
|
-
const response = await checkTestRunNameUniqueAction(name, id)
|
|
69
|
-
|
|
70
|
-
// Handle server errors - allow submission but log the error
|
|
71
|
-
if (response.status === 500) {
|
|
72
|
-
console.error('Server error checking name uniqueness:', response.error)
|
|
73
|
-
// Return valid to allow submission (server will handle validation)
|
|
74
|
-
return { isValid: true }
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Handle successful response
|
|
78
|
-
if (response.status === 200) {
|
|
79
|
-
const isUnique = (response.data as { isUnique: boolean })?.isUnique ?? true
|
|
80
|
-
if (!isUnique) {
|
|
81
|
-
return {
|
|
82
|
-
isValid: false,
|
|
83
|
-
error: 'A test run with this name already exists. Please choose a different name.',
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
return { isValid: true }
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Unexpected status code - allow submission
|
|
90
|
-
console.warn('Unexpected response status when checking name uniqueness:', response.status)
|
|
91
|
-
return { isValid: true }
|
|
92
|
-
} catch (error) {
|
|
93
|
-
console.error('Error checking name uniqueness:', error)
|
|
94
|
-
// Allow submission if check fails (network error, etc.)
|
|
95
|
-
// Server will handle validation on submit
|
|
96
|
-
return { isValid: true }
|
|
97
|
-
}
|
|
98
|
-
},
|
|
99
|
-
[id],
|
|
100
|
-
)
|
|
101
|
-
|
|
102
|
-
// Debounced validation function
|
|
103
|
-
const debouncedNameValidation = useCallback(
|
|
104
|
-
(name: string): Promise<{ isValid: boolean; error?: string }> => {
|
|
105
|
-
return new Promise(resolve => {
|
|
106
|
-
if (debounceTimeoutRef.current) {
|
|
107
|
-
clearTimeout(debounceTimeoutRef.current)
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
debounceTimeoutRef.current = setTimeout(async () => {
|
|
111
|
-
const result = await checkNameUniqueness(name)
|
|
112
|
-
resolve(result)
|
|
113
|
-
}, 500) // 500ms debounce
|
|
114
|
-
})
|
|
115
|
-
},
|
|
116
|
-
[checkNameUniqueness],
|
|
117
|
-
)
|
|
118
83
|
|
|
119
84
|
const form = useForm({
|
|
120
|
-
defaultValues: defaultValues ?? formOpts
|
|
85
|
+
defaultValues: defaultValues ?? formOpts.defaultValues,
|
|
86
|
+
validators: formOpts.validators,
|
|
121
87
|
onSubmit: async ({ value }) => {
|
|
122
|
-
const submitValue =
|
|
123
|
-
...value,
|
|
124
|
-
tags: testSelectionType === TestSelectionType.TAGS ? value.tags : [],
|
|
125
|
-
testSuites: testSelectionType === TestSelectionType.TEST_SUITES ? value.testSuites : [],
|
|
126
|
-
}
|
|
88
|
+
const submitValue = buildTestRunSubmitValue(value, testSelectionType)
|
|
127
89
|
const res = await onSubmitAction(undefined, submitValue, id)
|
|
128
90
|
if (res.status === 200) {
|
|
129
91
|
toast({
|
|
130
92
|
title: successTitle,
|
|
131
93
|
description: successMessage,
|
|
132
94
|
})
|
|
133
|
-
|
|
134
|
-
if (res.data && typeof res.data === 'object' && 'id' in res.data) {
|
|
135
|
-
router.push(`/test-runs/${res.data.id}`)
|
|
136
|
-
} else {
|
|
137
|
-
router.push('/test-runs')
|
|
138
|
-
}
|
|
95
|
+
router.push(getTestRunSuccessPath(res.data))
|
|
139
96
|
}
|
|
140
97
|
if (res.status === 400) {
|
|
141
98
|
toast({
|
|
142
99
|
title: 'Error',
|
|
143
|
-
description: res
|
|
100
|
+
description: getActionErrorMessage(res),
|
|
144
101
|
variant: 'destructive',
|
|
145
102
|
})
|
|
146
103
|
}
|
|
147
104
|
if (res.status === 500) {
|
|
148
105
|
toast({
|
|
149
106
|
title: 'Error',
|
|
150
|
-
description: res
|
|
107
|
+
description: getActionErrorMessage(res),
|
|
151
108
|
variant: 'destructive',
|
|
152
109
|
})
|
|
153
110
|
}
|
|
154
111
|
},
|
|
155
112
|
})
|
|
113
|
+
|
|
114
|
+
const handleSelectionTypeChange = (nextType: TestSelectionType) => {
|
|
115
|
+
testSelectionTypeRef.current = nextType
|
|
116
|
+
setTestSelectionType(nextType)
|
|
117
|
+
|
|
118
|
+
if (nextType === testSelectionTypes.TAGS) {
|
|
119
|
+
form.setFieldValue('testSuites', [])
|
|
120
|
+
} else {
|
|
121
|
+
form.setFieldValue('tags', [])
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
form.validateField('tags', 'change')
|
|
125
|
+
form.validateField('testSuites', 'change')
|
|
126
|
+
}
|
|
127
|
+
|
|
156
128
|
return (
|
|
157
129
|
<form
|
|
158
130
|
onSubmit={e => {
|
|
@@ -170,55 +142,30 @@ const TestRunForm = ({
|
|
|
170
142
|
</CardHeader>
|
|
171
143
|
<CardContent>
|
|
172
144
|
<RadioGroup
|
|
173
|
-
|
|
174
|
-
onValueChange={value =>
|
|
175
|
-
const newType = value as TestSelectionType
|
|
176
|
-
// Update ref first so validators have the correct value
|
|
177
|
-
testSelectionTypeRef.current = newType
|
|
178
|
-
setTestSelectionType(newType)
|
|
179
|
-
// Clear the other field when switching filter types
|
|
180
|
-
if (newType === TestSelectionType.TAGS) {
|
|
181
|
-
form.setFieldValue('testSuites', [])
|
|
182
|
-
// Validate both fields to clear any errors
|
|
183
|
-
form.validateField('tags', 'change')
|
|
184
|
-
form.validateField('testSuites', 'change')
|
|
185
|
-
} else {
|
|
186
|
-
form.setFieldValue('tags', [])
|
|
187
|
-
// Validate both fields to clear any errors
|
|
188
|
-
form.validateField('tags', 'change')
|
|
189
|
-
form.validateField('testSuites', 'change')
|
|
190
|
-
}
|
|
191
|
-
}}
|
|
145
|
+
value={testSelectionType}
|
|
146
|
+
onValueChange={value => handleSelectionTypeChange(value as TestSelectionType)}
|
|
192
147
|
className="mb-4 flex gap-4"
|
|
193
148
|
>
|
|
194
149
|
<div className="flex items-center space-x-2">
|
|
195
|
-
<RadioGroupItem value={
|
|
196
|
-
<Label htmlFor={
|
|
150
|
+
<RadioGroupItem value={testSelectionTypes.TAGS} id={testSelectionTypes.TAGS} />
|
|
151
|
+
<Label htmlFor={testSelectionTypes.TAGS}>By Tags</Label>
|
|
197
152
|
</div>
|
|
198
153
|
<div className="flex items-center space-x-2">
|
|
199
|
-
<RadioGroupItem value={
|
|
200
|
-
<Label htmlFor={
|
|
154
|
+
<RadioGroupItem value={testSelectionTypes.TEST_SUITES} id={testSelectionTypes.TEST_SUITES} />
|
|
155
|
+
<Label htmlFor={testSelectionTypes.TEST_SUITES}>By Test Suites</Label>
|
|
201
156
|
</div>
|
|
202
157
|
</RadioGroup>
|
|
203
158
|
|
|
204
159
|
<form.Field
|
|
205
160
|
name="tags"
|
|
206
161
|
validators={{
|
|
207
|
-
onChange: ({ value }) =>
|
|
208
|
-
const currentSelectionType = testSelectionTypeRef.current
|
|
209
|
-
if (currentSelectionType === TestSelectionType.TAGS) {
|
|
210
|
-
if (!Array.isArray(value) || value.length === 0) {
|
|
211
|
-
return 'Tags are required'
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
return undefined
|
|
215
|
-
},
|
|
162
|
+
onChange: ({ value }) => validateTagSelections(value, testSelectionTypeRef.current),
|
|
216
163
|
}}
|
|
217
164
|
>
|
|
218
165
|
{field => {
|
|
219
166
|
return (
|
|
220
167
|
<div
|
|
221
|
-
className={`mb-4 flex flex-col gap-2 ${testSelectionType ===
|
|
168
|
+
className={`mb-4 flex flex-col gap-2 ${testSelectionType === testSelectionTypes.TAGS ? 'block' : 'hidden'}`}
|
|
222
169
|
>
|
|
223
170
|
<MultiSelect
|
|
224
171
|
options={tags.map(tag => ({ label: tag.name, value: tag.id }))}
|
|
@@ -226,13 +173,9 @@ const TestRunForm = ({
|
|
|
226
173
|
onChange={field.handleChange}
|
|
227
174
|
placeholder="Select tags"
|
|
228
175
|
emptyMessage="No tags available"
|
|
176
|
+
label="Test tags"
|
|
229
177
|
/>
|
|
230
|
-
{field.state.meta.isTouched
|
|
231
|
-
field.state.meta.errors.map((error, index) => (
|
|
232
|
-
<p key={index} className="text-xs text-pink-500">
|
|
233
|
-
{typeof error === 'string' ? error : String(error)}
|
|
234
|
-
</p>
|
|
235
|
-
))}
|
|
178
|
+
<TestRunFieldErrors errors={field.state.meta.errors} isTouched={field.state.meta.isTouched} />
|
|
236
179
|
</div>
|
|
237
180
|
)
|
|
238
181
|
}}
|
|
@@ -241,28 +184,13 @@ const TestRunForm = ({
|
|
|
241
184
|
<form.Field
|
|
242
185
|
name="testSuites"
|
|
243
186
|
validators={{
|
|
244
|
-
onChange: ({ value }) =>
|
|
245
|
-
const currentSelectionType = testSelectionTypeRef.current
|
|
246
|
-
if (currentSelectionType === TestSelectionType.TEST_SUITES) {
|
|
247
|
-
if (!Array.isArray(value) || value.length === 0) {
|
|
248
|
-
return 'At least one test suite is required'
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
const invalidSuite = value.find(
|
|
252
|
-
suiteSelection => !suiteSelection.runAll && suiteSelection.testCaseIds.length === 0,
|
|
253
|
-
)
|
|
254
|
-
if (invalidSuite) {
|
|
255
|
-
return 'Partial suite selections must include at least one test case'
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
return undefined
|
|
259
|
-
},
|
|
187
|
+
onChange: ({ value }) => validateTestSuiteSelections(value, testSelectionTypeRef.current),
|
|
260
188
|
}}
|
|
261
189
|
>
|
|
262
190
|
{field => {
|
|
263
191
|
return (
|
|
264
192
|
<div
|
|
265
|
-
className={`mb-4 flex flex-col gap-2 ${testSelectionType ===
|
|
193
|
+
className={`mb-4 flex flex-col gap-2 ${testSelectionType === testSelectionTypes.TEST_SUITES ? 'block' : 'hidden'}`}
|
|
266
194
|
>
|
|
267
195
|
<TestSuitePicker
|
|
268
196
|
testSuites={testSuites}
|
|
@@ -273,12 +201,7 @@ const TestRunForm = ({
|
|
|
273
201
|
dialogDescription="Browse suites, expand child test cases, and save the suite-scoped selection for this test run."
|
|
274
202
|
selectedLabel="Selected test suite(s)"
|
|
275
203
|
/>
|
|
276
|
-
{field.state.meta.isTouched
|
|
277
|
-
field.state.meta.errors.map((error, index) => (
|
|
278
|
-
<p key={index} className="text-xs text-pink-500">
|
|
279
|
-
{typeof error === 'string' ? error : String(error)}
|
|
280
|
-
</p>
|
|
281
|
-
))}
|
|
204
|
+
<TestRunFieldErrors errors={field.state.meta.errors} isTouched={field.state.meta.isTouched} />
|
|
282
205
|
</div>
|
|
283
206
|
)
|
|
284
207
|
}}
|
|
@@ -295,12 +218,10 @@ const TestRunForm = ({
|
|
|
295
218
|
<form.Field
|
|
296
219
|
name="name"
|
|
297
220
|
validators={{
|
|
298
|
-
onChange:
|
|
221
|
+
onChange: testRunFieldValidators.name,
|
|
299
222
|
onChangeAsync: async ({ value }) => {
|
|
300
223
|
if (!value || value.length < 1) return undefined
|
|
301
224
|
const result = await debouncedNameValidation(value)
|
|
302
|
-
// Only return error if validation explicitly failed (duplicate name)
|
|
303
|
-
// Server errors are handled by allowing submission and letting server validate
|
|
304
225
|
if (!result.isValid && result.error) {
|
|
305
226
|
return result.error
|
|
306
227
|
}
|
|
@@ -318,12 +239,7 @@ const TestRunForm = ({
|
|
|
318
239
|
onChange={e => field.handleChange(e.target.value)}
|
|
319
240
|
placeholder="Enter name for your test run"
|
|
320
241
|
/>
|
|
321
|
-
{field.state.meta.isTouched
|
|
322
|
-
field.state.meta.errors.map((error, index) => (
|
|
323
|
-
<p key={index} className="text-xs text-pink-500">
|
|
324
|
-
{typeof error === 'string' ? error : error?.message || String(error)}
|
|
325
|
-
</p>
|
|
326
|
-
))}
|
|
242
|
+
<TestRunFieldErrors errors={field.state.meta.errors} isTouched={field.state.meta.isTouched} />
|
|
327
243
|
</div>
|
|
328
244
|
)
|
|
329
245
|
}}
|
|
@@ -331,7 +247,7 @@ const TestRunForm = ({
|
|
|
331
247
|
<form.Field
|
|
332
248
|
name="environmentId"
|
|
333
249
|
validators={{
|
|
334
|
-
onChange:
|
|
250
|
+
onChange: testRunFieldValidators.environmentId,
|
|
335
251
|
}}
|
|
336
252
|
>
|
|
337
253
|
{field => {
|
|
@@ -339,7 +255,7 @@ const TestRunForm = ({
|
|
|
339
255
|
<div className="mb-4 flex flex-col gap-2">
|
|
340
256
|
<Label htmlFor={field.name}>Environment</Label>
|
|
341
257
|
<Select value={field.state.value} onValueChange={value => field.handleChange(value)}>
|
|
342
|
-
<SelectTrigger>
|
|
258
|
+
<SelectTrigger id={field.name}>
|
|
343
259
|
<SelectValue placeholder="Select an environment" />
|
|
344
260
|
</SelectTrigger>
|
|
345
261
|
<SelectContent isEmpty={environments.length === 0} emptyMessage="No environments available">
|
|
@@ -350,12 +266,7 @@ const TestRunForm = ({
|
|
|
350
266
|
))}
|
|
351
267
|
</SelectContent>
|
|
352
268
|
</Select>
|
|
353
|
-
{field.state.meta.isTouched
|
|
354
|
-
field.state.meta.errors.map((error, index) => (
|
|
355
|
-
<p key={index} className="text-xs text-pink-500">
|
|
356
|
-
{typeof error === 'string' ? error : error?.message || String(error)}
|
|
357
|
-
</p>
|
|
358
|
-
))}
|
|
269
|
+
<TestRunFieldErrors errors={field.state.meta.errors} isTouched={field.state.meta.isTouched} />
|
|
359
270
|
</div>
|
|
360
271
|
)
|
|
361
272
|
}}
|
|
@@ -363,7 +274,7 @@ const TestRunForm = ({
|
|
|
363
274
|
|
|
364
275
|
<form.Field
|
|
365
276
|
name="testWorkersCount"
|
|
366
|
-
validators={{ onChange:
|
|
277
|
+
validators={{ onChange: testRunFieldValidators.testWorkersCount }}
|
|
367
278
|
>
|
|
368
279
|
{field => {
|
|
369
280
|
return (
|
|
@@ -374,40 +285,29 @@ const TestRunForm = ({
|
|
|
374
285
|
value={field.state.value}
|
|
375
286
|
onChange={e => field.handleChange(Number(e.target.value))}
|
|
376
287
|
/>
|
|
377
|
-
{field.state.meta.isTouched
|
|
378
|
-
field.state.meta.errors.map((error, index) => (
|
|
379
|
-
<p key={index} className="text-xs text-pink-500">
|
|
380
|
-
{typeof error === 'string' ? error : String(error)}
|
|
381
|
-
</p>
|
|
382
|
-
))}
|
|
288
|
+
<TestRunFieldErrors errors={field.state.meta.errors} isTouched={field.state.meta.isTouched} />
|
|
383
289
|
</div>
|
|
384
290
|
)
|
|
385
291
|
}}
|
|
386
292
|
</form.Field>
|
|
387
|
-
<form.Field name="browserEngine" validators={{ onChange:
|
|
293
|
+
<form.Field name="browserEngine" validators={{ onChange: testRunFieldValidators.browserEngine }}>
|
|
388
294
|
{field => {
|
|
389
295
|
return (
|
|
390
296
|
<div className="mb-4 flex flex-col gap-2">
|
|
391
297
|
<Label htmlFor={field.name}>Browser Engine</Label>
|
|
392
|
-
<Select
|
|
393
|
-
|
|
394
|
-
onValueChange={value => field.handleChange(value as unknown as BrowserEngine)}
|
|
395
|
-
>
|
|
396
|
-
<SelectTrigger>
|
|
298
|
+
<Select value={field.state.value} onValueChange={value => field.handleChange(value as BrowserEngine)}>
|
|
299
|
+
<SelectTrigger id={field.name}>
|
|
397
300
|
<SelectValue placeholder="Select a browser engine" />
|
|
398
301
|
</SelectTrigger>
|
|
399
302
|
<SelectContent>
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
303
|
+
{getBrowserEngineOptions().map(option => (
|
|
304
|
+
<SelectItem key={option.value} value={option.value}>
|
|
305
|
+
{option.label}
|
|
306
|
+
</SelectItem>
|
|
307
|
+
))}
|
|
403
308
|
</SelectContent>
|
|
404
309
|
</Select>
|
|
405
|
-
{field.state.meta.isTouched
|
|
406
|
-
field.state.meta.errors.map((error, index) => (
|
|
407
|
-
<p key={index} className="text-xs text-pink-500">
|
|
408
|
-
{typeof error === 'string' ? error : String(error)}
|
|
409
|
-
</p>
|
|
410
|
-
))}
|
|
310
|
+
<TestRunFieldErrors errors={field.state.meta.errors} isTouched={field.state.meta.isTouched} />
|
|
411
311
|
</div>
|
|
412
312
|
)
|
|
413
313
|
}}
|
|
@@ -424,69 +324,24 @@ const TestRunForm = ({
|
|
|
424
324
|
</CardTitle>
|
|
425
325
|
</CardHeader>
|
|
426
326
|
<CardContent className="flex flex-col gap-6">
|
|
427
|
-
|
|
428
|
-
<
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
<div className="flex flex-col gap-1">
|
|
432
|
-
<span className="text-base font-bold">Choose a descriptive name</span>
|
|
433
|
-
<span className="text-sm text-muted-foreground">
|
|
434
|
-
Use clear, specific names that indicate the purpose for your test run
|
|
435
|
-
</span>
|
|
436
|
-
</div>
|
|
437
|
-
</div>
|
|
438
|
-
<div className="flex items-start gap-4">
|
|
439
|
-
<span className="flex h-6 w-6 items-center justify-center rounded-full bg-emerald-500/10 text-emerald-500">
|
|
440
|
-
2
|
|
441
|
-
</span>
|
|
442
|
-
<div className="flex flex-col gap-1">
|
|
443
|
-
<span className="text-base font-bold">Select the environment for your test run</span>
|
|
444
|
-
<span className="text-sm text-muted-foreground">
|
|
445
|
-
Choose the environment that best suits your selected tests
|
|
446
|
-
</span>
|
|
447
|
-
</div>
|
|
448
|
-
</div>
|
|
449
|
-
<div className="flex items-start gap-4">
|
|
450
|
-
<span className="flex h-6 w-6 items-center justify-center rounded-full bg-emerald-500/10 text-emerald-500">
|
|
451
|
-
3
|
|
452
|
-
</span>
|
|
453
|
-
<div className="flex flex-col gap-1">
|
|
454
|
-
<span className="text-base font-bold">Select the browser engine for your test run</span>
|
|
455
|
-
<span className="text-sm text-muted-foreground">
|
|
456
|
-
Select the browser engine that is compatible with your selected test cases
|
|
457
|
-
</span>
|
|
458
|
-
</div>
|
|
459
|
-
</div>
|
|
460
|
-
<div className="flex items-start gap-4">
|
|
461
|
-
<span className="flex h-6 w-6 items-center justify-center rounded-full bg-emerald-500/10 text-emerald-500">
|
|
462
|
-
4
|
|
463
|
-
</span>
|
|
464
|
-
<div className="flex flex-col gap-1">
|
|
465
|
-
<span className="text-base font-bold">Select the test suites or tags for your test run</span>
|
|
466
|
-
<span className="text-sm text-muted-foreground">
|
|
467
|
-
You can filter by tags or browse suites and choose full suites or child subsets
|
|
468
|
-
</span>
|
|
469
|
-
</div>
|
|
470
|
-
</div>
|
|
471
|
-
<div className="flex items-start gap-4">
|
|
472
|
-
<span className="flex h-6 w-6 items-center justify-center rounded-full bg-emerald-500/10 text-emerald-500">
|
|
473
|
-
5
|
|
474
|
-
</span>
|
|
475
|
-
<div className="flex flex-col gap-1">
|
|
476
|
-
<span className="text-base font-bold">Select the test workers count for your test run</span>
|
|
477
|
-
<span className="text-sm text-muted-foreground">
|
|
478
|
-
Parallel workers can be used to run your test cases in parallel to speed up the test execution
|
|
327
|
+
{testRunQuickTips.map((tip, index) => (
|
|
328
|
+
<div key={tip.title} className="flex items-start gap-4">
|
|
329
|
+
<span className="flex h-6 w-6 items-center justify-center rounded-full bg-emerald-500/10 text-emerald-500">
|
|
330
|
+
{index + 1}
|
|
479
331
|
</span>
|
|
332
|
+
<div className="flex flex-col gap-1">
|
|
333
|
+
<span className="text-base font-bold">{tip.title}</span>
|
|
334
|
+
<span className="text-sm text-muted-foreground">{tip.description}</span>
|
|
335
|
+
</div>
|
|
480
336
|
</div>
|
|
481
|
-
|
|
337
|
+
))}
|
|
482
338
|
</CardContent>
|
|
483
339
|
</Card>
|
|
484
340
|
</div>
|
|
485
341
|
</div>
|
|
486
342
|
<form.Subscribe selector={formState => [formState.canSubmit, formState.isSubmitting]}>
|
|
487
|
-
{([canSubmit, isSubmitting
|
|
343
|
+
{([canSubmit, isSubmitting]) => (
|
|
488
344
|
<>
|
|
489
|
-
<span>{errors}</span>
|
|
490
345
|
<Button type="submit" disabled={!canSubmit} className="hover:bg-emerald-500">
|
|
491
346
|
<Play className="h-4 w-4" />
|
|
492
347
|
<span className="font-bold">{isSubmitting ? '...' : 'Start'}</span>
|