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,248 +1,248 @@
|
|
|
1
|
-
import { Page } from 'playwright'
|
|
2
|
-
import { LocatorCache, LocatorMapCache } from './cache.util.js'
|
|
3
|
-
|
|
4
|
-
const sleep = (ms: number) => new Promise(r => setTimeout(r, ms))
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Retry helper: immediate first attempt, exponential backoff, selective retry.
|
|
8
|
-
*/
|
|
9
|
-
export async function retry<T>(
|
|
10
|
-
fn: () => Promise<T>,
|
|
11
|
-
{
|
|
12
|
-
retries = 5,
|
|
13
|
-
delayMs = 100,
|
|
14
|
-
backoff = 1.6,
|
|
15
|
-
shouldRetry = () => true,
|
|
16
|
-
}: {
|
|
17
|
-
retries?: number
|
|
18
|
-
delayMs?: number
|
|
19
|
-
backoff?: number
|
|
20
|
-
shouldRetry?: (e: unknown) => boolean
|
|
21
|
-
} = {},
|
|
22
|
-
): Promise<T> {
|
|
23
|
-
let lastErr: unknown
|
|
24
|
-
let delay = delayMs
|
|
25
|
-
|
|
26
|
-
for (let i = 0; i <= retries; i++) {
|
|
27
|
-
try {
|
|
28
|
-
return await fn()
|
|
29
|
-
} catch (e) {
|
|
30
|
-
lastErr = e
|
|
31
|
-
if (i === retries || !shouldRetry(e)) break
|
|
32
|
-
await sleep(delay)
|
|
33
|
-
delay = Math.floor(delay * backoff)
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
throw lastErr
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const routeKey = (page: Page, includeSearch = false) => {
|
|
41
|
-
const u = new URL(page.url())
|
|
42
|
-
return includeSearch ? `${u.pathname}${u.search}` : u.pathname
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Wait for route to be "settled" without AUT changes:
|
|
47
|
-
* - URL stable for urlStableMs
|
|
48
|
-
* - no frame navigations during that window
|
|
49
|
-
* - DOM quiet (no mutations) for domQuietMs
|
|
50
|
-
*/
|
|
51
|
-
export async function waitForRouteSettled(
|
|
52
|
-
page: Page,
|
|
53
|
-
{
|
|
54
|
-
timeoutMs = 15_000,
|
|
55
|
-
pollMs = 50,
|
|
56
|
-
urlStableMs = 500,
|
|
57
|
-
domQuietMs = 300,
|
|
58
|
-
includeSearch = false,
|
|
59
|
-
}: {
|
|
60
|
-
timeoutMs?: number
|
|
61
|
-
pollMs?: number
|
|
62
|
-
urlStableMs?: number
|
|
63
|
-
domQuietMs?: number
|
|
64
|
-
includeSearch?: boolean
|
|
65
|
-
} = {},
|
|
66
|
-
): Promise<string> {
|
|
67
|
-
const deadline = Date.now() + timeoutMs
|
|
68
|
-
|
|
69
|
-
await page.waitForLoadState('domcontentloaded', { timeout: timeoutMs })
|
|
70
|
-
|
|
71
|
-
let lastKey = routeKey(page, includeSearch)
|
|
72
|
-
let stableSince = Date.now()
|
|
73
|
-
|
|
74
|
-
let navBumpedAt = Date.now()
|
|
75
|
-
const onFrameNav = () => {
|
|
76
|
-
navBumpedAt = Date.now()
|
|
77
|
-
}
|
|
78
|
-
page.on('framenavigated', onFrameNav)
|
|
79
|
-
|
|
80
|
-
try {
|
|
81
|
-
while (Date.now() < deadline) {
|
|
82
|
-
await sleep(pollMs)
|
|
83
|
-
|
|
84
|
-
const key = routeKey(page, includeSearch)
|
|
85
|
-
if (key !== lastKey) {
|
|
86
|
-
lastKey = key
|
|
87
|
-
stableSince = Date.now()
|
|
88
|
-
continue
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const now = Date.now()
|
|
92
|
-
const urlStableLongEnough = now - stableSince >= urlStableMs
|
|
93
|
-
const noRecentNav = now - navBumpedAt >= urlStableMs
|
|
94
|
-
if (!urlStableLongEnough || !noRecentNav) continue
|
|
95
|
-
|
|
96
|
-
const domQuiet = await page
|
|
97
|
-
.evaluate(quietMs => {
|
|
98
|
-
return new Promise<boolean>(resolve => {
|
|
99
|
-
let lastMutation = Date.now()
|
|
100
|
-
const obs = new MutationObserver(() => {
|
|
101
|
-
lastMutation = Date.now()
|
|
102
|
-
})
|
|
103
|
-
obs.observe(document, { subtree: true, childList: true, attributes: true })
|
|
104
|
-
|
|
105
|
-
const tick = () => {
|
|
106
|
-
if (Date.now() - lastMutation >= quietMs) {
|
|
107
|
-
obs.disconnect()
|
|
108
|
-
resolve(true)
|
|
109
|
-
return
|
|
110
|
-
}
|
|
111
|
-
setTimeout(tick, 50)
|
|
112
|
-
}
|
|
113
|
-
tick()
|
|
114
|
-
})
|
|
115
|
-
}, domQuietMs)
|
|
116
|
-
.catch(() => false)
|
|
117
|
-
|
|
118
|
-
if (domQuiet) return lastKey
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return routeKey(page, includeSearch)
|
|
122
|
-
} finally {
|
|
123
|
-
page.off('framenavigated', onFrameNav)
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Throw tagged error so we only retry on "map missing" cases.
|
|
129
|
-
*/
|
|
130
|
-
const getLocatorMapData = async (page: Page) => {
|
|
131
|
-
const locatorMap = LocatorMapCache.getInstance()
|
|
132
|
-
const currentPath = new URL(page.url()).pathname
|
|
133
|
-
|
|
134
|
-
const data = locatorMap.get(currentPath)
|
|
135
|
-
if (!data) throw new Error(`LOCATOR_MAP_NOT_FOUND::${currentPath}`)
|
|
136
|
-
return data
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Validate that a selector "belongs" to the current page state.
|
|
141
|
-
* - attached: element exists in DOM
|
|
142
|
-
* - visible: element is visible (optional but very useful to avoid stale hidden elements)
|
|
143
|
-
* - unique: avoids matching some leftover layout/header element found everywhere
|
|
144
|
-
*/
|
|
145
|
-
async function validateResolvedSelector(
|
|
146
|
-
page: Page,
|
|
147
|
-
selector: string,
|
|
148
|
-
{
|
|
149
|
-
timeoutMs = 1500,
|
|
150
|
-
requireVisible = true,
|
|
151
|
-
requireUnique = false,
|
|
152
|
-
}: {
|
|
153
|
-
timeoutMs?: number
|
|
154
|
-
requireVisible?: boolean
|
|
155
|
-
requireUnique?: boolean
|
|
156
|
-
} = {},
|
|
157
|
-
): Promise<boolean> {
|
|
158
|
-
try {
|
|
159
|
-
const loc = page.locator(selector)
|
|
160
|
-
|
|
161
|
-
// "attached" (exists) quickly
|
|
162
|
-
await loc.first().waitFor({ state: 'attached', timeout: timeoutMs })
|
|
163
|
-
|
|
164
|
-
if (requireVisible) {
|
|
165
|
-
// visible check helps avoid stale hidden DOM (old route kept around)
|
|
166
|
-
await loc.first().waitFor({ state: 'visible', timeout: timeoutMs })
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
if (requireUnique) {
|
|
170
|
-
const c = await loc.count()
|
|
171
|
-
if (c !== 1) return false
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
return true
|
|
175
|
-
} catch {
|
|
176
|
-
return false
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Resolve locator with:
|
|
182
|
-
* - route settled
|
|
183
|
-
* - map lookup retry
|
|
184
|
-
* - selector validation (protects against stale "same key across pages")
|
|
185
|
-
* - rerun if validation fails or route changes mid-flight
|
|
186
|
-
*/
|
|
187
|
-
export async function resolveLocator(
|
|
188
|
-
page: Page,
|
|
189
|
-
locatorName: string,
|
|
190
|
-
{
|
|
191
|
-
maxResolvePasses = 2,
|
|
192
|
-
validate = {
|
|
193
|
-
timeoutMs: 1500,
|
|
194
|
-
requireVisible: true,
|
|
195
|
-
requireUnique: false,
|
|
196
|
-
},
|
|
197
|
-
}: {
|
|
198
|
-
maxResolvePasses?: number
|
|
199
|
-
validate?: {
|
|
200
|
-
timeoutMs?: number
|
|
201
|
-
requireVisible?: boolean
|
|
202
|
-
requireUnique?: boolean
|
|
203
|
-
}
|
|
204
|
-
} = {},
|
|
205
|
-
) {
|
|
206
|
-
try {
|
|
207
|
-
for (let pass = 0; pass < maxResolvePasses; pass++) {
|
|
208
|
-
await waitForRouteSettled(page, {
|
|
209
|
-
timeoutMs: 15_000,
|
|
210
|
-
urlStableMs: 500,
|
|
211
|
-
domQuietMs: 300,
|
|
212
|
-
pollMs: 50,
|
|
213
|
-
includeSearch: false,
|
|
214
|
-
})
|
|
215
|
-
|
|
216
|
-
const beforePath = new URL(page.url()).pathname
|
|
217
|
-
|
|
218
|
-
const locatorMapData = await retry(() => getLocatorMapData(page), {
|
|
219
|
-
retries: 6,
|
|
220
|
-
delayMs: 80,
|
|
221
|
-
backoff: 1.5,
|
|
222
|
-
shouldRetry: e => e instanceof Error && e.message.startsWith('LOCATOR_MAP_NOT_FOUND::'),
|
|
223
|
-
})
|
|
224
|
-
|
|
225
|
-
const locators = LocatorCache.getInstance().get(locatorMapData.name)
|
|
226
|
-
if (!locators) throw new Error(`Locator bundle not found for name ${locatorMapData.name}`)
|
|
227
|
-
|
|
228
|
-
const selector = locators[locatorName]
|
|
229
|
-
if (!selector) throw new Error(`Locator "${locatorName}" not found for name ${locatorMapData.name}`)
|
|
230
|
-
|
|
231
|
-
// Guard: route changed mid-resolution → re-run
|
|
232
|
-
const afterPath = new URL(page.url()).pathname
|
|
233
|
-
if (afterPath !== beforePath) continue
|
|
234
|
-
|
|
235
|
-
// Critical: validate selector matches current page state.
|
|
236
|
-
const ok = await validateResolvedSelector(page, selector as unknown as string, validate)
|
|
237
|
-
if (ok) return selector as unknown as string
|
|
238
|
-
|
|
239
|
-
// If validation failed, likely stale bundle (same locator key on multiple pages),
|
|
240
|
-
// or transition still in progress. Loop and re-resolve after settling again.
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
throw new Error(`Failed to resolve a valid locator for "${locatorName}" after ${maxResolvePasses} passes`)
|
|
244
|
-
} catch (error) {
|
|
245
|
-
console.error(error)
|
|
246
|
-
return null
|
|
247
|
-
}
|
|
248
|
-
}
|
|
1
|
+
import { Page } from 'playwright'
|
|
2
|
+
import { LocatorCache, LocatorMapCache } from './cache.util.js'
|
|
3
|
+
|
|
4
|
+
const sleep = (ms: number) => new Promise(r => setTimeout(r, ms))
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Retry helper: immediate first attempt, exponential backoff, selective retry.
|
|
8
|
+
*/
|
|
9
|
+
export async function retry<T>(
|
|
10
|
+
fn: () => Promise<T>,
|
|
11
|
+
{
|
|
12
|
+
retries = 5,
|
|
13
|
+
delayMs = 100,
|
|
14
|
+
backoff = 1.6,
|
|
15
|
+
shouldRetry = () => true,
|
|
16
|
+
}: {
|
|
17
|
+
retries?: number
|
|
18
|
+
delayMs?: number
|
|
19
|
+
backoff?: number
|
|
20
|
+
shouldRetry?: (e: unknown) => boolean
|
|
21
|
+
} = {},
|
|
22
|
+
): Promise<T> {
|
|
23
|
+
let lastErr: unknown
|
|
24
|
+
let delay = delayMs
|
|
25
|
+
|
|
26
|
+
for (let i = 0; i <= retries; i++) {
|
|
27
|
+
try {
|
|
28
|
+
return await fn()
|
|
29
|
+
} catch (e) {
|
|
30
|
+
lastErr = e
|
|
31
|
+
if (i === retries || !shouldRetry(e)) break
|
|
32
|
+
await sleep(delay)
|
|
33
|
+
delay = Math.floor(delay * backoff)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
throw lastErr
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const routeKey = (page: Page, includeSearch = false) => {
|
|
41
|
+
const u = new URL(page.url())
|
|
42
|
+
return includeSearch ? `${u.pathname}${u.search}` : u.pathname
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Wait for route to be "settled" without AUT changes:
|
|
47
|
+
* - URL stable for urlStableMs
|
|
48
|
+
* - no frame navigations during that window
|
|
49
|
+
* - DOM quiet (no mutations) for domQuietMs
|
|
50
|
+
*/
|
|
51
|
+
export async function waitForRouteSettled(
|
|
52
|
+
page: Page,
|
|
53
|
+
{
|
|
54
|
+
timeoutMs = 15_000,
|
|
55
|
+
pollMs = 50,
|
|
56
|
+
urlStableMs = 500,
|
|
57
|
+
domQuietMs = 300,
|
|
58
|
+
includeSearch = false,
|
|
59
|
+
}: {
|
|
60
|
+
timeoutMs?: number
|
|
61
|
+
pollMs?: number
|
|
62
|
+
urlStableMs?: number
|
|
63
|
+
domQuietMs?: number
|
|
64
|
+
includeSearch?: boolean
|
|
65
|
+
} = {},
|
|
66
|
+
): Promise<string> {
|
|
67
|
+
const deadline = Date.now() + timeoutMs
|
|
68
|
+
|
|
69
|
+
await page.waitForLoadState('domcontentloaded', { timeout: timeoutMs })
|
|
70
|
+
|
|
71
|
+
let lastKey = routeKey(page, includeSearch)
|
|
72
|
+
let stableSince = Date.now()
|
|
73
|
+
|
|
74
|
+
let navBumpedAt = Date.now()
|
|
75
|
+
const onFrameNav = () => {
|
|
76
|
+
navBumpedAt = Date.now()
|
|
77
|
+
}
|
|
78
|
+
page.on('framenavigated', onFrameNav)
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
while (Date.now() < deadline) {
|
|
82
|
+
await sleep(pollMs)
|
|
83
|
+
|
|
84
|
+
const key = routeKey(page, includeSearch)
|
|
85
|
+
if (key !== lastKey) {
|
|
86
|
+
lastKey = key
|
|
87
|
+
stableSince = Date.now()
|
|
88
|
+
continue
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const now = Date.now()
|
|
92
|
+
const urlStableLongEnough = now - stableSince >= urlStableMs
|
|
93
|
+
const noRecentNav = now - navBumpedAt >= urlStableMs
|
|
94
|
+
if (!urlStableLongEnough || !noRecentNav) continue
|
|
95
|
+
|
|
96
|
+
const domQuiet = await page
|
|
97
|
+
.evaluate(quietMs => {
|
|
98
|
+
return new Promise<boolean>(resolve => {
|
|
99
|
+
let lastMutation = Date.now()
|
|
100
|
+
const obs = new MutationObserver(() => {
|
|
101
|
+
lastMutation = Date.now()
|
|
102
|
+
})
|
|
103
|
+
obs.observe(document, { subtree: true, childList: true, attributes: true })
|
|
104
|
+
|
|
105
|
+
const tick = () => {
|
|
106
|
+
if (Date.now() - lastMutation >= quietMs) {
|
|
107
|
+
obs.disconnect()
|
|
108
|
+
resolve(true)
|
|
109
|
+
return
|
|
110
|
+
}
|
|
111
|
+
setTimeout(tick, 50)
|
|
112
|
+
}
|
|
113
|
+
tick()
|
|
114
|
+
})
|
|
115
|
+
}, domQuietMs)
|
|
116
|
+
.catch(() => false)
|
|
117
|
+
|
|
118
|
+
if (domQuiet) return lastKey
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return routeKey(page, includeSearch)
|
|
122
|
+
} finally {
|
|
123
|
+
page.off('framenavigated', onFrameNav)
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Throw tagged error so we only retry on "map missing" cases.
|
|
129
|
+
*/
|
|
130
|
+
const getLocatorMapData = async (page: Page) => {
|
|
131
|
+
const locatorMap = LocatorMapCache.getInstance()
|
|
132
|
+
const currentPath = new URL(page.url()).pathname
|
|
133
|
+
|
|
134
|
+
const data = locatorMap.get(currentPath)
|
|
135
|
+
if (!data) throw new Error(`LOCATOR_MAP_NOT_FOUND::${currentPath}`)
|
|
136
|
+
return data
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Validate that a selector "belongs" to the current page state.
|
|
141
|
+
* - attached: element exists in DOM
|
|
142
|
+
* - visible: element is visible (optional but very useful to avoid stale hidden elements)
|
|
143
|
+
* - unique: avoids matching some leftover layout/header element found everywhere
|
|
144
|
+
*/
|
|
145
|
+
async function validateResolvedSelector(
|
|
146
|
+
page: Page,
|
|
147
|
+
selector: string,
|
|
148
|
+
{
|
|
149
|
+
timeoutMs = 1500,
|
|
150
|
+
requireVisible = true,
|
|
151
|
+
requireUnique = false,
|
|
152
|
+
}: {
|
|
153
|
+
timeoutMs?: number
|
|
154
|
+
requireVisible?: boolean
|
|
155
|
+
requireUnique?: boolean
|
|
156
|
+
} = {},
|
|
157
|
+
): Promise<boolean> {
|
|
158
|
+
try {
|
|
159
|
+
const loc = page.locator(selector)
|
|
160
|
+
|
|
161
|
+
// "attached" (exists) quickly
|
|
162
|
+
await loc.first().waitFor({ state: 'attached', timeout: timeoutMs })
|
|
163
|
+
|
|
164
|
+
if (requireVisible) {
|
|
165
|
+
// visible check helps avoid stale hidden DOM (old route kept around)
|
|
166
|
+
await loc.first().waitFor({ state: 'visible', timeout: timeoutMs })
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (requireUnique) {
|
|
170
|
+
const c = await loc.count()
|
|
171
|
+
if (c !== 1) return false
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return true
|
|
175
|
+
} catch {
|
|
176
|
+
return false
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Resolve locator with:
|
|
182
|
+
* - route settled
|
|
183
|
+
* - map lookup retry
|
|
184
|
+
* - selector validation (protects against stale "same key across pages")
|
|
185
|
+
* - rerun if validation fails or route changes mid-flight
|
|
186
|
+
*/
|
|
187
|
+
export async function resolveLocator(
|
|
188
|
+
page: Page,
|
|
189
|
+
locatorName: string,
|
|
190
|
+
{
|
|
191
|
+
maxResolvePasses = 2,
|
|
192
|
+
validate = {
|
|
193
|
+
timeoutMs: 1500,
|
|
194
|
+
requireVisible: true,
|
|
195
|
+
requireUnique: false,
|
|
196
|
+
},
|
|
197
|
+
}: {
|
|
198
|
+
maxResolvePasses?: number
|
|
199
|
+
validate?: {
|
|
200
|
+
timeoutMs?: number
|
|
201
|
+
requireVisible?: boolean
|
|
202
|
+
requireUnique?: boolean
|
|
203
|
+
}
|
|
204
|
+
} = {},
|
|
205
|
+
) {
|
|
206
|
+
try {
|
|
207
|
+
for (let pass = 0; pass < maxResolvePasses; pass++) {
|
|
208
|
+
await waitForRouteSettled(page, {
|
|
209
|
+
timeoutMs: 15_000,
|
|
210
|
+
urlStableMs: 500,
|
|
211
|
+
domQuietMs: 300,
|
|
212
|
+
pollMs: 50,
|
|
213
|
+
includeSearch: false,
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
const beforePath = new URL(page.url()).pathname
|
|
217
|
+
|
|
218
|
+
const locatorMapData = await retry(() => getLocatorMapData(page), {
|
|
219
|
+
retries: 6,
|
|
220
|
+
delayMs: 80,
|
|
221
|
+
backoff: 1.5,
|
|
222
|
+
shouldRetry: e => e instanceof Error && e.message.startsWith('LOCATOR_MAP_NOT_FOUND::'),
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
const locators = LocatorCache.getInstance().get(locatorMapData.name)
|
|
226
|
+
if (!locators) throw new Error(`Locator bundle not found for name ${locatorMapData.name}`)
|
|
227
|
+
|
|
228
|
+
const selector = locators[locatorName]
|
|
229
|
+
if (!selector) throw new Error(`Locator "${locatorName}" not found for name ${locatorMapData.name}`)
|
|
230
|
+
|
|
231
|
+
// Guard: route changed mid-resolution → re-run
|
|
232
|
+
const afterPath = new URL(page.url()).pathname
|
|
233
|
+
if (afterPath !== beforePath) continue
|
|
234
|
+
|
|
235
|
+
// Critical: validate selector matches current page state.
|
|
236
|
+
const ok = await validateResolvedSelector(page, selector as unknown as string, validate)
|
|
237
|
+
if (ok) return selector as unknown as string
|
|
238
|
+
|
|
239
|
+
// If validation failed, likely stale bundle (same locator key on multiple pages),
|
|
240
|
+
// or transition still in progress. Loop and re-resolve after settling again.
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
throw new Error(`Failed to resolve a valid locator for "${locatorName}" after ${maxResolvePasses} passes`)
|
|
244
|
+
} catch (error) {
|
|
245
|
+
console.error(error)
|
|
246
|
+
return null
|
|
247
|
+
}
|
|
248
|
+
}
|
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
import { faker } from '@faker-js/faker';
|
|
2
|
-
|
|
3
|
-
export enum RandomDataType {
|
|
4
|
-
FULL_NAME = 'fullName',
|
|
5
|
-
FIRST_NAME = 'firstName',
|
|
6
|
-
LAST_NAME = 'lastName',
|
|
7
|
-
EMAIL = 'email',
|
|
8
|
-
PASSWORD = 'password',
|
|
9
|
-
PHONE = 'phone',
|
|
10
|
-
ADDRESS = 'address',
|
|
11
|
-
UNIQUE_TEXT = 'uniqueText',
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export function generateRandomData(randomDataType: RandomDataType): string {
|
|
15
|
-
let data: string;
|
|
16
|
-
switch (randomDataType) {
|
|
17
|
-
case RandomDataType.FULL_NAME:
|
|
18
|
-
data = faker.person.fullName();
|
|
19
|
-
break;
|
|
20
|
-
case RandomDataType.FIRST_NAME:
|
|
21
|
-
data = faker.person.firstName();
|
|
22
|
-
break;
|
|
23
|
-
case RandomDataType.LAST_NAME:
|
|
24
|
-
data = faker.person.lastName();
|
|
25
|
-
break;
|
|
26
|
-
case RandomDataType.EMAIL:
|
|
27
|
-
data = faker.internet.email();
|
|
28
|
-
break;
|
|
29
|
-
case RandomDataType.PASSWORD:
|
|
30
|
-
data = faker.internet.password();
|
|
31
|
-
break;
|
|
32
|
-
case RandomDataType.PHONE:
|
|
33
|
-
data = faker.phone.number();
|
|
34
|
-
break;
|
|
35
|
-
case RandomDataType.ADDRESS:
|
|
36
|
-
data = faker.location.streetAddress();
|
|
37
|
-
break;
|
|
38
|
-
case RandomDataType.UNIQUE_TEXT:
|
|
39
|
-
data = faker.string.uuid();
|
|
40
|
-
break;
|
|
41
|
-
default:
|
|
42
|
-
throw new Error(`Invalid random data type: ${randomDataType}`);
|
|
43
|
-
}
|
|
44
|
-
return data;
|
|
1
|
+
import { faker } from '@faker-js/faker';
|
|
2
|
+
|
|
3
|
+
export enum RandomDataType {
|
|
4
|
+
FULL_NAME = 'fullName',
|
|
5
|
+
FIRST_NAME = 'firstName',
|
|
6
|
+
LAST_NAME = 'lastName',
|
|
7
|
+
EMAIL = 'email',
|
|
8
|
+
PASSWORD = 'password',
|
|
9
|
+
PHONE = 'phone',
|
|
10
|
+
ADDRESS = 'address',
|
|
11
|
+
UNIQUE_TEXT = 'uniqueText',
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function generateRandomData(randomDataType: RandomDataType): string {
|
|
15
|
+
let data: string;
|
|
16
|
+
switch (randomDataType) {
|
|
17
|
+
case RandomDataType.FULL_NAME:
|
|
18
|
+
data = faker.person.fullName();
|
|
19
|
+
break;
|
|
20
|
+
case RandomDataType.FIRST_NAME:
|
|
21
|
+
data = faker.person.firstName();
|
|
22
|
+
break;
|
|
23
|
+
case RandomDataType.LAST_NAME:
|
|
24
|
+
data = faker.person.lastName();
|
|
25
|
+
break;
|
|
26
|
+
case RandomDataType.EMAIL:
|
|
27
|
+
data = faker.internet.email();
|
|
28
|
+
break;
|
|
29
|
+
case RandomDataType.PASSWORD:
|
|
30
|
+
data = faker.internet.password();
|
|
31
|
+
break;
|
|
32
|
+
case RandomDataType.PHONE:
|
|
33
|
+
data = faker.phone.number();
|
|
34
|
+
break;
|
|
35
|
+
case RandomDataType.ADDRESS:
|
|
36
|
+
data = faker.location.streetAddress();
|
|
37
|
+
break;
|
|
38
|
+
case RandomDataType.UNIQUE_TEXT:
|
|
39
|
+
data = faker.string.uuid();
|
|
40
|
+
break;
|
|
41
|
+
default:
|
|
42
|
+
throw new Error(`Invalid random data type: ${randomDataType}`);
|
|
43
|
+
}
|
|
44
|
+
return data;
|
|
45
45
|
}
|