E2E Testing Strategy
Follow Netflix Testing Pyramid: 5% E2E, 15% Integration, 80% Unit.
Philosophy
- •E2E is slow (5-10s per test vs 10ms unit)
- •E2E is brittle (UI changes break tests)
- •E2E is expensive (requires full stack + containers)
- •Most bugs caught earlier (unit + integration)
Result: Only test critical user workflows at E2E level.
What to Test
✅ Critical User Workflows:
- •Navigate to feature page
- •Create entity via modal
- •View in grid/list layout
- •Toggle view modes
- •Edit entity
- •Delete entity with confirmation
- •Form validation errors
❌ Don't Test:
- •Every error case (API tests do that)
- •CSS details (not visual testing)
- •Internal state transitions
Test Count
| Per Feature | ~6 critical paths |
|---|---|
| Total Duration | 14-19 seconds |
Architecture
code
e2e/ ├── features/ │ └── <feature>/ │ ├── <feature>.spec.ts # Tests │ ├── <feature>.page.ts # Page Object │ └── <feature>.data.ts # Test data ├── support/ │ ├── config/ │ │ └── test-credentials.ts # (gitignored) │ ├── pages/ │ │ └── base.page.ts │ └── utils/ └── playwright.config.ts
Commands
bash
# Run all E2E task e2e # Run with UI task e2e -- --headed # Debug mode task e2e -- --debug
Required Run Order
E2E depends on a clean infra + a known user:
- •Start Docker infra for E2E (DB/Redis/etc).
- •Login with the static test account (see
e2e/support/config/test-credentials.ts). - •Create a Store for each run (fresh infra each time).
- •Run core E2E flows.
Why: Each run uses a new infra setup, so a Store must exist before the main flows.
Quick Component Checks (Selectors)
To keep E2E stable and fast, add short data-* hooks on key components:
- •Prefer
data-test-idor the standard attributes from/.claude/skills/e2e-selectors/SKILL.md - •Keep names short, explicit, and feature-scoped (e.g.,
product-create,storage-delete) - •Add only on interactive or critical flow elements
- •Avoid Tailwind classes or text selectors
Best Practices
Do ✅
- •Use Page Objects for UI interactions
- •Setup data via API (faster than UI clicks)
- •Use meaningful test names
- •Verify via API assertions (more reliable)
- •Isolate test data (unique names per run)
- •Use
waitFor*notsleep - •Clean up after each test
Don't ❌
- •Don't test every error (API tests do that)
- •Don't test CSS details
- •Don't share state between tests
- •Don't use fixed sleeps
- •Don't leave test data
- •Don't run 100 E2E tests (max 5-10 per feature)