create-appraisejs 0.1.10-alpha.8 → 0.2.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -52
- package/dist/cli.e2e.test.d.ts +2 -0
- package/dist/cli.e2e.test.d.ts.map +1 -0
- package/dist/cli.e2e.test.js +73 -0
- package/dist/cli.e2e.test.js.map +1 -0
- package/dist/config.test.d.ts +2 -0
- package/dist/config.test.d.ts.map +1 -0
- package/dist/config.test.js +65 -0
- package/dist/config.test.js.map +1 -0
- package/dist/copy-template.test.d.ts +2 -0
- package/dist/copy-template.test.d.ts.map +1 -0
- package/dist/copy-template.test.js +71 -0
- package/dist/copy-template.test.js.map +1 -0
- package/dist/download-repo.test.d.ts +2 -0
- package/dist/download-repo.test.d.ts.map +1 -0
- package/dist/download-repo.test.js +14 -0
- package/dist/download-repo.test.js.map +1 -0
- package/dist/install.test.d.ts +2 -0
- package/dist/install.test.d.ts.map +1 -0
- package/dist/install.test.js +119 -0
- package/dist/install.test.js.map +1 -0
- package/dist/prepare-template-utils.d.ts.map +1 -1
- package/dist/prepare-template-utils.js +5 -0
- package/dist/prepare-template-utils.js.map +1 -1
- package/dist/prompts.test.d.ts +2 -0
- package/dist/prompts.test.d.ts.map +1 -0
- package/dist/prompts.test.js +58 -0
- package/dist/prompts.test.js.map +1 -0
- package/dist/scaffold-gitignore.d.ts +1 -0
- package/dist/scaffold-gitignore.d.ts.map +1 -1
- package/dist/scaffold-gitignore.js +3 -0
- package/dist/scaffold-gitignore.js.map +1 -1
- package/package.json +3 -2
- package/templates/default/.appraise-template-meta.json +2 -2
- package/templates/default/.env.example +2 -2
- package/templates/default/.vscode/settings.json +2 -1
- package/templates/default/README.md +53 -53
- package/templates/default/automation/mapping/locator-map.json +1 -14
- package/templates/default/automation/steps/actions/click.step.ts +58 -58
- package/templates/default/automation/steps/actions/hover.step.ts +27 -27
- package/templates/default/automation/steps/actions/input.step.ts +84 -84
- package/templates/default/automation/steps/actions/navigation.step.ts +70 -70
- package/templates/default/automation/steps/actions/random_data.step.ts +142 -142
- package/templates/default/automation/steps/actions/store.step.ts +86 -86
- package/templates/default/automation/steps/actions/wait.step.ts +90 -90
- package/templates/default/automation/steps/validations/active_state_assertion.step.ts +30 -30
- package/templates/default/automation/steps/validations/navigation_assertion.step.ts +22 -22
- package/templates/default/automation/steps/validations/text_assertion.step.ts +107 -107
- package/templates/default/automation/steps/validations/visibility_assertion.step.ts +26 -26
- package/templates/default/components.json +24 -24
- package/templates/default/cucumber.mjs +16 -16
- package/templates/default/eslint.config.mjs +16 -16
- package/templates/default/gitignore +3 -0
- package/templates/default/next-env.d.ts +6 -6
- package/templates/default/next.config.ts +11 -11
- package/templates/default/package-lock.json +146 -75
- package/templates/default/package.json +2 -1
- package/templates/default/packages/cucumber-runtime/package.json +13 -13
- package/templates/default/packages/cucumber-runtime/src/cache.util.ts +93 -93
- package/templates/default/packages/cucumber-runtime/src/cli.ts +68 -68
- package/templates/default/packages/cucumber-runtime/src/environment.util.ts +21 -21
- package/templates/default/packages/cucumber-runtime/src/executor.ts +32 -32
- package/templates/default/packages/cucumber-runtime/src/hooks.ts +25 -3
- package/templates/default/packages/cucumber-runtime/src/index.ts +17 -17
- package/templates/default/packages/cucumber-runtime/src/locator.util.ts +234 -234
- package/templates/default/packages/cucumber-runtime/src/parameter-types.ts +7 -7
- package/templates/default/packages/cucumber-runtime/src/paths.ts +66 -1
- package/templates/default/packages/cucumber-runtime/src/random-data.util.ts +35 -35
- package/templates/default/packages/cucumber-runtime/src/types.ts +13 -13
- package/templates/default/packages/cucumber-runtime/src/world.ts +44 -44
- package/templates/default/packages/cucumber-runtime/tsconfig.json +11 -11
- package/templates/default/packages/locator-picker-companion/dist/cli.d.ts +1 -0
- package/templates/default/packages/locator-picker-companion/dist/cli.js +302 -0
- package/templates/default/packages/locator-picker-companion/dist/index.d.ts +3 -0
- package/templates/default/packages/locator-picker-companion/dist/index.js +3 -0
- package/templates/default/packages/locator-picker-companion/dist/injected-picker-script.d.ts +1 -0
- package/templates/default/packages/locator-picker-companion/dist/injected-picker-script.js +615 -0
- package/templates/default/packages/locator-picker-companion/dist/launcher.d.ts +11 -0
- package/templates/default/packages/locator-picker-companion/dist/launcher.js +59 -0
- package/templates/default/packages/locator-picker-companion/dist/selector-generator.d.ts +3 -0
- package/templates/default/packages/locator-picker-companion/dist/selector-generator.js +257 -0
- package/templates/default/packages/locator-picker-companion/dist/session-file.d.ts +22 -0
- package/templates/default/packages/locator-picker-companion/dist/session-file.js +150 -0
- package/templates/default/packages/locator-picker-companion/dist/types.d.ts +31 -0
- package/templates/default/packages/locator-picker-companion/dist/types.js +1 -0
- package/templates/default/packages/locator-picker-companion/package.json +17 -0
- package/templates/default/packages/locator-picker-companion/src/cli.ts +428 -0
- package/templates/default/packages/locator-picker-companion/src/index.ts +3 -0
- package/templates/default/packages/locator-picker-companion/src/injected-picker-script.ts +771 -0
- package/templates/default/packages/locator-picker-companion/src/launcher.ts +77 -0
- package/templates/default/packages/locator-picker-companion/src/selector-generator.ts +339 -0
- package/templates/default/packages/locator-picker-companion/src/session-file.ts +226 -0
- package/templates/default/packages/locator-picker-companion/src/types.ts +42 -0
- package/templates/default/packages/locator-picker-companion/tsconfig.json +14 -0
- package/templates/default/postcss.config.mjs +8 -8
- package/templates/default/prisma/dev.db +0 -0
- package/templates/default/prisma/migrations/20251104113456_add_type_for_template_step_groups/migration.sql +16 -16
- package/templates/default/prisma/migrations/20251104170946_add_tags_to_test_suite_and_test_case/migration.sql +27 -27
- package/templates/default/prisma/migrations/20251112190024_add_cascade_delete_to_test_run_test_case/migration.sql +17 -17
- package/templates/default/prisma/migrations/20251113181100_add_test_run_log/migration.sql +12 -12
- package/templates/default/prisma/migrations/20251119191838_add_tag_type/migration.sql +28 -28
- package/templates/default/prisma/migrations/20251121164059_add_conflict_resolution/migration.sql +12 -12
- package/templates/default/prisma/migrations/20251223183400_add_report_model_to_db_schema/migration.sql +10 -10
- package/templates/default/prisma/migrations/20251223183637_add_report_test_case_entity_for_storing_test_results_for_individual_test_cases/migration.sql +10 -10
- package/templates/default/prisma/migrations/20251224083549_add_comprehensive_report_storage/migration.sql +108 -108
- package/templates/default/prisma/migrations/20251229194422_migrate_duration_to_string/migration.sql +55 -55
- package/templates/default/prisma/migrations/20251230124637_add_unique_constraint_to_test_run_name/migration.sql +27 -27
- package/templates/default/prisma/migrations/20260115094436_add_dashboard_metrics/migration.sql +59 -59
- package/templates/default/prisma/migrations/20260127172022_add_cascade_delete_to_step_parameters/migration.sql +34 -34
- package/templates/default/prisma/migrations/20260313093000_add_report_step_screenshot_path/migration.sql +1 -0
- package/templates/default/prisma/migrations/20260318120000_add_test_suite_context_to_test_run_test_case/migration.sql +20 -0
- package/templates/default/prisma/migrations/20260318173512_add_support_of_test_suite_level_runs/migration.sql +2 -0
- package/templates/default/prisma/schema.prisma +4 -0
- package/templates/default/scripts/install-playwright.ts +20 -0
- package/templates/default/scripts/protect-seeded-files.ts +38 -38
- package/templates/default/scripts/regenerate-features.ts +94 -94
- package/templates/default/scripts/setup-env.ts +19 -19
- package/templates/default/scripts/sync-all.ts +22 -66
- package/templates/default/scripts/sync-appraise-base-template.ts +57 -19
- package/templates/default/scripts/sync-environments.ts +40 -21
- package/templates/default/scripts/sync-locator-groups.ts +410 -410
- package/templates/default/scripts/sync-locators.ts +398 -398
- package/templates/default/scripts/sync-modules.ts +341 -341
- package/templates/default/scripts/sync-tags.ts +2 -3
- package/templates/default/scripts/sync-template-step-groups.ts +0 -3
- package/templates/default/scripts/sync-template-steps.ts +37 -11
- package/templates/default/scripts/sync-test-cases.ts +68 -16
- package/templates/default/scripts/sync-test-suites.ts +7 -5
- package/templates/default/src/actions/conflict/conflict.action.ts +33 -33
- package/templates/default/src/actions/dashboard/dashboard-actions.ts +240 -240
- package/templates/default/src/actions/environments/environment-actions.ts +188 -188
- package/templates/default/src/actions/locator/locator-actions.ts +490 -490
- package/templates/default/src/actions/locator-groups/locator-group-actions.ts +6 -3
- package/templates/default/src/actions/locator-picker/locator-picker-actions.ts +243 -0
- package/templates/default/src/actions/modules/module-actions.ts +135 -135
- package/templates/default/src/actions/reports/report-actions.ts +51 -49
- package/templates/default/src/actions/review/review-actions.ts +147 -147
- package/templates/default/src/actions/settings/sync-actions.ts +46 -0
- package/templates/default/src/actions/tags/tag-actions.ts +107 -107
- package/templates/default/src/actions/template-step/template-step-actions.ts +38 -4
- package/templates/default/src/actions/template-step-group/template-step-group-actions.ts +10 -3
- package/templates/default/src/actions/template-test-case/template-test-case-actions.ts +238 -238
- package/templates/default/src/actions/test-case/test-case-actions.ts +356 -356
- package/templates/default/src/actions/test-run/test-run-actions.ts +222 -129
- package/templates/default/src/actions/test-suite/test-suite-actions.ts +95 -17
- package/templates/default/src/actions/user/user-actions.ts +13 -13
- package/templates/default/src/app/(base)/environments/create/page.tsx +28 -28
- package/templates/default/src/app/(base)/environments/environment-form.tsx +219 -219
- package/templates/default/src/app/(base)/environments/environment-table-columns.tsx +96 -96
- package/templates/default/src/app/(base)/environments/environment-table.tsx +24 -24
- package/templates/default/src/app/(base)/environments/modify/[id]/page.tsx +46 -46
- package/templates/default/src/app/(base)/environments/page.tsx +59 -59
- package/templates/default/src/app/(base)/layout.tsx +10 -10
- package/templates/default/src/app/(base)/locator-groups/create/page.tsx +44 -44
- package/templates/default/src/app/(base)/locator-groups/locator-group-form.tsx +215 -215
- package/templates/default/src/app/(base)/locator-groups/locator-group-table-columns.tsx +77 -77
- package/templates/default/src/app/(base)/locator-groups/locator-group-table.tsx +28 -28
- package/templates/default/src/app/(base)/locator-groups/modify/[id]/page.tsx +46 -46
- package/templates/default/src/app/(base)/locator-groups/page.tsx +20 -8
- package/templates/default/src/app/(base)/locators/create/create-locator-workspace.tsx +542 -0
- package/templates/default/src/app/(base)/locators/create/page.tsx +32 -19
- package/templates/default/src/app/(base)/locators/locator-form.tsx +163 -163
- package/templates/default/src/app/(base)/locators/locator-table-columns.tsx +73 -73
- package/templates/default/src/app/(base)/locators/locator-table.tsx +28 -28
- package/templates/default/src/app/(base)/locators/modify/[id]/page.tsx +56 -27
- package/templates/default/src/app/(base)/locators/page.tsx +13 -13
- package/templates/default/src/app/(base)/locators/picker/page.tsx +7 -0
- package/templates/default/src/app/(base)/locators/sync-locators-button.tsx +66 -66
- package/templates/default/src/app/(base)/modules/create/page.tsx +34 -34
- package/templates/default/src/app/(base)/modules/modify/[id]/page.tsx +46 -46
- package/templates/default/src/app/(base)/modules/module-form.tsx +126 -126
- package/templates/default/src/app/(base)/modules/module-table-columns.tsx +85 -85
- package/templates/default/src/app/(base)/modules/module-table.tsx +24 -24
- package/templates/default/src/app/(base)/modules/page.tsx +59 -59
- package/templates/default/src/app/(base)/reports/[id]/page.tsx +40 -33
- package/templates/default/src/app/(base)/reports/duration-chart.tsx +33 -33
- package/templates/default/src/app/(base)/reports/feature-chart.tsx +78 -78
- package/templates/default/src/app/(base)/reports/overview-chart.tsx +49 -46
- package/templates/default/src/app/(base)/reports/page.tsx +98 -98
- package/templates/default/src/app/(base)/reports/report-metric-card.tsx +78 -16
- package/templates/default/src/app/(base)/reports/report-table-columns.tsx +189 -189
- package/templates/default/src/app/(base)/reports/report-table.tsx +72 -72
- package/templates/default/src/app/(base)/reports/report-view-table-columns.tsx +12 -1
- package/templates/default/src/app/(base)/reports/report-view-table.tsx +1 -0
- package/templates/default/src/app/(base)/reports/test-cases/page.tsx +40 -42
- package/templates/default/src/app/(base)/reports/test-cases/test-cases-metric-table-columns.tsx +115 -115
- package/templates/default/src/app/(base)/reports/test-cases/test-cases-metric-table.tsx +27 -27
- package/templates/default/src/app/(base)/reports/test-suites/page.tsx +42 -42
- package/templates/default/src/app/(base)/reports/test-suites/test-suites-metric-table-columns.tsx +79 -79
- package/templates/default/src/app/(base)/reports/test-suites/test-suites-metric-table.tsx +27 -27
- package/templates/default/src/app/(base)/reports/view-logs-button.tsx +58 -60
- package/templates/default/src/app/(base)/reviews/create/page.tsx +26 -26
- package/templates/default/src/app/(base)/reviews/created-reviews-table.tsx +15 -15
- package/templates/default/src/app/(base)/reviews/modify/[id]/page.tsx +26 -26
- package/templates/default/src/app/(base)/reviews/page.tsx +26 -26
- package/templates/default/src/app/(base)/reviews/review/[id]/page.tsx +26 -26
- package/templates/default/src/app/(base)/reviews/review-form.tsx +11 -11
- package/templates/default/src/app/(base)/reviews/review-table-by-creator-columns.tsx +9 -9
- package/templates/default/src/app/(base)/reviews/review-table-by-reviewer-columns.tsx +9 -9
- package/templates/default/src/app/(base)/reviews/reviewer-reviews-table.tsx +15 -15
- package/templates/default/src/app/(base)/settings/page.tsx +30 -0
- package/templates/default/src/app/(base)/settings/settings-sync-panel.tsx +261 -0
- package/templates/default/src/app/(base)/tags/create/page.tsx +39 -39
- package/templates/default/src/app/(base)/tags/modify/[id]/page.tsx +50 -50
- package/templates/default/src/app/(base)/tags/page.tsx +58 -58
- package/templates/default/src/app/(base)/tags/tag-form.tsx +147 -147
- package/templates/default/src/app/(base)/tags/tag-table-columns.tsx +63 -63
- package/templates/default/src/app/(base)/tags/tag-table.tsx +29 -29
- package/templates/default/src/app/(base)/template-step-groups/create/page.tsx +28 -28
- package/templates/default/src/app/(base)/template-step-groups/modify/[id]/page.tsx +45 -45
- package/templates/default/src/app/(base)/template-step-groups/page.tsx +60 -60
- package/templates/default/src/app/(base)/template-step-groups/template-step-group-form.tsx +167 -167
- package/templates/default/src/app/(base)/template-step-groups/template-step-group-table-columns.tsx +89 -89
- package/templates/default/src/app/(base)/template-step-groups/template-step-group-table.tsx +32 -32
- package/templates/default/src/app/(base)/template-steps/create/page.tsx +37 -37
- package/templates/default/src/app/(base)/template-steps/modify/[id]/page.tsx +49 -49
- package/templates/default/src/app/(base)/template-steps/page.tsx +58 -58
- package/templates/default/src/app/(base)/template-steps/paramChip.tsx +213 -213
- package/templates/default/src/app/(base)/template-steps/template-step-form.tsx +384 -384
- package/templates/default/src/app/(base)/template-steps/template-step-table-columns.tsx +158 -158
- package/templates/default/src/app/(base)/template-steps/template-step-table.tsx +24 -24
- package/templates/default/src/app/(base)/template-test-cases/create/page.tsx +56 -56
- package/templates/default/src/app/(base)/template-test-cases/modify/[id]/page.tsx +89 -89
- package/templates/default/src/app/(base)/template-test-cases/page.tsx +58 -58
- package/templates/default/src/app/(base)/template-test-cases/template-test-case-flow.tsx +84 -84
- package/templates/default/src/app/(base)/template-test-cases/template-test-case-form.tsx +262 -262
- package/templates/default/src/app/(base)/template-test-cases/template-test-case-table-columns.tsx +76 -76
- package/templates/default/src/app/(base)/template-test-cases/template-test-case-table.tsx +32 -32
- package/templates/default/src/app/(base)/test-cases/create/page.tsx +76 -76
- package/templates/default/src/app/(base)/test-cases/create-from-template/generate/[id]/page.tsx +96 -96
- package/templates/default/src/app/(base)/test-cases/create-from-template/page.tsx +38 -38
- package/templates/default/src/app/(base)/test-cases/create-from-template/template-selection-form.tsx +73 -73
- package/templates/default/src/app/(base)/test-cases/modify/[id]/page.tsx +106 -106
- package/templates/default/src/app/(base)/test-cases/page.tsx +2 -2
- package/templates/default/src/app/(base)/test-cases/test-case-flow.tsx +82 -82
- package/templates/default/src/app/(base)/test-cases/test-case-form.tsx +395 -395
- package/templates/default/src/app/(base)/test-cases/test-case-table-columns.tsx +6 -71
- package/templates/default/src/app/(base)/test-cases/test-case-table.tsx +2 -2
- package/templates/default/src/app/(base)/test-runs/[id]/page.tsx +4 -1
- package/templates/default/src/app/(base)/test-runs/create/page.tsx +11 -9
- package/templates/default/src/app/(base)/test-runs/page.tsx +60 -60
- package/templates/default/src/app/(base)/test-runs/test-run-form.tsx +37 -44
- package/templates/default/src/app/(base)/test-runs/test-run-table-columns.tsx +229 -229
- package/templates/default/src/app/(base)/test-runs/test-run-table.tsx +127 -127
- package/templates/default/src/app/(base)/test-suites/create/page.tsx +3 -2
- package/templates/default/src/app/(base)/test-suites/modify/[id]/page.tsx +2 -1
- package/templates/default/src/app/(base)/test-suites/page.tsx +57 -21
- package/templates/default/src/app/(base)/test-suites/test-suite-form.tsx +16 -17
- package/templates/default/src/app/(base)/test-suites/test-suite-table-columns.tsx +2 -1
- package/templates/default/src/app/(base)/test-suites/test-suite-table.tsx +29 -29
- package/templates/default/src/app/(dashboard-components)/app-drawer.tsx +187 -187
- package/templates/default/src/app/(dashboard-components)/data-card-grid.tsx +12 -12
- package/templates/default/src/app/(dashboard-components)/data-card.tsx +26 -26
- package/templates/default/src/app/(dashboard-components)/execution-health-panel.tsx +56 -56
- package/templates/default/src/app/(dashboard-components)/ongoing-test-runs-card.tsx +87 -87
- package/templates/default/src/app/(dashboard-components)/quick-actions-drawer.tsx +44 -44
- package/templates/default/src/app/api/reports/steps/[stepId]/screenshot/route.ts +52 -0
- package/templates/default/src/app/api/test-runs/[runId]/download/route.ts +97 -34
- package/templates/default/src/app/api/test-runs/[runId]/logs/route.ts +4 -1
- package/templates/default/src/app/api/test-runs/[runId]/trace/[testCaseId]/route.ts +146 -147
- package/templates/default/src/app/globals.css +147 -147
- package/templates/default/src/app/layout.tsx +4 -0
- package/templates/default/src/app/page.tsx +2 -0
- package/templates/default/src/assets/icons/empty-tube.tsx +23 -23
- package/templates/default/src/assets/icons/tube-plus.tsx +29 -29
- package/templates/default/src/components/base-node.tsx +21 -21
- package/templates/default/src/components/chart/pie-chart.tsx +73 -73
- package/templates/default/src/components/data-extraction/locator-inspector.tsx +460 -460
- package/templates/default/src/components/data-state/empty-state.tsx +40 -40
- package/templates/default/src/components/data-visualization/info-card.tsx +70 -70
- package/templates/default/src/components/data-visualization/info-grid.tsx +22 -22
- package/templates/default/src/components/diagram/button-edge.tsx +54 -54
- package/templates/default/src/components/diagram/dynamic-parameters.tsx +474 -474
- package/templates/default/src/components/diagram/edit-header-option.tsx +36 -36
- package/templates/default/src/components/diagram/flow-diagram.tsx +470 -470
- package/templates/default/src/components/diagram/node-form.tsx +262 -262
- package/templates/default/src/components/diagram/options-header-node.tsx +57 -57
- package/templates/default/src/components/diagram/template-step-combobox.tsx +155 -155
- package/templates/default/src/components/form/error-message.tsx +7 -7
- package/templates/default/src/components/kokonutui/smooth-tab.tsx +453 -453
- package/templates/default/src/components/loading-skeleton/data-table/data-table-skeleton.tsx +30 -30
- package/templates/default/src/components/loading-skeleton/form/button-skeleton.tsx +8 -8
- package/templates/default/src/components/loading-skeleton/form/icon-button-skeleton.tsx +8 -8
- package/templates/default/src/components/loading-skeleton/form/text-input-skeleton.tsx +8 -8
- package/templates/default/src/components/loading-skeleton/visualization/table-skeleton.tsx +14 -14
- package/templates/default/src/components/logo.tsx +15 -15
- package/templates/default/src/components/navigation/command-badge.tsx +34 -34
- package/templates/default/src/components/navigation/command-chain-input.tsx +51 -51
- package/templates/default/src/components/navigation/entity-search-command.tsx +116 -116
- package/templates/default/src/components/navigation/nav-card.tsx +31 -31
- package/templates/default/src/components/navigation/nav-command.tsx +13 -0
- package/templates/default/src/components/navigation/nav-link.tsx +60 -60
- package/templates/default/src/components/navigation/nav-menu-card-deck.tsx +112 -112
- package/templates/default/src/components/node-header.tsx +159 -159
- package/templates/default/src/components/reports/test-case-logs-modal.tsx +310 -253
- package/templates/default/src/components/table/table-actions.tsx +172 -172
- package/templates/default/src/components/test-case/test-case-columns.tsx +76 -0
- package/templates/default/src/components/test-case/test-case-picker.tsx +244 -0
- package/templates/default/src/components/test-run/download-logs-button.tsx +92 -99
- package/templates/default/src/components/test-run/log-viewer.tsx +1 -14
- package/templates/default/src/components/test-run/test-run-details.tsx +15 -2
- package/templates/default/src/components/test-run/test-run-header.tsx +149 -149
- package/templates/default/src/components/test-run/view-report-button.tsx +102 -102
- package/templates/default/src/components/test-suite/test-suite-picker.tsx +444 -0
- package/templates/default/src/components/theme/mode-toggle.tsx +54 -54
- package/templates/default/src/components/theme/theme-provider.tsx +8 -8
- package/templates/default/src/components/typography/page-header-subtitle.tsx +7 -7
- package/templates/default/src/components/typography/page-header.tsx +7 -7
- package/templates/default/src/components/ui/alert-dialog.tsx +106 -106
- package/templates/default/src/components/ui/alert.tsx +43 -43
- package/templates/default/src/components/ui/avatar.tsx +40 -40
- package/templates/default/src/components/ui/badge.tsx +29 -29
- package/templates/default/src/components/ui/button.tsx +47 -47
- package/templates/default/src/components/ui/calendar.tsx +158 -158
- package/templates/default/src/components/ui/card.tsx +43 -43
- package/templates/default/src/components/ui/checkbox.tsx +28 -28
- package/templates/default/src/components/ui/command.tsx +135 -135
- package/templates/default/src/components/ui/data-table-column-header.tsx +61 -61
- package/templates/default/src/components/ui/data-table-pagination.tsx +87 -87
- package/templates/default/src/components/ui/data-table-view-options.tsx +50 -50
- package/templates/default/src/components/ui/data-table.tsx +261 -261
- package/templates/default/src/components/ui/dialog.tsx +97 -97
- package/templates/default/src/components/ui/dropdown-menu.tsx +182 -182
- package/templates/default/src/components/ui/input.tsx +22 -22
- package/templates/default/src/components/ui/kbd.tsx +28 -28
- package/templates/default/src/components/ui/label.tsx +19 -19
- package/templates/default/src/components/ui/loading.tsx +12 -12
- package/templates/default/src/components/ui/multi-select-with-preview.tsx +116 -116
- package/templates/default/src/components/ui/multi-select.tsx +142 -142
- package/templates/default/src/components/ui/navigation-menu.tsx +120 -120
- package/templates/default/src/components/ui/popover.tsx +33 -33
- package/templates/default/src/components/ui/progress.tsx +25 -25
- package/templates/default/src/components/ui/radio-group.tsx +44 -44
- package/templates/default/src/components/ui/scroll-area.tsx +40 -40
- package/templates/default/src/components/ui/select.tsx +151 -151
- package/templates/default/src/components/ui/separator.tsx +22 -22
- package/templates/default/src/components/ui/skeleton.tsx +7 -7
- package/templates/default/src/components/ui/table.tsx +76 -76
- package/templates/default/src/components/ui/tabs.tsx +55 -55
- package/templates/default/src/components/ui/textarea.tsx +21 -21
- package/templates/default/src/components/ui/toast.tsx +113 -113
- package/templates/default/src/components/ui/toaster.tsx +26 -26
- package/templates/default/src/components/user-prompt/delete-prompt.tsx +87 -87
- package/templates/default/src/config/db-config.ts +10 -10
- package/templates/default/src/constants/form-opts/diagram/node-form.ts +30 -30
- package/templates/default/src/constants/form-opts/environment-form-opts.ts +24 -24
- package/templates/default/src/constants/form-opts/locator-form-opts.ts +20 -20
- package/templates/default/src/constants/form-opts/locator-group-form-opts.ts +28 -28
- package/templates/default/src/constants/form-opts/module-form-opts.ts +21 -21
- package/templates/default/src/constants/form-opts/review-form-opts.ts +23 -23
- package/templates/default/src/constants/form-opts/tag-form-opts.ts +42 -42
- package/templates/default/src/constants/form-opts/template-selection-form-opts.ts +16 -16
- package/templates/default/src/constants/form-opts/template-step-group-form-opts.ts +24 -24
- package/templates/default/src/constants/form-opts/template-test-case-form-opts.ts +39 -39
- package/templates/default/src/constants/form-opts/template-test-step-form-opts.ts +36 -36
- package/templates/default/src/constants/form-opts/test-case-form-opts.ts +43 -43
- package/templates/default/src/constants/form-opts/test-run-form-opts.ts +5 -3
- package/templates/default/src/constants/form-opts/test-suite-form-opts.ts +24 -24
- package/templates/default/src/hooks/use-toast.ts +187 -187
- package/templates/default/src/lib/automation/paths.ts +42 -12
- package/templates/default/src/lib/automation/projection-service.ts +2 -1
- package/templates/default/src/lib/bidirectional-sync.ts +432 -432
- package/templates/default/src/lib/database-sync.ts +2 -7
- package/templates/default/src/lib/environment-file-utils.ts +184 -184
- package/templates/default/src/lib/executor/local-executor-adapter.ts +24 -25
- package/templates/default/src/lib/executor/types.ts +2 -2
- package/templates/default/src/lib/feature-file-generator.ts +5 -66
- package/templates/default/src/lib/gherkin-parser.ts +259 -259
- package/templates/default/src/lib/locator-group-file-utils.ts +307 -307
- package/templates/default/src/lib/locator-picker/session-manager.ts +452 -0
- package/templates/default/src/lib/locator-picker/suggestions.ts +124 -0
- package/templates/default/src/lib/metrics/metric-calculator.ts +5 -0
- package/templates/default/src/lib/module-hierarchy-builder.ts +205 -205
- package/templates/default/src/lib/path-helpers/module-path.ts +71 -71
- package/templates/default/src/lib/process/task-spawner.ts +39 -2
- package/templates/default/src/lib/sync/projected-feature-utils.ts +113 -0
- package/templates/default/src/lib/sync/sync-executor.ts +130 -0
- package/templates/default/src/lib/sync/sync-pending-counts.test.ts +239 -0
- package/templates/default/src/lib/sync/sync-pending-counts.ts +1358 -0
- package/templates/default/src/lib/sync/sync-registry.ts +149 -0
- package/templates/default/src/lib/tag-utils.ts +28 -0
- package/templates/default/src/lib/template-sync-utils.d.ts +6 -6
- package/templates/default/src/lib/template-sync-utils.js +46 -46
- package/templates/default/src/lib/template-sync-utils.ts +63 -63
- package/templates/default/src/lib/test-case-utils.ts +6 -6
- package/templates/default/src/lib/test-run/log-formatter.ts +83 -83
- package/templates/default/src/lib/test-run/matching.ts +117 -0
- package/templates/default/src/lib/test-run/process-manager.ts +2 -0
- package/templates/default/src/lib/test-run/report-parser.ts +352 -316
- package/templates/default/src/lib/test-run/test-run-executor.ts +13 -15
- package/templates/default/src/lib/test-run/winston-logger.ts +64 -66
- package/templates/default/src/lib/test-suite-identifier-service.ts +76 -0
- package/templates/default/src/lib/test-suite-utils.ts +6 -0
- package/templates/default/src/lib/transformers/gherkin-converter.ts +42 -42
- package/templates/default/src/lib/transformers/key-to-icon-transformer.tsx +95 -95
- package/templates/default/src/lib/transformers/template-test-case-converter.ts +160 -160
- package/templates/default/src/lib/utils/node-param-validation.ts +81 -81
- package/templates/default/src/lib/utils/template-step-file-generator.ts +104 -104
- package/templates/default/src/lib/utils/template-step-file-manager-intelligent.ts +0 -8
- package/templates/default/src/lib/utils/template-step-file-manager.ts +166 -166
- package/templates/default/src/lib/utils.ts +31 -31
- package/templates/default/src/types/diagram/diagram.ts +34 -34
- package/templates/default/src/types/diagram/template-step.ts +11 -11
- package/templates/default/src/types/executor/browser.type.ts +1 -1
- package/templates/default/src/types/form/actionHandler.ts +6 -6
- package/templates/default/src/types/locator/locator.type.ts +11 -11
- package/templates/default/src/types/locator-picker.ts +65 -0
- package/templates/default/src/types/step/step.type.ts +1 -1
- package/templates/default/src/types/table/data-table.ts +6 -6
- package/templates/default/src/types/test-case-picker.ts +6 -0
- package/templates/default/src/types/test-suite-picker.ts +18 -0
- package/templates/default/tailwind.config.ts +62 -62
- package/templates/default/tsconfig.json +4 -1
- package/templates/default/appraisejs.config.json +0 -1
|
@@ -1,307 +1,307 @@
|
|
|
1
|
-
import { promises as fs } from 'fs'
|
|
2
|
-
import path from 'path'
|
|
3
|
-
import prisma from '@/config/db-config'
|
|
4
|
-
import { buildModulePath } from '@/lib/path-helpers/module-path'
|
|
5
|
-
import {
|
|
6
|
-
ensureAutomationWorkspaceReady,
|
|
7
|
-
getAutomationLocatorsDir,
|
|
8
|
-
getAutomationMappingDir,
|
|
9
|
-
} from '@/lib/automation/paths'
|
|
10
|
-
|
|
11
|
-
export async function getLocatorGroupFilePath(locatorGroupId: string): Promise<string | null> {
|
|
12
|
-
try {
|
|
13
|
-
await ensureAutomationWorkspaceReady()
|
|
14
|
-
const locatorGroup = await prisma.locatorGroup.findUnique({
|
|
15
|
-
where: { id: locatorGroupId },
|
|
16
|
-
include: { module: true },
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
if (!locatorGroup) {
|
|
20
|
-
return null
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const allModules = await prisma.module.findMany()
|
|
24
|
-
const modulePath = buildModulePath(allModules, locatorGroup.module)
|
|
25
|
-
const sanitizedPath = modulePath.replace(/^\//, '').replace(/\//g, path.sep)
|
|
26
|
-
const fileName = `${locatorGroup.name}.json`
|
|
27
|
-
|
|
28
|
-
return path.join(getAutomationLocatorsDir(), sanitizedPath, fileName)
|
|
29
|
-
} catch (error) {
|
|
30
|
-
console.error('Error getting locator group file path:', error)
|
|
31
|
-
return null
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export async function generateLocatorGroupContent(locatorGroupId: string): Promise<Record<string, string>> {
|
|
36
|
-
try {
|
|
37
|
-
const locatorGroup = await prisma.locatorGroup.findUnique({
|
|
38
|
-
where: { id: locatorGroupId },
|
|
39
|
-
include: {
|
|
40
|
-
locators: {
|
|
41
|
-
select: { name: true, value: true },
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
if (!locatorGroup) {
|
|
47
|
-
return {}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return Object.fromEntries(locatorGroup.locators.map(locator => [locator.name, locator.value]))
|
|
51
|
-
} catch (error) {
|
|
52
|
-
console.error('Error generating locator group content:', error)
|
|
53
|
-
return {}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export async function ensureDirectoryExists(filePath: string): Promise<void> {
|
|
58
|
-
await ensureAutomationWorkspaceReady()
|
|
59
|
-
await fs.mkdir(path.dirname(filePath), { recursive: true })
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export async function createOrUpdateLocatorGroupFile(locatorGroupId: string): Promise<boolean> {
|
|
63
|
-
try {
|
|
64
|
-
await ensureAutomationWorkspaceReady()
|
|
65
|
-
const filePath = await getLocatorGroupFilePath(locatorGroupId)
|
|
66
|
-
if (!filePath) {
|
|
67
|
-
return false
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
await ensureDirectoryExists(filePath)
|
|
71
|
-
const content = await generateLocatorGroupContent(locatorGroupId)
|
|
72
|
-
await fs.writeFile(filePath, JSON.stringify(content, null, 2))
|
|
73
|
-
return true
|
|
74
|
-
} catch (error) {
|
|
75
|
-
console.error('Error creating/updating locator group file:', error)
|
|
76
|
-
return false
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export async function deleteLocatorGroupFile(locatorGroupId: string, filePathOverride?: string): Promise<boolean> {
|
|
81
|
-
try {
|
|
82
|
-
await ensureAutomationWorkspaceReady()
|
|
83
|
-
const filePath = filePathOverride ?? (await getLocatorGroupFilePath(locatorGroupId))
|
|
84
|
-
if (!filePath) {
|
|
85
|
-
return false
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
try {
|
|
89
|
-
await fs.access(filePath)
|
|
90
|
-
} catch {
|
|
91
|
-
return true
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
await fs.unlink(filePath)
|
|
95
|
-
await cleanupEmptyDirectories(filePath)
|
|
96
|
-
return true
|
|
97
|
-
} catch (error) {
|
|
98
|
-
console.error('Error deleting locator group file:', error)
|
|
99
|
-
return false
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
export async function renameLocatorGroupFile(
|
|
104
|
-
locatorGroupId: string,
|
|
105
|
-
newName: string,
|
|
106
|
-
oldName?: string,
|
|
107
|
-
): Promise<boolean> {
|
|
108
|
-
try {
|
|
109
|
-
await ensureAutomationWorkspaceReady()
|
|
110
|
-
const currentFilePath = await getLocatorGroupFilePath(locatorGroupId)
|
|
111
|
-
if (!currentFilePath) {
|
|
112
|
-
return false
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const oldFilePath = oldName ? path.join(path.dirname(currentFilePath), `${oldName}.json`) : currentFilePath
|
|
116
|
-
const newFilePath = path.join(path.dirname(currentFilePath), `${newName}.json`)
|
|
117
|
-
|
|
118
|
-
try {
|
|
119
|
-
await fs.access(oldFilePath)
|
|
120
|
-
await fs.rename(oldFilePath, newFilePath)
|
|
121
|
-
} catch {
|
|
122
|
-
return createOrUpdateLocatorGroupFile(locatorGroupId)
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return true
|
|
126
|
-
} catch (error) {
|
|
127
|
-
console.error('Error renaming locator group file:', error)
|
|
128
|
-
return false
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
export async function moveLocatorGroupFile(locatorGroupId: string, previousFilePath?: string): Promise<boolean> {
|
|
133
|
-
try {
|
|
134
|
-
await ensureAutomationWorkspaceReady()
|
|
135
|
-
if (previousFilePath) {
|
|
136
|
-
await deleteLocatorGroupFile(locatorGroupId, previousFilePath)
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return createOrUpdateLocatorGroupFile(locatorGroupId)
|
|
140
|
-
} catch (error) {
|
|
141
|
-
console.error('Error moving locator group file:', error)
|
|
142
|
-
return false
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
async function cleanupEmptyDirectories(filePath: string): Promise<void> {
|
|
147
|
-
let currentDir = path.dirname(filePath)
|
|
148
|
-
const locatorsRoot = getAutomationLocatorsDir()
|
|
149
|
-
|
|
150
|
-
while (currentDir.startsWith(locatorsRoot) && currentDir !== locatorsRoot && currentDir !== path.dirname(currentDir)) {
|
|
151
|
-
try {
|
|
152
|
-
const files = await fs.readdir(currentDir)
|
|
153
|
-
if (files.length === 0) {
|
|
154
|
-
await fs.rmdir(currentDir)
|
|
155
|
-
currentDir = path.dirname(currentDir)
|
|
156
|
-
} else {
|
|
157
|
-
break
|
|
158
|
-
}
|
|
159
|
-
} catch {
|
|
160
|
-
break
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
export async function createEmptyLocatorGroupFile(locatorGroupId: string): Promise<boolean> {
|
|
166
|
-
try {
|
|
167
|
-
await ensureAutomationWorkspaceReady()
|
|
168
|
-
const filePath = await getLocatorGroupFilePath(locatorGroupId)
|
|
169
|
-
if (!filePath) {
|
|
170
|
-
return false
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
await ensureDirectoryExists(filePath)
|
|
174
|
-
await fs.writeFile(filePath, JSON.stringify({}, null, 2))
|
|
175
|
-
return true
|
|
176
|
-
} catch (error) {
|
|
177
|
-
console.error('Error creating empty locator group file:', error)
|
|
178
|
-
return false
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
export async function readLocatorGroupFile(
|
|
183
|
-
locatorGroupId: string,
|
|
184
|
-
): Promise<{ filePath: string; content: Record<string, string> } | null> {
|
|
185
|
-
try {
|
|
186
|
-
await ensureAutomationWorkspaceReady()
|
|
187
|
-
const filePath = await getLocatorGroupFilePath(locatorGroupId)
|
|
188
|
-
if (!filePath) {
|
|
189
|
-
return null
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
const fileContent = await fs.readFile(filePath, 'utf-8')
|
|
193
|
-
return { filePath, content: JSON.parse(fileContent) }
|
|
194
|
-
} catch (error) {
|
|
195
|
-
console.error('Error reading locator group file:', error)
|
|
196
|
-
return null
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
export async function updateLocatorMapFile(
|
|
201
|
-
currentLocatorGroupRoute: string,
|
|
202
|
-
newLocatorGroupRoute: string,
|
|
203
|
-
currentLocatorGroupName: string,
|
|
204
|
-
newLocatorGroupName: string,
|
|
205
|
-
): Promise<boolean>
|
|
206
|
-
export async function updateLocatorMapFile(newLocatorGroupName: string, newLocatorGroupRoute: string): Promise<boolean>
|
|
207
|
-
export async function updateLocatorMapFile(
|
|
208
|
-
param1: string,
|
|
209
|
-
param2: string,
|
|
210
|
-
param3?: string,
|
|
211
|
-
param4?: string,
|
|
212
|
-
): Promise<boolean> {
|
|
213
|
-
try {
|
|
214
|
-
await ensureAutomationWorkspaceReady()
|
|
215
|
-
const locatorMapPath = path.join(getAutomationMappingDir(), 'locator-map.json')
|
|
216
|
-
await ensureDirectoryExists(locatorMapPath)
|
|
217
|
-
|
|
218
|
-
let locatorMap: Array<{ name: string; path: string }> = []
|
|
219
|
-
|
|
220
|
-
try {
|
|
221
|
-
const fileContent = await fs.readFile(locatorMapPath, 'utf-8')
|
|
222
|
-
locatorMap = JSON.parse(fileContent)
|
|
223
|
-
} catch {
|
|
224
|
-
locatorMap = []
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
const isNewEntry = param3 === undefined && param4 === undefined
|
|
228
|
-
|
|
229
|
-
if (isNewEntry) {
|
|
230
|
-
const name = param1
|
|
231
|
-
const route = param2
|
|
232
|
-
const existingEntry = locatorMap.find(entry => entry.name === name)
|
|
233
|
-
if (existingEntry) {
|
|
234
|
-
console.error(`Locator group with name "${name}" already exists in locator map`)
|
|
235
|
-
return false
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
locatorMap.push({ name, path: route })
|
|
239
|
-
} else {
|
|
240
|
-
const currentLocatorGroupRoute = param1
|
|
241
|
-
const newLocatorGroupRoute = param2
|
|
242
|
-
const currentLocatorGroupName = param3!
|
|
243
|
-
const newLocatorGroupName = param4!
|
|
244
|
-
|
|
245
|
-
const entryIndex = locatorMap.findIndex(entry => entry.name === currentLocatorGroupName)
|
|
246
|
-
if (entryIndex === -1) {
|
|
247
|
-
console.error(`Locator group with name "${currentLocatorGroupName}" not found in locator map`)
|
|
248
|
-
return false
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
if (currentLocatorGroupName !== newLocatorGroupName) {
|
|
252
|
-
const existingEntry = locatorMap.find(entry => entry.name === newLocatorGroupName)
|
|
253
|
-
if (existingEntry) {
|
|
254
|
-
console.error(`Locator group with name "${newLocatorGroupName}" already exists in locator map`)
|
|
255
|
-
return false
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
const updatedEntry = { ...locatorMap[entryIndex] }
|
|
260
|
-
|
|
261
|
-
if (currentLocatorGroupName !== newLocatorGroupName) {
|
|
262
|
-
updatedEntry.name = newLocatorGroupName
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
if (currentLocatorGroupRoute !== newLocatorGroupRoute) {
|
|
266
|
-
updatedEntry.path = newLocatorGroupRoute
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
locatorMap[entryIndex] = updatedEntry
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
await fs.writeFile(locatorMapPath, JSON.stringify(locatorMap, null, 2))
|
|
273
|
-
return true
|
|
274
|
-
} catch (error) {
|
|
275
|
-
console.error('Error updating locator map file:', error)
|
|
276
|
-
return false
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
export async function removeLocatorMapEntry(locatorGroupNames: string[]): Promise<boolean> {
|
|
281
|
-
try {
|
|
282
|
-
await ensureAutomationWorkspaceReady()
|
|
283
|
-
const locatorMapPath = path.join(getAutomationMappingDir(), 'locator-map.json')
|
|
284
|
-
|
|
285
|
-
try {
|
|
286
|
-
await fs.access(locatorMapPath)
|
|
287
|
-
} catch {
|
|
288
|
-
return true
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
const fileContent = await fs.readFile(locatorMapPath, 'utf-8')
|
|
292
|
-
let locatorMap: Array<{ name: string; path: string }> = JSON.parse(fileContent)
|
|
293
|
-
|
|
294
|
-
const originalLength = locatorMap.length
|
|
295
|
-
locatorMap = locatorMap.filter(entry => !locatorGroupNames.includes(entry.name))
|
|
296
|
-
|
|
297
|
-
if (originalLength === locatorMap.length) {
|
|
298
|
-
return true
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
await fs.writeFile(locatorMapPath, JSON.stringify(locatorMap, null, 2))
|
|
302
|
-
return true
|
|
303
|
-
} catch (error) {
|
|
304
|
-
console.error('Error removing locator map entries:', error)
|
|
305
|
-
return false
|
|
306
|
-
}
|
|
307
|
-
}
|
|
1
|
+
import { promises as fs } from 'fs'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import prisma from '@/config/db-config'
|
|
4
|
+
import { buildModulePath } from '@/lib/path-helpers/module-path'
|
|
5
|
+
import {
|
|
6
|
+
ensureAutomationWorkspaceReady,
|
|
7
|
+
getAutomationLocatorsDir,
|
|
8
|
+
getAutomationMappingDir,
|
|
9
|
+
} from '@/lib/automation/paths'
|
|
10
|
+
|
|
11
|
+
export async function getLocatorGroupFilePath(locatorGroupId: string): Promise<string | null> {
|
|
12
|
+
try {
|
|
13
|
+
await ensureAutomationWorkspaceReady()
|
|
14
|
+
const locatorGroup = await prisma.locatorGroup.findUnique({
|
|
15
|
+
where: { id: locatorGroupId },
|
|
16
|
+
include: { module: true },
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
if (!locatorGroup) {
|
|
20
|
+
return null
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const allModules = await prisma.module.findMany()
|
|
24
|
+
const modulePath = buildModulePath(allModules, locatorGroup.module)
|
|
25
|
+
const sanitizedPath = modulePath.replace(/^\//, '').replace(/\//g, path.sep)
|
|
26
|
+
const fileName = `${locatorGroup.name}.json`
|
|
27
|
+
|
|
28
|
+
return path.join(getAutomationLocatorsDir(), sanitizedPath, fileName)
|
|
29
|
+
} catch (error) {
|
|
30
|
+
console.error('Error getting locator group file path:', error)
|
|
31
|
+
return null
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function generateLocatorGroupContent(locatorGroupId: string): Promise<Record<string, string>> {
|
|
36
|
+
try {
|
|
37
|
+
const locatorGroup = await prisma.locatorGroup.findUnique({
|
|
38
|
+
where: { id: locatorGroupId },
|
|
39
|
+
include: {
|
|
40
|
+
locators: {
|
|
41
|
+
select: { name: true, value: true },
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
if (!locatorGroup) {
|
|
47
|
+
return {}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return Object.fromEntries(locatorGroup.locators.map(locator => [locator.name, locator.value]))
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.error('Error generating locator group content:', error)
|
|
53
|
+
return {}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export async function ensureDirectoryExists(filePath: string): Promise<void> {
|
|
58
|
+
await ensureAutomationWorkspaceReady()
|
|
59
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true })
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export async function createOrUpdateLocatorGroupFile(locatorGroupId: string): Promise<boolean> {
|
|
63
|
+
try {
|
|
64
|
+
await ensureAutomationWorkspaceReady()
|
|
65
|
+
const filePath = await getLocatorGroupFilePath(locatorGroupId)
|
|
66
|
+
if (!filePath) {
|
|
67
|
+
return false
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
await ensureDirectoryExists(filePath)
|
|
71
|
+
const content = await generateLocatorGroupContent(locatorGroupId)
|
|
72
|
+
await fs.writeFile(filePath, JSON.stringify(content, null, 2))
|
|
73
|
+
return true
|
|
74
|
+
} catch (error) {
|
|
75
|
+
console.error('Error creating/updating locator group file:', error)
|
|
76
|
+
return false
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export async function deleteLocatorGroupFile(locatorGroupId: string, filePathOverride?: string): Promise<boolean> {
|
|
81
|
+
try {
|
|
82
|
+
await ensureAutomationWorkspaceReady()
|
|
83
|
+
const filePath = filePathOverride ?? (await getLocatorGroupFilePath(locatorGroupId))
|
|
84
|
+
if (!filePath) {
|
|
85
|
+
return false
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
await fs.access(filePath)
|
|
90
|
+
} catch {
|
|
91
|
+
return true
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
await fs.unlink(filePath)
|
|
95
|
+
await cleanupEmptyDirectories(filePath)
|
|
96
|
+
return true
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.error('Error deleting locator group file:', error)
|
|
99
|
+
return false
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export async function renameLocatorGroupFile(
|
|
104
|
+
locatorGroupId: string,
|
|
105
|
+
newName: string,
|
|
106
|
+
oldName?: string,
|
|
107
|
+
): Promise<boolean> {
|
|
108
|
+
try {
|
|
109
|
+
await ensureAutomationWorkspaceReady()
|
|
110
|
+
const currentFilePath = await getLocatorGroupFilePath(locatorGroupId)
|
|
111
|
+
if (!currentFilePath) {
|
|
112
|
+
return false
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const oldFilePath = oldName ? path.join(path.dirname(currentFilePath), `${oldName}.json`) : currentFilePath
|
|
116
|
+
const newFilePath = path.join(path.dirname(currentFilePath), `${newName}.json`)
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
await fs.access(oldFilePath)
|
|
120
|
+
await fs.rename(oldFilePath, newFilePath)
|
|
121
|
+
} catch {
|
|
122
|
+
return createOrUpdateLocatorGroupFile(locatorGroupId)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return true
|
|
126
|
+
} catch (error) {
|
|
127
|
+
console.error('Error renaming locator group file:', error)
|
|
128
|
+
return false
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export async function moveLocatorGroupFile(locatorGroupId: string, previousFilePath?: string): Promise<boolean> {
|
|
133
|
+
try {
|
|
134
|
+
await ensureAutomationWorkspaceReady()
|
|
135
|
+
if (previousFilePath) {
|
|
136
|
+
await deleteLocatorGroupFile(locatorGroupId, previousFilePath)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return createOrUpdateLocatorGroupFile(locatorGroupId)
|
|
140
|
+
} catch (error) {
|
|
141
|
+
console.error('Error moving locator group file:', error)
|
|
142
|
+
return false
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
async function cleanupEmptyDirectories(filePath: string): Promise<void> {
|
|
147
|
+
let currentDir = path.dirname(filePath)
|
|
148
|
+
const locatorsRoot = getAutomationLocatorsDir()
|
|
149
|
+
|
|
150
|
+
while (currentDir.startsWith(locatorsRoot) && currentDir !== locatorsRoot && currentDir !== path.dirname(currentDir)) {
|
|
151
|
+
try {
|
|
152
|
+
const files = await fs.readdir(currentDir)
|
|
153
|
+
if (files.length === 0) {
|
|
154
|
+
await fs.rmdir(currentDir)
|
|
155
|
+
currentDir = path.dirname(currentDir)
|
|
156
|
+
} else {
|
|
157
|
+
break
|
|
158
|
+
}
|
|
159
|
+
} catch {
|
|
160
|
+
break
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export async function createEmptyLocatorGroupFile(locatorGroupId: string): Promise<boolean> {
|
|
166
|
+
try {
|
|
167
|
+
await ensureAutomationWorkspaceReady()
|
|
168
|
+
const filePath = await getLocatorGroupFilePath(locatorGroupId)
|
|
169
|
+
if (!filePath) {
|
|
170
|
+
return false
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
await ensureDirectoryExists(filePath)
|
|
174
|
+
await fs.writeFile(filePath, JSON.stringify({}, null, 2))
|
|
175
|
+
return true
|
|
176
|
+
} catch (error) {
|
|
177
|
+
console.error('Error creating empty locator group file:', error)
|
|
178
|
+
return false
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export async function readLocatorGroupFile(
|
|
183
|
+
locatorGroupId: string,
|
|
184
|
+
): Promise<{ filePath: string; content: Record<string, string> } | null> {
|
|
185
|
+
try {
|
|
186
|
+
await ensureAutomationWorkspaceReady()
|
|
187
|
+
const filePath = await getLocatorGroupFilePath(locatorGroupId)
|
|
188
|
+
if (!filePath) {
|
|
189
|
+
return null
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const fileContent = await fs.readFile(filePath, 'utf-8')
|
|
193
|
+
return { filePath, content: JSON.parse(fileContent) }
|
|
194
|
+
} catch (error) {
|
|
195
|
+
console.error('Error reading locator group file:', error)
|
|
196
|
+
return null
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export async function updateLocatorMapFile(
|
|
201
|
+
currentLocatorGroupRoute: string,
|
|
202
|
+
newLocatorGroupRoute: string,
|
|
203
|
+
currentLocatorGroupName: string,
|
|
204
|
+
newLocatorGroupName: string,
|
|
205
|
+
): Promise<boolean>
|
|
206
|
+
export async function updateLocatorMapFile(newLocatorGroupName: string, newLocatorGroupRoute: string): Promise<boolean>
|
|
207
|
+
export async function updateLocatorMapFile(
|
|
208
|
+
param1: string,
|
|
209
|
+
param2: string,
|
|
210
|
+
param3?: string,
|
|
211
|
+
param4?: string,
|
|
212
|
+
): Promise<boolean> {
|
|
213
|
+
try {
|
|
214
|
+
await ensureAutomationWorkspaceReady()
|
|
215
|
+
const locatorMapPath = path.join(getAutomationMappingDir(), 'locator-map.json')
|
|
216
|
+
await ensureDirectoryExists(locatorMapPath)
|
|
217
|
+
|
|
218
|
+
let locatorMap: Array<{ name: string; path: string }> = []
|
|
219
|
+
|
|
220
|
+
try {
|
|
221
|
+
const fileContent = await fs.readFile(locatorMapPath, 'utf-8')
|
|
222
|
+
locatorMap = JSON.parse(fileContent)
|
|
223
|
+
} catch {
|
|
224
|
+
locatorMap = []
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const isNewEntry = param3 === undefined && param4 === undefined
|
|
228
|
+
|
|
229
|
+
if (isNewEntry) {
|
|
230
|
+
const name = param1
|
|
231
|
+
const route = param2
|
|
232
|
+
const existingEntry = locatorMap.find(entry => entry.name === name)
|
|
233
|
+
if (existingEntry) {
|
|
234
|
+
console.error(`Locator group with name "${name}" already exists in locator map`)
|
|
235
|
+
return false
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
locatorMap.push({ name, path: route })
|
|
239
|
+
} else {
|
|
240
|
+
const currentLocatorGroupRoute = param1
|
|
241
|
+
const newLocatorGroupRoute = param2
|
|
242
|
+
const currentLocatorGroupName = param3!
|
|
243
|
+
const newLocatorGroupName = param4!
|
|
244
|
+
|
|
245
|
+
const entryIndex = locatorMap.findIndex(entry => entry.name === currentLocatorGroupName)
|
|
246
|
+
if (entryIndex === -1) {
|
|
247
|
+
console.error(`Locator group with name "${currentLocatorGroupName}" not found in locator map`)
|
|
248
|
+
return false
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if (currentLocatorGroupName !== newLocatorGroupName) {
|
|
252
|
+
const existingEntry = locatorMap.find(entry => entry.name === newLocatorGroupName)
|
|
253
|
+
if (existingEntry) {
|
|
254
|
+
console.error(`Locator group with name "${newLocatorGroupName}" already exists in locator map`)
|
|
255
|
+
return false
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const updatedEntry = { ...locatorMap[entryIndex] }
|
|
260
|
+
|
|
261
|
+
if (currentLocatorGroupName !== newLocatorGroupName) {
|
|
262
|
+
updatedEntry.name = newLocatorGroupName
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (currentLocatorGroupRoute !== newLocatorGroupRoute) {
|
|
266
|
+
updatedEntry.path = newLocatorGroupRoute
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
locatorMap[entryIndex] = updatedEntry
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
await fs.writeFile(locatorMapPath, JSON.stringify(locatorMap, null, 2))
|
|
273
|
+
return true
|
|
274
|
+
} catch (error) {
|
|
275
|
+
console.error('Error updating locator map file:', error)
|
|
276
|
+
return false
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
export async function removeLocatorMapEntry(locatorGroupNames: string[]): Promise<boolean> {
|
|
281
|
+
try {
|
|
282
|
+
await ensureAutomationWorkspaceReady()
|
|
283
|
+
const locatorMapPath = path.join(getAutomationMappingDir(), 'locator-map.json')
|
|
284
|
+
|
|
285
|
+
try {
|
|
286
|
+
await fs.access(locatorMapPath)
|
|
287
|
+
} catch {
|
|
288
|
+
return true
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
const fileContent = await fs.readFile(locatorMapPath, 'utf-8')
|
|
292
|
+
let locatorMap: Array<{ name: string; path: string }> = JSON.parse(fileContent)
|
|
293
|
+
|
|
294
|
+
const originalLength = locatorMap.length
|
|
295
|
+
locatorMap = locatorMap.filter(entry => !locatorGroupNames.includes(entry.name))
|
|
296
|
+
|
|
297
|
+
if (originalLength === locatorMap.length) {
|
|
298
|
+
return true
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
await fs.writeFile(locatorMapPath, JSON.stringify(locatorMap, null, 2))
|
|
302
|
+
return true
|
|
303
|
+
} catch (error) {
|
|
304
|
+
console.error('Error removing locator map entries:', error)
|
|
305
|
+
return false
|
|
306
|
+
}
|
|
307
|
+
}
|