create-appraisejs 0.1.6 → 0.1.8-alpha
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 +45 -45
- package/dist/cli.js +4 -4
- package/dist/cli.js.map +1 -1
- package/dist/copy-template.d.ts +2 -1
- package/dist/copy-template.d.ts.map +1 -1
- package/dist/copy-template.js +10 -7
- package/dist/copy-template.js.map +1 -1
- package/dist/copy-template.test.js +19 -0
- package/dist/copy-template.test.js.map +1 -1
- package/package.json +69 -67
- package/templates/default/.vscode/settings.json +5 -0
- package/templates/default/appraisejs.config.json +1 -1
- package/templates/default/components.json +24 -24
- package/templates/default/cucumber.mjs +16 -0
- package/templates/default/eslint.config.mjs +15 -15
- package/templates/default/next.config.ts +13 -7
- package/templates/default/package-lock.json +13732 -14321
- package/templates/default/package.json +11 -9
- package/templates/default/postcss.config.mjs +8 -8
- 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/schema.prisma +554 -554
- 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 +341 -341
- package/templates/default/scripts/sync-appraise-base-template.ts +52 -2
- package/templates/default/scripts/sync-environments.ts +323 -323
- package/templates/default/scripts/sync-locator-groups.ts +413 -413
- package/templates/default/scripts/sync-locators.ts +402 -402
- package/templates/default/scripts/sync-modules.ts +349 -349
- package/templates/default/scripts/sync-tags.ts +292 -292
- package/templates/default/scripts/sync-template-step-groups.ts +399 -399
- package/templates/default/scripts/sync-template-steps.ts +806 -806
- package/templates/default/scripts/sync-test-cases.ts +905 -905
- package/templates/default/scripts/sync-test-suites.ts +411 -411
- 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 +205 -205
- package/templates/default/src/actions/locator/locator-actions.ts +547 -547
- package/templates/default/src/actions/locator-groups/locator-group-actions.ts +344 -344
- package/templates/default/src/actions/modules/module-actions.ts +133 -133
- package/templates/default/src/actions/reports/report-actions.ts +613 -613
- package/templates/default/src/actions/review/review-actions.ts +147 -147
- package/templates/default/src/actions/tags/tag-actions.ts +104 -104
- package/templates/default/src/actions/template-step/template-step-actions.ts +332 -332
- package/templates/default/src/actions/template-step-group/template-step-group-actions.ts +278 -278
- 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 +419 -419
- package/templates/default/src/actions/test-run/test-run-actions.ts +1185 -1185
- package/templates/default/src/actions/test-suite/test-suite-actions.ts +253 -253
- 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 +61 -61
- package/templates/default/src/app/(base)/locators/create/page.tsx +38 -38
- package/templates/default/src/app/(base)/locators/locator-form.tsx +163 -163
- package/templates/default/src/app/(base)/locators/locator-table-columns.tsx +73 -90
- package/templates/default/src/app/(base)/locators/locator-table.tsx +28 -28
- package/templates/default/src/app/(base)/locators/modify/[id]/page.tsx +45 -45
- package/templates/default/src/app/(base)/locators/page.tsx +65 -65
- 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 +517 -517
- 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 +46 -46
- package/templates/default/src/app/(base)/reports/page.tsx +98 -98
- package/templates/default/src/app/(base)/reports/report-metric-card.tsx +16 -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 +131 -131
- package/templates/default/src/app/(base)/reports/report-view-table.tsx +82 -82
- package/templates/default/src/app/(base)/reports/test-cases/page.tsx +42 -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 +60 -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)/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 +59 -59
- 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 +60 -60
- 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 +90 -90
- package/templates/default/src/app/(base)/test-cases/test-case-table.tsx +35 -35
- package/templates/default/src/app/(base)/test-runs/[id]/page.tsx +56 -56
- package/templates/default/src/app/(base)/test-runs/create/page.tsx +47 -47
- package/templates/default/src/app/(base)/test-runs/page.tsx +60 -60
- package/templates/default/src/app/(base)/test-runs/test-run-form.tsx +508 -512
- 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 +45 -45
- package/templates/default/src/app/(base)/test-suites/modify/[id]/page.tsx +55 -55
- package/templates/default/src/app/(base)/test-suites/page.tsx +82 -82
- package/templates/default/src/app/(base)/test-suites/test-suite-form.tsx +269 -269
- package/templates/default/src/app/(base)/test-suites/test-suite-table-columns.tsx +97 -97
- 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/test-runs/[runId]/download/route.ts +133 -133
- package/templates/default/src/app/api/test-runs/[runId]/logs/route.ts +420 -420
- package/templates/default/src/app/api/test-runs/[runId]/trace/[testCaseId]/route.ts +146 -146
- package/templates/default/src/app/globals.css +147 -147
- package/templates/default/src/app/layout.tsx +171 -171
- package/templates/default/src/app/page.tsx +64 -64
- 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/devtools/providers.tsx +19 -13
- package/templates/default/src/components/diagram/button-edge.tsx +54 -54
- package/templates/default/src/components/diagram/dynamic-parameters.tsx +438 -438
- 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 +508 -508
- 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 +253 -253
- package/templates/default/src/components/table/table-actions.tsx +172 -172
- package/templates/default/src/components/test-run/download-logs-button.tsx +99 -99
- package/templates/default/src/components/test-run/log-viewer.tsx +445 -445
- package/templates/default/src/components/test-run/test-run-details.tsx +611 -611
- 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/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 +267 -267
- 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 -144
- 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 +31 -31
- 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/bidirectional-sync.ts +432 -432
- package/templates/default/src/lib/database-sync.ts +531 -531
- package/templates/default/src/lib/environment-file-utils.ts +221 -221
- package/templates/default/src/lib/feature-file-generator.ts +411 -411
- package/templates/default/src/lib/gherkin-parser.ts +259 -259
- package/templates/default/src/lib/locator-group-file-utils.ts +370 -370
- package/templates/default/src/lib/metrics/metric-calculator.ts +613 -613
- 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/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/process-manager.ts +191 -191
- package/templates/default/src/lib/test-run/report-parser.ts +316 -316
- package/templates/default/src/lib/test-run/test-run-executor.ts +144 -144
- package/templates/default/src/lib/test-run/winston-logger.ts +95 -95
- 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 +167 -167
- package/templates/default/src/lib/utils/template-step-file-manager-intelligent.ts +723 -723
- 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/tests/config/executor/world.ts +41 -41
- package/templates/default/src/tests/executor.ts +80 -80
- package/templates/default/src/tests/hooks/hooks.ts +99 -99
- package/templates/default/src/tests/mapping/locator-map.json +1 -1
- package/templates/default/src/tests/steps/actions/click.step.ts +62 -62
- package/templates/default/src/tests/steps/actions/navigation.step.ts +73 -72
- package/templates/default/src/tests/steps/validations/active_state_assertion.step.ts +34 -34
- package/templates/default/src/tests/steps/validations/navigation_assertion.step.ts +24 -23
- package/templates/default/src/tests/steps/validations/text_assertion.step.ts +111 -111
- package/templates/default/src/tests/steps/validations/visibility_assertion.step.ts +30 -30
- package/templates/default/src/tests/support/parameter-types.ts +12 -12
- package/templates/default/src/tests/utils/cache.util.ts +260 -260
- package/templates/default/src/tests/utils/cli.util.ts +177 -177
- package/templates/default/src/tests/utils/environment.util.ts +65 -65
- package/templates/default/src/tests/utils/locator.util.ts +248 -248
- package/templates/default/src/tests/utils/random-data.util.ts +44 -44
- package/templates/default/src/tests/utils/spawner.util.ts +617 -617
- 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/step/step.type.ts +1 -1
- package/templates/default/src/types/table/data-table.ts +6 -6
- package/templates/default/tailwind.config.ts +62 -62
- package/templates/default/.env +0 -2
- package/templates/default/next-env.d.ts +0 -6
- package/templates/default/prisma/prisma/dev.db +0 -0
- package/templates/default/src/tests/config/environments/environments.json +0 -14
|
@@ -1,370 +1,370 @@
|
|
|
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
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Gets the file path for a locator group based on its module hierarchy
|
|
8
|
-
*/
|
|
9
|
-
export async function getLocatorGroupFilePath(locatorGroupId: string): Promise<string | null> {
|
|
10
|
-
try {
|
|
11
|
-
const locatorGroup = await prisma.locatorGroup.findUnique({
|
|
12
|
-
where: { id: locatorGroupId },
|
|
13
|
-
include: { module: true },
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
if (!locatorGroup) return null
|
|
17
|
-
|
|
18
|
-
const allModules = await prisma.module.findMany()
|
|
19
|
-
const modulePath = buildModulePath(allModules, locatorGroup.module)
|
|
20
|
-
|
|
21
|
-
const sanitizedPath = modulePath.replace(/^\//, '').replace(/\//g, path.sep)
|
|
22
|
-
const fileName = `${locatorGroup.name}.json`
|
|
23
|
-
|
|
24
|
-
return path.join('src', 'tests', 'locators', sanitizedPath, fileName)
|
|
25
|
-
} catch (error) {
|
|
26
|
-
console.error('Error getting locator group file path:', error)
|
|
27
|
-
return null
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Generates JSON content for a locator group from its locators
|
|
33
|
-
*/
|
|
34
|
-
export async function generateLocatorGroupContent(locatorGroupId: string): Promise<Record<string, string>> {
|
|
35
|
-
try {
|
|
36
|
-
const locatorGroup = await prisma.locatorGroup.findUnique({
|
|
37
|
-
where: { id: locatorGroupId },
|
|
38
|
-
include: {
|
|
39
|
-
locators: {
|
|
40
|
-
select: { name: true, value: true },
|
|
41
|
-
},
|
|
42
|
-
},
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
if (!locatorGroup) return {}
|
|
46
|
-
|
|
47
|
-
return Object.fromEntries(locatorGroup.locators.map(locator => [locator.name, locator.value]))
|
|
48
|
-
} catch (error) {
|
|
49
|
-
console.error('Error generating locator group content:', error)
|
|
50
|
-
return {}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Ensures a directory exists, creating it if necessary
|
|
56
|
-
*/
|
|
57
|
-
export async function ensureDirectoryExists(filePath: string): Promise<void> {
|
|
58
|
-
const dir = path.dirname(filePath)
|
|
59
|
-
try {
|
|
60
|
-
await fs.access(dir)
|
|
61
|
-
} catch {
|
|
62
|
-
await fs.mkdir(dir, { recursive: true })
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Creates or updates a locator group JSON file
|
|
68
|
-
*/
|
|
69
|
-
export async function createOrUpdateLocatorGroupFile(locatorGroupId: string): Promise<boolean> {
|
|
70
|
-
try {
|
|
71
|
-
const filePath = await getLocatorGroupFilePath(locatorGroupId)
|
|
72
|
-
if (!filePath) return false
|
|
73
|
-
|
|
74
|
-
await ensureDirectoryExists(filePath)
|
|
75
|
-
const content = await generateLocatorGroupContent(locatorGroupId)
|
|
76
|
-
|
|
77
|
-
await fs.writeFile(filePath, JSON.stringify(content, null, 2))
|
|
78
|
-
return true
|
|
79
|
-
} catch (error) {
|
|
80
|
-
console.error('Error creating/updating locator group file:', error)
|
|
81
|
-
return false
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Deletes a locator group JSON file and cleans up empty directories
|
|
87
|
-
*/
|
|
88
|
-
export async function deleteLocatorGroupFile(locatorGroupId: string): Promise<boolean> {
|
|
89
|
-
try {
|
|
90
|
-
const filePath = await getLocatorGroupFilePath(locatorGroupId)
|
|
91
|
-
if (!filePath) return false
|
|
92
|
-
|
|
93
|
-
// Check if file exists before trying to delete
|
|
94
|
-
try {
|
|
95
|
-
await fs.access(filePath)
|
|
96
|
-
} catch {
|
|
97
|
-
return true // File doesn't exist, nothing to delete
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
await fs.unlink(filePath)
|
|
101
|
-
await cleanupEmptyDirectories(filePath)
|
|
102
|
-
return true
|
|
103
|
-
} catch (error) {
|
|
104
|
-
console.error('Error deleting locator group file:', error)
|
|
105
|
-
return false
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Renames a locator group file when the name changes
|
|
111
|
-
*/
|
|
112
|
-
export async function renameLocatorGroupFile(
|
|
113
|
-
oldLocatorGroupId: string,
|
|
114
|
-
newName: string,
|
|
115
|
-
oldName?: string,
|
|
116
|
-
): Promise<boolean> {
|
|
117
|
-
try {
|
|
118
|
-
// Get the current file path (with new name) for the directory
|
|
119
|
-
const currentFilePath = await getLocatorGroupFilePath(oldLocatorGroupId)
|
|
120
|
-
if (!currentFilePath) return false
|
|
121
|
-
|
|
122
|
-
// If oldName is provided, construct the old file path manually
|
|
123
|
-
// Otherwise, try to get it from the current path (fallback)
|
|
124
|
-
let oldFilePath: string
|
|
125
|
-
if (oldName) {
|
|
126
|
-
oldFilePath = path.join(path.dirname(currentFilePath), `${oldName}.json`)
|
|
127
|
-
} else {
|
|
128
|
-
oldFilePath = currentFilePath
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const newFilePath = path.join(path.dirname(currentFilePath), `${newName}.json`)
|
|
132
|
-
|
|
133
|
-
try {
|
|
134
|
-
await fs.access(oldFilePath)
|
|
135
|
-
console.log('oldFilePath exists:', oldFilePath)
|
|
136
|
-
await fs.rename(oldFilePath, newFilePath)
|
|
137
|
-
console.log('File renamed successfully from', oldFilePath, 'to', newFilePath)
|
|
138
|
-
} catch (error) {
|
|
139
|
-
console.log('File not found at old path, creating new one:', error)
|
|
140
|
-
// File doesn't exist, create new one
|
|
141
|
-
return await createOrUpdateLocatorGroupFile(oldLocatorGroupId)
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
return true
|
|
145
|
-
} catch (error) {
|
|
146
|
-
console.error('Error renaming locator group file:', error)
|
|
147
|
-
return false
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Moves a locator group file when the module changes
|
|
153
|
-
*/
|
|
154
|
-
export async function moveLocatorGroupFile(locatorGroupId: string): Promise<boolean> {
|
|
155
|
-
try {
|
|
156
|
-
// Delete old file and create new one in correct location
|
|
157
|
-
await deleteLocatorGroupFile(locatorGroupId)
|
|
158
|
-
return await createOrUpdateLocatorGroupFile(locatorGroupId)
|
|
159
|
-
} catch (error) {
|
|
160
|
-
console.error('Error moving locator group file:', error)
|
|
161
|
-
return false
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Cleans up empty directories recursively
|
|
167
|
-
*/
|
|
168
|
-
async function cleanupEmptyDirectories(filePath: string): Promise<void> {
|
|
169
|
-
let currentDir = path.dirname(filePath)
|
|
170
|
-
|
|
171
|
-
while (currentDir !== 'tests' && currentDir !== '.') {
|
|
172
|
-
try {
|
|
173
|
-
const files = await fs.readdir(currentDir)
|
|
174
|
-
if (files.length === 0) {
|
|
175
|
-
await fs.rmdir(currentDir)
|
|
176
|
-
currentDir = path.dirname(currentDir)
|
|
177
|
-
} else {
|
|
178
|
-
break
|
|
179
|
-
}
|
|
180
|
-
} catch {
|
|
181
|
-
break
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Creates an empty JSON file for a new locator group
|
|
188
|
-
*/
|
|
189
|
-
export async function createEmptyLocatorGroupFile(locatorGroupId: string): Promise<boolean> {
|
|
190
|
-
try {
|
|
191
|
-
const filePath = await getLocatorGroupFilePath(locatorGroupId)
|
|
192
|
-
if (!filePath) return false
|
|
193
|
-
|
|
194
|
-
await ensureDirectoryExists(filePath)
|
|
195
|
-
await fs.writeFile(filePath, JSON.stringify({}, null, 2))
|
|
196
|
-
return true
|
|
197
|
-
} catch (error) {
|
|
198
|
-
console.error('Error creating empty locator group file:', error)
|
|
199
|
-
return false
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Reads and parses the content of a locator group file
|
|
205
|
-
*/
|
|
206
|
-
export async function readLocatorGroupFile(
|
|
207
|
-
locatorGroupId: string,
|
|
208
|
-
): Promise<{ filePath: string; content: Record<string, string> } | null> {
|
|
209
|
-
try {
|
|
210
|
-
const filePath = await getLocatorGroupFilePath(locatorGroupId)
|
|
211
|
-
if (!filePath) return null
|
|
212
|
-
|
|
213
|
-
const fileContent = await fs.readFile(filePath, 'utf-8')
|
|
214
|
-
const jsonContent = JSON.parse(fileContent)
|
|
215
|
-
|
|
216
|
-
return { filePath, content: jsonContent }
|
|
217
|
-
} catch (error) {
|
|
218
|
-
console.error('Error reading locator group file:', error)
|
|
219
|
-
return null
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
/**
|
|
224
|
-
* Updates the locator map file with locator group information
|
|
225
|
-
* Overload for updating existing entries (4 parameters)
|
|
226
|
-
*/
|
|
227
|
-
export async function updateLocatorMapFile(
|
|
228
|
-
currentLocatorGroupRoute: string,
|
|
229
|
-
newLocatorGroupRoute: string,
|
|
230
|
-
currentLocatorGroupName: string,
|
|
231
|
-
newLocatorGroupName: string,
|
|
232
|
-
): Promise<boolean>
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Updates the locator map file with locator group information
|
|
236
|
-
* Overload for adding new entries (2 parameters)
|
|
237
|
-
*/
|
|
238
|
-
export async function updateLocatorMapFile(newLocatorGroupName: string, newLocatorGroupRoute: string): Promise<boolean>
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* Implementation of updateLocatorMapFile with proper overload handling
|
|
242
|
-
*/
|
|
243
|
-
export async function updateLocatorMapFile(
|
|
244
|
-
param1: string,
|
|
245
|
-
param2: string,
|
|
246
|
-
param3?: string,
|
|
247
|
-
param4?: string,
|
|
248
|
-
): Promise<boolean> {
|
|
249
|
-
try {
|
|
250
|
-
const locatorMapPath = path.join('src', 'tests', 'mapping', 'locator-map.json')
|
|
251
|
-
|
|
252
|
-
// Ensure the mapping directory exists
|
|
253
|
-
await ensureDirectoryExists(locatorMapPath)
|
|
254
|
-
|
|
255
|
-
let locatorMap: Array<{ name: string; path: string }> = []
|
|
256
|
-
|
|
257
|
-
// Read existing locator map or create empty array
|
|
258
|
-
try {
|
|
259
|
-
const fileContent = await fs.readFile(locatorMapPath, 'utf-8')
|
|
260
|
-
locatorMap = JSON.parse(fileContent)
|
|
261
|
-
} catch {
|
|
262
|
-
// File doesn't exist, start with empty array
|
|
263
|
-
locatorMap = []
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// Determine if this is a 2-param call (new entry) or 4-param call (update)
|
|
267
|
-
const isNewEntry = param3 === undefined && param4 === undefined
|
|
268
|
-
|
|
269
|
-
if (isNewEntry) {
|
|
270
|
-
// 2 params: newLocatorGroupName, newLocatorGroupRoute
|
|
271
|
-
const name = param1
|
|
272
|
-
const route = param2
|
|
273
|
-
|
|
274
|
-
// Check for uniqueness
|
|
275
|
-
const existingEntry = locatorMap.find(entry => entry.name === name)
|
|
276
|
-
if (existingEntry) {
|
|
277
|
-
console.error(`Locator group with name "${name}" already exists in locator map`)
|
|
278
|
-
return false
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
// Add new entry
|
|
282
|
-
locatorMap.push({ name, path: route })
|
|
283
|
-
} else {
|
|
284
|
-
// 4 params: update existing entry
|
|
285
|
-
const currentLocatorGroupRoute = param1
|
|
286
|
-
const newLocatorGroupRoute = param2
|
|
287
|
-
const currentLocatorGroupName = param3!
|
|
288
|
-
const newLocatorGroupName = param4!
|
|
289
|
-
|
|
290
|
-
// Find the entry to update
|
|
291
|
-
const entryIndex = locatorMap.findIndex(entry => entry.name === currentLocatorGroupName)
|
|
292
|
-
if (entryIndex === -1) {
|
|
293
|
-
console.error(`Locator group with name "${currentLocatorGroupName}" not found in locator map`)
|
|
294
|
-
return false
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// Check if new name is unique (if name is changing)
|
|
298
|
-
if (currentLocatorGroupName !== newLocatorGroupName) {
|
|
299
|
-
const existingEntry = locatorMap.find(entry => entry.name === newLocatorGroupName)
|
|
300
|
-
if (existingEntry) {
|
|
301
|
-
console.error(`Locator group with name "${newLocatorGroupName}" already exists in locator map`)
|
|
302
|
-
return false
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
// Update the entry
|
|
307
|
-
const updatedEntry = { ...locatorMap[entryIndex] }
|
|
308
|
-
|
|
309
|
-
// Update name if it changed
|
|
310
|
-
if (currentLocatorGroupName !== newLocatorGroupName) {
|
|
311
|
-
updatedEntry.name = newLocatorGroupName
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
// Update path if it changed
|
|
315
|
-
if (currentLocatorGroupRoute !== newLocatorGroupRoute) {
|
|
316
|
-
updatedEntry.path = newLocatorGroupRoute
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
locatorMap[entryIndex] = updatedEntry
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
// Write the updated locator map back to file
|
|
323
|
-
await fs.writeFile(locatorMapPath, JSON.stringify(locatorMap, null, 2))
|
|
324
|
-
return true
|
|
325
|
-
} catch (error) {
|
|
326
|
-
console.error('Error updating locator map file:', error)
|
|
327
|
-
return false
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
/**
|
|
332
|
-
* Removes locator group entries from the locator map file
|
|
333
|
-
* @param locatorGroupNames - Array of locator group names to remove
|
|
334
|
-
*/
|
|
335
|
-
export async function removeLocatorMapEntry(locatorGroupNames: string[]): Promise<boolean> {
|
|
336
|
-
try {
|
|
337
|
-
const locatorMapPath = path.join('src', 'tests', 'mapping', 'locator-map.json')
|
|
338
|
-
|
|
339
|
-
// Check if file exists
|
|
340
|
-
try {
|
|
341
|
-
await fs.access(locatorMapPath)
|
|
342
|
-
} catch {
|
|
343
|
-
// File doesn't exist, nothing to remove
|
|
344
|
-
return true
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
// Read existing locator map
|
|
348
|
-
const fileContent = await fs.readFile(locatorMapPath, 'utf-8')
|
|
349
|
-
let locatorMap: Array<{ name: string; path: string }> = JSON.parse(fileContent)
|
|
350
|
-
|
|
351
|
-
// Filter out the entries to be removed
|
|
352
|
-
const originalLength = locatorMap.length
|
|
353
|
-
locatorMap = locatorMap.filter(entry => !locatorGroupNames.includes(entry.name))
|
|
354
|
-
|
|
355
|
-
// Check if any entries were actually removed
|
|
356
|
-
const removedCount = originalLength - locatorMap.length
|
|
357
|
-
if (removedCount === 0) {
|
|
358
|
-
console.log('No matching locator group entries found in locator map')
|
|
359
|
-
return true
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
// Write the updated locator map back to file
|
|
363
|
-
await fs.writeFile(locatorMapPath, JSON.stringify(locatorMap, null, 2))
|
|
364
|
-
console.log(`Removed ${removedCount} locator group entry(ies) from locator map`)
|
|
365
|
-
return true
|
|
366
|
-
} catch (error) {
|
|
367
|
-
console.error('Error removing locator map entries:', error)
|
|
368
|
-
return false
|
|
369
|
-
}
|
|
370
|
-
}
|
|
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
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Gets the file path for a locator group based on its module hierarchy
|
|
8
|
+
*/
|
|
9
|
+
export async function getLocatorGroupFilePath(locatorGroupId: string): Promise<string | null> {
|
|
10
|
+
try {
|
|
11
|
+
const locatorGroup = await prisma.locatorGroup.findUnique({
|
|
12
|
+
where: { id: locatorGroupId },
|
|
13
|
+
include: { module: true },
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
if (!locatorGroup) return null
|
|
17
|
+
|
|
18
|
+
const allModules = await prisma.module.findMany()
|
|
19
|
+
const modulePath = buildModulePath(allModules, locatorGroup.module)
|
|
20
|
+
|
|
21
|
+
const sanitizedPath = modulePath.replace(/^\//, '').replace(/\//g, path.sep)
|
|
22
|
+
const fileName = `${locatorGroup.name}.json`
|
|
23
|
+
|
|
24
|
+
return path.join('src', 'tests', 'locators', sanitizedPath, fileName)
|
|
25
|
+
} catch (error) {
|
|
26
|
+
console.error('Error getting locator group file path:', error)
|
|
27
|
+
return null
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Generates JSON content for a locator group from its locators
|
|
33
|
+
*/
|
|
34
|
+
export async function generateLocatorGroupContent(locatorGroupId: string): Promise<Record<string, string>> {
|
|
35
|
+
try {
|
|
36
|
+
const locatorGroup = await prisma.locatorGroup.findUnique({
|
|
37
|
+
where: { id: locatorGroupId },
|
|
38
|
+
include: {
|
|
39
|
+
locators: {
|
|
40
|
+
select: { name: true, value: true },
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
if (!locatorGroup) return {}
|
|
46
|
+
|
|
47
|
+
return Object.fromEntries(locatorGroup.locators.map(locator => [locator.name, locator.value]))
|
|
48
|
+
} catch (error) {
|
|
49
|
+
console.error('Error generating locator group content:', error)
|
|
50
|
+
return {}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Ensures a directory exists, creating it if necessary
|
|
56
|
+
*/
|
|
57
|
+
export async function ensureDirectoryExists(filePath: string): Promise<void> {
|
|
58
|
+
const dir = path.dirname(filePath)
|
|
59
|
+
try {
|
|
60
|
+
await fs.access(dir)
|
|
61
|
+
} catch {
|
|
62
|
+
await fs.mkdir(dir, { recursive: true })
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Creates or updates a locator group JSON file
|
|
68
|
+
*/
|
|
69
|
+
export async function createOrUpdateLocatorGroupFile(locatorGroupId: string): Promise<boolean> {
|
|
70
|
+
try {
|
|
71
|
+
const filePath = await getLocatorGroupFilePath(locatorGroupId)
|
|
72
|
+
if (!filePath) return false
|
|
73
|
+
|
|
74
|
+
await ensureDirectoryExists(filePath)
|
|
75
|
+
const content = await generateLocatorGroupContent(locatorGroupId)
|
|
76
|
+
|
|
77
|
+
await fs.writeFile(filePath, JSON.stringify(content, null, 2))
|
|
78
|
+
return true
|
|
79
|
+
} catch (error) {
|
|
80
|
+
console.error('Error creating/updating locator group file:', error)
|
|
81
|
+
return false
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Deletes a locator group JSON file and cleans up empty directories
|
|
87
|
+
*/
|
|
88
|
+
export async function deleteLocatorGroupFile(locatorGroupId: string): Promise<boolean> {
|
|
89
|
+
try {
|
|
90
|
+
const filePath = await getLocatorGroupFilePath(locatorGroupId)
|
|
91
|
+
if (!filePath) return false
|
|
92
|
+
|
|
93
|
+
// Check if file exists before trying to delete
|
|
94
|
+
try {
|
|
95
|
+
await fs.access(filePath)
|
|
96
|
+
} catch {
|
|
97
|
+
return true // File doesn't exist, nothing to delete
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
await fs.unlink(filePath)
|
|
101
|
+
await cleanupEmptyDirectories(filePath)
|
|
102
|
+
return true
|
|
103
|
+
} catch (error) {
|
|
104
|
+
console.error('Error deleting locator group file:', error)
|
|
105
|
+
return false
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Renames a locator group file when the name changes
|
|
111
|
+
*/
|
|
112
|
+
export async function renameLocatorGroupFile(
|
|
113
|
+
oldLocatorGroupId: string,
|
|
114
|
+
newName: string,
|
|
115
|
+
oldName?: string,
|
|
116
|
+
): Promise<boolean> {
|
|
117
|
+
try {
|
|
118
|
+
// Get the current file path (with new name) for the directory
|
|
119
|
+
const currentFilePath = await getLocatorGroupFilePath(oldLocatorGroupId)
|
|
120
|
+
if (!currentFilePath) return false
|
|
121
|
+
|
|
122
|
+
// If oldName is provided, construct the old file path manually
|
|
123
|
+
// Otherwise, try to get it from the current path (fallback)
|
|
124
|
+
let oldFilePath: string
|
|
125
|
+
if (oldName) {
|
|
126
|
+
oldFilePath = path.join(path.dirname(currentFilePath), `${oldName}.json`)
|
|
127
|
+
} else {
|
|
128
|
+
oldFilePath = currentFilePath
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const newFilePath = path.join(path.dirname(currentFilePath), `${newName}.json`)
|
|
132
|
+
|
|
133
|
+
try {
|
|
134
|
+
await fs.access(oldFilePath)
|
|
135
|
+
console.log('oldFilePath exists:', oldFilePath)
|
|
136
|
+
await fs.rename(oldFilePath, newFilePath)
|
|
137
|
+
console.log('File renamed successfully from', oldFilePath, 'to', newFilePath)
|
|
138
|
+
} catch (error) {
|
|
139
|
+
console.log('File not found at old path, creating new one:', error)
|
|
140
|
+
// File doesn't exist, create new one
|
|
141
|
+
return await createOrUpdateLocatorGroupFile(oldLocatorGroupId)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return true
|
|
145
|
+
} catch (error) {
|
|
146
|
+
console.error('Error renaming locator group file:', error)
|
|
147
|
+
return false
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Moves a locator group file when the module changes
|
|
153
|
+
*/
|
|
154
|
+
export async function moveLocatorGroupFile(locatorGroupId: string): Promise<boolean> {
|
|
155
|
+
try {
|
|
156
|
+
// Delete old file and create new one in correct location
|
|
157
|
+
await deleteLocatorGroupFile(locatorGroupId)
|
|
158
|
+
return await createOrUpdateLocatorGroupFile(locatorGroupId)
|
|
159
|
+
} catch (error) {
|
|
160
|
+
console.error('Error moving locator group file:', error)
|
|
161
|
+
return false
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Cleans up empty directories recursively
|
|
167
|
+
*/
|
|
168
|
+
async function cleanupEmptyDirectories(filePath: string): Promise<void> {
|
|
169
|
+
let currentDir = path.dirname(filePath)
|
|
170
|
+
|
|
171
|
+
while (currentDir !== 'tests' && currentDir !== '.') {
|
|
172
|
+
try {
|
|
173
|
+
const files = await fs.readdir(currentDir)
|
|
174
|
+
if (files.length === 0) {
|
|
175
|
+
await fs.rmdir(currentDir)
|
|
176
|
+
currentDir = path.dirname(currentDir)
|
|
177
|
+
} else {
|
|
178
|
+
break
|
|
179
|
+
}
|
|
180
|
+
} catch {
|
|
181
|
+
break
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Creates an empty JSON file for a new locator group
|
|
188
|
+
*/
|
|
189
|
+
export async function createEmptyLocatorGroupFile(locatorGroupId: string): Promise<boolean> {
|
|
190
|
+
try {
|
|
191
|
+
const filePath = await getLocatorGroupFilePath(locatorGroupId)
|
|
192
|
+
if (!filePath) return false
|
|
193
|
+
|
|
194
|
+
await ensureDirectoryExists(filePath)
|
|
195
|
+
await fs.writeFile(filePath, JSON.stringify({}, null, 2))
|
|
196
|
+
return true
|
|
197
|
+
} catch (error) {
|
|
198
|
+
console.error('Error creating empty locator group file:', error)
|
|
199
|
+
return false
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Reads and parses the content of a locator group file
|
|
205
|
+
*/
|
|
206
|
+
export async function readLocatorGroupFile(
|
|
207
|
+
locatorGroupId: string,
|
|
208
|
+
): Promise<{ filePath: string; content: Record<string, string> } | null> {
|
|
209
|
+
try {
|
|
210
|
+
const filePath = await getLocatorGroupFilePath(locatorGroupId)
|
|
211
|
+
if (!filePath) return null
|
|
212
|
+
|
|
213
|
+
const fileContent = await fs.readFile(filePath, 'utf-8')
|
|
214
|
+
const jsonContent = JSON.parse(fileContent)
|
|
215
|
+
|
|
216
|
+
return { filePath, content: jsonContent }
|
|
217
|
+
} catch (error) {
|
|
218
|
+
console.error('Error reading locator group file:', error)
|
|
219
|
+
return null
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Updates the locator map file with locator group information
|
|
225
|
+
* Overload for updating existing entries (4 parameters)
|
|
226
|
+
*/
|
|
227
|
+
export async function updateLocatorMapFile(
|
|
228
|
+
currentLocatorGroupRoute: string,
|
|
229
|
+
newLocatorGroupRoute: string,
|
|
230
|
+
currentLocatorGroupName: string,
|
|
231
|
+
newLocatorGroupName: string,
|
|
232
|
+
): Promise<boolean>
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Updates the locator map file with locator group information
|
|
236
|
+
* Overload for adding new entries (2 parameters)
|
|
237
|
+
*/
|
|
238
|
+
export async function updateLocatorMapFile(newLocatorGroupName: string, newLocatorGroupRoute: string): Promise<boolean>
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Implementation of updateLocatorMapFile with proper overload handling
|
|
242
|
+
*/
|
|
243
|
+
export async function updateLocatorMapFile(
|
|
244
|
+
param1: string,
|
|
245
|
+
param2: string,
|
|
246
|
+
param3?: string,
|
|
247
|
+
param4?: string,
|
|
248
|
+
): Promise<boolean> {
|
|
249
|
+
try {
|
|
250
|
+
const locatorMapPath = path.join('src', 'tests', 'mapping', 'locator-map.json')
|
|
251
|
+
|
|
252
|
+
// Ensure the mapping directory exists
|
|
253
|
+
await ensureDirectoryExists(locatorMapPath)
|
|
254
|
+
|
|
255
|
+
let locatorMap: Array<{ name: string; path: string }> = []
|
|
256
|
+
|
|
257
|
+
// Read existing locator map or create empty array
|
|
258
|
+
try {
|
|
259
|
+
const fileContent = await fs.readFile(locatorMapPath, 'utf-8')
|
|
260
|
+
locatorMap = JSON.parse(fileContent)
|
|
261
|
+
} catch {
|
|
262
|
+
// File doesn't exist, start with empty array
|
|
263
|
+
locatorMap = []
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Determine if this is a 2-param call (new entry) or 4-param call (update)
|
|
267
|
+
const isNewEntry = param3 === undefined && param4 === undefined
|
|
268
|
+
|
|
269
|
+
if (isNewEntry) {
|
|
270
|
+
// 2 params: newLocatorGroupName, newLocatorGroupRoute
|
|
271
|
+
const name = param1
|
|
272
|
+
const route = param2
|
|
273
|
+
|
|
274
|
+
// Check for uniqueness
|
|
275
|
+
const existingEntry = locatorMap.find(entry => entry.name === name)
|
|
276
|
+
if (existingEntry) {
|
|
277
|
+
console.error(`Locator group with name "${name}" already exists in locator map`)
|
|
278
|
+
return false
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Add new entry
|
|
282
|
+
locatorMap.push({ name, path: route })
|
|
283
|
+
} else {
|
|
284
|
+
// 4 params: update existing entry
|
|
285
|
+
const currentLocatorGroupRoute = param1
|
|
286
|
+
const newLocatorGroupRoute = param2
|
|
287
|
+
const currentLocatorGroupName = param3!
|
|
288
|
+
const newLocatorGroupName = param4!
|
|
289
|
+
|
|
290
|
+
// Find the entry to update
|
|
291
|
+
const entryIndex = locatorMap.findIndex(entry => entry.name === currentLocatorGroupName)
|
|
292
|
+
if (entryIndex === -1) {
|
|
293
|
+
console.error(`Locator group with name "${currentLocatorGroupName}" not found in locator map`)
|
|
294
|
+
return false
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Check if new name is unique (if name is changing)
|
|
298
|
+
if (currentLocatorGroupName !== newLocatorGroupName) {
|
|
299
|
+
const existingEntry = locatorMap.find(entry => entry.name === newLocatorGroupName)
|
|
300
|
+
if (existingEntry) {
|
|
301
|
+
console.error(`Locator group with name "${newLocatorGroupName}" already exists in locator map`)
|
|
302
|
+
return false
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Update the entry
|
|
307
|
+
const updatedEntry = { ...locatorMap[entryIndex] }
|
|
308
|
+
|
|
309
|
+
// Update name if it changed
|
|
310
|
+
if (currentLocatorGroupName !== newLocatorGroupName) {
|
|
311
|
+
updatedEntry.name = newLocatorGroupName
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Update path if it changed
|
|
315
|
+
if (currentLocatorGroupRoute !== newLocatorGroupRoute) {
|
|
316
|
+
updatedEntry.path = newLocatorGroupRoute
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
locatorMap[entryIndex] = updatedEntry
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Write the updated locator map back to file
|
|
323
|
+
await fs.writeFile(locatorMapPath, JSON.stringify(locatorMap, null, 2))
|
|
324
|
+
return true
|
|
325
|
+
} catch (error) {
|
|
326
|
+
console.error('Error updating locator map file:', error)
|
|
327
|
+
return false
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Removes locator group entries from the locator map file
|
|
333
|
+
* @param locatorGroupNames - Array of locator group names to remove
|
|
334
|
+
*/
|
|
335
|
+
export async function removeLocatorMapEntry(locatorGroupNames: string[]): Promise<boolean> {
|
|
336
|
+
try {
|
|
337
|
+
const locatorMapPath = path.join('src', 'tests', 'mapping', 'locator-map.json')
|
|
338
|
+
|
|
339
|
+
// Check if file exists
|
|
340
|
+
try {
|
|
341
|
+
await fs.access(locatorMapPath)
|
|
342
|
+
} catch {
|
|
343
|
+
// File doesn't exist, nothing to remove
|
|
344
|
+
return true
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Read existing locator map
|
|
348
|
+
const fileContent = await fs.readFile(locatorMapPath, 'utf-8')
|
|
349
|
+
let locatorMap: Array<{ name: string; path: string }> = JSON.parse(fileContent)
|
|
350
|
+
|
|
351
|
+
// Filter out the entries to be removed
|
|
352
|
+
const originalLength = locatorMap.length
|
|
353
|
+
locatorMap = locatorMap.filter(entry => !locatorGroupNames.includes(entry.name))
|
|
354
|
+
|
|
355
|
+
// Check if any entries were actually removed
|
|
356
|
+
const removedCount = originalLength - locatorMap.length
|
|
357
|
+
if (removedCount === 0) {
|
|
358
|
+
console.log('No matching locator group entries found in locator map')
|
|
359
|
+
return true
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Write the updated locator map back to file
|
|
363
|
+
await fs.writeFile(locatorMapPath, JSON.stringify(locatorMap, null, 2))
|
|
364
|
+
console.log(`Removed ${removedCount} locator group entry(ies) from locator map`)
|
|
365
|
+
return true
|
|
366
|
+
} catch (error) {
|
|
367
|
+
console.error('Error removing locator map entries:', error)
|
|
368
|
+
return false
|
|
369
|
+
}
|
|
370
|
+
}
|