create-appraise 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -0
- package/package.json +63 -0
- package/templates/default/.env.example +2 -0
- package/templates/default/README.md +51 -0
- package/templates/default/appraise.config.json +4 -0
- package/templates/default/components.json +24 -0
- package/templates/default/eslint.config.mjs +15 -0
- package/templates/default/next-env.d.ts +6 -0
- package/templates/default/next.config.ts +7 -0
- package/templates/default/package-lock.json +14321 -0
- package/templates/default/package.json +124 -0
- package/templates/default/postcss.config.mjs +8 -0
- package/templates/default/prisma/migrations/20251026202316_migrate_back_to_sqlite/migration.sql +257 -0
- package/templates/default/prisma/migrations/20251104113456_add_type_for_template_step_groups/migration.sql +16 -0
- package/templates/default/prisma/migrations/20251104170946_add_tags_to_test_suite_and_test_case/migration.sql +27 -0
- package/templates/default/prisma/migrations/20251112190024_add_cascade_delete_to_test_run_test_case/migration.sql +17 -0
- package/templates/default/prisma/migrations/20251113181100_add_test_run_log/migration.sql +12 -0
- package/templates/default/prisma/migrations/20251119191838_add_tag_type/migration.sql +28 -0
- package/templates/default/prisma/migrations/20251121164059_add_conflict_resolution/migration.sql +12 -0
- package/templates/default/prisma/migrations/20251130190737_add_trace_path_to_test_run_test_case/migration.sql +2 -0
- package/templates/default/prisma/migrations/20251213074835_add_log_path_to_test_run/migration.sql +2 -0
- package/templates/default/prisma/migrations/20251213183952_add_name_property_for_the_test_run_entities/migration.sql +30 -0
- package/templates/default/prisma/migrations/20251223183400_add_report_model_to_db_schema/migration.sql +10 -0
- package/templates/default/prisma/migrations/20251223183637_add_report_test_case_entity_for_storing_test_results_for_individual_test_cases/migration.sql +10 -0
- package/templates/default/prisma/migrations/20251224083549_add_comprehensive_report_storage/migration.sql +108 -0
- package/templates/default/prisma/migrations/20251229194422_migrate_duration_to_string/migration.sql +55 -0
- package/templates/default/prisma/migrations/20251230124637_add_unique_constraint_to_test_run_name/migration.sql +27 -0
- package/templates/default/prisma/migrations/20260115094436_add_dashboard_metrics/migration.sql +59 -0
- package/templates/default/prisma/migrations/20260127172022_add_cascade_delete_to_step_parameters/migration.sql +34 -0
- package/templates/default/prisma/migrations/migration_lock.toml +3 -0
- package/templates/default/prisma/schema.prisma +554 -0
- package/templates/default/public/favicon.ico +0 -0
- package/templates/default/public/file.svg +1 -0
- package/templates/default/public/globe.svg +1 -0
- package/templates/default/public/next.svg +1 -0
- package/templates/default/public/vercel.svg +1 -0
- package/templates/default/public/window.svg +1 -0
- package/templates/default/scripts/regenerate-features.ts +94 -0
- package/templates/default/scripts/setup-env.ts +19 -0
- package/templates/default/scripts/sync-all.ts +341 -0
- package/templates/default/scripts/sync-environments.ts +323 -0
- package/templates/default/scripts/sync-locator-groups.ts +413 -0
- package/templates/default/scripts/sync-locators.ts +402 -0
- package/templates/default/scripts/sync-modules.ts +349 -0
- package/templates/default/scripts/sync-tags.ts +292 -0
- package/templates/default/scripts/sync-template-step-groups.ts +399 -0
- package/templates/default/scripts/sync-template-steps.ts +806 -0
- package/templates/default/scripts/sync-test-cases.ts +905 -0
- package/templates/default/scripts/sync-test-suites.ts +411 -0
- package/templates/default/src/actions/conflict/conflict.action.ts +33 -0
- package/templates/default/src/actions/dashboard/dashboard-actions.ts +241 -0
- package/templates/default/src/actions/environments/environment-actions.ts +205 -0
- package/templates/default/src/actions/locator/locator-actions.ts +547 -0
- package/templates/default/src/actions/locator-groups/locator-group-actions.ts +344 -0
- package/templates/default/src/actions/modules/module-actions.ts +133 -0
- package/templates/default/src/actions/reports/report-actions.ts +614 -0
- package/templates/default/src/actions/review/review-actions.ts +147 -0
- package/templates/default/src/actions/tags/tag-actions.ts +104 -0
- package/templates/default/src/actions/template-step/template-step-actions.ts +332 -0
- package/templates/default/src/actions/template-step-group/template-step-group-actions.ts +278 -0
- package/templates/default/src/actions/template-test-case/template-test-case-actions.ts +238 -0
- package/templates/default/src/actions/test-case/test-case-actions.ts +419 -0
- package/templates/default/src/actions/test-run/test-run-actions.ts +1185 -0
- package/templates/default/src/actions/test-suite/test-suite-actions.ts +253 -0
- package/templates/default/src/actions/user/user-actions.ts +13 -0
- package/templates/default/src/app/(base)/environments/create/page.tsx +28 -0
- package/templates/default/src/app/(base)/environments/environment-form.tsx +219 -0
- package/templates/default/src/app/(base)/environments/environment-table-columns.tsx +96 -0
- package/templates/default/src/app/(base)/environments/environment-table.tsx +24 -0
- package/templates/default/src/app/(base)/environments/modify/[id]/page.tsx +46 -0
- package/templates/default/src/app/(base)/environments/page.tsx +59 -0
- package/templates/default/src/app/(base)/layout.tsx +10 -0
- package/templates/default/src/app/(base)/locator-groups/create/page.tsx +44 -0
- package/templates/default/src/app/(base)/locator-groups/locator-group-form.tsx +215 -0
- package/templates/default/src/app/(base)/locator-groups/locator-group-table-columns.tsx +77 -0
- package/templates/default/src/app/(base)/locator-groups/locator-group-table.tsx +28 -0
- package/templates/default/src/app/(base)/locator-groups/modify/[id]/page.tsx +46 -0
- package/templates/default/src/app/(base)/locator-groups/page.tsx +61 -0
- package/templates/default/src/app/(base)/locators/create/page.tsx +38 -0
- package/templates/default/src/app/(base)/locators/locator-form.tsx +163 -0
- package/templates/default/src/app/(base)/locators/locator-table-columns.tsx +90 -0
- package/templates/default/src/app/(base)/locators/locator-table.tsx +28 -0
- package/templates/default/src/app/(base)/locators/modify/[id]/page.tsx +45 -0
- package/templates/default/src/app/(base)/locators/page.tsx +65 -0
- package/templates/default/src/app/(base)/locators/sync-locators-button.tsx +66 -0
- package/templates/default/src/app/(base)/modules/create/page.tsx +34 -0
- package/templates/default/src/app/(base)/modules/modify/[id]/page.tsx +46 -0
- package/templates/default/src/app/(base)/modules/module-form.tsx +126 -0
- package/templates/default/src/app/(base)/modules/module-table-columns.tsx +85 -0
- package/templates/default/src/app/(base)/modules/module-table.tsx +24 -0
- package/templates/default/src/app/(base)/modules/page.tsx +59 -0
- package/templates/default/src/app/(base)/reports/[id]/page.tsx +517 -0
- package/templates/default/src/app/(base)/reports/duration-chart.tsx +33 -0
- package/templates/default/src/app/(base)/reports/feature-chart.tsx +78 -0
- package/templates/default/src/app/(base)/reports/overview-chart.tsx +46 -0
- package/templates/default/src/app/(base)/reports/page.tsx +98 -0
- package/templates/default/src/app/(base)/reports/report-metric-card.tsx +16 -0
- package/templates/default/src/app/(base)/reports/report-table-columns.tsx +189 -0
- package/templates/default/src/app/(base)/reports/report-table.tsx +72 -0
- package/templates/default/src/app/(base)/reports/report-view-table-columns.tsx +131 -0
- package/templates/default/src/app/(base)/reports/report-view-table.tsx +82 -0
- package/templates/default/src/app/(base)/reports/test-cases/page.tsx +42 -0
- package/templates/default/src/app/(base)/reports/test-cases/test-cases-metric-table-columns.tsx +115 -0
- package/templates/default/src/app/(base)/reports/test-cases/test-cases-metric-table.tsx +27 -0
- package/templates/default/src/app/(base)/reports/test-suites/page.tsx +42 -0
- package/templates/default/src/app/(base)/reports/test-suites/test-suites-metric-table-columns.tsx +79 -0
- package/templates/default/src/app/(base)/reports/test-suites/test-suites-metric-table.tsx +27 -0
- package/templates/default/src/app/(base)/reports/view-logs-button.tsx +60 -0
- package/templates/default/src/app/(base)/reviews/create/page.tsx +26 -0
- package/templates/default/src/app/(base)/reviews/created-reviews-table.tsx +15 -0
- package/templates/default/src/app/(base)/reviews/modify/[id]/page.tsx +26 -0
- package/templates/default/src/app/(base)/reviews/page.tsx +26 -0
- package/templates/default/src/app/(base)/reviews/review/[id]/page.tsx +26 -0
- package/templates/default/src/app/(base)/reviews/review-form.tsx +11 -0
- package/templates/default/src/app/(base)/reviews/review-table-by-creator-columns.tsx +9 -0
- package/templates/default/src/app/(base)/reviews/review-table-by-reviewer-columns.tsx +9 -0
- package/templates/default/src/app/(base)/reviews/reviewer-reviews-table.tsx +15 -0
- package/templates/default/src/app/(base)/tags/create/page.tsx +39 -0
- package/templates/default/src/app/(base)/tags/modify/[id]/page.tsx +50 -0
- package/templates/default/src/app/(base)/tags/page.tsx +58 -0
- package/templates/default/src/app/(base)/tags/tag-form.tsx +147 -0
- package/templates/default/src/app/(base)/tags/tag-table-columns.tsx +63 -0
- package/templates/default/src/app/(base)/tags/tag-table.tsx +29 -0
- package/templates/default/src/app/(base)/template-step-groups/create/page.tsx +28 -0
- package/templates/default/src/app/(base)/template-step-groups/modify/[id]/page.tsx +45 -0
- package/templates/default/src/app/(base)/template-step-groups/page.tsx +60 -0
- package/templates/default/src/app/(base)/template-step-groups/template-step-group-form.tsx +167 -0
- package/templates/default/src/app/(base)/template-step-groups/template-step-group-table-columns.tsx +89 -0
- package/templates/default/src/app/(base)/template-step-groups/template-step-group-table.tsx +32 -0
- package/templates/default/src/app/(base)/template-steps/create/page.tsx +37 -0
- package/templates/default/src/app/(base)/template-steps/modify/[id]/page.tsx +49 -0
- package/templates/default/src/app/(base)/template-steps/page.tsx +59 -0
- package/templates/default/src/app/(base)/template-steps/paramChip.tsx +213 -0
- package/templates/default/src/app/(base)/template-steps/template-step-form.tsx +384 -0
- package/templates/default/src/app/(base)/template-steps/template-step-table-columns.tsx +158 -0
- package/templates/default/src/app/(base)/template-steps/template-step-table.tsx +24 -0
- package/templates/default/src/app/(base)/template-test-cases/create/page.tsx +56 -0
- package/templates/default/src/app/(base)/template-test-cases/modify/[id]/page.tsx +89 -0
- package/templates/default/src/app/(base)/template-test-cases/page.tsx +58 -0
- package/templates/default/src/app/(base)/template-test-cases/template-test-case-flow.tsx +84 -0
- package/templates/default/src/app/(base)/template-test-cases/template-test-case-form.tsx +262 -0
- package/templates/default/src/app/(base)/template-test-cases/template-test-case-table-columns.tsx +76 -0
- package/templates/default/src/app/(base)/template-test-cases/template-test-case-table.tsx +32 -0
- package/templates/default/src/app/(base)/test-cases/create/page.tsx +76 -0
- package/templates/default/src/app/(base)/test-cases/create-from-template/generate/[id]/page.tsx +96 -0
- package/templates/default/src/app/(base)/test-cases/create-from-template/page.tsx +38 -0
- package/templates/default/src/app/(base)/test-cases/create-from-template/template-selection-form.tsx +73 -0
- package/templates/default/src/app/(base)/test-cases/modify/[id]/page.tsx +106 -0
- package/templates/default/src/app/(base)/test-cases/page.tsx +60 -0
- package/templates/default/src/app/(base)/test-cases/test-case-flow.tsx +82 -0
- package/templates/default/src/app/(base)/test-cases/test-case-form.tsx +395 -0
- package/templates/default/src/app/(base)/test-cases/test-case-table-columns.tsx +90 -0
- package/templates/default/src/app/(base)/test-cases/test-case-table.tsx +35 -0
- package/templates/default/src/app/(base)/test-runs/[id]/page.tsx +56 -0
- package/templates/default/src/app/(base)/test-runs/create/page.tsx +47 -0
- package/templates/default/src/app/(base)/test-runs/page.tsx +60 -0
- package/templates/default/src/app/(base)/test-runs/test-run-form.tsx +512 -0
- package/templates/default/src/app/(base)/test-runs/test-run-table-columns.tsx +229 -0
- package/templates/default/src/app/(base)/test-runs/test-run-table.tsx +127 -0
- package/templates/default/src/app/(base)/test-suites/create/page.tsx +45 -0
- package/templates/default/src/app/(base)/test-suites/modify/[id]/page.tsx +55 -0
- package/templates/default/src/app/(base)/test-suites/page.tsx +82 -0
- package/templates/default/src/app/(base)/test-suites/test-suite-form.tsx +269 -0
- package/templates/default/src/app/(base)/test-suites/test-suite-table-columns.tsx +97 -0
- package/templates/default/src/app/(base)/test-suites/test-suite-table.tsx +29 -0
- package/templates/default/src/app/(dashboard-components)/app-drawer.tsx +187 -0
- package/templates/default/src/app/(dashboard-components)/data-card-grid.tsx +13 -0
- package/templates/default/src/app/(dashboard-components)/data-card.tsx +27 -0
- package/templates/default/src/app/(dashboard-components)/execution-health-panel.tsx +57 -0
- package/templates/default/src/app/(dashboard-components)/ongoing-test-runs-card.tsx +87 -0
- package/templates/default/src/app/(dashboard-components)/quick-actions-drawer.tsx +45 -0
- package/templates/default/src/app/api/test-runs/[runId]/download/route.ts +133 -0
- package/templates/default/src/app/api/test-runs/[runId]/logs/route.ts +420 -0
- package/templates/default/src/app/api/test-runs/[runId]/trace/[testCaseId]/route.ts +146 -0
- package/templates/default/src/app/favicon.ico +0 -0
- package/templates/default/src/app/globals.css +147 -0
- package/templates/default/src/app/layout.tsx +171 -0
- package/templates/default/src/app/page.tsx +64 -0
- package/templates/default/src/assets/icons/empty-tube.tsx +23 -0
- package/templates/default/src/assets/icons/tube-plus.tsx +29 -0
- package/templates/default/src/components/base-node.tsx +21 -0
- package/templates/default/src/components/chart/pie-chart.tsx +73 -0
- package/templates/default/src/components/data-extraction/locator-inspector.tsx +460 -0
- package/templates/default/src/components/data-state/empty-state.tsx +40 -0
- package/templates/default/src/components/data-visualization/info-card.tsx +70 -0
- package/templates/default/src/components/data-visualization/info-grid.tsx +22 -0
- package/templates/default/src/components/devtools/providers.tsx +13 -0
- package/templates/default/src/components/diagram/button-edge.tsx +54 -0
- package/templates/default/src/components/diagram/dynamic-parameters.tsx +438 -0
- package/templates/default/src/components/diagram/edit-header-option.tsx +36 -0
- package/templates/default/src/components/diagram/flow-diagram.tsx +470 -0
- package/templates/default/src/components/diagram/node-form.tsx +262 -0
- package/templates/default/src/components/diagram/options-header-node.tsx +57 -0
- package/templates/default/src/components/diagram/template-step-combobox.tsx +155 -0
- package/templates/default/src/components/form/error-message.tsx +7 -0
- package/templates/default/src/components/kokonutui/smooth-tab.tsx +453 -0
- package/templates/default/src/components/loading-skeleton/data-table/data-table-skeleton.tsx +30 -0
- package/templates/default/src/components/loading-skeleton/form/button-skeleton.tsx +8 -0
- package/templates/default/src/components/loading-skeleton/form/icon-button-skeleton.tsx +8 -0
- package/templates/default/src/components/loading-skeleton/form/text-input-skeleton.tsx +8 -0
- package/templates/default/src/components/loading-skeleton/visualization/table-skeleton.tsx +14 -0
- package/templates/default/src/components/logo.tsx +15 -0
- package/templates/default/src/components/navigation/command-badge.tsx +34 -0
- package/templates/default/src/components/navigation/command-chain-input.tsx +51 -0
- package/templates/default/src/components/navigation/entity-search-command.tsx +116 -0
- package/templates/default/src/components/navigation/nav-card.tsx +31 -0
- package/templates/default/src/components/navigation/nav-command.tsx +508 -0
- package/templates/default/src/components/navigation/nav-link.tsx +60 -0
- package/templates/default/src/components/navigation/nav-menu-card-deck.tsx +112 -0
- package/templates/default/src/components/node-header.tsx +159 -0
- package/templates/default/src/components/reports/test-case-logs-modal.tsx +253 -0
- package/templates/default/src/components/table/table-actions.tsx +172 -0
- package/templates/default/src/components/test-run/download-logs-button.tsx +99 -0
- package/templates/default/src/components/test-run/log-viewer.tsx +445 -0
- package/templates/default/src/components/test-run/test-run-details.tsx +611 -0
- package/templates/default/src/components/test-run/test-run-header.tsx +149 -0
- package/templates/default/src/components/test-run/view-report-button.tsx +102 -0
- package/templates/default/src/components/theme/mode-toggle.tsx +54 -0
- package/templates/default/src/components/theme/theme-provider.tsx +8 -0
- package/templates/default/src/components/typography/page-header-subtitle.tsx +7 -0
- package/templates/default/src/components/typography/page-header.tsx +7 -0
- package/templates/default/src/components/ui/alert-dialog.tsx +106 -0
- package/templates/default/src/components/ui/alert.tsx +43 -0
- package/templates/default/src/components/ui/avatar.tsx +40 -0
- package/templates/default/src/components/ui/badge.tsx +29 -0
- package/templates/default/src/components/ui/button.tsx +47 -0
- package/templates/default/src/components/ui/calendar.tsx +158 -0
- package/templates/default/src/components/ui/card.tsx +43 -0
- package/templates/default/src/components/ui/chart.tsx +369 -0
- package/templates/default/src/components/ui/checkbox.tsx +28 -0
- package/templates/default/src/components/ui/command.tsx +135 -0
- package/templates/default/src/components/ui/data-table-column-header.tsx +61 -0
- package/templates/default/src/components/ui/data-table-pagination.tsx +87 -0
- package/templates/default/src/components/ui/data-table-view-options.tsx +50 -0
- package/templates/default/src/components/ui/data-table.tsx +267 -0
- package/templates/default/src/components/ui/dialog.tsx +97 -0
- package/templates/default/src/components/ui/dropdown-menu.tsx +182 -0
- package/templates/default/src/components/ui/empty.tsx +104 -0
- package/templates/default/src/components/ui/input.tsx +22 -0
- package/templates/default/src/components/ui/kbd.tsx +28 -0
- package/templates/default/src/components/ui/label.tsx +19 -0
- package/templates/default/src/components/ui/loading.tsx +12 -0
- package/templates/default/src/components/ui/multi-select-with-preview.tsx +116 -0
- package/templates/default/src/components/ui/multi-select.tsx +142 -0
- package/templates/default/src/components/ui/navigation-menu.tsx +120 -0
- package/templates/default/src/components/ui/popover.tsx +33 -0
- package/templates/default/src/components/ui/progress.tsx +25 -0
- package/templates/default/src/components/ui/radio-group.tsx +44 -0
- package/templates/default/src/components/ui/scroll-area.tsx +40 -0
- package/templates/default/src/components/ui/select.tsx +144 -0
- package/templates/default/src/components/ui/separator.tsx +22 -0
- package/templates/default/src/components/ui/skeleton.tsx +7 -0
- package/templates/default/src/components/ui/table.tsx +76 -0
- package/templates/default/src/components/ui/tabs.tsx +55 -0
- package/templates/default/src/components/ui/textarea.tsx +21 -0
- package/templates/default/src/components/ui/toast.tsx +113 -0
- package/templates/default/src/components/ui/toaster.tsx +26 -0
- package/templates/default/src/components/ui/tooltip.tsx +32 -0
- package/templates/default/src/components/user-prompt/delete-prompt.tsx +87 -0
- package/templates/default/src/config/db-config.ts +10 -0
- package/templates/default/src/constants/form-opts/diagram/node-form.ts +30 -0
- package/templates/default/src/constants/form-opts/environment-form-opts.ts +24 -0
- package/templates/default/src/constants/form-opts/locator-form-opts.ts +20 -0
- package/templates/default/src/constants/form-opts/locator-group-form-opts.ts +28 -0
- package/templates/default/src/constants/form-opts/module-form-opts.ts +21 -0
- package/templates/default/src/constants/form-opts/review-form-opts.ts +23 -0
- package/templates/default/src/constants/form-opts/tag-form-opts.ts +42 -0
- package/templates/default/src/constants/form-opts/template-selection-form-opts.ts +16 -0
- package/templates/default/src/constants/form-opts/template-step-group-form-opts.ts +24 -0
- package/templates/default/src/constants/form-opts/template-test-case-form-opts.ts +39 -0
- package/templates/default/src/constants/form-opts/template-test-step-form-opts.ts +36 -0
- package/templates/default/src/constants/form-opts/test-case-form-opts.ts +43 -0
- package/templates/default/src/constants/form-opts/test-run-form-opts.ts +31 -0
- package/templates/default/src/constants/form-opts/test-suite-form-opts.ts +24 -0
- package/templates/default/src/hooks/use-toast.ts +187 -0
- package/templates/default/src/lib/bidirectional-sync.ts +432 -0
- package/templates/default/src/lib/database-sync.ts +531 -0
- package/templates/default/src/lib/environment-file-utils.ts +221 -0
- package/templates/default/src/lib/feature-file-generator.ts +411 -0
- package/templates/default/src/lib/gherkin-parser.ts +259 -0
- package/templates/default/src/lib/locator-group-file-utils.ts +370 -0
- package/templates/default/src/lib/metrics/metric-calculator.ts +613 -0
- package/templates/default/src/lib/module-hierarchy-builder.ts +205 -0
- package/templates/default/src/lib/path-helpers/module-path.ts +71 -0
- package/templates/default/src/lib/test-case-utils.ts +6 -0
- package/templates/default/src/lib/test-run/log-formatter.ts +83 -0
- package/templates/default/src/lib/test-run/process-manager.ts +191 -0
- package/templates/default/src/lib/test-run/report-parser.ts +316 -0
- package/templates/default/src/lib/test-run/test-run-executor.ts +144 -0
- package/templates/default/src/lib/test-run/winston-logger.ts +95 -0
- package/templates/default/src/lib/transformers/gherkin-converter.ts +42 -0
- package/templates/default/src/lib/transformers/key-to-icon-transformer.tsx +95 -0
- package/templates/default/src/lib/transformers/template-test-case-converter.ts +160 -0
- package/templates/default/src/lib/utils/node-param-validation.ts +81 -0
- package/templates/default/src/lib/utils/template-step-file-generator.ts +167 -0
- package/templates/default/src/lib/utils/template-step-file-manager-intelligent.ts +723 -0
- package/templates/default/src/lib/utils/template-step-file-manager.ts +166 -0
- package/templates/default/src/lib/utils.ts +31 -0
- package/templates/default/src/tests/config/environments/environments.json +14 -0
- package/templates/default/src/tests/config/executor/world.ts +41 -0
- package/templates/default/src/tests/executor.ts +80 -0
- package/templates/default/src/tests/hooks/hooks.ts +99 -0
- package/templates/default/src/tests/mapping/locator-map.json +1 -0
- package/templates/default/src/tests/steps/actions/click.step.ts +62 -0
- package/templates/default/src/tests/steps/actions/hover.step.ts +31 -0
- package/templates/default/src/tests/steps/actions/input.step.ts +149 -0
- package/templates/default/src/tests/steps/actions/navigation.step.ts +72 -0
- package/templates/default/src/tests/steps/actions/random_data.step.ts +146 -0
- package/templates/default/src/tests/steps/actions/store.step.ts +90 -0
- package/templates/default/src/tests/steps/actions/wait.step.ts +107 -0
- package/templates/default/src/tests/steps/validations/active_state_assertion.step.ts +34 -0
- package/templates/default/src/tests/steps/validations/navigation_assertion.step.ts +23 -0
- package/templates/default/src/tests/steps/validations/text_assertion.step.ts +111 -0
- package/templates/default/src/tests/steps/validations/visibility_assertion.step.ts +30 -0
- package/templates/default/src/tests/support/parameter-types.ts +12 -0
- package/templates/default/src/tests/utils/cache.util.ts +260 -0
- package/templates/default/src/tests/utils/cli.util.ts +177 -0
- package/templates/default/src/tests/utils/environment.util.ts +65 -0
- package/templates/default/src/tests/utils/locator.util.ts +248 -0
- package/templates/default/src/tests/utils/random-data.util.ts +45 -0
- package/templates/default/src/tests/utils/spawner.util.ts +617 -0
- package/templates/default/src/types/diagram/diagram.ts +34 -0
- package/templates/default/src/types/diagram/template-step.ts +11 -0
- package/templates/default/src/types/executor/browser.type.ts +1 -0
- package/templates/default/src/types/form/actionHandler.ts +6 -0
- package/templates/default/src/types/locator/locator.type.ts +11 -0
- package/templates/default/src/types/step/step.type.ts +1 -0
- package/templates/default/src/types/table/data-table.ts +6 -0
- package/templates/default/tailwind.config.ts +62 -0
- package/templates/default/tsconfig.json +28 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import prisma from '@/config/db-config'
|
|
2
|
+
import { writeTemplateStepFile, deleteTemplateStepFile, generateFileContent } from './template-step-file-generator'
|
|
3
|
+
import { TemplateStepGroupType } from '@prisma/client'
|
|
4
|
+
|
|
5
|
+
// TemplateStepGroupType helper - will be available from @prisma/client after migration
|
|
6
|
+
type TemplateStepGroupTypeLocal = 'ACTION' | 'VALIDATION'
|
|
7
|
+
|
|
8
|
+
// Type helper to safely extract type from Prisma templateStepGroup records
|
|
9
|
+
type TemplateStepGroupWithType = {
|
|
10
|
+
id: string
|
|
11
|
+
name: string
|
|
12
|
+
description: string | null
|
|
13
|
+
type?: TemplateStepGroupTypeLocal
|
|
14
|
+
createdAt: Date
|
|
15
|
+
updatedAt: Date
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function getGroupType(group: unknown): TemplateStepGroupTypeLocal {
|
|
19
|
+
const groupWithType = group as TemplateStepGroupWithType
|
|
20
|
+
const type = groupWithType.type
|
|
21
|
+
if (type === 'VALIDATION' || type === 'ACTION') {
|
|
22
|
+
return type
|
|
23
|
+
}
|
|
24
|
+
return 'ACTION' // default
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Regenerates the file for a specific template step group
|
|
29
|
+
* This function is called whenever template steps in a group change
|
|
30
|
+
*/
|
|
31
|
+
export async function regenerateTemplateStepGroupFile(groupId: string): Promise<void> {
|
|
32
|
+
try {
|
|
33
|
+
// Get the template step group with all its template steps
|
|
34
|
+
const group = await prisma.templateStepGroup.findUnique({
|
|
35
|
+
where: { id: groupId },
|
|
36
|
+
include: {
|
|
37
|
+
templateSteps: {
|
|
38
|
+
orderBy: {
|
|
39
|
+
// Order by creation time or any other field you prefer
|
|
40
|
+
createdAt: 'asc',
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
if (!group) {
|
|
47
|
+
throw new Error(`Template step group with ID ${groupId} not found`)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Generate file content from template steps
|
|
51
|
+
const content = generateFileContent(group.templateSteps)
|
|
52
|
+
|
|
53
|
+
// Write the file
|
|
54
|
+
const type = getGroupType(group)
|
|
55
|
+
await writeTemplateStepFile(group.name, content, type)
|
|
56
|
+
|
|
57
|
+
console.log(`File regenerated for template step group: ${group.name}`)
|
|
58
|
+
} catch (error) {
|
|
59
|
+
console.error(`Failed to regenerate file for template step group ${groupId}:`, error)
|
|
60
|
+
throw new Error(`File regeneration failed: ${error}`)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Creates a placeholder file for a new template step group
|
|
66
|
+
* Called when a new group is created
|
|
67
|
+
* @deprecated Use createTemplateStepGroupFile from template-step-file-manager-intelligent.ts instead
|
|
68
|
+
*/
|
|
69
|
+
export async function createTemplateStepGroupFile(
|
|
70
|
+
groupName: string,
|
|
71
|
+
type: TemplateStepGroupType | string = 'ACTION',
|
|
72
|
+
): Promise<void> {
|
|
73
|
+
try {
|
|
74
|
+
// Create empty placeholder content with required imports
|
|
75
|
+
const placeholderContent =
|
|
76
|
+
'// This file is generated automatically. Add template steps to this group to generate content.'
|
|
77
|
+
|
|
78
|
+
// Write the placeholder file
|
|
79
|
+
await writeTemplateStepFile(groupName, placeholderContent, type)
|
|
80
|
+
|
|
81
|
+
console.log(`Placeholder file created for template step group: ${groupName}`)
|
|
82
|
+
} catch (error) {
|
|
83
|
+
console.error(`Failed to create placeholder file for group "${groupName}":`, error)
|
|
84
|
+
throw new Error(`File creation failed: ${error}`)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Deletes the file for a template step group
|
|
90
|
+
* Called when a group is deleted
|
|
91
|
+
* @deprecated Use removeTemplateStepGroupFile from template-step-file-manager-intelligent.ts instead
|
|
92
|
+
*/
|
|
93
|
+
export async function removeTemplateStepGroupFile(
|
|
94
|
+
groupName: string,
|
|
95
|
+
type: TemplateStepGroupType | string = 'ACTION',
|
|
96
|
+
): Promise<void> {
|
|
97
|
+
try {
|
|
98
|
+
await deleteTemplateStepFile(groupName, type)
|
|
99
|
+
|
|
100
|
+
console.log(`File deleted for template step group: ${groupName}`)
|
|
101
|
+
} catch (error) {
|
|
102
|
+
console.error(`Failed to delete file for group "${groupName}":`, error)
|
|
103
|
+
throw new Error(`File deletion failed: ${error}`)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Handles file regeneration when a template step is created, updated, or deleted
|
|
109
|
+
* This function determines which groups need file regeneration
|
|
110
|
+
*/
|
|
111
|
+
export async function handleTemplateStepChange(
|
|
112
|
+
templateStepId: string,
|
|
113
|
+
operation: 'create' | 'update' | 'delete',
|
|
114
|
+
): Promise<void> {
|
|
115
|
+
try {
|
|
116
|
+
let groupId: string | null = null
|
|
117
|
+
|
|
118
|
+
if (operation === 'delete') {
|
|
119
|
+
// For delete operations, we need to get the group ID before deletion
|
|
120
|
+
const step = await prisma.templateStep.findUnique({
|
|
121
|
+
where: { id: templateStepId },
|
|
122
|
+
select: { templateStepGroupId: true },
|
|
123
|
+
})
|
|
124
|
+
groupId = step?.templateStepGroupId || null
|
|
125
|
+
} else {
|
|
126
|
+
// For create/update operations, get the current group ID
|
|
127
|
+
const step = await prisma.templateStep.findUnique({
|
|
128
|
+
where: { id: templateStepId },
|
|
129
|
+
select: { templateStepGroupId: true },
|
|
130
|
+
})
|
|
131
|
+
groupId = step?.templateStepGroupId || null
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (groupId) {
|
|
135
|
+
// Regenerate the file for the affected group
|
|
136
|
+
await regenerateTemplateStepGroupFile(groupId)
|
|
137
|
+
}
|
|
138
|
+
} catch (error) {
|
|
139
|
+
console.error(`Failed to handle template step change for step ${templateStepId}:`, error)
|
|
140
|
+
throw new Error(`File update failed: ${error}`)
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Handles file regeneration when a template step is moved between groups
|
|
146
|
+
* This is a special case that requires regenerating files for both groups
|
|
147
|
+
*/
|
|
148
|
+
export async function handleTemplateStepGroupChange(
|
|
149
|
+
oldGroupId: string | null,
|
|
150
|
+
newGroupId: string | null,
|
|
151
|
+
): Promise<void> {
|
|
152
|
+
try {
|
|
153
|
+
// Regenerate file for the old group (if it exists)
|
|
154
|
+
if (oldGroupId) {
|
|
155
|
+
await regenerateTemplateStepGroupFile(oldGroupId)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Regenerate file for the new group (if it exists)
|
|
159
|
+
if (newGroupId) {
|
|
160
|
+
await regenerateTemplateStepGroupFile(newGroupId)
|
|
161
|
+
}
|
|
162
|
+
} catch (error) {
|
|
163
|
+
console.error(`Failed to handle template step group change:`, error)
|
|
164
|
+
throw new Error(`File update failed: ${error}`)
|
|
165
|
+
}
|
|
166
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { clsx, type ClassValue } from 'clsx'
|
|
2
|
+
import { twMerge } from 'tailwind-merge'
|
|
3
|
+
export function cn(...inputs: ClassValue[]) {
|
|
4
|
+
return twMerge(clsx(inputs))
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function calculateCompletionPercentage(total: number, completed: number) {
|
|
8
|
+
return Math.round((completed / total) * 100)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Formats a date to show only date and time (without seconds/milliseconds)
|
|
13
|
+
* @param date - Date string or Date object
|
|
14
|
+
* @returns Formatted date string in format: "MM/DD/YYYY, HH:MM AM/PM"
|
|
15
|
+
*/
|
|
16
|
+
export function formatDateTime(date: string | Date | null | undefined): string {
|
|
17
|
+
if (!date) return '-'
|
|
18
|
+
|
|
19
|
+
const dateObj = typeof date === 'string' ? new Date(date) : date
|
|
20
|
+
|
|
21
|
+
if (isNaN(dateObj.getTime())) return '-'
|
|
22
|
+
|
|
23
|
+
return dateObj.toLocaleString('en-US', {
|
|
24
|
+
year: 'numeric',
|
|
25
|
+
month: '2-digit',
|
|
26
|
+
day: '2-digit',
|
|
27
|
+
hour: '2-digit',
|
|
28
|
+
minute: '2-digit',
|
|
29
|
+
hour12: true,
|
|
30
|
+
})
|
|
31
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"demoqa": {
|
|
3
|
+
"baseUrl": "https://demoqa.com/",
|
|
4
|
+
"apiBaseUrl": "",
|
|
5
|
+
"email": "",
|
|
6
|
+
"password": ""
|
|
7
|
+
},
|
|
8
|
+
"demo_test_site": {
|
|
9
|
+
"baseUrl": "https://demo-test-site-beta.vercel.app/login",
|
|
10
|
+
"apiBaseUrl": "",
|
|
11
|
+
"email": "demo@example.com",
|
|
12
|
+
"password": ""
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { World, IWorldOptions, setWorldConstructor, setDefaultTimeout } from '@cucumber/cucumber'
|
|
2
|
+
import * as chai from 'chai'
|
|
3
|
+
import chaiAsPromised from 'chai-as-promised'
|
|
4
|
+
import { BrowserContext, Page } from 'playwright'
|
|
5
|
+
|
|
6
|
+
setDefaultTimeout(120 * 1000)
|
|
7
|
+
|
|
8
|
+
export interface ScenarioData {
|
|
9
|
+
token?: string
|
|
10
|
+
vars: Record<string, unknown>
|
|
11
|
+
}
|
|
12
|
+
export class CustomWorld extends World {
|
|
13
|
+
context!: BrowserContext
|
|
14
|
+
page!: Page
|
|
15
|
+
data: ScenarioData = {
|
|
16
|
+
vars: {},
|
|
17
|
+
}
|
|
18
|
+
constructor(options: IWorldOptions) {
|
|
19
|
+
super(options)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
setVar(key: string, value: unknown): void {
|
|
23
|
+
this.data.vars[key] = value
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
getVar<T = unknown>(key: string): T {
|
|
27
|
+
if (!(key in this.data.vars)) {
|
|
28
|
+
throw new Error(`Variable ${key} not found`)
|
|
29
|
+
}
|
|
30
|
+
return this.data.vars[key] as T
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
clearVars(): void {
|
|
34
|
+
this.data.vars = {}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
setWorldConstructor(CustomWorld)
|
|
39
|
+
|
|
40
|
+
chai.use(chaiAsPromised)
|
|
41
|
+
export const expect = chai.expect
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { BrowserName } from '@/types/executor/browser.type'
|
|
2
|
+
import { CliOptions, startCli } from '@/tests/utils/cli.util.js'
|
|
3
|
+
import { spawnTask, waitForTask } from '@/tests/utils/spawner.util.js'
|
|
4
|
+
import { config } from 'dotenv'
|
|
5
|
+
|
|
6
|
+
function setEnvironmentVariables(environment: string, headless: boolean, browser: BrowserName) {
|
|
7
|
+
process.env.ENVIRONMENT = environment
|
|
8
|
+
process.env.HEADLESS = headless.toString()
|
|
9
|
+
process.env.BROWSER = browser
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Main entry point for the CLI application
|
|
14
|
+
* Handles CLI parsing, error handling, and application lifecycle
|
|
15
|
+
*/
|
|
16
|
+
async function bootstrap(): Promise<void> {
|
|
17
|
+
// Load environment variables
|
|
18
|
+
config()
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
// Parse CLI arguments and get options
|
|
22
|
+
const { environment, tags, parallel, browser, headless }: CliOptions = startCli()
|
|
23
|
+
|
|
24
|
+
// Log parsed options with better formatting
|
|
25
|
+
console.log(
|
|
26
|
+
`Running tests in the following configuration\nEnvironment: ${environment}\nTags: ${tags}\nParallel: ${parallel}\nBrowser: ${browser}\nHeadless: ${headless}`,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
setEnvironmentVariables(environment, headless as unknown as boolean, browser as unknown as BrowserName)
|
|
30
|
+
|
|
31
|
+
// Build the cucumber command with appropriate flags
|
|
32
|
+
const cucumberArgs: string[] = []
|
|
33
|
+
|
|
34
|
+
if (tags) {
|
|
35
|
+
cucumberArgs.push('-t', tags)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (parallel > 1) {
|
|
39
|
+
cucumberArgs.push('--parallel', parallel.toString())
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Spawn the cucumber test process
|
|
43
|
+
console.log('🚀 Starting cucumber test process...')
|
|
44
|
+
await spawnTask('npm', ['run', 'test', ...cucumberArgs], {
|
|
45
|
+
streamLogs: true,
|
|
46
|
+
prefixLogs: true,
|
|
47
|
+
logPrefix: 'cucumber-test',
|
|
48
|
+
captureOutput: true,
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
// Wait for the test process to complete
|
|
52
|
+
const exitCode = await waitForTask('cucumber-test')
|
|
53
|
+
|
|
54
|
+
if (exitCode === 0) {
|
|
55
|
+
console.log('✅ Tests completed successfully')
|
|
56
|
+
} else {
|
|
57
|
+
console.log(`❌ Tests failed with exit code: ${exitCode}`)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
process.exit(exitCode || 0)
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error('❌ Application failed with error:')
|
|
63
|
+
console.error(error instanceof Error ? error.message : 'Unknown error occurred')
|
|
64
|
+
process.exit(1)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Handle uncaught exceptions and unhandled rejections
|
|
69
|
+
process.on('uncaughtException', error => {
|
|
70
|
+
console.error('❌ Uncaught Exception:', error.message)
|
|
71
|
+
process.exit(1)
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
process.on('unhandledRejection', reason => {
|
|
75
|
+
console.error('❌ Unhandled Rejection:', reason)
|
|
76
|
+
process.exit(1)
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
// Start the application
|
|
80
|
+
bootstrap()
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { After, AfterAll, AfterStep, Before, BeforeAll, setDefaultTimeout } from '@cucumber/cucumber'
|
|
2
|
+
import { CustomWorld } from '../config/executor/world.js'
|
|
3
|
+
import { BrowserName } from '@/types/executor/browser.type'
|
|
4
|
+
import { config } from 'dotenv'
|
|
5
|
+
import { chromium, ChromiumBrowser, firefox, FirefoxBrowser, webkit, WebKitBrowser } from 'playwright'
|
|
6
|
+
|
|
7
|
+
// Load environment variables
|
|
8
|
+
config()
|
|
9
|
+
|
|
10
|
+
// Initialize browser
|
|
11
|
+
let browser: ChromiumBrowser | FirefoxBrowser | WebKitBrowser
|
|
12
|
+
|
|
13
|
+
// Track scenario status
|
|
14
|
+
let currentScenarioStatus: string = 'unknown'
|
|
15
|
+
|
|
16
|
+
BeforeAll(async function () {
|
|
17
|
+
setDefaultTimeout(60000)
|
|
18
|
+
const browserName = (process.env.BROWSER as BrowserName) || 'chromium'
|
|
19
|
+
switch (browserName) {
|
|
20
|
+
case 'chromium':
|
|
21
|
+
browser = await chromium.launch({
|
|
22
|
+
headless: process.env.HEADLESS === 'true',
|
|
23
|
+
})
|
|
24
|
+
break
|
|
25
|
+
case 'firefox':
|
|
26
|
+
browser = await firefox.launch({
|
|
27
|
+
headless: process.env.HEADLESS === 'true',
|
|
28
|
+
})
|
|
29
|
+
break
|
|
30
|
+
case 'webkit':
|
|
31
|
+
browser = await webkit.launch({
|
|
32
|
+
headless: process.env.HEADLESS === 'true',
|
|
33
|
+
})
|
|
34
|
+
break
|
|
35
|
+
default:
|
|
36
|
+
throw new Error(`Invalid browser name: ${browserName}`)
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
Before(async function (this: CustomWorld) {
|
|
41
|
+
this.clearVars()
|
|
42
|
+
this.context = await browser.newContext()
|
|
43
|
+
await this.context.tracing.start({
|
|
44
|
+
screenshots: true,
|
|
45
|
+
snapshots: true,
|
|
46
|
+
sources: true,
|
|
47
|
+
})
|
|
48
|
+
this.page = await this.context.newPage()
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
AfterStep(async function (this: CustomWorld, result) {
|
|
52
|
+
// Track the worst status encountered (failed > skipped > passed)
|
|
53
|
+
const status = result.result?.status
|
|
54
|
+
if (status === 'FAILED') {
|
|
55
|
+
currentScenarioStatus = 'failed'
|
|
56
|
+
} else if (status === 'SKIPPED' && currentScenarioStatus !== 'failed') {
|
|
57
|
+
currentScenarioStatus = 'skipped'
|
|
58
|
+
} else if (status === 'PASSED' && currentScenarioStatus === 'unknown') {
|
|
59
|
+
currentScenarioStatus = 'passed'
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
After(async function (this: CustomWorld, scenario) {
|
|
64
|
+
// Emit scenario end event as JSON to stdout
|
|
65
|
+
// ProcessManager will parse this and re-emit it as an event
|
|
66
|
+
let tracePath: string | undefined
|
|
67
|
+
if (scenario.result?.status === 'FAILED') {
|
|
68
|
+
tracePath = `${process.cwd()}/src/tests/reports/traces/${crypto.randomUUID()}.zip`
|
|
69
|
+
await this.context.tracing.stop({
|
|
70
|
+
path: tracePath,
|
|
71
|
+
})
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const eventData = {
|
|
75
|
+
event: 'scenario::end',
|
|
76
|
+
data: {
|
|
77
|
+
scenarioName: scenario.pickle.name,
|
|
78
|
+
status: currentScenarioStatus,
|
|
79
|
+
tracePath: tracePath,
|
|
80
|
+
},
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Write to stdout in a parseable JSON format
|
|
84
|
+
// Use process.stdout.write to ensure it's captured by TaskSpawner
|
|
85
|
+
const eventJson = JSON.stringify(eventData)
|
|
86
|
+
console.log(eventJson)
|
|
87
|
+
// Also write directly to stdout to ensure it's captured
|
|
88
|
+
process.stdout.write(eventJson + '\n')
|
|
89
|
+
|
|
90
|
+
// Reset status for next scenario
|
|
91
|
+
currentScenarioStatus = 'unknown'
|
|
92
|
+
|
|
93
|
+
await this.page.close()
|
|
94
|
+
await this.context.close()
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
AfterAll(async function () {
|
|
98
|
+
await browser.close()
|
|
99
|
+
})
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[]
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @name click
|
|
3
|
+
* @description Template step for handling element click
|
|
4
|
+
* @type ACTION
|
|
5
|
+
*/
|
|
6
|
+
import { When } from '@cucumber/cucumber'
|
|
7
|
+
import { CustomWorld } from '../../config/executor/world.js'
|
|
8
|
+
import { SelectorName } from '@/types/locator/locator.type'
|
|
9
|
+
import { resolveLocator } from '../../utils/locator.util.js'
|
|
10
|
+
|
|
11
|
+
// This file is generated automatically. Add template steps to this group to generate content.
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @name click
|
|
15
|
+
* @description Template step for clicking on an element
|
|
16
|
+
* @icon MOUSE
|
|
17
|
+
*/
|
|
18
|
+
When('the user clicks on the {string} element', async function (this: CustomWorld, elementName: SelectorName) {
|
|
19
|
+
const selector = await resolveLocator(this.page, elementName)
|
|
20
|
+
if (!selector) {
|
|
21
|
+
throw new Error(`Selector ${elementName} not found. Current url: ${this.page.url()}`)
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
await this.page.locator(selector).click()
|
|
25
|
+
} catch (error) {
|
|
26
|
+
throw new Error(`Failed to click on the ${elementName} element: ${error}`)
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @name double click
|
|
32
|
+
* @description Template step for double clicking on an element
|
|
33
|
+
* @icon MOUSE
|
|
34
|
+
*/
|
|
35
|
+
When('the user double clicks on the {string} element', async function (this: CustomWorld, elementName: SelectorName) {
|
|
36
|
+
const selector = await resolveLocator(this.page, elementName)
|
|
37
|
+
if (!selector) {
|
|
38
|
+
throw new Error(`Selector ${elementName} not found. Current url: ${this.page.url()}`)
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
await this.page.locator(selector).dblclick()
|
|
42
|
+
} catch (error) {
|
|
43
|
+
throw new Error(`Failed to double click on the ${elementName} element: ${error}`)
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @name right click
|
|
49
|
+
* @description Template step for right clicking on an element
|
|
50
|
+
* @icon MOUSE
|
|
51
|
+
*/
|
|
52
|
+
When('the user right clicks on the {string} element', async function (this: CustomWorld, elementName: SelectorName) {
|
|
53
|
+
const selector = await resolveLocator(this.page, elementName)
|
|
54
|
+
if (!selector) {
|
|
55
|
+
throw new Error(`Selector ${elementName} not found. Current url: ${this.page.url()}`)
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
await this.page.locator(selector).click({ button: 'right' })
|
|
59
|
+
} catch (error) {
|
|
60
|
+
throw new Error(`Failed to right click on the ${elementName} element: ${error}`)
|
|
61
|
+
}
|
|
62
|
+
})
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @name hover
|
|
3
|
+
* @description Template steps that handles hover actions
|
|
4
|
+
* @type ACTION
|
|
5
|
+
*/
|
|
6
|
+
import { When } from '@cucumber/cucumber';
|
|
7
|
+
import { CustomWorld } from '../../config/executor/world.js';
|
|
8
|
+
import { SelectorName } from '../../../types/locator/locator.type';
|
|
9
|
+
import { resolveLocator } from '../../utils/locator.util.js';
|
|
10
|
+
|
|
11
|
+
// This file is generated automatically. Add template steps to this group to generate content.
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @name hover
|
|
15
|
+
* @description Template step for hovering over an element
|
|
16
|
+
* @icon MOUSE
|
|
17
|
+
*/
|
|
18
|
+
When(
|
|
19
|
+
'the user hovers the cursor over the {string} element',
|
|
20
|
+
async function (this: CustomWorld, elementName: SelectorName) {
|
|
21
|
+
try {
|
|
22
|
+
const selector = await resolveLocator(this.page, elementName);
|
|
23
|
+
if (!selector) {
|
|
24
|
+
throw new Error(`Selector ${elementName} not found`);
|
|
25
|
+
}
|
|
26
|
+
await this.page.locator(selector).hover();
|
|
27
|
+
} catch (error) {
|
|
28
|
+
throw new Error(`Failed to hover over the ${elementName} element: ${error}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
);
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @name input
|
|
3
|
+
* @description Template steps that deal with inputs
|
|
4
|
+
* @type ACTION
|
|
5
|
+
*/
|
|
6
|
+
import { When } from '@cucumber/cucumber';
|
|
7
|
+
import { CustomWorld } from '../../config/executor/world.js';
|
|
8
|
+
import { SelectorName } from '@/types/locator/locator.type';
|
|
9
|
+
import { resolveLocator } from '../../utils/locator.util.js';
|
|
10
|
+
|
|
11
|
+
// This file is generated automatically. Add template steps to this group to generate content.
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @name fill
|
|
15
|
+
* @description Template step for filling up an input field with a provided value
|
|
16
|
+
* @icon INPUT
|
|
17
|
+
*/
|
|
18
|
+
When(
|
|
19
|
+
'the user fills in the {string} input field with value {string}',
|
|
20
|
+
async function (this: CustomWorld, elementName: SelectorName, value: string) {
|
|
21
|
+
const selector = await resolveLocator(this.page, elementName);
|
|
22
|
+
if (!selector) {
|
|
23
|
+
throw new Error(`Selector ${elementName} not found`);
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
await this.page.locator(selector).fill(value);
|
|
27
|
+
} catch (error) {
|
|
28
|
+
throw new Error(
|
|
29
|
+
`Failed to fill in the ${elementName} input field with value ${value}: ${error}`
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @name clear
|
|
37
|
+
* @description Template step for clearing an input field
|
|
38
|
+
* @icon INPUT
|
|
39
|
+
*/
|
|
40
|
+
When(
|
|
41
|
+
'the user clears the {string} field',
|
|
42
|
+
async function (this: CustomWorld, elementName: SelectorName) {
|
|
43
|
+
const selector = await resolveLocator(this.page, elementName);
|
|
44
|
+
if (!selector) {
|
|
45
|
+
throw new Error(`Selector ${elementName} not found`);
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
await this.page.locator(selector).clear();
|
|
49
|
+
} catch (error) {
|
|
50
|
+
throw new Error(`Failed to clear the ${elementName} field: ${error}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @name select dropdown option
|
|
57
|
+
* @description Template step for selecting a particular option inside a dropdown element
|
|
58
|
+
* @icon INPUT
|
|
59
|
+
*/
|
|
60
|
+
When(
|
|
61
|
+
'the user selects the {string} option of the {string} dropdown',
|
|
62
|
+
async function (
|
|
63
|
+
this: CustomWorld,
|
|
64
|
+
optionName: string,
|
|
65
|
+
elementName: SelectorName
|
|
66
|
+
) {
|
|
67
|
+
const selector = await resolveLocator(this.page, elementName);
|
|
68
|
+
if (!selector) {
|
|
69
|
+
throw new Error(`Selector ${elementName} not found`);
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
await this.page.locator(selector).selectOption(optionName);
|
|
73
|
+
} catch (error) {
|
|
74
|
+
throw new Error(
|
|
75
|
+
`Failed to select the ${optionName} option of the ${elementName} dropdown: ${error}`
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @name check
|
|
83
|
+
* @description Template step for checking a checkbox
|
|
84
|
+
* @icon INPUT
|
|
85
|
+
*/
|
|
86
|
+
When(
|
|
87
|
+
'the user checks the {string} checkbox',
|
|
88
|
+
async function (this: CustomWorld, elementName: SelectorName) {
|
|
89
|
+
const selector = await resolveLocator(this.page, elementName);
|
|
90
|
+
if (!selector) {
|
|
91
|
+
throw new Error(`Selector ${elementName} not found`);
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
await this.page.locator(selector).check();
|
|
95
|
+
} catch (error) {
|
|
96
|
+
throw new Error(`Failed to check the ${elementName} checkbox: ${error}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* @name uncheck
|
|
103
|
+
* @description Template step for unchecking a checkbox
|
|
104
|
+
* @icon INPUT
|
|
105
|
+
*/
|
|
106
|
+
When(
|
|
107
|
+
'the user unchecks the {string} checkbox',
|
|
108
|
+
async function (this: CustomWorld, elementName: SelectorName) {
|
|
109
|
+
const selector = await resolveLocator(this.page, elementName);
|
|
110
|
+
if (!selector) {
|
|
111
|
+
throw new Error(`Selector ${elementName} not found`);
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
await this.page.locator(selector).uncheck();
|
|
115
|
+
} catch (error) {
|
|
116
|
+
throw new Error(
|
|
117
|
+
`Failed to uncheck the ${elementName} checkbox: ${error}`
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @name fill input with stored value
|
|
125
|
+
* @description Template step for filling an input field with data from a stored variable
|
|
126
|
+
* @icon INPUT
|
|
127
|
+
*/
|
|
128
|
+
When(
|
|
129
|
+
'the user fills in the {string} input with data from the stored variable {string}',
|
|
130
|
+
async function (
|
|
131
|
+
this: CustomWorld,
|
|
132
|
+
fieldName: SelectorName,
|
|
133
|
+
variableName: string
|
|
134
|
+
) {
|
|
135
|
+
const value = this.getVar<string>(variableName);
|
|
136
|
+
if (!value) {
|
|
137
|
+
throw new Error(`Variable ${variableName} not found`);
|
|
138
|
+
}
|
|
139
|
+
const selector = await resolveLocator(this.page, fieldName);
|
|
140
|
+
if (!selector) {
|
|
141
|
+
throw new Error(`Selector ${fieldName} not found`);
|
|
142
|
+
}
|
|
143
|
+
try {
|
|
144
|
+
await this.page.locator(selector).fill(value);
|
|
145
|
+
} catch (error) {
|
|
146
|
+
throw new Error(`Failed to fill in the ${fieldName} input field with data from the stored variable ${variableName}: ${error}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
);
|