@nextsparkjs/ai-workflow 0.1.0-beta.100
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/LICENSE +21 -0
- package/README.md +115 -0
- package/claude/_docs/workflows-optimizations.md +359 -0
- package/claude/agents/api-tester.md +634 -0
- package/claude/agents/architecture-supervisor.md +1351 -0
- package/claude/agents/backend-developer.md +997 -0
- package/claude/agents/backend-validator.md +417 -0
- package/claude/agents/bdd-docs-writer.md +737 -0
- package/claude/agents/block-developer.md +677 -0
- package/claude/agents/code-reviewer.md +1432 -0
- package/claude/agents/db-developer.md +721 -0
- package/claude/agents/db-validator.md +407 -0
- package/claude/agents/demo-video-generator.md +493 -0
- package/claude/agents/documentation-writer.md +1268 -0
- package/claude/agents/frontend-developer.md +1234 -0
- package/claude/agents/frontend-validator.md +777 -0
- package/claude/agents/functional-validator.md +630 -0
- package/claude/agents/mock-analyst.md +387 -0
- package/claude/agents/product-manager.md +963 -0
- package/claude/agents/qa-automation.md +1762 -0
- package/claude/agents/release-manager.md +634 -0
- package/claude/agents/selectors-translator.md +262 -0
- package/claude/agents/unit-test-writer.md +785 -0
- package/claude/agents/visual-comparator.md +329 -0
- package/claude/agents/workflow-maintainer.md +352 -0
- package/claude/commands/do/README.md +88 -0
- package/claude/commands/do/create-api.md +64 -0
- package/claude/commands/do/create-entity.md +66 -0
- package/claude/commands/do/create-migration.md +64 -0
- package/claude/commands/do/create-plugin.md +56 -0
- package/claude/commands/do/create-theme.md +70 -0
- package/claude/commands/do/mock-data.md +67 -0
- package/claude/commands/do/reset-db.md +71 -0
- package/claude/commands/do/setup-scheduled-action.md +75 -0
- package/claude/commands/do/sync-code-review.md +117 -0
- package/claude/commands/do/update-selectors.md +112 -0
- package/claude/commands/do/use-skills.md +90 -0
- package/claude/commands/do/validate-blocks.md +69 -0
- package/claude/commands/how-to/README.md +261 -0
- package/claude/commands/how-to/add-metadata.md +692 -0
- package/claude/commands/how-to/add-taxonomies.md +806 -0
- package/claude/commands/how-to/add-translations.md +571 -0
- package/claude/commands/how-to/create-api.md +577 -0
- package/claude/commands/how-to/create-block.md +575 -0
- package/claude/commands/how-to/create-child-entities.md +771 -0
- package/claude/commands/how-to/create-entity.md +597 -0
- package/claude/commands/how-to/create-migrations.md +605 -0
- package/claude/commands/how-to/create-plugin.md +654 -0
- package/claude/commands/how-to/customize-app.md +481 -0
- package/claude/commands/how-to/customize-dashboard.md +553 -0
- package/claude/commands/how-to/customize-theme.md +438 -0
- package/claude/commands/how-to/define-features-flows.md +632 -0
- package/claude/commands/how-to/deploy.md +507 -0
- package/claude/commands/how-to/handle-file-uploads.md +746 -0
- package/claude/commands/how-to/implement-search.md +1001 -0
- package/claude/commands/how-to/install-plugins.md +352 -0
- package/claude/commands/how-to/manage-test-coverage.md +984 -0
- package/claude/commands/how-to/run-tests.md +400 -0
- package/claude/commands/how-to/set-app-languages.md +601 -0
- package/claude/commands/how-to/set-plans-and-permissions.md +575 -0
- package/claude/commands/how-to/set-scheduled-actions.md +527 -0
- package/claude/commands/how-to/set-user-roles-and-permissions.md +550 -0
- package/claude/commands/how-to/setup-authentication.md +388 -0
- package/claude/commands/how-to/setup-claude-code.md +440 -0
- package/claude/commands/how-to/setup-database.md +274 -0
- package/claude/commands/how-to/setup-email-providers.md +598 -0
- package/claude/commands/how-to/setup-mobile-dev.md +627 -0
- package/claude/commands/how-to/start.md +500 -0
- package/claude/commands/how-to/use-devtools.md +639 -0
- package/claude/commands/how-to/use-superadmin.md +622 -0
- package/claude/commands/session/README.md +193 -0
- package/claude/commands/session/block-create.md +190 -0
- package/claude/commands/session/block-list.md +203 -0
- package/claude/commands/session/block-update.md +192 -0
- package/claude/commands/session/block-validate.md +218 -0
- package/claude/commands/session/changelog.md +115 -0
- package/claude/commands/session/close.md +225 -0
- package/claude/commands/session/commit.md +174 -0
- package/claude/commands/session/db-entity.md +206 -0
- package/claude/commands/session/db-fix.md +212 -0
- package/claude/commands/session/db-sample.md +206 -0
- package/claude/commands/session/demo.md +178 -0
- package/claude/commands/session/doc-bdd.md +207 -0
- package/claude/commands/session/doc-feature.md +218 -0
- package/claude/commands/session/doc-read.md +225 -0
- package/claude/commands/session/execute.md +204 -0
- package/claude/commands/session/explain.md +202 -0
- package/claude/commands/session/fix-bug.md +210 -0
- package/claude/commands/session/fix-build.md +182 -0
- package/claude/commands/session/fix-test.md +189 -0
- package/claude/commands/session/pending.md +232 -0
- package/claude/commands/session/refine.md +188 -0
- package/claude/commands/session/resume.md +192 -0
- package/claude/commands/session/review.md +192 -0
- package/claude/commands/session/scope-change.md +181 -0
- package/claude/commands/session/start-blocks.md +347 -0
- package/claude/commands/session/start.md +604 -0
- package/claude/commands/session/status.md +169 -0
- package/claude/commands/session/test-fix.md +221 -0
- package/claude/commands/session/test-run.md +203 -0
- package/claude/commands/session/test-write.md +242 -0
- package/claude/commands/session/validate.md +162 -0
- package/claude/config/context.json +40 -0
- package/claude/config/github.json +69 -0
- package/claude/config/github.schema.json +106 -0
- package/claude/config/team.json +46 -0
- package/claude/config/team.schema.json +106 -0
- package/claude/config/workspace.json +43 -0
- package/claude/config/workspace.schema.json +75 -0
- package/claude/skills/README.md +228 -0
- package/claude/skills/accessibility/SKILL.md +573 -0
- package/claude/skills/api-bypass-layers/SKILL.md +550 -0
- package/claude/skills/asana-integration/SKILL.md +499 -0
- package/claude/skills/better-auth/SKILL.md +666 -0
- package/claude/skills/billing-subscriptions/SKILL.md +660 -0
- package/claude/skills/block-decision-matrix/SKILL.md +359 -0
- package/claude/skills/clickup-integration/SKILL.md +434 -0
- package/claude/skills/core-theme-responsibilities/SKILL.md +485 -0
- package/claude/skills/create-plugin/SKILL.md +425 -0
- package/claude/skills/create-theme/SKILL.md +331 -0
- package/claude/skills/cypress-api/SKILL.md +511 -0
- package/claude/skills/cypress-api/scripts/generate-api-controller.py +329 -0
- package/claude/skills/cypress-api/scripts/generate-api-test.py +930 -0
- package/claude/skills/cypress-e2e/SKILL.md +526 -0
- package/claude/skills/cypress-e2e/scripts/extract-selectors.py +383 -0
- package/claude/skills/cypress-e2e/scripts/generate-uat-test.py +788 -0
- package/claude/skills/cypress-selectors/SKILL.md +309 -0
- package/claude/skills/cypress-selectors/scripts/extract-missing.py +243 -0
- package/claude/skills/cypress-selectors/scripts/generate-block-selectors.py +283 -0
- package/claude/skills/cypress-selectors/scripts/validate-selectors.py +145 -0
- package/claude/skills/database-migrations/SKILL.md +335 -0
- package/claude/skills/database-migrations/scripts/generate-sample-data.py +284 -0
- package/claude/skills/database-migrations/scripts/validate-migration.py +323 -0
- package/claude/skills/design-system/SKILL.md +682 -0
- package/claude/skills/documentation/SKILL.md +540 -0
- package/claude/skills/entity-api/SKILL.md +482 -0
- package/claude/skills/entity-system/SKILL.md +635 -0
- package/claude/skills/entity-system/scripts/generate-child-migration.py +298 -0
- package/claude/skills/entity-system/scripts/generate-metas-migration.py +233 -0
- package/claude/skills/entity-system/scripts/generate-migration.py +382 -0
- package/claude/skills/entity-system/scripts/generate-sample-data.py +418 -0
- package/claude/skills/entity-system/scripts/scaffold-entity.py +661 -0
- package/claude/skills/github/SKILL.md +467 -0
- package/claude/skills/i18n-nextintl/SKILL.md +302 -0
- package/claude/skills/i18n-nextintl/scripts/add-translation.py +243 -0
- package/claude/skills/i18n-nextintl/scripts/extract-hardcoded.py +246 -0
- package/claude/skills/i18n-nextintl/scripts/validate-translations.py +260 -0
- package/claude/skills/impact-analysis/SKILL.md +203 -0
- package/claude/skills/jest-unit/SKILL.md +306 -0
- package/claude/skills/jest-unit/references/component-testing.md +371 -0
- package/claude/skills/jest-unit/references/mocking-patterns.md +380 -0
- package/claude/skills/jest-unit/references/service-hook-testing.md +454 -0
- package/claude/skills/jira-integration/SKILL.md +539 -0
- package/claude/skills/media-library/SKILL.md +743 -0
- package/claude/skills/mock-analysis/SKILL.md +276 -0
- package/claude/skills/monorepo-architecture/SKILL.md +162 -0
- package/claude/skills/nextjs-api-development/SKILL.md +364 -0
- package/claude/skills/nextjs-api-development/scripts/generate-crud-tests.py +456 -0
- package/claude/skills/nextjs-api-development/scripts/scaffold-endpoint.py +481 -0
- package/claude/skills/nextjs-api-development/scripts/validate-api.py +283 -0
- package/claude/skills/notion-integration/SKILL.md +641 -0
- package/claude/skills/npm-development-workflow/SKILL.md +480 -0
- package/claude/skills/page-builder-blocks/SKILL.md +530 -0
- package/claude/skills/page-builder-blocks/scripts/scaffold-block.py +444 -0
- package/claude/skills/permissions-system/SKILL.md +619 -0
- package/claude/skills/plugins/SKILL.md +340 -0
- package/claude/skills/plugins/references/plugin-templates.md +414 -0
- package/claude/skills/plugins/references/plugin-testing.md +353 -0
- package/claude/skills/plugins/references/plugin-types.md +198 -0
- package/claude/skills/plugins/scripts/scaffold-plugin.py +443 -0
- package/claude/skills/pom-patterns/SKILL.md +452 -0
- package/claude/skills/pom-patterns/scripts/generate-pom.py +392 -0
- package/claude/skills/rate-limiting/SKILL.md +342 -0
- package/claude/skills/react-best-practices/AGENTS.md +2410 -0
- package/claude/skills/react-best-practices/README.md +123 -0
- package/claude/skills/react-best-practices/SKILL.md +125 -0
- package/claude/skills/react-best-practices/metadata.json +15 -0
- package/claude/skills/react-best-practices/rules/_sections.md +46 -0
- package/claude/skills/react-best-practices/rules/_template.md +28 -0
- package/claude/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/claude/skills/react-best-practices/rules/advanced-use-latest.md +49 -0
- package/claude/skills/react-best-practices/rules/async-api-routes.md +38 -0
- package/claude/skills/react-best-practices/rules/async-defer-await.md +80 -0
- package/claude/skills/react-best-practices/rules/async-dependencies.md +36 -0
- package/claude/skills/react-best-practices/rules/async-parallel.md +28 -0
- package/claude/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/claude/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
- package/claude/skills/react-best-practices/rules/bundle-conditional.md +31 -0
- package/claude/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/claude/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/claude/skills/react-best-practices/rules/bundle-preload.md +50 -0
- package/claude/skills/react-best-practices/rules/client-event-listeners.md +74 -0
- package/claude/skills/react-best-practices/rules/client-localstorage-schema.md +71 -0
- package/claude/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/claude/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
- package/claude/skills/react-best-practices/rules/js-batch-dom-css.md +82 -0
- package/claude/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
- package/claude/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/claude/skills/react-best-practices/rules/js-cache-storage.md +70 -0
- package/claude/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/claude/skills/react-best-practices/rules/js-early-exit.md +50 -0
- package/claude/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/claude/skills/react-best-practices/rules/js-index-maps.md +37 -0
- package/claude/skills/react-best-practices/rules/js-length-check-first.md +49 -0
- package/claude/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/claude/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/claude/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/claude/skills/react-best-practices/rules/rendering-activity.md +26 -0
- package/claude/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/claude/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/claude/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/claude/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/claude/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/claude/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/claude/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/claude/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/claude/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/claude/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/claude/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/claude/skills/react-best-practices/rules/rerender-memo.md +44 -0
- package/claude/skills/react-best-practices/rules/rerender-transitions.md +40 -0
- package/claude/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/claude/skills/react-best-practices/rules/server-cache-lru.md +41 -0
- package/claude/skills/react-best-practices/rules/server-cache-react.md +76 -0
- package/claude/skills/react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/claude/skills/react-best-practices/rules/server-serialization.md +38 -0
- package/claude/skills/react-patterns/SKILL.md +688 -0
- package/claude/skills/registry-system/SKILL.md +331 -0
- package/claude/skills/scheduled-actions/SKILL.md +671 -0
- package/claude/skills/scope-enforcement/SKILL.md +542 -0
- package/claude/skills/scope-enforcement/scripts/validate-scope.py +357 -0
- package/claude/skills/server-actions/SKILL.md +493 -0
- package/claude/skills/service-layer/SKILL.md +587 -0
- package/claude/skills/session-management/SKILL.md +266 -0
- package/claude/skills/session-management/scripts/create-session.py +166 -0
- package/claude/skills/session-management/scripts/iteration-close.sh +105 -0
- package/claude/skills/session-management/scripts/iteration-init.sh +180 -0
- package/claude/skills/session-management/scripts/session-archive.sh +87 -0
- package/claude/skills/session-management/scripts/session-close.sh +133 -0
- package/claude/skills/session-management/scripts/session-init.sh +225 -0
- package/claude/skills/session-management/scripts/session-list.sh +163 -0
- package/claude/skills/session-management/scripts/split-plan.sh +116 -0
- package/claude/skills/shadcn-components/SKILL.md +586 -0
- package/claude/skills/shadcn-theming/SKILL.md +446 -0
- package/claude/skills/suspense-loading/SKILL.md +280 -0
- package/claude/skills/tailwind-theming/SKILL.md +507 -0
- package/claude/skills/tanstack-query/SKILL.md +608 -0
- package/claude/skills/test-coverage/SKILL.md +239 -0
- package/claude/skills/web-design-guidelines/SKILL.md +39 -0
- package/claude/skills/zod-validation/SKILL.md +537 -0
- package/claude/templates/blocks/progress.md +86 -0
- package/claude/templates/iteration/changes.md +61 -0
- package/claude/templates/iteration/progress.md +55 -0
- package/claude/templates/log.md +31 -0
- package/claude/templates/story/context.md +77 -0
- package/claude/templates/story/pendings.md +37 -0
- package/claude/templates/story/plan.md +299 -0
- package/claude/templates/story/requirements.md +109 -0
- package/claude/templates/story/scope.json +10 -0
- package/claude/templates/story/tests.md +91 -0
- package/claude/templates/task/progress.md +58 -0
- package/claude/templates/task/requirements.md +54 -0
- package/claude/workflows/README.md +154 -0
- package/claude/workflows/blocks.md +614 -0
- package/claude/workflows/story.md +1207 -0
- package/claude/workflows/task.md +927 -0
- package/claude/workflows/tweak.md +527 -0
- package/cursor/.gitkeep +0 -0
- package/package.json +35 -0
- package/scripts/postinstall.mjs +198 -0
- package/scripts/setup.mjs +282 -0
- package/scripts/sync.mjs +209 -0
|
@@ -0,0 +1,984 @@
|
|
|
1
|
+
# /how-to:manage-test-coverage
|
|
2
|
+
|
|
3
|
+
Interactive guide to create Cypress tests, maintain coverage, and use the testing infrastructure in NextSpark.
|
|
4
|
+
|
|
5
|
+
**Aliases:** `/how-to:coverage`, `/how-to:testing-strategy`
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Required Skills
|
|
10
|
+
|
|
11
|
+
Before executing, these skills provide deeper context:
|
|
12
|
+
- `.claude/skills/cypress-e2e/SKILL.md` - End-to-end testing patterns
|
|
13
|
+
- `.claude/skills/cypress-api/SKILL.md` - API testing with Cypress
|
|
14
|
+
- `.claude/skills/cypress-selectors/SKILL.md` - 3-level selector system
|
|
15
|
+
- `.claude/skills/test-coverage/SKILL.md` - FEATURE_REGISTRY and coverage metrics
|
|
16
|
+
- `.claude/skills/pom-patterns/SKILL.md` - Page Object Model structure
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Syntax
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
/how-to:manage-test-coverage
|
|
24
|
+
/how-to:manage-test-coverage --gaps
|
|
25
|
+
/how-to:manage-test-coverage --selectors
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Behavior
|
|
31
|
+
|
|
32
|
+
Guides the user through the complete testing infrastructure: selectors, tests, tags, BDD documentation, registries, and coverage validation.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Tutorial Structure
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
STEPS OVERVIEW (6 steps)
|
|
40
|
+
|
|
41
|
+
Step 1: The Selector System
|
|
42
|
+
└── CORE, BLOCK, THEME selectors (NO HARDCODING!)
|
|
43
|
+
|
|
44
|
+
Step 2: Creating Cypress Tests
|
|
45
|
+
└── Structure, POMs, and best practices
|
|
46
|
+
|
|
47
|
+
Step 3: Using Tags Effectively
|
|
48
|
+
└── Tag prefixes and feature/flow connection
|
|
49
|
+
|
|
50
|
+
Step 4: BDD Documentation
|
|
51
|
+
└── .bdd.md files for Devtools
|
|
52
|
+
|
|
53
|
+
Step 5: Registry & Coverage Metrics
|
|
54
|
+
└── Auto-generation and coverage tracking
|
|
55
|
+
|
|
56
|
+
Step 6: Lint & Build Validations
|
|
57
|
+
└── Enforcing quality in CI/CD
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Step 1: The Selector System
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
66
|
+
📚 HOW TO: MANAGE TEST COVERAGE
|
|
67
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
68
|
+
|
|
69
|
+
STEP 1 OF 6: The Selector System
|
|
70
|
+
|
|
71
|
+
⚠️ CRITICAL RULE: NEVER HARDCODE SELECTORS!
|
|
72
|
+
|
|
73
|
+
All selectors come from a 3-level system.
|
|
74
|
+
This ensures consistency, maintainability,
|
|
75
|
+
and prevents brittle tests.
|
|
76
|
+
|
|
77
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**📋 The 3-Level Selector Architecture:**
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
┌─────────────────────────────────────────────┐
|
|
84
|
+
│ Level 1: CORE_SELECTORS │
|
|
85
|
+
│ ───────────────────────────────────────── │
|
|
86
|
+
│ From: @nextsparkjs/testing │
|
|
87
|
+
│ Contains: All core UI element selectors │
|
|
88
|
+
│ Examples: login forms, dashboard, nav │
|
|
89
|
+
└─────────────────────────────────────────────┘
|
|
90
|
+
│
|
|
91
|
+
▼
|
|
92
|
+
┌─────────────────────────────────────────────┐
|
|
93
|
+
│ Level 2: BLOCK_SELECTORS │
|
|
94
|
+
│ ───────────────────────────────────────── │
|
|
95
|
+
│ From: Theme's block definitions │
|
|
96
|
+
│ Contains: Page builder block selectors │
|
|
97
|
+
│ Examples: hero-banner, features-grid │
|
|
98
|
+
└─────────────────────────────────────────────┘
|
|
99
|
+
│
|
|
100
|
+
▼
|
|
101
|
+
┌─────────────────────────────────────────────┐
|
|
102
|
+
│ Level 3: THEME_SELECTORS │
|
|
103
|
+
│ ───────────────────────────────────────── │
|
|
104
|
+
│ From: Theme-specific extensions │
|
|
105
|
+
│ Contains: Custom theme UI selectors │
|
|
106
|
+
│ Examples: custom widgets, layouts │
|
|
107
|
+
└─────────────────────────────────────────────┘
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**📋 Using Selectors in Tests:**
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
// ✅ CORRECT: Import from selector system
|
|
114
|
+
import { CORE_SELECTORS } from '@nextsparkjs/testing'
|
|
115
|
+
import { sel } from '@/tests/cypress/support/helpers'
|
|
116
|
+
|
|
117
|
+
// Use the sel() helper for data-cy attributes
|
|
118
|
+
cy.get(sel(CORE_SELECTORS.auth.login.emailInput))
|
|
119
|
+
.type('test@example.com')
|
|
120
|
+
|
|
121
|
+
// Or use cySelector() from POMs
|
|
122
|
+
this.cySelector(CORE_SELECTORS.auth.login.submitButton)
|
|
123
|
+
.click()
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
// ❌ WRONG: Hardcoded selectors
|
|
128
|
+
cy.get('[data-cy="login-email-input"]') // NEVER DO THIS!
|
|
129
|
+
cy.get('.login-form input') // NEVER DO THIS!
|
|
130
|
+
cy.get('#email') // NEVER DO THIS!
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**📋 Selector Naming Convention:**
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
pattern: "{domain}-{element}-{variant}"
|
|
137
|
+
|
|
138
|
+
Examples:
|
|
139
|
+
• login-email-input
|
|
140
|
+
• login-submit-button
|
|
141
|
+
• dashboard-sidebar-nav
|
|
142
|
+
• entity-{slug}-row-{id} ← Dynamic with placeholders
|
|
143
|
+
• settings-{section}-form ← Dynamic with placeholders
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**📋 Dynamic Selectors with Placeholders:**
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
// CORE_SELECTORS has dynamic patterns
|
|
150
|
+
CORE_SELECTORS.entities.list.row // "{slug}-row-{id}"
|
|
151
|
+
|
|
152
|
+
// Use entitySelectors() helper for dynamic entities
|
|
153
|
+
import { entitySelectors } from '@nextsparkjs/testing'
|
|
154
|
+
|
|
155
|
+
const taskSelectors = entitySelectors('tasks')
|
|
156
|
+
cy.get(sel(taskSelectors.row('task-123')))
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**📋 Adding New Selectors:**
|
|
160
|
+
|
|
161
|
+
When you need a new selector:
|
|
162
|
+
|
|
163
|
+
1. **For core UI:** Add to `packages/testing/src/selectors/core-selectors.ts`
|
|
164
|
+
2. **For blocks:** Add to block's component with `data-cy` attribute
|
|
165
|
+
3. **For theme:** Add to theme's selector extension file
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
// In your component:
|
|
169
|
+
<button data-cy="feature-action-button">
|
|
170
|
+
Action
|
|
171
|
+
</button>
|
|
172
|
+
|
|
173
|
+
// In selectors file:
|
|
174
|
+
export const FEATURE_SELECTORS = {
|
|
175
|
+
actionButton: 'feature-action-button'
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
181
|
+
|
|
182
|
+
What would you like to do?
|
|
183
|
+
|
|
184
|
+
[1] Continue to Step 2 (Creating Cypress Tests)
|
|
185
|
+
[2] Show me the full CORE_SELECTORS structure
|
|
186
|
+
[3] How do I add a new selector?
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Step 2: Creating Cypress Tests
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
195
|
+
STEP 2 OF 6: Creating Cypress Tests
|
|
196
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
197
|
+
|
|
198
|
+
NextSpark has two types of Cypress tests:
|
|
199
|
+
• UAT (User Acceptance Tests) - UI interactions
|
|
200
|
+
• API Tests - Endpoint validation
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**📋 Test File Structure:**
|
|
204
|
+
|
|
205
|
+
```
|
|
206
|
+
contents/themes/{theme}/tests/cypress/
|
|
207
|
+
├── e2e/
|
|
208
|
+
│ ├── uat/ # User acceptance tests
|
|
209
|
+
│ │ ├── auth/
|
|
210
|
+
│ │ │ ├── login.cy.ts
|
|
211
|
+
│ │ │ └── login.bdd.md
|
|
212
|
+
│ │ └── entities/
|
|
213
|
+
│ │ ├── tasks.cy.ts
|
|
214
|
+
│ │ └── tasks.bdd.md
|
|
215
|
+
│ └── api/ # API tests
|
|
216
|
+
│ └── entities/
|
|
217
|
+
│ ├── tasks.cy.ts
|
|
218
|
+
│ └── tasks.bdd.md
|
|
219
|
+
├── support/
|
|
220
|
+
│ ├── commands.ts # Custom Cypress commands
|
|
221
|
+
│ └── helpers.ts # Test helpers (sel, etc.)
|
|
222
|
+
└── fixtures/
|
|
223
|
+
└── test-data.json # Test data
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**📋 UAT Test Example:**
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
// contents/themes/default/tests/cypress/e2e/uat/auth/login.cy.ts
|
|
230
|
+
import { CORE_SELECTORS } from '@nextsparkjs/testing'
|
|
231
|
+
import { LoginPOM } from '@/tests/cypress/support/pom/auth/login.pom'
|
|
232
|
+
|
|
233
|
+
describe('@uat @smoke @feat-auth Login Form', () => {
|
|
234
|
+
let loginPage: LoginPOM
|
|
235
|
+
|
|
236
|
+
beforeEach(() => {
|
|
237
|
+
loginPage = new LoginPOM()
|
|
238
|
+
loginPage.visit()
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
it('@SEL_AUTH_001 should login with valid credentials', () => {
|
|
242
|
+
loginPage
|
|
243
|
+
.fillEmail('test@example.com')
|
|
244
|
+
.fillPassword('Test1234')
|
|
245
|
+
.submit()
|
|
246
|
+
|
|
247
|
+
cy.url().should('include', '/dashboard')
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
it('@SEL_AUTH_002 @regression should show error for invalid email', () => {
|
|
251
|
+
loginPage
|
|
252
|
+
.fillEmail('invalid-email')
|
|
253
|
+
.fillPassword('Test1234')
|
|
254
|
+
.submit()
|
|
255
|
+
|
|
256
|
+
loginPage.getEmailError()
|
|
257
|
+
.should('be.visible')
|
|
258
|
+
.and('contain', 'Invalid email')
|
|
259
|
+
})
|
|
260
|
+
})
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
**📋 Page Object Model (POM):**
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
// cypress/support/pom/auth/login.pom.ts
|
|
267
|
+
import { BasePOM } from '../base.pom'
|
|
268
|
+
import { CORE_SELECTORS } from '@nextsparkjs/testing'
|
|
269
|
+
|
|
270
|
+
export class LoginPOM extends BasePOM {
|
|
271
|
+
private selectors = CORE_SELECTORS.auth.login
|
|
272
|
+
|
|
273
|
+
visit() {
|
|
274
|
+
cy.visit('/login')
|
|
275
|
+
return this
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
fillEmail(email: string) {
|
|
279
|
+
this.cySelector(this.selectors.emailInput)
|
|
280
|
+
.clear()
|
|
281
|
+
.type(email)
|
|
282
|
+
return this
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
fillPassword(password: string) {
|
|
286
|
+
this.cySelector(this.selectors.passwordInput)
|
|
287
|
+
.clear()
|
|
288
|
+
.type(password)
|
|
289
|
+
return this
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
submit() {
|
|
293
|
+
this.cySelector(this.selectors.submitButton).click()
|
|
294
|
+
return this
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
getEmailError() {
|
|
298
|
+
return this.cySelector(this.selectors.emailError)
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
**📋 API Test Example:**
|
|
304
|
+
|
|
305
|
+
```typescript
|
|
306
|
+
// contents/themes/default/tests/cypress/e2e/api/entities/tasks.cy.ts
|
|
307
|
+
import { BaseAPIController } from '@/tests/cypress/support/api/base.controller'
|
|
308
|
+
|
|
309
|
+
describe('@api @feat-tasks Tasks API', () => {
|
|
310
|
+
const api = new BaseAPIController('tasks')
|
|
311
|
+
|
|
312
|
+
beforeEach(() => {
|
|
313
|
+
cy.getApiKey().as('apiKey')
|
|
314
|
+
})
|
|
315
|
+
|
|
316
|
+
it('@TASKS_API_001 should list all tasks', function() {
|
|
317
|
+
api.list(this.apiKey).then((response) => {
|
|
318
|
+
expect(response.status).to.eq(200)
|
|
319
|
+
expect(response.body.success).to.be.true
|
|
320
|
+
expect(response.body.data).to.be.an('array')
|
|
321
|
+
})
|
|
322
|
+
})
|
|
323
|
+
|
|
324
|
+
it('@TASKS_API_002 should create a task', function() {
|
|
325
|
+
api.create(this.apiKey, {
|
|
326
|
+
title: 'Test Task',
|
|
327
|
+
status: 'pending'
|
|
328
|
+
}).then((response) => {
|
|
329
|
+
expect(response.status).to.eq(201)
|
|
330
|
+
expect(response.body.data.title).to.eq('Test Task')
|
|
331
|
+
})
|
|
332
|
+
})
|
|
333
|
+
})
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
```
|
|
337
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
338
|
+
|
|
339
|
+
What would you like to do?
|
|
340
|
+
|
|
341
|
+
[1] Continue to Step 3 (Using Tags Effectively)
|
|
342
|
+
[2] Show me more POM examples
|
|
343
|
+
[3] How do I set up authentication in tests?
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
---
|
|
347
|
+
|
|
348
|
+
## Step 3: Using Tags Effectively
|
|
349
|
+
|
|
350
|
+
```
|
|
351
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
352
|
+
STEP 3 OF 6: Using Tags Effectively
|
|
353
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
354
|
+
|
|
355
|
+
Tags connect tests to features and flows.
|
|
356
|
+
This is where everything comes together!
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
**📋 Tag Categories & Prefixes:**
|
|
360
|
+
|
|
361
|
+
```
|
|
362
|
+
┌─────────────────────────────────────────────┐
|
|
363
|
+
│ LAYER TAGS (test type) │
|
|
364
|
+
│ ───────────────────────────────────────── │
|
|
365
|
+
│ @uat User acceptance tests │
|
|
366
|
+
│ @api API/integration tests │
|
|
367
|
+
│ @e2e Full end-to-end tests │
|
|
368
|
+
│ @unit Unit tests (Jest) │
|
|
369
|
+
└─────────────────────────────────────────────┘
|
|
370
|
+
|
|
371
|
+
┌─────────────────────────────────────────────┐
|
|
372
|
+
│ PRIORITY TAGS (when to run) │
|
|
373
|
+
│ ───────────────────────────────────────── │
|
|
374
|
+
│ @smoke Run on EVERY deploy │
|
|
375
|
+
│ @regression Run on release candidates │
|
|
376
|
+
│ @nightly Run in nightly builds │
|
|
377
|
+
└─────────────────────────────────────────────┘
|
|
378
|
+
|
|
379
|
+
┌─────────────────────────────────────────────┐
|
|
380
|
+
│ FEATURE TAGS (what feature) │
|
|
381
|
+
│ ───────────────────────────────────────── │
|
|
382
|
+
│ @feat-auth Authentication feature │
|
|
383
|
+
│ @feat-teams Teams management feature │
|
|
384
|
+
│ @feat-tasks Tasks entity feature │
|
|
385
|
+
│ @feat-{name} Any feature from features.json│
|
|
386
|
+
└─────────────────────────────────────────────┘
|
|
387
|
+
|
|
388
|
+
┌─────────────────────────────────────────────┐
|
|
389
|
+
│ FLOW TAGS (what user journey) │
|
|
390
|
+
│ ───────────────────────────────────────── │
|
|
391
|
+
│ @flow-onboarding User onboarding flow │
|
|
392
|
+
│ @flow-checkout Purchase flow │
|
|
393
|
+
│ @flow-{name} Any flow from features.json│
|
|
394
|
+
└─────────────────────────────────────────────┘
|
|
395
|
+
|
|
396
|
+
┌─────────────────────────────────────────────┐
|
|
397
|
+
│ OPERATION TAGS (type of test) │
|
|
398
|
+
│ ───────────────────────────────────────── │
|
|
399
|
+
│ @crud CRUD operations │
|
|
400
|
+
│ @search Search functionality │
|
|
401
|
+
│ @workflow Multi-step workflows │
|
|
402
|
+
└─────────────────────────────────────────────┘
|
|
403
|
+
|
|
404
|
+
┌─────────────────────────────────────────────┐
|
|
405
|
+
│ AREA TAGS (app section) │
|
|
406
|
+
│ ───────────────────────────────────────── │
|
|
407
|
+
│ @area-devtools Devtools section │
|
|
408
|
+
│ @area-superadmin Admin panel │
|
|
409
|
+
│ @area-settings Settings section │
|
|
410
|
+
└─────────────────────────────────────────────┘
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
**📋 Tag Placement Rules:**
|
|
414
|
+
|
|
415
|
+
```typescript
|
|
416
|
+
// Tags go in the describe() block name
|
|
417
|
+
describe('@uat @smoke @feat-auth Login Form', () => {
|
|
418
|
+
|
|
419
|
+
// Individual test IDs in it() blocks
|
|
420
|
+
it('@SEL_AUTH_001 should login successfully', () => {
|
|
421
|
+
// ...
|
|
422
|
+
})
|
|
423
|
+
|
|
424
|
+
// Additional tags can be added per test
|
|
425
|
+
it('@SEL_AUTH_002 @regression should handle errors', () => {
|
|
426
|
+
// ...
|
|
427
|
+
})
|
|
428
|
+
})
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
**📋 Connecting to features.json:**
|
|
432
|
+
|
|
433
|
+
```json
|
|
434
|
+
// In features.json:
|
|
435
|
+
{
|
|
436
|
+
"features": {
|
|
437
|
+
"authentication": {
|
|
438
|
+
"testTags": ["@feat-auth"] // ← This tag
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// In your test:
|
|
444
|
+
describe('@feat-auth ...', () => { // ← Must match!
|
|
445
|
+
// Tests...
|
|
446
|
+
})
|
|
447
|
+
|
|
448
|
+
// The registry build will:
|
|
449
|
+
// 1. Find tests with @feat-auth
|
|
450
|
+
// 2. Link them to "authentication" feature
|
|
451
|
+
// 3. Update coverage metrics
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
**📋 Running Tests by Tag:**
|
|
455
|
+
|
|
456
|
+
```bash
|
|
457
|
+
# Run only smoke tests
|
|
458
|
+
pnpm cypress:run --env grepTags="@smoke"
|
|
459
|
+
|
|
460
|
+
# Run authentication feature tests
|
|
461
|
+
pnpm cypress:run --env grepTags="@feat-auth"
|
|
462
|
+
|
|
463
|
+
# Run all UAT tests except smoke
|
|
464
|
+
pnpm cypress:run --env grepTags="@uat -@smoke"
|
|
465
|
+
|
|
466
|
+
# Run onboarding flow tests
|
|
467
|
+
pnpm cypress:run --env grepTags="@flow-onboarding"
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
```
|
|
471
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
472
|
+
|
|
473
|
+
What would you like to do?
|
|
474
|
+
|
|
475
|
+
[1] Continue to Step 4 (BDD Documentation)
|
|
476
|
+
[2] Show me tag combination examples
|
|
477
|
+
[3] How do I choose which tags to use?
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
---
|
|
481
|
+
|
|
482
|
+
## Step 4: BDD Documentation
|
|
483
|
+
|
|
484
|
+
```
|
|
485
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
486
|
+
STEP 4 OF 6: BDD Documentation
|
|
487
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
488
|
+
|
|
489
|
+
Every .cy.ts file should have a companion .bdd.md
|
|
490
|
+
file for human-readable documentation.
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
**📋 BDD File Structure:**
|
|
494
|
+
|
|
495
|
+
```
|
|
496
|
+
cypress/e2e/uat/auth/
|
|
497
|
+
├── login.cy.ts # Cypress test file
|
|
498
|
+
└── login.bdd.md # BDD documentation
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
**📋 BDD Template:**
|
|
502
|
+
|
|
503
|
+
```markdown
|
|
504
|
+
# Login Form Validation
|
|
505
|
+
|
|
506
|
+
## Feature
|
|
507
|
+
User authentication through email/password login.
|
|
508
|
+
|
|
509
|
+
## Tags
|
|
510
|
+
- @uat
|
|
511
|
+
- @smoke
|
|
512
|
+
- @feat-auth
|
|
513
|
+
|
|
514
|
+
## Preconditions
|
|
515
|
+
- User account exists in the system
|
|
516
|
+
- User is not logged in
|
|
517
|
+
- Login page is accessible
|
|
518
|
+
|
|
519
|
+
## Scenarios
|
|
520
|
+
|
|
521
|
+
### 1. Successful login with email
|
|
522
|
+
**ID:** @SEL_AUTH_001
|
|
523
|
+
**Priority:** @smoke
|
|
524
|
+
|
|
525
|
+
- **Given:** Login page is displayed
|
|
526
|
+
- **When:** User enters valid email "test@example.com"
|
|
527
|
+
- **And:** User enters valid password "Test1234"
|
|
528
|
+
- **And:** User clicks submit button
|
|
529
|
+
- **Then:** User is redirected to dashboard
|
|
530
|
+
- **And:** Session is created
|
|
531
|
+
|
|
532
|
+
### 2. Error on invalid email format
|
|
533
|
+
**ID:** @SEL_AUTH_002
|
|
534
|
+
**Priority:** @regression
|
|
535
|
+
|
|
536
|
+
- **Given:** Login page is displayed
|
|
537
|
+
- **When:** User enters invalid email "not-an-email"
|
|
538
|
+
- **And:** User clicks submit button
|
|
539
|
+
- **Then:** Error message "Invalid email format" is displayed
|
|
540
|
+
- **And:** Email input is highlighted with error state
|
|
541
|
+
|
|
542
|
+
## Test Data
|
|
543
|
+
| Email | Password | Expected Result |
|
|
544
|
+
|-------|----------|-----------------|
|
|
545
|
+
| test@example.com | Test1234 | Success |
|
|
546
|
+
| invalid-email | Test1234 | Validation error |
|
|
547
|
+
| test@example.com | wrong | Auth error |
|
|
548
|
+
|
|
549
|
+
## Related Features
|
|
550
|
+
- Password Reset: /how-to:password-reset
|
|
551
|
+
- OAuth Login: /how-to:oauth-login
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
**📋 Why BDD Documentation Matters:**
|
|
555
|
+
|
|
556
|
+
```
|
|
557
|
+
┌─────────────────────────────────────────────┐
|
|
558
|
+
│ BDD docs are used in DEVTOOLS │
|
|
559
|
+
│ ───────────────────────────────────────── │
|
|
560
|
+
│ │
|
|
561
|
+
│ The Devtools test viewer reads .bdd.md │
|
|
562
|
+
│ files to show human-readable test docs. │
|
|
563
|
+
│ │
|
|
564
|
+
│ Benefits: │
|
|
565
|
+
│ • Non-technical stakeholders can read │
|
|
566
|
+
│ • QA team can verify coverage │
|
|
567
|
+
│ • New developers understand intent │
|
|
568
|
+
│ • Auto-generates test reports │
|
|
569
|
+
└─────────────────────────────────────────────┘
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
**📋 Keeping BDD in Sync:**
|
|
573
|
+
|
|
574
|
+
After modifying tests, update the BDD:
|
|
575
|
+
|
|
576
|
+
```bash
|
|
577
|
+
# Use the BDD writer command
|
|
578
|
+
/bdd:write path/to/test.cy.ts
|
|
579
|
+
|
|
580
|
+
# Or manually update the .bdd.md file
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
```
|
|
584
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
585
|
+
|
|
586
|
+
What would you like to do?
|
|
587
|
+
|
|
588
|
+
[1] Continue to Step 5 (Registry & Coverage)
|
|
589
|
+
[2] Generate BDD for my test file
|
|
590
|
+
[3] Show me more BDD examples
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
---
|
|
594
|
+
|
|
595
|
+
## Step 5: Registry & Coverage Metrics
|
|
596
|
+
|
|
597
|
+
```
|
|
598
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
599
|
+
STEP 5 OF 6: Registry & Coverage Metrics
|
|
600
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
601
|
+
|
|
602
|
+
The registry system auto-generates coverage
|
|
603
|
+
metrics from your tests and features.json.
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
**📋 How It Works:**
|
|
607
|
+
|
|
608
|
+
```
|
|
609
|
+
┌──────────────┐
|
|
610
|
+
│ features.json│ ─── Defines expected features/flows
|
|
611
|
+
└──────┬───────┘
|
|
612
|
+
│
|
|
613
|
+
▼
|
|
614
|
+
┌──────────────┐
|
|
615
|
+
│ Cypress Tests│ ─── Contains @feat-* and @flow-* tags
|
|
616
|
+
└──────┬───────┘
|
|
617
|
+
│
|
|
618
|
+
▼
|
|
619
|
+
┌──────────────┐
|
|
620
|
+
│ Build Script │ ─── pnpm build:registries
|
|
621
|
+
└──────┬───────┘
|
|
622
|
+
│
|
|
623
|
+
▼
|
|
624
|
+
┌──────────────────────────────────────────────┐
|
|
625
|
+
│ testing-registry.ts │
|
|
626
|
+
│ ├── FEATURE_REGISTRY (features + test data) │
|
|
627
|
+
│ ├── FLOW_REGISTRY (flows + test data) │
|
|
628
|
+
│ ├── TAGS_REGISTRY (all discovered tags) │
|
|
629
|
+
│ └── COVERAGE_SUMMARY (metrics) │
|
|
630
|
+
└──────────────────────────────────────────────┘
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
**📋 Generated Registry Example:**
|
|
634
|
+
|
|
635
|
+
```typescript
|
|
636
|
+
// .nextspark/registries/testing-registry.ts (auto-generated)
|
|
637
|
+
|
|
638
|
+
export const FEATURE_REGISTRY = {
|
|
639
|
+
'authentication': {
|
|
640
|
+
name: 'Authentication',
|
|
641
|
+
category: 'core',
|
|
642
|
+
testing: {
|
|
643
|
+
hasTests: true,
|
|
644
|
+
testCount: 15,
|
|
645
|
+
files: ['login.cy.ts', 'signup.cy.ts', 'password-reset.cy.ts']
|
|
646
|
+
}
|
|
647
|
+
},
|
|
648
|
+
'tasks': {
|
|
649
|
+
name: 'Task Management',
|
|
650
|
+
category: 'entities',
|
|
651
|
+
testing: {
|
|
652
|
+
hasTests: true,
|
|
653
|
+
testCount: 8,
|
|
654
|
+
files: ['tasks.cy.ts']
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
export const COVERAGE_SUMMARY = {
|
|
660
|
+
theme: 'default',
|
|
661
|
+
generatedAt: '2024-12-18T10:30:00Z',
|
|
662
|
+
features: {
|
|
663
|
+
total: 15,
|
|
664
|
+
withTests: 12,
|
|
665
|
+
withoutTests: 3
|
|
666
|
+
},
|
|
667
|
+
flows: {
|
|
668
|
+
total: 5,
|
|
669
|
+
withTests: 3,
|
|
670
|
+
withoutTests: 2
|
|
671
|
+
},
|
|
672
|
+
tags: {
|
|
673
|
+
total: 97,
|
|
674
|
+
testFiles: 25
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
**📋 Using the FeatureService:**
|
|
680
|
+
|
|
681
|
+
```typescript
|
|
682
|
+
import { FeatureService } from '@/core/lib/services/feature.service'
|
|
683
|
+
|
|
684
|
+
// Get coverage metrics
|
|
685
|
+
const coverage = FeatureService.getCoverageSummary()
|
|
686
|
+
console.log(`Feature coverage: ${FeatureService.getFeatureCoveragePercent()}%`)
|
|
687
|
+
|
|
688
|
+
// Find features without tests
|
|
689
|
+
const gaps = FeatureService.getFeaturesWithoutTests()
|
|
690
|
+
gaps.forEach(f => console.log(`Missing tests: ${f.name}`))
|
|
691
|
+
|
|
692
|
+
// Get all tests for a feature
|
|
693
|
+
const auth = FeatureService.getFeature('authentication')
|
|
694
|
+
console.log(`Auth has ${auth.testing.testCount} tests`)
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
**📋 Coverage Targets:**
|
|
698
|
+
|
|
699
|
+
```
|
|
700
|
+
┌─────────────────────────────────────────────┐
|
|
701
|
+
│ COVERAGE TARGETS │
|
|
702
|
+
│ ───────────────────────────────────────── │
|
|
703
|
+
│ │
|
|
704
|
+
│ Critical (90%+): │
|
|
705
|
+
│ • Authentication │
|
|
706
|
+
│ • Payments/Billing │
|
|
707
|
+
│ • Permissions │
|
|
708
|
+
│ │
|
|
709
|
+
│ Important (80%+): │
|
|
710
|
+
│ • API endpoints │
|
|
711
|
+
│ • Form validations │
|
|
712
|
+
│ • Business logic │
|
|
713
|
+
│ │
|
|
714
|
+
│ General (70%+): │
|
|
715
|
+
│ • UI components │
|
|
716
|
+
│ • Utilities │
|
|
717
|
+
│ • Settings │
|
|
718
|
+
└─────────────────────────────────────────────┘
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
```
|
|
722
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
723
|
+
|
|
724
|
+
What would you like to do?
|
|
725
|
+
|
|
726
|
+
[1] Continue to Step 6 (Lint & Build Validations)
|
|
727
|
+
[2] Show me my current coverage gaps
|
|
728
|
+
[3] How do I rebuild the registry?
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
---
|
|
732
|
+
|
|
733
|
+
## Step 6: Lint & Build Validations
|
|
734
|
+
|
|
735
|
+
```
|
|
736
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
737
|
+
STEP 6 OF 6: Lint & Build Validations
|
|
738
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
739
|
+
|
|
740
|
+
The testing system has built-in validations
|
|
741
|
+
that run during lint and build.
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
**📋 Lint Rules:**
|
|
745
|
+
|
|
746
|
+
```typescript
|
|
747
|
+
// ESLint rules enforce testing standards
|
|
748
|
+
|
|
749
|
+
// Rule: no-hardcoded-selectors
|
|
750
|
+
// ❌ cy.get('[data-cy="login-button"]')
|
|
751
|
+
// ✅ cy.get(sel(CORE_SELECTORS.auth.login.button))
|
|
752
|
+
|
|
753
|
+
// Rule: require-test-tags
|
|
754
|
+
// ❌ describe('Login', () => {})
|
|
755
|
+
// ✅ describe('@uat @feat-auth Login', () => {})
|
|
756
|
+
|
|
757
|
+
// Rule: require-bdd-file
|
|
758
|
+
// ❌ login.cy.ts without login.bdd.md
|
|
759
|
+
// ✅ login.cy.ts with login.bdd.md
|
|
760
|
+
```
|
|
761
|
+
|
|
762
|
+
**📋 Build Validations:**
|
|
763
|
+
|
|
764
|
+
```bash
|
|
765
|
+
# During pnpm build, the system checks:
|
|
766
|
+
|
|
767
|
+
✓ All test files have required tags
|
|
768
|
+
✓ All @feat-* tags match features.json
|
|
769
|
+
✓ All @flow-* tags match features.json
|
|
770
|
+
✓ All .cy.ts files have .bdd.md companions
|
|
771
|
+
✓ No hardcoded selectors detected
|
|
772
|
+
✓ COVERAGE_SUMMARY generated successfully
|
|
773
|
+
```
|
|
774
|
+
|
|
775
|
+
**📋 CI/CD Integration:**
|
|
776
|
+
|
|
777
|
+
```yaml
|
|
778
|
+
# In your CI pipeline:
|
|
779
|
+
jobs:
|
|
780
|
+
test:
|
|
781
|
+
steps:
|
|
782
|
+
- name: Lint tests
|
|
783
|
+
run: pnpm lint:tests
|
|
784
|
+
|
|
785
|
+
- name: Build registries
|
|
786
|
+
run: pnpm build:registries
|
|
787
|
+
|
|
788
|
+
- name: Run smoke tests
|
|
789
|
+
run: pnpm cypress:run --env grepTags="@smoke"
|
|
790
|
+
|
|
791
|
+
- name: Check coverage thresholds
|
|
792
|
+
run: pnpm test:coverage-check
|
|
793
|
+
```
|
|
794
|
+
|
|
795
|
+
**📋 Coverage Check Script:**
|
|
796
|
+
|
|
797
|
+
```typescript
|
|
798
|
+
// scripts/check-coverage.ts
|
|
799
|
+
import { FeatureService } from '@/core/lib/services/feature.service'
|
|
800
|
+
|
|
801
|
+
const featureCoverage = FeatureService.getFeatureCoveragePercent()
|
|
802
|
+
const flowCoverage = FeatureService.getFlowCoveragePercent()
|
|
803
|
+
|
|
804
|
+
if (featureCoverage < 70) {
|
|
805
|
+
console.error(`Feature coverage ${featureCoverage}% is below 70% threshold`)
|
|
806
|
+
process.exit(1)
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
if (flowCoverage < 60) {
|
|
810
|
+
console.error(`Flow coverage ${flowCoverage}% is below 60% threshold`)
|
|
811
|
+
process.exit(1)
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
console.log(`✓ Coverage OK: Features ${featureCoverage}%, Flows ${flowCoverage}%`)
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
**📋 Common Validation Errors:**
|
|
818
|
+
|
|
819
|
+
```
|
|
820
|
+
ERROR: Unknown tag @feat-unknown in login.cy.ts
|
|
821
|
+
FIX: Add "unknown" feature to features.json or fix tag name
|
|
822
|
+
|
|
823
|
+
ERROR: Hardcoded selector in tasks.cy.ts:45
|
|
824
|
+
FIX: Import from CORE_SELECTORS instead of hardcoding
|
|
825
|
+
|
|
826
|
+
ERROR: Missing BDD file for auth/signup.cy.ts
|
|
827
|
+
FIX: Create auth/signup.bdd.md with test documentation
|
|
828
|
+
|
|
829
|
+
ERROR: Test without required tags in settings.cy.ts
|
|
830
|
+
FIX: Add @uat and @feat-* tags to describe block
|
|
831
|
+
```
|
|
832
|
+
|
|
833
|
+
```
|
|
834
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
835
|
+
|
|
836
|
+
✅ TUTORIAL STORY!
|
|
837
|
+
|
|
838
|
+
You've learned:
|
|
839
|
+
• 3-level selector system (NO HARDCODING!)
|
|
840
|
+
• Creating UAT and API tests with POMs
|
|
841
|
+
• Tag system and feature/flow connection
|
|
842
|
+
• BDD documentation for Devtools
|
|
843
|
+
• Registry generation and coverage metrics
|
|
844
|
+
• Lint and build validations
|
|
845
|
+
|
|
846
|
+
📚 PREVIOUS STEP:
|
|
847
|
+
/how-to:define-features-flows
|
|
848
|
+
└── Understand features & flows concept
|
|
849
|
+
|
|
850
|
+
📚 Related tutorials:
|
|
851
|
+
• /how-to:run-tests - Execute test suites
|
|
852
|
+
• /how-to:create-entity - Entity tests included
|
|
853
|
+
|
|
854
|
+
🔙 Back to menu: /how-to:start
|
|
855
|
+
```
|
|
856
|
+
|
|
857
|
+
---
|
|
858
|
+
|
|
859
|
+
## Interactive Options
|
|
860
|
+
|
|
861
|
+
### "Show me my current coverage gaps"
|
|
862
|
+
|
|
863
|
+
Claude should run:
|
|
864
|
+
|
|
865
|
+
```bash
|
|
866
|
+
pnpm build:registries
|
|
867
|
+
```
|
|
868
|
+
|
|
869
|
+
Then analyze the generated registry to report:
|
|
870
|
+
|
|
871
|
+
```
|
|
872
|
+
📊 COVERAGE ANALYSIS
|
|
873
|
+
|
|
874
|
+
FEATURES WITHOUT TESTS:
|
|
875
|
+
❌ billing - No @feat-billing tests found
|
|
876
|
+
❌ notifications - No @feat-notifications tests found
|
|
877
|
+
❌ superadmin - No @feat-superadmin tests found
|
|
878
|
+
|
|
879
|
+
FLOWS WITHOUT TESTS:
|
|
880
|
+
❌ team-collaboration - No @flow-team-collaboration tests
|
|
881
|
+
❌ checkout - No @flow-checkout tests
|
|
882
|
+
|
|
883
|
+
COVERAGE SUMMARY:
|
|
884
|
+
Features: 12/15 (80%)
|
|
885
|
+
Flows: 3/5 (60%)
|
|
886
|
+
|
|
887
|
+
RECOMMENDATIONS:
|
|
888
|
+
1. Add billing tests (critical feature)
|
|
889
|
+
2. Add team-collaboration flow tests
|
|
890
|
+
3. Increase superadmin coverage
|
|
891
|
+
```
|
|
892
|
+
|
|
893
|
+
### "How do I choose which tags to use?"
|
|
894
|
+
|
|
895
|
+
```
|
|
896
|
+
📋 Tag Selection Guide:
|
|
897
|
+
|
|
898
|
+
ALWAYS include:
|
|
899
|
+
• @uat or @api (test type)
|
|
900
|
+
• @feat-{name} (which feature)
|
|
901
|
+
|
|
902
|
+
ADD @smoke if:
|
|
903
|
+
• Critical user path
|
|
904
|
+
• Must work on every deploy
|
|
905
|
+
• Happy path scenarios
|
|
906
|
+
|
|
907
|
+
ADD @regression if:
|
|
908
|
+
• Edge cases
|
|
909
|
+
• Error scenarios
|
|
910
|
+
• Less critical paths
|
|
911
|
+
|
|
912
|
+
ADD @flow-{name} if:
|
|
913
|
+
• Tests multiple features
|
|
914
|
+
• Represents user journey
|
|
915
|
+
• Integration scenario
|
|
916
|
+
|
|
917
|
+
ADD operation tags (@crud, @search) if:
|
|
918
|
+
• Want to run all CRUD tests together
|
|
919
|
+
• Useful for debugging specific operations
|
|
920
|
+
|
|
921
|
+
EXAMPLE COMBINATIONS:
|
|
922
|
+
• @uat @smoke @feat-auth → Critical auth test
|
|
923
|
+
• @api @regression @feat-tasks @crud → Task API edge cases
|
|
924
|
+
• @uat @smoke @flow-onboarding → Critical onboarding flow
|
|
925
|
+
```
|
|
926
|
+
|
|
927
|
+
---
|
|
928
|
+
|
|
929
|
+
## Common Questions
|
|
930
|
+
|
|
931
|
+
### "How do I add a new selector?"
|
|
932
|
+
|
|
933
|
+
```
|
|
934
|
+
📋 Adding a New Selector:
|
|
935
|
+
|
|
936
|
+
1. Add data-cy to your component:
|
|
937
|
+
<button data-cy="my-feature-action">
|
|
938
|
+
|
|
939
|
+
2. Add to appropriate selector file:
|
|
940
|
+
|
|
941
|
+
For CORE (all themes):
|
|
942
|
+
packages/testing/src/selectors/core-selectors.ts
|
|
943
|
+
|
|
944
|
+
For BLOCKS:
|
|
945
|
+
Add to block component, follows block-{name}-{element}
|
|
946
|
+
|
|
947
|
+
For THEME-SPECIFIC:
|
|
948
|
+
contents/themes/{theme}/tests/selectors.ts
|
|
949
|
+
|
|
950
|
+
3. Rebuild:
|
|
951
|
+
pnpm build:registries
|
|
952
|
+
|
|
953
|
+
4. Use in tests:
|
|
954
|
+
import { CORE_SELECTORS } from '@nextsparkjs/testing'
|
|
955
|
+
cy.get(sel(CORE_SELECTORS.myFeature.action))
|
|
956
|
+
```
|
|
957
|
+
|
|
958
|
+
### "How do I rebuild the registry?"
|
|
959
|
+
|
|
960
|
+
```bash
|
|
961
|
+
# Rebuild all registries (including testing)
|
|
962
|
+
pnpm build:registries
|
|
963
|
+
|
|
964
|
+
# Or specifically the testing registry
|
|
965
|
+
node packages/core/scripts/build/registry.mjs --testing
|
|
966
|
+
|
|
967
|
+
# The script will:
|
|
968
|
+
# 1. Scan all .cy.ts files
|
|
969
|
+
# 2. Extract tags
|
|
970
|
+
# 3. Match with features.json
|
|
971
|
+
# 4. Generate testing-registry.ts
|
|
972
|
+
# 5. Calculate COVERAGE_SUMMARY
|
|
973
|
+
```
|
|
974
|
+
|
|
975
|
+
---
|
|
976
|
+
|
|
977
|
+
## Related Commands
|
|
978
|
+
|
|
979
|
+
| Command | Description |
|
|
980
|
+
|---------|-------------|
|
|
981
|
+
| `/how-to:define-features-flows` | **PREVIOUS STEP** - Understand features & flows |
|
|
982
|
+
| `/how-to:run-tests` | Execute Cypress test suites |
|
|
983
|
+
| `/test:write` | Write tests for a feature |
|
|
984
|
+
| `/bdd:write` | Generate BDD documentation |
|