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,259 +1,259 @@
|
|
|
1
|
-
import { promises as fs } from 'fs'
|
|
2
|
-
import { join, relative } from 'path'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Represents a parsed feature file with its scenarios and steps
|
|
6
|
-
*/
|
|
7
|
-
export interface ParsedFeature {
|
|
8
|
-
filePath: string
|
|
9
|
-
featureName: string
|
|
10
|
-
featureDescription?: string
|
|
11
|
-
tags: string[]
|
|
12
|
-
scenarios: ParsedScenario[]
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Represents a parsed scenario from a feature file
|
|
17
|
-
*/
|
|
18
|
-
export interface ParsedScenario {
|
|
19
|
-
name: string
|
|
20
|
-
description?: string
|
|
21
|
-
tags: string[]
|
|
22
|
-
steps: ParsedStep[]
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Represents a parsed step from a feature file
|
|
27
|
-
*/
|
|
28
|
-
export interface ParsedStep {
|
|
29
|
-
keyword: string
|
|
30
|
-
text: string
|
|
31
|
-
order: number
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Parses a Gherkin feature file and extracts scenarios and steps
|
|
36
|
-
* @param filePath - Path to the feature file
|
|
37
|
-
* @returns Promise<ParsedFeature | null> - Parsed feature data or null if parsing fails
|
|
38
|
-
*/
|
|
39
|
-
export async function parseFeatureFile(filePath: string): Promise<ParsedFeature | null> {
|
|
40
|
-
try {
|
|
41
|
-
const content = await fs.readFile(filePath, 'utf-8')
|
|
42
|
-
|
|
43
|
-
// Simple Gherkin parser implementation
|
|
44
|
-
const lines = content.split('\n').map(line => line.trim())
|
|
45
|
-
const scenarios: ParsedScenario[] = []
|
|
46
|
-
|
|
47
|
-
let featureName = ''
|
|
48
|
-
let featureDescription = ''
|
|
49
|
-
const featureTags: string[] = []
|
|
50
|
-
let currentScenario: ParsedScenario | null = null
|
|
51
|
-
let stepOrder = 1
|
|
52
|
-
|
|
53
|
-
// Find feature line and extract tags before it
|
|
54
|
-
let _featureLineIndex = -1
|
|
55
|
-
for (let i = 0; i < lines.length; i++) {
|
|
56
|
-
if (lines[i].startsWith('Feature:')) {
|
|
57
|
-
_featureLineIndex = i
|
|
58
|
-
// Look backwards for tags (skip comments and empty lines)
|
|
59
|
-
for (let j = i - 1; j >= 0; j--) {
|
|
60
|
-
const prevLine = lines[j]
|
|
61
|
-
if (prevLine === '' || prevLine.startsWith('#')) {
|
|
62
|
-
continue
|
|
63
|
-
}
|
|
64
|
-
if (prevLine.startsWith('@')) {
|
|
65
|
-
featureTags.unshift(prevLine) // Add to beginning to maintain order
|
|
66
|
-
} else {
|
|
67
|
-
break // Stop when we hit a non-tag line
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
break
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
for (let i = 0; i < lines.length; i++) {
|
|
75
|
-
const line = lines[i]
|
|
76
|
-
|
|
77
|
-
// Skip comments and empty lines
|
|
78
|
-
if (line.startsWith('#') || line === '') {
|
|
79
|
-
continue
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Parse Feature line
|
|
83
|
-
if (line.startsWith('Feature:')) {
|
|
84
|
-
featureName = line.replace('Feature:', '').trim()
|
|
85
|
-
// Look for description in next lines
|
|
86
|
-
let j = i + 1
|
|
87
|
-
while (j < lines.length && lines[j] && !lines[j].startsWith('Scenario:') && !lines[j].startsWith('Feature:')) {
|
|
88
|
-
if (lines[j] && !lines[j].startsWith('#')) {
|
|
89
|
-
featureDescription += (featureDescription ? ' ' : '') + lines[j]
|
|
90
|
-
}
|
|
91
|
-
j++
|
|
92
|
-
}
|
|
93
|
-
continue
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Parse Scenario line
|
|
97
|
-
if (line.startsWith('Scenario:')) {
|
|
98
|
-
// Save previous scenario if exists
|
|
99
|
-
if (currentScenario) {
|
|
100
|
-
scenarios.push(currentScenario)
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Extract tags before this scenario
|
|
104
|
-
const scenarioTags: string[] = []
|
|
105
|
-
for (let j = i - 1; j >= 0; j--) {
|
|
106
|
-
const prevLine = lines[j]
|
|
107
|
-
if (prevLine === '' || prevLine.startsWith('#')) {
|
|
108
|
-
continue
|
|
109
|
-
}
|
|
110
|
-
if (prevLine.startsWith('@')) {
|
|
111
|
-
scenarioTags.unshift(prevLine) // Add to beginning to maintain order
|
|
112
|
-
} else {
|
|
113
|
-
break // Stop when we hit a non-tag line
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const scenarioText = line.replace('Scenario:', '').trim()
|
|
118
|
-
const [name, description] =
|
|
119
|
-
scenarioText.split(']').length > 1
|
|
120
|
-
? [scenarioText.split(']')[1].trim(), scenarioText.split(']')[0].replace('[', '').trim()]
|
|
121
|
-
: [scenarioText, '']
|
|
122
|
-
|
|
123
|
-
currentScenario = {
|
|
124
|
-
name: name,
|
|
125
|
-
description: description || undefined,
|
|
126
|
-
tags: scenarioTags,
|
|
127
|
-
steps: [],
|
|
128
|
-
}
|
|
129
|
-
stepOrder = 1
|
|
130
|
-
continue
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Parse steps (Given, When, Then, And, But)
|
|
134
|
-
if (
|
|
135
|
-
currentScenario &&
|
|
136
|
-
(line.startsWith('Given ') ||
|
|
137
|
-
line.startsWith('When ') ||
|
|
138
|
-
line.startsWith('Then ') ||
|
|
139
|
-
line.startsWith('And ') ||
|
|
140
|
-
line.startsWith('But '))
|
|
141
|
-
) {
|
|
142
|
-
const keyword = line.split(' ')[0]
|
|
143
|
-
const text = line.substring(keyword.length).trim()
|
|
144
|
-
|
|
145
|
-
currentScenario.steps.push({
|
|
146
|
-
keyword: keyword,
|
|
147
|
-
text: text,
|
|
148
|
-
order: stepOrder++,
|
|
149
|
-
})
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// Add the last scenario
|
|
154
|
-
if (currentScenario) {
|
|
155
|
-
scenarios.push(currentScenario)
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (!featureName) {
|
|
159
|
-
console.warn(`No feature found in file: ${filePath}`)
|
|
160
|
-
return null
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return {
|
|
164
|
-
filePath,
|
|
165
|
-
featureName,
|
|
166
|
-
featureDescription: featureDescription || undefined,
|
|
167
|
-
tags: featureTags,
|
|
168
|
-
scenarios,
|
|
169
|
-
}
|
|
170
|
-
} catch (error) {
|
|
171
|
-
console.error(`Error parsing feature file ${filePath}:`, error)
|
|
172
|
-
return null
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Scans a directory for feature files and parses them
|
|
178
|
-
* @param directoryPath - Path to scan for feature files
|
|
179
|
-
* @returns Promise<ParsedFeature[]> - Array of parsed feature files
|
|
180
|
-
*/
|
|
181
|
-
export async function scanFeatureFiles(directoryPath: string): Promise<ParsedFeature[]> {
|
|
182
|
-
const parsedFeatures: ParsedFeature[] = []
|
|
183
|
-
|
|
184
|
-
try {
|
|
185
|
-
const entries = await fs.readdir(directoryPath, { withFileTypes: true })
|
|
186
|
-
|
|
187
|
-
for (const entry of entries) {
|
|
188
|
-
const fullPath = join(directoryPath, entry.name)
|
|
189
|
-
|
|
190
|
-
if (entry.isDirectory()) {
|
|
191
|
-
// Recursively scan subdirectories
|
|
192
|
-
const subFeatures = await scanFeatureFiles(fullPath)
|
|
193
|
-
parsedFeatures.push(...subFeatures)
|
|
194
|
-
} else if (entry.isFile() && entry.name.endsWith('.feature')) {
|
|
195
|
-
// Parse feature file
|
|
196
|
-
const parsedFeature = await parseFeatureFile(fullPath)
|
|
197
|
-
if (parsedFeature) {
|
|
198
|
-
parsedFeatures.push(parsedFeature)
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
} catch (error) {
|
|
203
|
-
console.error(`Error scanning directory ${directoryPath}:`, error)
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
return parsedFeatures
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Extracts module path from feature file path
|
|
211
|
-
* Works cross-platform (Windows, Mac, Linux)
|
|
212
|
-
* @param featureFilePath - Full path to the feature file
|
|
213
|
-
* @param featuresBaseDir - Base directory for features
|
|
214
|
-
* @returns string - Module path (e.g., "/module1/submodule")
|
|
215
|
-
*/
|
|
216
|
-
export function extractModulePathFromFilePath(featureFilePath: string, featuresBaseDir: string): string {
|
|
217
|
-
// Use path.relative for cross-platform path handling
|
|
218
|
-
const relativePath = relative(featuresBaseDir, featureFilePath)
|
|
219
|
-
|
|
220
|
-
// Normalize to forward slashes for module path format (database uses /)
|
|
221
|
-
const normalizedPath = relativePath.replace(/\\/g, '/')
|
|
222
|
-
const pathParts = normalizedPath.split('/').filter(part => part && part !== '')
|
|
223
|
-
|
|
224
|
-
// Remove the filename and join the remaining parts
|
|
225
|
-
const moduleParts = pathParts.slice(0, -1)
|
|
226
|
-
return moduleParts.length > 0 ? '/' + moduleParts.join('/') : '/'
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* Generates a safe test suite name from feature name
|
|
231
|
-
* @param featureName - Name of the feature
|
|
232
|
-
* @returns string - Safe test suite name
|
|
233
|
-
*/
|
|
234
|
-
export function generateSafeTestSuiteName(featureName: string): string {
|
|
235
|
-
return featureName
|
|
236
|
-
.toLowerCase()
|
|
237
|
-
.replace(/[^a-z0-9\s]+/g, '')
|
|
238
|
-
.replace(/\s+/g, ' ')
|
|
239
|
-
.trim()
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Generates a safe test case name from scenario name
|
|
244
|
-
* @param scenarioName - Name of the scenario
|
|
245
|
-
* @returns string - Safe test case name
|
|
246
|
-
*/
|
|
247
|
-
export function generateSafeTestCaseName(scenarioName: string): string {
|
|
248
|
-
// Remove scenario prefix if present and clean up the name
|
|
249
|
-
const cleanName = scenarioName
|
|
250
|
-
.replace(/^Scenario:\s*/i, '')
|
|
251
|
-
.replace(/^\[.*?\]\s*/, '') // Remove [brackets] prefix
|
|
252
|
-
.trim()
|
|
253
|
-
|
|
254
|
-
return cleanName
|
|
255
|
-
.toLowerCase()
|
|
256
|
-
.replace(/[^a-z0-9\s]+/g, '')
|
|
257
|
-
.replace(/\s+/g, ' ')
|
|
258
|
-
.trim()
|
|
259
|
-
}
|
|
1
|
+
import { promises as fs } from 'fs'
|
|
2
|
+
import { join, relative } from 'path'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Represents a parsed feature file with its scenarios and steps
|
|
6
|
+
*/
|
|
7
|
+
export interface ParsedFeature {
|
|
8
|
+
filePath: string
|
|
9
|
+
featureName: string
|
|
10
|
+
featureDescription?: string
|
|
11
|
+
tags: string[]
|
|
12
|
+
scenarios: ParsedScenario[]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Represents a parsed scenario from a feature file
|
|
17
|
+
*/
|
|
18
|
+
export interface ParsedScenario {
|
|
19
|
+
name: string
|
|
20
|
+
description?: string
|
|
21
|
+
tags: string[]
|
|
22
|
+
steps: ParsedStep[]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Represents a parsed step from a feature file
|
|
27
|
+
*/
|
|
28
|
+
export interface ParsedStep {
|
|
29
|
+
keyword: string
|
|
30
|
+
text: string
|
|
31
|
+
order: number
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Parses a Gherkin feature file and extracts scenarios and steps
|
|
36
|
+
* @param filePath - Path to the feature file
|
|
37
|
+
* @returns Promise<ParsedFeature | null> - Parsed feature data or null if parsing fails
|
|
38
|
+
*/
|
|
39
|
+
export async function parseFeatureFile(filePath: string): Promise<ParsedFeature | null> {
|
|
40
|
+
try {
|
|
41
|
+
const content = await fs.readFile(filePath, 'utf-8')
|
|
42
|
+
|
|
43
|
+
// Simple Gherkin parser implementation
|
|
44
|
+
const lines = content.split('\n').map(line => line.trim())
|
|
45
|
+
const scenarios: ParsedScenario[] = []
|
|
46
|
+
|
|
47
|
+
let featureName = ''
|
|
48
|
+
let featureDescription = ''
|
|
49
|
+
const featureTags: string[] = []
|
|
50
|
+
let currentScenario: ParsedScenario | null = null
|
|
51
|
+
let stepOrder = 1
|
|
52
|
+
|
|
53
|
+
// Find feature line and extract tags before it
|
|
54
|
+
let _featureLineIndex = -1
|
|
55
|
+
for (let i = 0; i < lines.length; i++) {
|
|
56
|
+
if (lines[i].startsWith('Feature:')) {
|
|
57
|
+
_featureLineIndex = i
|
|
58
|
+
// Look backwards for tags (skip comments and empty lines)
|
|
59
|
+
for (let j = i - 1; j >= 0; j--) {
|
|
60
|
+
const prevLine = lines[j]
|
|
61
|
+
if (prevLine === '' || prevLine.startsWith('#')) {
|
|
62
|
+
continue
|
|
63
|
+
}
|
|
64
|
+
if (prevLine.startsWith('@')) {
|
|
65
|
+
featureTags.unshift(prevLine) // Add to beginning to maintain order
|
|
66
|
+
} else {
|
|
67
|
+
break // Stop when we hit a non-tag line
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
break
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
for (let i = 0; i < lines.length; i++) {
|
|
75
|
+
const line = lines[i]
|
|
76
|
+
|
|
77
|
+
// Skip comments and empty lines
|
|
78
|
+
if (line.startsWith('#') || line === '') {
|
|
79
|
+
continue
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Parse Feature line
|
|
83
|
+
if (line.startsWith('Feature:')) {
|
|
84
|
+
featureName = line.replace('Feature:', '').trim()
|
|
85
|
+
// Look for description in next lines
|
|
86
|
+
let j = i + 1
|
|
87
|
+
while (j < lines.length && lines[j] && !lines[j].startsWith('Scenario:') && !lines[j].startsWith('Feature:')) {
|
|
88
|
+
if (lines[j] && !lines[j].startsWith('#')) {
|
|
89
|
+
featureDescription += (featureDescription ? ' ' : '') + lines[j]
|
|
90
|
+
}
|
|
91
|
+
j++
|
|
92
|
+
}
|
|
93
|
+
continue
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Parse Scenario line
|
|
97
|
+
if (line.startsWith('Scenario:')) {
|
|
98
|
+
// Save previous scenario if exists
|
|
99
|
+
if (currentScenario) {
|
|
100
|
+
scenarios.push(currentScenario)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Extract tags before this scenario
|
|
104
|
+
const scenarioTags: string[] = []
|
|
105
|
+
for (let j = i - 1; j >= 0; j--) {
|
|
106
|
+
const prevLine = lines[j]
|
|
107
|
+
if (prevLine === '' || prevLine.startsWith('#')) {
|
|
108
|
+
continue
|
|
109
|
+
}
|
|
110
|
+
if (prevLine.startsWith('@')) {
|
|
111
|
+
scenarioTags.unshift(prevLine) // Add to beginning to maintain order
|
|
112
|
+
} else {
|
|
113
|
+
break // Stop when we hit a non-tag line
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const scenarioText = line.replace('Scenario:', '').trim()
|
|
118
|
+
const [name, description] =
|
|
119
|
+
scenarioText.split(']').length > 1
|
|
120
|
+
? [scenarioText.split(']')[1].trim(), scenarioText.split(']')[0].replace('[', '').trim()]
|
|
121
|
+
: [scenarioText, '']
|
|
122
|
+
|
|
123
|
+
currentScenario = {
|
|
124
|
+
name: name,
|
|
125
|
+
description: description || undefined,
|
|
126
|
+
tags: scenarioTags,
|
|
127
|
+
steps: [],
|
|
128
|
+
}
|
|
129
|
+
stepOrder = 1
|
|
130
|
+
continue
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Parse steps (Given, When, Then, And, But)
|
|
134
|
+
if (
|
|
135
|
+
currentScenario &&
|
|
136
|
+
(line.startsWith('Given ') ||
|
|
137
|
+
line.startsWith('When ') ||
|
|
138
|
+
line.startsWith('Then ') ||
|
|
139
|
+
line.startsWith('And ') ||
|
|
140
|
+
line.startsWith('But '))
|
|
141
|
+
) {
|
|
142
|
+
const keyword = line.split(' ')[0]
|
|
143
|
+
const text = line.substring(keyword.length).trim()
|
|
144
|
+
|
|
145
|
+
currentScenario.steps.push({
|
|
146
|
+
keyword: keyword,
|
|
147
|
+
text: text,
|
|
148
|
+
order: stepOrder++,
|
|
149
|
+
})
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Add the last scenario
|
|
154
|
+
if (currentScenario) {
|
|
155
|
+
scenarios.push(currentScenario)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (!featureName) {
|
|
159
|
+
console.warn(`No feature found in file: ${filePath}`)
|
|
160
|
+
return null
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return {
|
|
164
|
+
filePath,
|
|
165
|
+
featureName,
|
|
166
|
+
featureDescription: featureDescription || undefined,
|
|
167
|
+
tags: featureTags,
|
|
168
|
+
scenarios,
|
|
169
|
+
}
|
|
170
|
+
} catch (error) {
|
|
171
|
+
console.error(`Error parsing feature file ${filePath}:`, error)
|
|
172
|
+
return null
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Scans a directory for feature files and parses them
|
|
178
|
+
* @param directoryPath - Path to scan for feature files
|
|
179
|
+
* @returns Promise<ParsedFeature[]> - Array of parsed feature files
|
|
180
|
+
*/
|
|
181
|
+
export async function scanFeatureFiles(directoryPath: string): Promise<ParsedFeature[]> {
|
|
182
|
+
const parsedFeatures: ParsedFeature[] = []
|
|
183
|
+
|
|
184
|
+
try {
|
|
185
|
+
const entries = await fs.readdir(directoryPath, { withFileTypes: true })
|
|
186
|
+
|
|
187
|
+
for (const entry of entries) {
|
|
188
|
+
const fullPath = join(directoryPath, entry.name)
|
|
189
|
+
|
|
190
|
+
if (entry.isDirectory()) {
|
|
191
|
+
// Recursively scan subdirectories
|
|
192
|
+
const subFeatures = await scanFeatureFiles(fullPath)
|
|
193
|
+
parsedFeatures.push(...subFeatures)
|
|
194
|
+
} else if (entry.isFile() && entry.name.endsWith('.feature')) {
|
|
195
|
+
// Parse feature file
|
|
196
|
+
const parsedFeature = await parseFeatureFile(fullPath)
|
|
197
|
+
if (parsedFeature) {
|
|
198
|
+
parsedFeatures.push(parsedFeature)
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
} catch (error) {
|
|
203
|
+
console.error(`Error scanning directory ${directoryPath}:`, error)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return parsedFeatures
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Extracts module path from feature file path
|
|
211
|
+
* Works cross-platform (Windows, Mac, Linux)
|
|
212
|
+
* @param featureFilePath - Full path to the feature file
|
|
213
|
+
* @param featuresBaseDir - Base directory for features
|
|
214
|
+
* @returns string - Module path (e.g., "/module1/submodule")
|
|
215
|
+
*/
|
|
216
|
+
export function extractModulePathFromFilePath(featureFilePath: string, featuresBaseDir: string): string {
|
|
217
|
+
// Use path.relative for cross-platform path handling
|
|
218
|
+
const relativePath = relative(featuresBaseDir, featureFilePath)
|
|
219
|
+
|
|
220
|
+
// Normalize to forward slashes for module path format (database uses /)
|
|
221
|
+
const normalizedPath = relativePath.replace(/\\/g, '/')
|
|
222
|
+
const pathParts = normalizedPath.split('/').filter(part => part && part !== '')
|
|
223
|
+
|
|
224
|
+
// Remove the filename and join the remaining parts
|
|
225
|
+
const moduleParts = pathParts.slice(0, -1)
|
|
226
|
+
return moduleParts.length > 0 ? '/' + moduleParts.join('/') : '/'
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Generates a safe test suite name from feature name
|
|
231
|
+
* @param featureName - Name of the feature
|
|
232
|
+
* @returns string - Safe test suite name
|
|
233
|
+
*/
|
|
234
|
+
export function generateSafeTestSuiteName(featureName: string): string {
|
|
235
|
+
return featureName
|
|
236
|
+
.toLowerCase()
|
|
237
|
+
.replace(/[^a-z0-9\s]+/g, '')
|
|
238
|
+
.replace(/\s+/g, ' ')
|
|
239
|
+
.trim()
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Generates a safe test case name from scenario name
|
|
244
|
+
* @param scenarioName - Name of the scenario
|
|
245
|
+
* @returns string - Safe test case name
|
|
246
|
+
*/
|
|
247
|
+
export function generateSafeTestCaseName(scenarioName: string): string {
|
|
248
|
+
// Remove scenario prefix if present and clean up the name
|
|
249
|
+
const cleanName = scenarioName
|
|
250
|
+
.replace(/^Scenario:\s*/i, '')
|
|
251
|
+
.replace(/^\[.*?\]\s*/, '') // Remove [brackets] prefix
|
|
252
|
+
.trim()
|
|
253
|
+
|
|
254
|
+
return cleanName
|
|
255
|
+
.toLowerCase()
|
|
256
|
+
.replace(/[^a-z0-9\s]+/g, '')
|
|
257
|
+
.replace(/\s+/g, ' ')
|
|
258
|
+
.trim()
|
|
259
|
+
}
|