Skip to content

Commit 19e5643

Browse files
authored
Merge pull request #74 from lambda-curry/codegen-bot/update-playwright-cursor-rules-1748122643
2 parents 136fee2 + 1452217 commit 19e5643

2 files changed

Lines changed: 237 additions & 27 deletions

File tree

.cursor/rules/storybook-testing.mdc

Lines changed: 191 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ lambda-curry/forms/
2323
├── apps/docs/ # Storybook app
2424
│ ├── .storybook/ # Storybook configuration
2525
│ ├── src/remix-hook-form/ # Story files with tests
26+
│ ├── simple-server.js # Custom static server for testing
2627
│ └── package.json # Test scripts
2728
├── packages/components/ # Component library
2829
│ └── src/
@@ -31,6 +32,106 @@ lambda-curry/forms/
3132
└── .cursor/rules/ # Cursor rules directory
3233
```
3334

35+
# Environment Setup and Testing Infrastructure
36+
37+
## Prerequisites
38+
Before running Playwright tests locally, ensure the following setup is complete:
39+
40+
### 1. System Dependencies
41+
```bash
42+
# Install Node.js dependencies
43+
cd apps/docs
44+
yarn install
45+
46+
# Install Playwright browsers
47+
npx playwright install
48+
49+
# Install system dependencies for Playwright
50+
npx playwright install-deps
51+
```
52+
53+
### 2. Build Storybook Static Files
54+
```bash
55+
cd apps/docs
56+
yarn build # Creates storybook-static directory
57+
```
58+
59+
### 3. Server Setup for Local Testing
60+
Due to common port conflicts in development environments, use the custom static server for local testing:
61+
62+
```bash
63+
# Start the custom static server (handles port conflicts)
64+
cd apps/docs
65+
node simple-server.js & # Runs on port 45678
66+
```
67+
68+
The `simple-server.js` file provides:
69+
- Static file serving with proper MIME types
70+
- CORS headers for cross-origin requests
71+
- SPA routing fallback to index.html
72+
- Conflict-free port allocation (45678)
73+
74+
### 4. Run Tests Locally
75+
```bash
76+
# Run tests against the static server
77+
cd apps/docs
78+
npx test-storybook --url http://127.0.0.1:45678
79+
```
80+
81+
## Complete Local Testing Workflow
82+
```bash
83+
# Full local testing workflow from scratch
84+
cd apps/docs
85+
86+
# 1. Install dependencies (if needed)
87+
yarn install
88+
npx playwright install
89+
npx playwright install-deps
90+
91+
# 2. Build Storybook
92+
yarn build
93+
94+
# 3. Start static server
95+
node simple-server.js &
96+
97+
# 4. Run tests
98+
npx test-storybook --url http://127.0.0.1:45678
99+
100+
# 5. Stop server when done
101+
pkill -f "simple-server.js"
102+
```
103+
104+
## Troubleshooting Common Issues
105+
106+
### Port Conflicts
107+
If you encounter "EADDRINUSE" errors:
108+
- **Problem**: Default ports (6006, 6007, 8080, etc.) are occupied
109+
- **Solution**: Use the custom static server on port 45678
110+
- **Alternative**: Find available ports with `netstat -tulpn | grep :PORT`
111+
112+
### Browser Installation Issues
113+
If Playwright can't find browsers:
114+
```bash
115+
# Reinstall browsers
116+
npx playwright install chromium
117+
118+
# Install system dependencies
119+
npx playwright install-deps
120+
```
121+
122+
### Build Issues
123+
If Storybook build fails:
124+
```bash
125+
# Clean and rebuild
126+
rm -rf storybook-static
127+
yarn build
128+
```
129+
130+
### Test Execution Issues
131+
- **Timeout errors**: Increase timeout in test configuration
132+
- **Element not found**: Ensure proper async handling with `findBy*`
133+
- **Server not responding**: Verify static server is running on correct port
134+
34135
# Core Principles for Storybook Testing
35136

36137
## Story Structure Pattern
@@ -194,29 +295,90 @@ const testConditionalFields = async ({ canvas }: StoryContext) => {
194295
};
195296
```
196297

197-
## Environment Setup Requirements
198-
- Node.js (version in .nvmrc)
199-
- Yarn 4.7.0 via corepack
200-
- Playwright browsers: `npx playwright install chromium`
298+
## Performance and Best Practices
201299

202-
## Test Commands
300+
### Test Execution Optimization
301+
- **Fast Feedback**: Tests should complete in under 10 seconds
302+
- **Parallel Execution**: Leverage Playwright's parallel test execution
303+
- **Focused Testing**: Each story should test one primary workflow
304+
- **Efficient Selectors**: Use semantic queries (role, label) over CSS selectors
305+
306+
### Local Development Workflow
203307
```bash
204-
# Development workflow
308+
# Local development commands
205309
cd apps/docs
206-
yarn dev # Start Storybook
207-
yarn test:local # Run tests against running Storybook
310+
yarn dev # Start Storybook for development
311+
yarn test:local # Run tests against running Storybook (if available)
208312

209-
# CI/Production
210-
yarn test # Build, serve, and test
313+
# Local testing of built Storybook
314+
yarn build # Build static Storybook
315+
node simple-server.js & # Start custom server
316+
npx test-storybook --url http://127.0.0.1:45678 # Test built version
317+
```
318+
319+
### Codegen Testing Workflow
320+
This setup is optimized for Codegen agents and local development testing:
321+
```bash
322+
# Codegen workflow for testing built Storybook
323+
cd apps/docs
324+
yarn install
325+
npx playwright install
326+
npx playwright install-deps
327+
yarn build
328+
node simple-server.js &
329+
npx test-storybook --url http://127.0.0.1:45678
330+
```
331+
332+
## Advanced Testing Patterns
333+
334+
### Accessibility Testing
335+
```typescript
336+
// Include accessibility checks in stories
337+
import { checkA11y } from '@storybook/addon-a11y';
338+
339+
export const AccessibilityTest: Story = {
340+
play: async (storyContext) => {
341+
await checkA11y(storyContext.canvasElement);
342+
// Additional accessibility-specific tests
343+
},
344+
};
345+
```
346+
347+
### Visual Regression Testing
348+
```typescript
349+
// Use Playwright's screenshot capabilities
350+
export const VisualTest: Story = {
351+
play: async ({ canvasElement }) => {
352+
// Interact with component to desired state
353+
// Screenshot will be taken automatically by test-runner
354+
},
355+
};
356+
```
357+
358+
### Cross-Browser Testing
359+
```typescript
360+
// Configure multiple browsers in test-runner config
361+
// Tests run automatically across Chromium, Firefox, WebKit
211362
```
212363

