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
|
@@ -3,6 +3,7 @@ import prisma from '@/config/db-config'
|
|
|
3
3
|
import { ParsedFeature, ParsedStep } from './gherkin-parser'
|
|
4
4
|
import { buildModuleHierarchy } from './module-hierarchy-builder'
|
|
5
5
|
import { TemplateStepType, TemplateStepIcon, TestCase, TagType } from '@prisma/client'
|
|
6
|
+
import { getTagTypeFromExpression } from './tag-utils'
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Syncs feature files to the database by creating missing test suites and test cases
|
|
@@ -93,13 +94,7 @@ export async function syncFeaturesToDatabase(
|
|
|
93
94
|
* @returns TagType - IDENTIFIER if matches pattern, FILTER otherwise
|
|
94
95
|
*/
|
|
95
96
|
function determineTagType(tagExpression: string): TagType {
|
|
96
|
-
|
|
97
|
-
// - @ = literal @
|
|
98
|
-
// - xx = any 2 characters
|
|
99
|
-
// - _id_ = literal string
|
|
100
|
-
// - xxxxxxxx = any characters
|
|
101
|
-
const identifierPattern = /^@.{2}_id_.+$/
|
|
102
|
-
return identifierPattern.test(tagExpression) ? TagType.IDENTIFIER : TagType.FILTER
|
|
97
|
+
return getTagTypeFromExpression(tagExpression)
|
|
103
98
|
}
|
|
104
99
|
|
|
105
100
|
/**
|
|
@@ -1,184 +1,184 @@
|
|
|
1
|
-
import { promises as fs } from 'fs'
|
|
2
|
-
import * as path from 'path'
|
|
3
|
-
import prisma from '@/config/db-config'
|
|
4
|
-
import { ensureAutomationWorkspaceReady, getAutomationEnvironmentsDir } from '@/lib/automation/paths'
|
|
5
|
-
|
|
6
|
-
interface EnvironmentConfig {
|
|
7
|
-
baseUrl: string
|
|
8
|
-
apiBaseUrl: string
|
|
9
|
-
email: string
|
|
10
|
-
password: string
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function getEnvironmentsFilePath(): string {
|
|
14
|
-
return path.join(getAutomationEnvironmentsDir(), 'environments.json')
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export async function ensureConfigDirectoryExists(): Promise<void> {
|
|
18
|
-
await ensureAutomationWorkspaceReady()
|
|
19
|
-
await fs.mkdir(path.dirname(getEnvironmentsFilePath()), { recursive: true })
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export async function generateEnvironmentsContent(): Promise<Record<string, EnvironmentConfig>> {
|
|
23
|
-
try {
|
|
24
|
-
const environments = await prisma.environment.findMany({
|
|
25
|
-
orderBy: { createdAt: 'asc' },
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
const environmentsConfig: Record<string, EnvironmentConfig> = {}
|
|
29
|
-
|
|
30
|
-
environments.forEach(env => {
|
|
31
|
-
const envKey = env.name.toLowerCase().replace(/\s+/g, '_')
|
|
32
|
-
environmentsConfig[envKey] = {
|
|
33
|
-
baseUrl: env.baseUrl,
|
|
34
|
-
apiBaseUrl: env.apiBaseUrl || '',
|
|
35
|
-
email: env.username || '',
|
|
36
|
-
password: env.password || '',
|
|
37
|
-
}
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
return environmentsConfig
|
|
41
|
-
} catch (error) {
|
|
42
|
-
console.error('Error generating environments content:', error)
|
|
43
|
-
return {}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export async function createOrUpdateEnvironmentsFile(): Promise<boolean> {
|
|
48
|
-
try {
|
|
49
|
-
await ensureAutomationWorkspaceReady()
|
|
50
|
-
const filePath = getEnvironmentsFilePath()
|
|
51
|
-
await ensureConfigDirectoryExists()
|
|
52
|
-
|
|
53
|
-
const content = await generateEnvironmentsContent()
|
|
54
|
-
|
|
55
|
-
if (Object.keys(content).length === 0) {
|
|
56
|
-
await deleteEnvironmentsFile()
|
|
57
|
-
return true
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
await fs.writeFile(filePath, JSON.stringify(content, null, 2))
|
|
61
|
-
return true
|
|
62
|
-
} catch (error) {
|
|
63
|
-
console.error('Error creating/updating environments file:', error)
|
|
64
|
-
return false
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export async function deleteEnvironmentsFile(): Promise<boolean> {
|
|
69
|
-
try {
|
|
70
|
-
await ensureAutomationWorkspaceReady()
|
|
71
|
-
const filePath = getEnvironmentsFilePath()
|
|
72
|
-
|
|
73
|
-
try {
|
|
74
|
-
await fs.access(filePath)
|
|
75
|
-
} catch {
|
|
76
|
-
return true
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
await fs.unlink(filePath)
|
|
80
|
-
return true
|
|
81
|
-
} catch (error) {
|
|
82
|
-
console.error('Error deleting environments file:', error)
|
|
83
|
-
return false
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export async function readEnvironmentsFile(): Promise<{
|
|
88
|
-
filePath: string
|
|
89
|
-
content: Record<string, EnvironmentConfig>
|
|
90
|
-
} | null> {
|
|
91
|
-
try {
|
|
92
|
-
await ensureAutomationWorkspaceReady()
|
|
93
|
-
const filePath = getEnvironmentsFilePath()
|
|
94
|
-
|
|
95
|
-
try {
|
|
96
|
-
await fs.access(filePath)
|
|
97
|
-
} catch {
|
|
98
|
-
return null
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const fileContent = await fs.readFile(filePath, 'utf-8')
|
|
102
|
-
const jsonContent = JSON.parse(fileContent)
|
|
103
|
-
|
|
104
|
-
return { filePath, content: jsonContent }
|
|
105
|
-
} catch (error) {
|
|
106
|
-
console.error('Error reading environments file:', error)
|
|
107
|
-
return null
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export async function updateEnvironmentEntry(environmentId: string, oldName?: string): Promise<boolean> {
|
|
112
|
-
try {
|
|
113
|
-
await ensureAutomationWorkspaceReady()
|
|
114
|
-
const environment = await prisma.environment.findUnique({
|
|
115
|
-
where: { id: environmentId },
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
if (!environment) {
|
|
119
|
-
console.error(`Environment with ID ${environmentId} not found`)
|
|
120
|
-
return false
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const filePath = getEnvironmentsFilePath()
|
|
124
|
-
let environmentsConfig: Record<string, EnvironmentConfig> = {}
|
|
125
|
-
|
|
126
|
-
try {
|
|
127
|
-
await fs.access(filePath)
|
|
128
|
-
const fileContent = await fs.readFile(filePath, 'utf-8')
|
|
129
|
-
environmentsConfig = JSON.parse(fileContent)
|
|
130
|
-
} catch {
|
|
131
|
-
environmentsConfig = {}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
if (oldName) {
|
|
135
|
-
const oldKey = oldName.toLowerCase().replace(/\s+/g, '_')
|
|
136
|
-
delete environmentsConfig[oldKey]
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const envKey = environment.name.toLowerCase().replace(/\s+/g, '_')
|
|
140
|
-
environmentsConfig[envKey] = {
|
|
141
|
-
baseUrl: environment.baseUrl,
|
|
142
|
-
apiBaseUrl: environment.apiBaseUrl || '',
|
|
143
|
-
email: environment.username || '',
|
|
144
|
-
password: environment.password || '',
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
await ensureConfigDirectoryExists()
|
|
148
|
-
await fs.writeFile(filePath, JSON.stringify(environmentsConfig, null, 2))
|
|
149
|
-
return true
|
|
150
|
-
} catch (error) {
|
|
151
|
-
console.error('Error updating environment entry:', error)
|
|
152
|
-
return false
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
export async function removeEnvironmentEntry(environmentName: string): Promise<boolean> {
|
|
157
|
-
try {
|
|
158
|
-
await ensureAutomationWorkspaceReady()
|
|
159
|
-
const filePath = getEnvironmentsFilePath()
|
|
160
|
-
|
|
161
|
-
try {
|
|
162
|
-
await fs.access(filePath)
|
|
163
|
-
} catch {
|
|
164
|
-
return true
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
const fileContent = await fs.readFile(filePath, 'utf-8')
|
|
168
|
-
const environmentsConfig: Record<string, EnvironmentConfig> = JSON.parse(fileContent)
|
|
169
|
-
|
|
170
|
-
const envKey = environmentName.toLowerCase().replace(/\s+/g, '_')
|
|
171
|
-
delete environmentsConfig[envKey]
|
|
172
|
-
|
|
173
|
-
if (Object.keys(environmentsConfig).length === 0) {
|
|
174
|
-
await deleteEnvironmentsFile()
|
|
175
|
-
return true
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
await fs.writeFile(filePath, JSON.stringify(environmentsConfig, null, 2))
|
|
179
|
-
return true
|
|
180
|
-
} catch (error) {
|
|
181
|
-
console.error('Error removing environment entry:', error)
|
|
182
|
-
return false
|
|
183
|
-
}
|
|
184
|
-
}
|
|
1
|
+
import { promises as fs } from 'fs'
|
|
2
|
+
import * as path from 'path'
|
|
3
|
+
import prisma from '@/config/db-config'
|
|
4
|
+
import { ensureAutomationWorkspaceReady, getAutomationEnvironmentsDir } from '@/lib/automation/paths'
|
|
5
|
+
|
|
6
|
+
interface EnvironmentConfig {
|
|
7
|
+
baseUrl: string
|
|
8
|
+
apiBaseUrl: string
|
|
9
|
+
email: string
|
|
10
|
+
password: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function getEnvironmentsFilePath(): string {
|
|
14
|
+
return path.join(getAutomationEnvironmentsDir(), 'environments.json')
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export async function ensureConfigDirectoryExists(): Promise<void> {
|
|
18
|
+
await ensureAutomationWorkspaceReady()
|
|
19
|
+
await fs.mkdir(path.dirname(getEnvironmentsFilePath()), { recursive: true })
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function generateEnvironmentsContent(): Promise<Record<string, EnvironmentConfig>> {
|
|
23
|
+
try {
|
|
24
|
+
const environments = await prisma.environment.findMany({
|
|
25
|
+
orderBy: { createdAt: 'asc' },
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
const environmentsConfig: Record<string, EnvironmentConfig> = {}
|
|
29
|
+
|
|
30
|
+
environments.forEach(env => {
|
|
31
|
+
const envKey = env.name.toLowerCase().replace(/\s+/g, '_')
|
|
32
|
+
environmentsConfig[envKey] = {
|
|
33
|
+
baseUrl: env.baseUrl,
|
|
34
|
+
apiBaseUrl: env.apiBaseUrl || '',
|
|
35
|
+
email: env.username || '',
|
|
36
|
+
password: env.password || '',
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
return environmentsConfig
|
|
41
|
+
} catch (error) {
|
|
42
|
+
console.error('Error generating environments content:', error)
|
|
43
|
+
return {}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export async function createOrUpdateEnvironmentsFile(): Promise<boolean> {
|
|
48
|
+
try {
|
|
49
|
+
await ensureAutomationWorkspaceReady()
|
|
50
|
+
const filePath = getEnvironmentsFilePath()
|
|
51
|
+
await ensureConfigDirectoryExists()
|
|
52
|
+
|
|
53
|
+
const content = await generateEnvironmentsContent()
|
|
54
|
+
|
|
55
|
+
if (Object.keys(content).length === 0) {
|
|
56
|
+
await deleteEnvironmentsFile()
|
|
57
|
+
return true
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
await fs.writeFile(filePath, JSON.stringify(content, null, 2))
|
|
61
|
+
return true
|
|
62
|
+
} catch (error) {
|
|
63
|
+
console.error('Error creating/updating environments file:', error)
|
|
64
|
+
return false
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export async function deleteEnvironmentsFile(): Promise<boolean> {
|
|
69
|
+
try {
|
|
70
|
+
await ensureAutomationWorkspaceReady()
|
|
71
|
+
const filePath = getEnvironmentsFilePath()
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
await fs.access(filePath)
|
|
75
|
+
} catch {
|
|
76
|
+
return true
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
await fs.unlink(filePath)
|
|
80
|
+
return true
|
|
81
|
+
} catch (error) {
|
|
82
|
+
console.error('Error deleting environments file:', error)
|
|
83
|
+
return false
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export async function readEnvironmentsFile(): Promise<{
|
|
88
|
+
filePath: string
|
|
89
|
+
content: Record<string, EnvironmentConfig>
|
|
90
|
+
} | null> {
|
|
91
|
+
try {
|
|
92
|
+
await ensureAutomationWorkspaceReady()
|
|
93
|
+
const filePath = getEnvironmentsFilePath()
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
await fs.access(filePath)
|
|
97
|
+
} catch {
|
|
98
|
+
return null
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const fileContent = await fs.readFile(filePath, 'utf-8')
|
|
102
|
+
const jsonContent = JSON.parse(fileContent)
|
|
103
|
+
|
|
104
|
+
return { filePath, content: jsonContent }
|
|
105
|
+
} catch (error) {
|
|
106
|
+
console.error('Error reading environments file:', error)
|
|
107
|
+
return null
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export async function updateEnvironmentEntry(environmentId: string, oldName?: string): Promise<boolean> {
|
|
112
|
+
try {
|
|
113
|
+
await ensureAutomationWorkspaceReady()
|
|
114
|
+
const environment = await prisma.environment.findUnique({
|
|
115
|
+
where: { id: environmentId },
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
if (!environment) {
|
|
119
|
+
console.error(`Environment with ID ${environmentId} not found`)
|
|
120
|
+
return false
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const filePath = getEnvironmentsFilePath()
|
|
124
|
+
let environmentsConfig: Record<string, EnvironmentConfig> = {}
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
await fs.access(filePath)
|
|
128
|
+
const fileContent = await fs.readFile(filePath, 'utf-8')
|
|
129
|
+
environmentsConfig = JSON.parse(fileContent)
|
|
130
|
+
} catch {
|
|
131
|
+
environmentsConfig = {}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (oldName) {
|
|
135
|
+
const oldKey = oldName.toLowerCase().replace(/\s+/g, '_')
|
|
136
|
+
delete environmentsConfig[oldKey]
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const envKey = environment.name.toLowerCase().replace(/\s+/g, '_')
|
|
140
|
+
environmentsConfig[envKey] = {
|
|
141
|
+
baseUrl: environment.baseUrl,
|
|
142
|
+
apiBaseUrl: environment.apiBaseUrl || '',
|
|
143
|
+
email: environment.username || '',
|
|
144
|
+
password: environment.password || '',
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
await ensureConfigDirectoryExists()
|
|
148
|
+
await fs.writeFile(filePath, JSON.stringify(environmentsConfig, null, 2))
|
|
149
|
+
return true
|
|
150
|
+
} catch (error) {
|
|
151
|
+
console.error('Error updating environment entry:', error)
|
|
152
|
+
return false
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export async function removeEnvironmentEntry(environmentName: string): Promise<boolean> {
|
|
157
|
+
try {
|
|
158
|
+
await ensureAutomationWorkspaceReady()
|
|
159
|
+
const filePath = getEnvironmentsFilePath()
|
|
160
|
+
|
|
161
|
+
try {
|
|
162
|
+
await fs.access(filePath)
|
|
163
|
+
} catch {
|
|
164
|
+
return true
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const fileContent = await fs.readFile(filePath, 'utf-8')
|
|
168
|
+
const environmentsConfig: Record<string, EnvironmentConfig> = JSON.parse(fileContent)
|
|
169
|
+
|
|
170
|
+
const envKey = environmentName.toLowerCase().replace(/\s+/g, '_')
|
|
171
|
+
delete environmentsConfig[envKey]
|
|
172
|
+
|
|
173
|
+
if (Object.keys(environmentsConfig).length === 0) {
|
|
174
|
+
await deleteEnvironmentsFile()
|
|
175
|
+
return true
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
await fs.writeFile(filePath, JSON.stringify(environmentsConfig, null, 2))
|
|
179
|
+
return true
|
|
180
|
+
} catch (error) {
|
|
181
|
+
console.error('Error removing environment entry:', error)
|
|
182
|
+
return false
|
|
183
|
+
}
|
|
184
|
+
}
|
|
@@ -1,10 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { dirname } from 'path'
|
|
2
2
|
import { spawnTask, taskSpawner, type SpawnedProcess, waitForTask, killTask } from '@/lib/process/task-spawner'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
ensureAutomationWorkspaceReady,
|
|
5
|
+
getAutomationRunReportPath,
|
|
6
|
+
toProjectRelativePath,
|
|
7
|
+
} from '@/lib/automation/paths'
|
|
4
8
|
import type { ExecutorAdapter, TestRunExecutionRequest, TestRunExecutionResult } from './types'
|
|
5
9
|
import { processManager } from '@/lib/test-run/process-manager'
|
|
10
|
+
import { promises as fs } from 'fs'
|
|
6
11
|
|
|
7
|
-
function mapBrowserEngineToName(
|
|
12
|
+
function mapBrowserEngineToName(
|
|
13
|
+
browserEngine: TestRunExecutionRequest['browserEngine'],
|
|
14
|
+
): 'chromium' | 'firefox' | 'webkit' {
|
|
8
15
|
switch (browserEngine) {
|
|
9
16
|
case 'CHROMIUM':
|
|
10
17
|
return 'chromium'
|
|
@@ -17,38 +24,29 @@ function mapBrowserEngineToName(browserEngine: TestRunExecutionRequest['browserE
|
|
|
17
24
|
}
|
|
18
25
|
}
|
|
19
26
|
|
|
20
|
-
function combineTagExpressions(tags: TestRunExecutionRequest['tags']): string | null {
|
|
21
|
-
if (tags.length === 0) {
|
|
22
|
-
return null
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (tags.length === 1) {
|
|
26
|
-
return tags[0].tagExpression
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return tags.map(tag => `(${tag.tagExpression})`).join(' or ')
|
|
30
|
-
}
|
|
31
|
-
|
|
32
27
|
function generateReportPath(testRunId: string): string {
|
|
33
|
-
|
|
34
|
-
return join(getAutomationReportsDir(), `cucumber-${testRunId}-${timestamp}.json`)
|
|
28
|
+
return getAutomationRunReportPath(testRunId)
|
|
35
29
|
}
|
|
36
30
|
|
|
37
31
|
export class LocalExecutorAdapter implements ExecutorAdapter {
|
|
38
32
|
async executeTestRun(config: TestRunExecutionRequest): Promise<TestRunExecutionResult> {
|
|
39
33
|
await ensureAutomationWorkspaceReady()
|
|
40
34
|
|
|
41
|
-
const { testRunId, environment,
|
|
35
|
+
const { testRunId, environment, tagExpression, testWorkersCount, browserEngine, headless = true } = config
|
|
42
36
|
const reportPath = generateReportPath(testRunId)
|
|
43
37
|
const browserName = mapBrowserEngineToName(browserEngine)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
38
|
+
await fs.mkdir(dirname(reportPath), { recursive: true })
|
|
39
|
+
const childEnv = {
|
|
40
|
+
...process.env,
|
|
41
|
+
ENVIRONMENT: environment.name,
|
|
42
|
+
HEADLESS: headless.toString(),
|
|
43
|
+
BROWSER: browserName,
|
|
44
|
+
REPORT_PATH: reportPath,
|
|
45
|
+
REPORT_FORMAT: `json:${reportPath}`,
|
|
46
|
+
TEST_RUN_ID: testRunId,
|
|
47
|
+
}
|
|
49
48
|
|
|
50
49
|
const cucumberArgs: string[] = ['cucumber-js']
|
|
51
|
-
const tagExpression = combineTagExpressions(tags)
|
|
52
50
|
|
|
53
51
|
if (tagExpression) {
|
|
54
52
|
cucumberArgs.push('-t', tagExpression)
|
|
@@ -63,6 +61,7 @@ export class LocalExecutorAdapter implements ExecutorAdapter {
|
|
|
63
61
|
prefixLogs: true,
|
|
64
62
|
logPrefix: `test-run-${testRunId}`,
|
|
65
63
|
captureOutput: true,
|
|
64
|
+
env: childEnv,
|
|
66
65
|
})
|
|
67
66
|
|
|
68
67
|
processManager.register(testRunId, spawnedProcess)
|
|
@@ -72,7 +71,7 @@ export class LocalExecutorAdapter implements ExecutorAdapter {
|
|
|
72
71
|
|
|
73
72
|
return {
|
|
74
73
|
process: spawnedProcess,
|
|
75
|
-
reportPath,
|
|
74
|
+
reportPath: toProjectRelativePath(reportPath),
|
|
76
75
|
}
|
|
77
76
|
}
|
|
78
77
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { BrowserEngine, Environment
|
|
1
|
+
import type { BrowserEngine, Environment } from '@prisma/client'
|
|
2
2
|
import type { SpawnedProcess } from '@/lib/process/task-spawner'
|
|
3
3
|
|
|
4
4
|
export interface TestRunExecutionRequest {
|
|
5
5
|
testRunId: string
|
|
6
6
|
environment: Environment
|
|
7
|
-
|
|
7
|
+
tagExpression: string | null
|
|
8
8
|
testWorkersCount: number
|
|
9
9
|
browserEngine: BrowserEngine
|
|
10
10
|
headless?: boolean
|
|
@@ -3,6 +3,7 @@ import { join, dirname } from 'path'
|
|
|
3
3
|
import prisma from '@/config/db-config'
|
|
4
4
|
import { buildModulePath } from '@/lib/path-helpers/module-path'
|
|
5
5
|
import { ensureAutomationWorkspaceReady, getAutomationFeaturesDir } from '@/lib/automation/paths'
|
|
6
|
+
import { generateProjectedGherkinSteps, getTestSuiteFilesystemKey } from '@/lib/sync/projected-feature-utils'
|
|
6
7
|
|
|
7
8
|
async function isDirectoryEmpty(dirPath: string): Promise<boolean> {
|
|
8
9
|
try {
|
|
@@ -76,7 +77,7 @@ export async function generateFeatureFile(
|
|
|
76
77
|
const moduleDir = join(featuresBaseDir, modulePath.substring(1))
|
|
77
78
|
await fs.mkdir(moduleDir, { recursive: true })
|
|
78
79
|
|
|
79
|
-
const safeFileName =
|
|
80
|
+
const safeFileName = getTestSuiteFilesystemKey(testSuiteName)
|
|
80
81
|
const featureFilePath = join(moduleDir, `${safeFileName}.feature`)
|
|
81
82
|
|
|
82
83
|
await fs.writeFile(featureFilePath, featureContent, 'utf8')
|
|
@@ -126,7 +127,7 @@ function generateFeatureContent(
|
|
|
126
127
|
|
|
127
128
|
testCases.forEach(testCase => {
|
|
128
129
|
if (testCase.steps && testCase.steps.length > 0) {
|
|
129
|
-
const gherkinSteps =
|
|
130
|
+
const gherkinSteps = generateProjectedGherkinSteps(testCase.steps)
|
|
130
131
|
|
|
131
132
|
if (gherkinSteps.length > 0) {
|
|
132
133
|
if (scenarioCount > 0) {
|
|
@@ -153,60 +154,6 @@ function generateFeatureContent(
|
|
|
153
154
|
return lines.join('\n') + '\n'
|
|
154
155
|
}
|
|
155
156
|
|
|
156
|
-
function generateGherkinStepsFromTestCase(
|
|
157
|
-
steps: Array<{
|
|
158
|
-
gherkinStep: string
|
|
159
|
-
order: number
|
|
160
|
-
}>,
|
|
161
|
-
): string[] {
|
|
162
|
-
if (!steps || steps.length === 0) {
|
|
163
|
-
return []
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const sortedSteps = steps.sort((a, b) => a.order - b.order)
|
|
167
|
-
let hasThenInPrevious = false
|
|
168
|
-
let hasWhenInPrevious = false
|
|
169
|
-
|
|
170
|
-
return sortedSteps.map((step, index) => {
|
|
171
|
-
const gherkinStep = step.gherkinStep?.trim() || ''
|
|
172
|
-
const firstWord = gherkinStep.split(' ')[0].toLowerCase()
|
|
173
|
-
const hasGherkinKeyword = ['given', 'when', 'then', 'and', 'but'].includes(firstWord)
|
|
174
|
-
const stepWithoutKeyword = hasGherkinKeyword ? gherkinStep.split(' ').slice(1).join(' ') : gherkinStep
|
|
175
|
-
|
|
176
|
-
if (index === 0) {
|
|
177
|
-
return `Given ${stepWithoutKeyword}`
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
const isThenStatement =
|
|
181
|
-
firstWord === 'then' ||
|
|
182
|
-
stepWithoutKeyword.toLowerCase().startsWith('should') ||
|
|
183
|
-
stepWithoutKeyword.toLowerCase().startsWith('must') ||
|
|
184
|
-
stepWithoutKeyword.toLowerCase().startsWith('will')
|
|
185
|
-
|
|
186
|
-
if (!hasThenInPrevious) {
|
|
187
|
-
if (isThenStatement) {
|
|
188
|
-
hasThenInPrevious = true
|
|
189
|
-
return `Then ${stepWithoutKeyword}`
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (!hasWhenInPrevious) {
|
|
193
|
-
hasWhenInPrevious = true
|
|
194
|
-
return `When ${stepWithoutKeyword}`
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
return `And ${stepWithoutKeyword}`
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
if (isThenStatement) {
|
|
201
|
-
return `And ${stepWithoutKeyword}`
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
hasThenInPrevious = false
|
|
205
|
-
hasWhenInPrevious = true
|
|
206
|
-
return `When ${stepWithoutKeyword}`
|
|
207
|
-
})
|
|
208
|
-
}
|
|
209
|
-
|
|
210
157
|
export async function deleteFeatureFile(testSuiteId: string): Promise<boolean> {
|
|
211
158
|
try {
|
|
212
159
|
await ensureAutomationWorkspaceReady()
|
|
@@ -225,7 +172,7 @@ export async function deleteFeatureFile(testSuiteId: string): Promise<boolean> {
|
|
|
225
172
|
}
|
|
226
173
|
|
|
227
174
|
const modulePath = buildModulePath(allModules, testSuite.module)
|
|
228
|
-
const safeFileName =
|
|
175
|
+
const safeFileName = getTestSuiteFilesystemKey(testSuite.name)
|
|
229
176
|
|
|
230
177
|
const featuresBaseDir = getAutomationFeaturesDir()
|
|
231
178
|
const moduleDir = join(featuresBaseDir, modulePath.substring(1))
|
|
@@ -295,7 +242,7 @@ export async function regenerateAllFeatureFiles(): Promise<string[]> {
|
|
|
295
242
|
const moduleDir = join(featuresBaseDir, modulePath.substring(1))
|
|
296
243
|
await fs.mkdir(moduleDir, { recursive: true })
|
|
297
244
|
|
|
298
|
-
const safeFileName =
|
|
245
|
+
const safeFileName = getTestSuiteFilesystemKey(testSuite.name)
|
|
299
246
|
const featureFilePath = join(moduleDir, `${safeFileName}.feature`)
|
|
300
247
|
|
|
301
248
|
await fs.writeFile(featureFilePath, featureContent, 'utf8')
|
|
@@ -311,11 +258,3 @@ export async function regenerateAllFeatureFiles(): Promise<string[]> {
|
|
|
311
258
|
throw error
|
|
312
259
|
}
|
|
313
260
|
}
|
|
314
|
-
|
|
315
|
-
function generateSafeFileName(testSuiteName: string): string {
|
|
316
|
-
return testSuiteName
|
|
317
|
-
.toLowerCase()
|
|
318
|
-
.replace(/[^a-z0-9]+/g, '-')
|
|
319
|
-
.replace(/^-+|-+$/g, '')
|
|
320
|
-
.replace(/-+/g, '-')
|
|
321
|
-
}
|