start-vibing 2.0.11 → 2.0.13
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 +177 -177
- package/dist/cli.js +19 -2
- package/package.json +42 -42
- package/template/.claude/CLAUDE.md +174 -174
- package/template/.claude/agents/01-orchestration/agent-selector.md +130 -130
- package/template/.claude/agents/01-orchestration/checkpoint-manager.md +142 -142
- package/template/.claude/agents/01-orchestration/context-manager.md +138 -138
- package/template/.claude/agents/01-orchestration/error-recovery.md +182 -182
- package/template/.claude/agents/01-orchestration/orchestrator.md +114 -114
- package/template/.claude/agents/01-orchestration/parallel-coordinator.md +141 -141
- package/template/.claude/agents/01-orchestration/task-decomposer.md +121 -121
- package/template/.claude/agents/01-orchestration/workflow-router.md +114 -114
- package/template/.claude/agents/02-typescript/bun-runtime-expert.md +197 -197
- package/template/.claude/agents/02-typescript/esm-resolver.md +193 -193
- package/template/.claude/agents/02-typescript/import-alias-enforcer.md +158 -158
- package/template/.claude/agents/02-typescript/ts-generics-helper.md +183 -183
- package/template/.claude/agents/02-typescript/ts-migration-helper.md +238 -238
- package/template/.claude/agents/02-typescript/ts-strict-checker.md +180 -180
- package/template/.claude/agents/02-typescript/ts-types-analyzer.md +199 -199
- package/template/.claude/agents/02-typescript/type-definition-writer.md +187 -187
- package/template/.claude/agents/02-typescript/zod-schema-designer.md +212 -212
- package/template/.claude/agents/02-typescript/zod-validator.md +158 -158
- package/template/.claude/agents/03-testing/playwright-assertions.md +265 -265
- package/template/.claude/agents/03-testing/playwright-e2e.md +247 -247
- package/template/.claude/agents/03-testing/playwright-fixtures.md +234 -234
- package/template/.claude/agents/03-testing/playwright-multi-viewport.md +256 -256
- package/template/.claude/agents/03-testing/playwright-page-objects.md +247 -247
- package/template/.claude/agents/03-testing/test-cleanup-manager.md +248 -248
- package/template/.claude/agents/03-testing/test-data-generator.md +254 -254
- package/template/.claude/agents/03-testing/tester-integration.md +278 -278
- package/template/.claude/agents/03-testing/tester-unit.md +207 -207
- package/template/.claude/agents/03-testing/vitest-config.md +287 -287
- package/template/.claude/agents/04-docker/container-health.md +255 -255
- package/template/.claude/agents/04-docker/deployment-validator.md +225 -225
- package/template/.claude/agents/04-docker/docker-compose-designer.md +281 -281
- package/template/.claude/agents/04-docker/docker-env-manager.md +235 -235
- package/template/.claude/agents/04-docker/docker-multi-stage.md +241 -241
- package/template/.claude/agents/04-docker/dockerfile-optimizer.md +208 -208
- package/template/.claude/agents/05-database/database-seeder.md +273 -273
- package/template/.claude/agents/05-database/mongodb-query-optimizer.md +230 -230
- package/template/.claude/agents/05-database/mongoose-aggregation.md +306 -306
- package/template/.claude/agents/05-database/mongoose-index-optimizer.md +182 -182
- package/template/.claude/agents/05-database/mongoose-schema-designer.md +267 -267
- package/template/.claude/agents/06-security/auth-session-validator.md +68 -68
- package/template/.claude/agents/06-security/input-sanitizer.md +80 -80
- package/template/.claude/agents/06-security/owasp-checker.md +97 -97
- package/template/.claude/agents/06-security/permission-auditor.md +100 -100
- package/template/.claude/agents/06-security/security-auditor.md +84 -84
- package/template/.claude/agents/06-security/sensitive-data-scanner.md +83 -83
- package/template/.claude/agents/07-documentation/api-documenter.md +136 -136
- package/template/.claude/agents/07-documentation/changelog-manager.md +105 -105
- package/template/.claude/agents/07-documentation/documenter.md +76 -76
- package/template/.claude/agents/07-documentation/domain-updater.md +81 -81
- package/template/.claude/agents/07-documentation/jsdoc-generator.md +114 -114
- package/template/.claude/agents/07-documentation/readme-generator.md +135 -135
- package/template/.claude/agents/08-git/branch-manager.md +58 -58
- package/template/.claude/agents/08-git/commit-manager.md +63 -63
- package/template/.claude/agents/08-git/pr-creator.md +76 -76
- package/template/.claude/agents/09-quality/code-reviewer.md +71 -71
- package/template/.claude/agents/09-quality/quality-checker.md +67 -67
- package/template/.claude/agents/10-research/best-practices-finder.md +89 -89
- package/template/.claude/agents/10-research/competitor-analyzer.md +106 -106
- package/template/.claude/agents/10-research/pattern-researcher.md +93 -93
- package/template/.claude/agents/10-research/research-cache-manager.md +76 -76
- package/template/.claude/agents/10-research/research-web.md +98 -98
- package/template/.claude/agents/10-research/tech-evaluator.md +101 -101
- package/template/.claude/agents/11-ui-ux/accessibility-auditor.md +136 -136
- package/template/.claude/agents/11-ui-ux/design-system-enforcer.md +125 -125
- package/template/.claude/agents/11-ui-ux/skeleton-generator.md +118 -118
- package/template/.claude/agents/11-ui-ux/ui-desktop.md +132 -132
- package/template/.claude/agents/11-ui-ux/ui-mobile.md +98 -98
- package/template/.claude/agents/11-ui-ux/ui-tablet.md +110 -110
- package/template/.claude/agents/12-performance/api-latency-analyzer.md +156 -156
- package/template/.claude/agents/12-performance/bundle-analyzer.md +113 -113
- package/template/.claude/agents/12-performance/memory-leak-detector.md +137 -137
- package/template/.claude/agents/12-performance/performance-profiler.md +115 -115
- package/template/.claude/agents/12-performance/query-optimizer.md +124 -124
- package/template/.claude/agents/12-performance/render-optimizer.md +154 -154
- package/template/.claude/agents/13-debugging/build-error-fixer.md +207 -207
- package/template/.claude/agents/13-debugging/debugger.md +149 -149
- package/template/.claude/agents/13-debugging/error-stack-analyzer.md +141 -141
- package/template/.claude/agents/13-debugging/network-debugger.md +208 -208
- package/template/.claude/agents/13-debugging/runtime-error-fixer.md +181 -181
- package/template/.claude/agents/13-debugging/type-error-resolver.md +185 -185
- package/template/.claude/agents/14-validation/final-validator.md +93 -93
- package/template/.claude/agents/_backup/analyzer.md +134 -134
- package/template/.claude/agents/_backup/code-reviewer.md +279 -279
- package/template/.claude/agents/_backup/commit-manager.md +219 -219
- package/template/.claude/agents/_backup/debugger.md +280 -280
- package/template/.claude/agents/_backup/documenter.md +237 -237
- package/template/.claude/agents/_backup/domain-updater.md +197 -197
- package/template/.claude/agents/_backup/final-validator.md +169 -169
- package/template/.claude/agents/_backup/orchestrator.md +149 -149
- package/template/.claude/agents/_backup/performance.md +232 -232
- package/template/.claude/agents/_backup/quality-checker.md +240 -240
- package/template/.claude/agents/_backup/research.md +315 -315
- package/template/.claude/agents/_backup/security-auditor.md +192 -192
- package/template/.claude/agents/_backup/tester.md +566 -566
- package/template/.claude/agents/_backup/ui-ux-reviewer.md +247 -247
- package/template/.claude/config/README.md +30 -30
- package/template/.claude/config/mcp-config.json +344 -344
- package/template/.claude/config/project-config.json +53 -53
- package/template/.claude/config/quality-gates.json +46 -46
- package/template/.claude/config/security-rules.json +45 -45
- package/template/.claude/config/testing-config.json +164 -164
- package/template/.claude/hooks/SETUP.md +126 -126
- package/template/.claude/hooks/run-hook.ts +176 -176
- package/template/.claude/hooks/stop-validator.ts +914 -824
- package/template/.claude/hooks/user-prompt-submit.ts +886 -886
- package/template/.claude/scripts/mcp-quick-install.ts +151 -151
- package/template/.claude/scripts/setup-mcps.ts +651 -651
- package/template/.claude/settings.json +275 -275
- package/template/.claude/skills/bun-runtime/SKILL.md +430 -430
- package/template/.claude/skills/codebase-knowledge/domains/claude-system.md +431 -431
- package/template/.claude/skills/codebase-knowledge/domains/mcp-integration.md +295 -295
- package/template/.claude/skills/debugging-patterns/SKILL.md +485 -485
- package/template/.claude/skills/docker-patterns/SKILL.md +555 -555
- package/template/.claude/skills/git-workflow/SKILL.md +454 -454
- package/template/.claude/skills/mongoose-patterns/SKILL.md +499 -499
- package/template/.claude/skills/nextjs-app-router/SKILL.md +327 -327
- package/template/.claude/skills/performance-patterns/SKILL.md +547 -547
- package/template/.claude/skills/playwright-automation/SKILL.md +438 -438
- package/template/.claude/skills/react-patterns/SKILL.md +389 -389
- package/template/.claude/skills/research-cache/SKILL.md +222 -222
- package/template/.claude/skills/shadcn-ui/SKILL.md +511 -511
- package/template/.claude/skills/tailwind-patterns/SKILL.md +465 -465
- package/template/.claude/skills/test-coverage/SKILL.md +467 -467
- package/template/.claude/skills/trpc-api/SKILL.md +434 -434
- package/template/.claude/skills/typescript-strict/SKILL.md +367 -367
- package/template/.claude/skills/zod-validation/SKILL.md +403 -403
- package/template/CLAUDE.md +117 -117
|
@@ -1,256 +1,256 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: playwright-multi-viewport
|
|
3
|
-
description: 'AUTOMATICALLY invoke AFTER any UI implementation. Triggers: UI feature implemented, responsive design, component created. Tests on desktop (1280px), tablet (768px), and mobile (375px) viewports. PROACTIVELY ensures cross-device compatibility.'
|
|
4
|
-
model: sonnet
|
|
5
|
-
tools: Read, Write, Edit, Bash, Grep, Glob
|
|
6
|
-
skills: test-coverage, playwright-automation
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# Playwright Multi-Viewport Agent
|
|
10
|
-
|
|
11
|
-
You create tests that run across multiple device viewports.
|
|
12
|
-
|
|
13
|
-
## Required Viewports (from CLAUDE.md)
|
|
14
|
-
|
|
15
|
-
| Platform | Width | Device | Key Features |
|
|
16
|
-
| -------- | ------- | --------- | ------------------------------- |
|
|
17
|
-
| Mobile | 375px | iPhone SE | Bottom nav, full-screen modals |
|
|
18
|
-
| Tablet | 768px | iPad | Collapsible sidebar, hybrid nav |
|
|
19
|
-
| Desktop | 1280px+ | Chrome | Sidebar + topbar, high density |
|
|
20
|
-
|
|
21
|
-
## Playwright Config
|
|
22
|
-
|
|
23
|
-
```typescript
|
|
24
|
-
// playwright.config.ts
|
|
25
|
-
import { defineConfig, devices } from '@playwright/test';
|
|
26
|
-
|
|
27
|
-
export default defineConfig({
|
|
28
|
-
testDir: './tests/e2e',
|
|
29
|
-
|
|
30
|
-
projects: [
|
|
31
|
-
// Desktop
|
|
32
|
-
{
|
|
33
|
-
name: 'Desktop Chrome',
|
|
34
|
-
use: { ...devices['Desktop Chrome'] },
|
|
35
|
-
},
|
|
36
|
-
|
|
37
|
-
// Tablet
|
|
38
|
-
{
|
|
39
|
-
name: 'iPad',
|
|
40
|
-
use: { ...devices['iPad'] },
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
name: 'iPad landscape',
|
|
44
|
-
use: { ...devices['iPad landscape'] },
|
|
45
|
-
},
|
|
46
|
-
|
|
47
|
-
// Mobile
|
|
48
|
-
{
|
|
49
|
-
name: 'iPhone SE',
|
|
50
|
-
use: { ...devices['iPhone SE'] },
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
name: 'iPhone 14',
|
|
54
|
-
use: { ...devices['iPhone 14'] },
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
name: 'iPhone 14 landscape',
|
|
58
|
-
use: { ...devices['iPhone 14 landscape'] },
|
|
59
|
-
},
|
|
60
|
-
],
|
|
61
|
-
});
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
## Viewport-Aware Tests
|
|
65
|
-
|
|
66
|
-
```typescript
|
|
67
|
-
// tests/e2e/flows/responsive.spec.ts
|
|
68
|
-
import { test, expect } from '../fixtures';
|
|
69
|
-
|
|
70
|
-
test.describe('Responsive Navigation', () => {
|
|
71
|
-
test('should show correct navigation', async ({ page, isMobile }) => {
|
|
72
|
-
await page.goto('/');
|
|
73
|
-
|
|
74
|
-
if (isMobile) {
|
|
75
|
-
// MOBILE: Bottom nav, hamburger menu
|
|
76
|
-
await expect(page.getByTestId('bottom-nav')).toBeVisible();
|
|
77
|
-
await expect(page.getByTestId('hamburger-menu')).toBeVisible();
|
|
78
|
-
await expect(page.getByTestId('desktop-sidebar')).toBeHidden();
|
|
79
|
-
|
|
80
|
-
// Open mobile menu
|
|
81
|
-
await page.getByTestId('hamburger-menu').click();
|
|
82
|
-
await expect(page.getByTestId('mobile-menu')).toBeVisible();
|
|
83
|
-
} else {
|
|
84
|
-
// DESKTOP/TABLET: Sidebar visible
|
|
85
|
-
await expect(page.getByTestId('desktop-sidebar')).toBeVisible();
|
|
86
|
-
await expect(page.getByTestId('hamburger-menu')).toBeHidden();
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
## Viewport-Specific Tests
|
|
93
|
-
|
|
94
|
-
```typescript
|
|
95
|
-
test.describe('Mobile-Only Tests', () => {
|
|
96
|
-
test.skip(({ isMobile }) => !isMobile, 'Mobile only');
|
|
97
|
-
|
|
98
|
-
test('should have bottom navigation', async ({ page }) => {
|
|
99
|
-
await page.goto('/');
|
|
100
|
-
await expect(page.getByTestId('bottom-nav')).toBeVisible();
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
test('should open full-screen modal', async ({ page }) => {
|
|
104
|
-
await page.goto('/');
|
|
105
|
-
await page.getByTestId('search-icon').click();
|
|
106
|
-
|
|
107
|
-
const modal = page.getByTestId('search-modal');
|
|
108
|
-
await expect(modal).toBeVisible();
|
|
109
|
-
|
|
110
|
-
// Verify full-screen
|
|
111
|
-
const box = await modal.boundingBox();
|
|
112
|
-
const viewport = page.viewportSize()!;
|
|
113
|
-
expect(box?.width).toBe(viewport.width);
|
|
114
|
-
expect(box?.height).toBe(viewport.height);
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
test.describe('Desktop-Only Tests', () => {
|
|
119
|
-
test.skip(({ isMobile }) => isMobile, 'Desktop only');
|
|
120
|
-
|
|
121
|
-
test('should have sidebar with search bar', async ({ page }) => {
|
|
122
|
-
await page.goto('/');
|
|
123
|
-
await expect(page.getByTestId('sidebar')).toBeVisible();
|
|
124
|
-
await expect(page.getByTestId('topbar-search')).toBeVisible();
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
## Custom Viewport Detection
|
|
130
|
-
|
|
131
|
-
```typescript
|
|
132
|
-
// tests/e2e/fixtures/viewport.fixture.ts
|
|
133
|
-
import { test as base } from '@playwright/test';
|
|
134
|
-
|
|
135
|
-
type ViewportType = 'mobile' | 'tablet' | 'desktop';
|
|
136
|
-
|
|
137
|
-
type ViewportFixture = {
|
|
138
|
-
viewportType: ViewportType;
|
|
139
|
-
isMobile: boolean;
|
|
140
|
-
isTablet: boolean;
|
|
141
|
-
isDesktop: boolean;
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
export const viewportFixture = base.extend<ViewportFixture>({
|
|
145
|
-
viewportType: async ({ page }, use) => {
|
|
146
|
-
const width = page.viewportSize()?.width || 1280;
|
|
147
|
-
if (width < 768) {
|
|
148
|
-
await use('mobile');
|
|
149
|
-
} else if (width < 1024) {
|
|
150
|
-
await use('tablet');
|
|
151
|
-
} else {
|
|
152
|
-
await use('desktop');
|
|
153
|
-
}
|
|
154
|
-
},
|
|
155
|
-
|
|
156
|
-
isMobile: async ({ viewportType }, use) => {
|
|
157
|
-
await use(viewportType === 'mobile');
|
|
158
|
-
},
|
|
159
|
-
|
|
160
|
-
isTablet: async ({ viewportType }, use) => {
|
|
161
|
-
await use(viewportType === 'tablet');
|
|
162
|
-
},
|
|
163
|
-
|
|
164
|
-
isDesktop: async ({ viewportType }, use) => {
|
|
165
|
-
await use(viewportType === 'desktop');
|
|
166
|
-
},
|
|
167
|
-
});
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
## Cross-Viewport Test Pattern
|
|
171
|
-
|
|
172
|
-
```typescript
|
|
173
|
-
test.describe('Feature works on all viewports', () => {
|
|
174
|
-
test('should complete checkout flow', async ({ page, isMobile, isTablet, isDesktop }) => {
|
|
175
|
-
await page.goto('/products');
|
|
176
|
-
|
|
177
|
-
// Add to cart (different buttons per viewport)
|
|
178
|
-
if (isMobile) {
|
|
179
|
-
await page.getByTestId('product-card').first().tap();
|
|
180
|
-
await page.getByTestId('add-to-cart-mobile').tap();
|
|
181
|
-
} else {
|
|
182
|
-
await page.getByTestId('product-card').first().hover();
|
|
183
|
-
await page.getByTestId('quick-add').click();
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// Verify cart
|
|
187
|
-
await expect(page.getByTestId('cart-count')).toHaveText('1');
|
|
188
|
-
|
|
189
|
-
// Go to checkout
|
|
190
|
-
if (isMobile) {
|
|
191
|
-
await page.getByTestId('bottom-nav-cart').tap();
|
|
192
|
-
} else {
|
|
193
|
-
await page.getByTestId('header-cart').click();
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
await expect(page).toHaveURL('/checkout');
|
|
197
|
-
});
|
|
198
|
-
});
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
## Visual Regression Per Viewport
|
|
202
|
-
|
|
203
|
-
```typescript
|
|
204
|
-
test.describe('Visual Snapshots', () => {
|
|
205
|
-
test('homepage matches snapshot', async ({ page }, testInfo) => {
|
|
206
|
-
await page.goto('/');
|
|
207
|
-
await page.waitForLoadState('networkidle');
|
|
208
|
-
|
|
209
|
-
// Snapshot includes project name (viewport)
|
|
210
|
-
await expect(page).toHaveScreenshot(`homepage-${testInfo.project.name}.png`);
|
|
211
|
-
});
|
|
212
|
-
});
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
## Running Multi-Viewport Tests
|
|
216
|
-
|
|
217
|
-
```bash
|
|
218
|
-
# Run all viewports
|
|
219
|
-
bunx playwright test
|
|
220
|
-
|
|
221
|
-
# Run specific viewport
|
|
222
|
-
bunx playwright test --project="iPhone SE"
|
|
223
|
-
|
|
224
|
-
# Run mobile only
|
|
225
|
-
bunx playwright test --project="iPhone SE" --project="iPhone 14"
|
|
226
|
-
|
|
227
|
-
# Run desktop only
|
|
228
|
-
bunx playwright test --project="Desktop Chrome"
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
## Viewport Checklist
|
|
232
|
-
|
|
233
|
-
```markdown
|
|
234
|
-
### Feature: [name]
|
|
235
|
-
|
|
236
|
-
- [ ] Desktop (1280px+)
|
|
237
|
-
- [ ] Sidebar visible
|
|
238
|
-
- [ ] Topbar with search
|
|
239
|
-
- [ ] Hover interactions work
|
|
240
|
-
- [ ] Tablet (768px)
|
|
241
|
-
- [ ] Collapsible sidebar works
|
|
242
|
-
- [ ] Touch + click both work
|
|
243
|
-
- [ ] Mobile (375px)
|
|
244
|
-
- [ ] Bottom nav visible
|
|
245
|
-
- [ ] No horizontal scroll
|
|
246
|
-
- [ ] Touch targets 44x44px+
|
|
247
|
-
- [ ] Full-screen modals work
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
## Critical Rules
|
|
251
|
-
|
|
252
|
-
1. **TEST ALL VIEWPORTS** - Desktop, tablet, mobile minimum
|
|
253
|
-
2. **SEPARATE UIs** - Not just responsive (from CLAUDE.md)
|
|
254
|
-
3. **TOUCH TARGETS** - 44x44px minimum on mobile
|
|
255
|
-
4. **NO HORIZONTAL SCROLL** - Never on mobile
|
|
256
|
-
5. **VIEWPORT-SPECIFIC LOGIC** - Use isMobile/isTablet/isDesktop
|
|
1
|
+
---
|
|
2
|
+
name: playwright-multi-viewport
|
|
3
|
+
description: 'AUTOMATICALLY invoke AFTER any UI implementation. Triggers: UI feature implemented, responsive design, component created. Tests on desktop (1280px), tablet (768px), and mobile (375px) viewports. PROACTIVELY ensures cross-device compatibility.'
|
|
4
|
+
model: sonnet
|
|
5
|
+
tools: Read, Write, Edit, Bash, Grep, Glob
|
|
6
|
+
skills: test-coverage, playwright-automation
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Playwright Multi-Viewport Agent
|
|
10
|
+
|
|
11
|
+
You create tests that run across multiple device viewports.
|
|
12
|
+
|
|
13
|
+
## Required Viewports (from CLAUDE.md)
|
|
14
|
+
|
|
15
|
+
| Platform | Width | Device | Key Features |
|
|
16
|
+
| -------- | ------- | --------- | ------------------------------- |
|
|
17
|
+
| Mobile | 375px | iPhone SE | Bottom nav, full-screen modals |
|
|
18
|
+
| Tablet | 768px | iPad | Collapsible sidebar, hybrid nav |
|
|
19
|
+
| Desktop | 1280px+ | Chrome | Sidebar + topbar, high density |
|
|
20
|
+
|
|
21
|
+
## Playwright Config
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
// playwright.config.ts
|
|
25
|
+
import { defineConfig, devices } from '@playwright/test';
|
|
26
|
+
|
|
27
|
+
export default defineConfig({
|
|
28
|
+
testDir: './tests/e2e',
|
|
29
|
+
|
|
30
|
+
projects: [
|
|
31
|
+
// Desktop
|
|
32
|
+
{
|
|
33
|
+
name: 'Desktop Chrome',
|
|
34
|
+
use: { ...devices['Desktop Chrome'] },
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
// Tablet
|
|
38
|
+
{
|
|
39
|
+
name: 'iPad',
|
|
40
|
+
use: { ...devices['iPad'] },
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'iPad landscape',
|
|
44
|
+
use: { ...devices['iPad landscape'] },
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
// Mobile
|
|
48
|
+
{
|
|
49
|
+
name: 'iPhone SE',
|
|
50
|
+
use: { ...devices['iPhone SE'] },
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'iPhone 14',
|
|
54
|
+
use: { ...devices['iPhone 14'] },
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'iPhone 14 landscape',
|
|
58
|
+
use: { ...devices['iPhone 14 landscape'] },
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Viewport-Aware Tests
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
// tests/e2e/flows/responsive.spec.ts
|
|
68
|
+
import { test, expect } from '../fixtures';
|
|
69
|
+
|
|
70
|
+
test.describe('Responsive Navigation', () => {
|
|
71
|
+
test('should show correct navigation', async ({ page, isMobile }) => {
|
|
72
|
+
await page.goto('/');
|
|
73
|
+
|
|
74
|
+
if (isMobile) {
|
|
75
|
+
// MOBILE: Bottom nav, hamburger menu
|
|
76
|
+
await expect(page.getByTestId('bottom-nav')).toBeVisible();
|
|
77
|
+
await expect(page.getByTestId('hamburger-menu')).toBeVisible();
|
|
78
|
+
await expect(page.getByTestId('desktop-sidebar')).toBeHidden();
|
|
79
|
+
|
|
80
|
+
// Open mobile menu
|
|
81
|
+
await page.getByTestId('hamburger-menu').click();
|
|
82
|
+
await expect(page.getByTestId('mobile-menu')).toBeVisible();
|
|
83
|
+
} else {
|
|
84
|
+
// DESKTOP/TABLET: Sidebar visible
|
|
85
|
+
await expect(page.getByTestId('desktop-sidebar')).toBeVisible();
|
|
86
|
+
await expect(page.getByTestId('hamburger-menu')).toBeHidden();
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Viewport-Specific Tests
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
test.describe('Mobile-Only Tests', () => {
|
|
96
|
+
test.skip(({ isMobile }) => !isMobile, 'Mobile only');
|
|
97
|
+
|
|
98
|
+
test('should have bottom navigation', async ({ page }) => {
|
|
99
|
+
await page.goto('/');
|
|
100
|
+
await expect(page.getByTestId('bottom-nav')).toBeVisible();
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test('should open full-screen modal', async ({ page }) => {
|
|
104
|
+
await page.goto('/');
|
|
105
|
+
await page.getByTestId('search-icon').click();
|
|
106
|
+
|
|
107
|
+
const modal = page.getByTestId('search-modal');
|
|
108
|
+
await expect(modal).toBeVisible();
|
|
109
|
+
|
|
110
|
+
// Verify full-screen
|
|
111
|
+
const box = await modal.boundingBox();
|
|
112
|
+
const viewport = page.viewportSize()!;
|
|
113
|
+
expect(box?.width).toBe(viewport.width);
|
|
114
|
+
expect(box?.height).toBe(viewport.height);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test.describe('Desktop-Only Tests', () => {
|
|
119
|
+
test.skip(({ isMobile }) => isMobile, 'Desktop only');
|
|
120
|
+
|
|
121
|
+
test('should have sidebar with search bar', async ({ page }) => {
|
|
122
|
+
await page.goto('/');
|
|
123
|
+
await expect(page.getByTestId('sidebar')).toBeVisible();
|
|
124
|
+
await expect(page.getByTestId('topbar-search')).toBeVisible();
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Custom Viewport Detection
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
// tests/e2e/fixtures/viewport.fixture.ts
|
|
133
|
+
import { test as base } from '@playwright/test';
|
|
134
|
+
|
|
135
|
+
type ViewportType = 'mobile' | 'tablet' | 'desktop';
|
|
136
|
+
|
|
137
|
+
type ViewportFixture = {
|
|
138
|
+
viewportType: ViewportType;
|
|
139
|
+
isMobile: boolean;
|
|
140
|
+
isTablet: boolean;
|
|
141
|
+
isDesktop: boolean;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
export const viewportFixture = base.extend<ViewportFixture>({
|
|
145
|
+
viewportType: async ({ page }, use) => {
|
|
146
|
+
const width = page.viewportSize()?.width || 1280;
|
|
147
|
+
if (width < 768) {
|
|
148
|
+
await use('mobile');
|
|
149
|
+
} else if (width < 1024) {
|
|
150
|
+
await use('tablet');
|
|
151
|
+
} else {
|
|
152
|
+
await use('desktop');
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
|
|
156
|
+
isMobile: async ({ viewportType }, use) => {
|
|
157
|
+
await use(viewportType === 'mobile');
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
isTablet: async ({ viewportType }, use) => {
|
|
161
|
+
await use(viewportType === 'tablet');
|
|
162
|
+
},
|
|
163
|
+
|
|
164
|
+
isDesktop: async ({ viewportType }, use) => {
|
|
165
|
+
await use(viewportType === 'desktop');
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Cross-Viewport Test Pattern
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
test.describe('Feature works on all viewports', () => {
|
|
174
|
+
test('should complete checkout flow', async ({ page, isMobile, isTablet, isDesktop }) => {
|
|
175
|
+
await page.goto('/products');
|
|
176
|
+
|
|
177
|
+
// Add to cart (different buttons per viewport)
|
|
178
|
+
if (isMobile) {
|
|
179
|
+
await page.getByTestId('product-card').first().tap();
|
|
180
|
+
await page.getByTestId('add-to-cart-mobile').tap();
|
|
181
|
+
} else {
|
|
182
|
+
await page.getByTestId('product-card').first().hover();
|
|
183
|
+
await page.getByTestId('quick-add').click();
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Verify cart
|
|
187
|
+
await expect(page.getByTestId('cart-count')).toHaveText('1');
|
|
188
|
+
|
|
189
|
+
// Go to checkout
|
|
190
|
+
if (isMobile) {
|
|
191
|
+
await page.getByTestId('bottom-nav-cart').tap();
|
|
192
|
+
} else {
|
|
193
|
+
await page.getByTestId('header-cart').click();
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
await expect(page).toHaveURL('/checkout');
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Visual Regression Per Viewport
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
test.describe('Visual Snapshots', () => {
|
|
205
|
+
test('homepage matches snapshot', async ({ page }, testInfo) => {
|
|
206
|
+
await page.goto('/');
|
|
207
|
+
await page.waitForLoadState('networkidle');
|
|
208
|
+
|
|
209
|
+
// Snapshot includes project name (viewport)
|
|
210
|
+
await expect(page).toHaveScreenshot(`homepage-${testInfo.project.name}.png`);
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Running Multi-Viewport Tests
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
# Run all viewports
|
|
219
|
+
bunx playwright test
|
|
220
|
+
|
|
221
|
+
# Run specific viewport
|
|
222
|
+
bunx playwright test --project="iPhone SE"
|
|
223
|
+
|
|
224
|
+
# Run mobile only
|
|
225
|
+
bunx playwright test --project="iPhone SE" --project="iPhone 14"
|
|
226
|
+
|
|
227
|
+
# Run desktop only
|
|
228
|
+
bunx playwright test --project="Desktop Chrome"
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Viewport Checklist
|
|
232
|
+
|
|
233
|
+
```markdown
|
|
234
|
+
### Feature: [name]
|
|
235
|
+
|
|
236
|
+
- [ ] Desktop (1280px+)
|
|
237
|
+
- [ ] Sidebar visible
|
|
238
|
+
- [ ] Topbar with search
|
|
239
|
+
- [ ] Hover interactions work
|
|
240
|
+
- [ ] Tablet (768px)
|
|
241
|
+
- [ ] Collapsible sidebar works
|
|
242
|
+
- [ ] Touch + click both work
|
|
243
|
+
- [ ] Mobile (375px)
|
|
244
|
+
- [ ] Bottom nav visible
|
|
245
|
+
- [ ] No horizontal scroll
|
|
246
|
+
- [ ] Touch targets 44x44px+
|
|
247
|
+
- [ ] Full-screen modals work
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## Critical Rules
|
|
251
|
+
|
|
252
|
+
1. **TEST ALL VIEWPORTS** - Desktop, tablet, mobile minimum
|
|
253
|
+
2. **SEPARATE UIs** - Not just responsive (from CLAUDE.md)
|
|
254
|
+
3. **TOUCH TARGETS** - 44x44px minimum on mobile
|
|
255
|
+
4. **NO HORIZONTAL SCROLL** - Never on mobile
|
|
256
|
+
5. **VIEWPORT-SPECIFIC LOGIC** - Use isMobile/isTablet/isDesktop
|