213364
## Error Handling and Debugging
214-
- Use Storybook UI at http://localhost:6006 for visual debugging
215-
- Add console.logs for test execution flow debugging
216-
- Use browser dev tools during test execution
217-
- Check network tab for form submission verification
218365

219-
## Verification Steps
366+
### Debug Mode
367+
```bash
368+
# Run tests with debug output
369+
npx test-storybook --url http://127.0.0.1:45678 --verbose
370+
371+
# Run specific story
372+
npx test-storybook --url http://127.0.0.1:45678 --testNamePattern="ComponentName"
373+
```
374+
375+
### Common Error Patterns
376+
1. **Element not found**: Use proper async queries (`findBy*`)
377+
2. **Timing issues**: Add appropriate waits for async operations
378+
3. **Form submission failures**: Verify fetcher setup and router configuration
379+
4. **Port conflicts**: Use the custom static server solution
380+
381+
## Verification Checklist
220382
When creating or modifying Storybook tests, ensure:
221383

222384
1. ✅ Story includes all three test phases (default, invalid, valid)
@@ -227,19 +389,21 @@ When creating or modifying Storybook tests, ensure:
227389
6. ✅ Includes proper error handling and success scenarios
228390
7. ✅ Story serves as both documentation and test
229391
8. ✅ Component is properly isolated and focused
392+
9. ✅ Tests complete in reasonable time (< 10 seconds)
393+
10. ✅ Uses semantic queries for better maintainability
230394

231-
## Common Pitfalls to Avoid
232-
- Port conflicts (6006 already in use) - kill existing processes
233-
- Missing Playwright system dependencies - run `npx playwright install-deps`
234-
- Test timeouts - add delays for complex async operations
235-
- Element not found errors - ensure proper async handling
236-
- Form submission issues - verify fetcher setup and decorator usage
395+
## Team Workflow Integration
237396

238-
## Advanced Patterns
239-
- Create reusable test utilities in `apps/docs/src/lib/test-utils.ts`
240-
- Use story composition for different scenarios
241-
- Implement mock data factories for consistent test data
242-
- Group related stories with shared decorators
397+
### Code Review Guidelines
398+
- Verify test coverage includes happy path and error scenarios
399+
- Ensure stories are self-documenting and demonstrate component usage
400+
- Check that tests follow established patterns and conventions
401+
- Validate that new tests don't introduce flaky behavior
243402

244-
Remember: Every story should test real user workflows and serve as living documentation. Focus on behavior, not implementation details.
403+
### Local Development Focus
404+
- This setup is designed for local development and Codegen testing
405+
- Tests run against built Storybook static files for consistency
406+
- Custom server resolves common port conflicts in development environments
407+
- Fast feedback loop optimized for developer productivity
245408

409+
Remember: Every story should test real user workflows and serve as living documentation. Focus on behavior, not implementation details. The testing infrastructure should be reliable, fast, and easy to maintain for local development and Codegen workflows.

apps/docs/simple-server.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
const http = require('http');
2+
const fs = require('fs');
3+
const path = require('path');
4+
5+
const server = http.createServer((req, res) => {
6+
// Add CORS headers
7+
res.setHeader('Access-Control-Allow-Origin', '*');
8+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
9+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
10+
11+
let filePath = path.join(__dirname, 'storybook-static', req.url === '/' ? 'index.html' : req.url);
12+
13+
// If file doesn't exist, serve index.html for SPA routing
14+
if (!fs.existsSync(filePath)) {
15+
filePath = path.join(__dirname, 'storybook-static', 'index.html');
16+
}
17+
18+
const ext = path.extname(filePath);
19+
const contentType = {
20+
'.html': 'text/html',
21+
'.js': 'text/javascript',
22+
'.css': 'text/css',
23+
'.json': 'application/json',
24+
'.png': 'image/png',
25+
'.jpg': 'image/jpeg',
26+
'.gif': 'image/gif',
27+
'.svg': 'image/svg+xml'
28+
}[ext] || 'text/plain';
29+
30+
fs.readFile(filePath, (err, content) => {
31+
if (err) {
32+
console.error('Error reading file:', filePath, err);
33+
res.writeHead(404);
34+
res.end('Not found');
35+
return;
36+
}
37+
res.writeHead(200, { 'Content-Type': contentType });
38+
res.end(content);
39+
});
40+
});
41+
42+
const PORT = 45678;
43+
server.listen(PORT, () => {
44+
console.log(`Server running on http://127.0.0.1:${PORT}`);
45+
});
46+

0 commit comments

Comments
 (0)