Initial commit
This commit is contained in:
491
commands/es-test-setup.md
Normal file
491
commands/es-test-setup.md
Normal file
@@ -0,0 +1,491 @@
|
||||
---
|
||||
description: Initialize Playwright E2E testing for Tanstack Start projects with Cloudflare Workers-specific configuration
|
||||
---
|
||||
|
||||
# Playwright Test Setup Command
|
||||
|
||||
<command_purpose> Configure Playwright for end-to-end testing in Tanstack Start projects deployed to Cloudflare Workers. Sets up test infrastructure, accessibility testing, and Workers-specific patterns. </command_purpose>
|
||||
|
||||
## Introduction
|
||||
|
||||
<role>Senior QA Engineer specializing in Playwright setup for Tanstack Start + Cloudflare Workers applications</role>
|
||||
|
||||
This command initializes a complete Playwright testing setup optimized for:
|
||||
- Tanstack Start (React + TanStack Router)
|
||||
- Cloudflare Workers deployment
|
||||
- Server function testing
|
||||
- Cloudflare bindings (KV, D1, R2, DO)
|
||||
- Accessibility testing
|
||||
- Performance monitoring
|
||||
|
||||
## Prerequisites
|
||||
|
||||
<requirements>
|
||||
- Tanstack Start project initialized
|
||||
- Cloudflare Workers configured (wrangler.jsonc)
|
||||
- Node.js 18+
|
||||
- npm/pnpm/yarn
|
||||
</requirements>
|
||||
|
||||
## Main Tasks
|
||||
|
||||
### 1. Verify Project Setup
|
||||
|
||||
<thinking>
|
||||
Ensure this is a Tanstack Start project before installing Playwright.
|
||||
</thinking>
|
||||
|
||||
```bash
|
||||
# Check for Tanstack Start
|
||||
if ! grep -q "@tanstack/start" package.json; then
|
||||
echo "❌ Not a Tanstack Start project"
|
||||
echo "This command requires Tanstack Start."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for wrangler config
|
||||
if [ ! -f "wrangler.jsonc" ] && [ ! -f "wrangler.toml" ]; then
|
||||
echo "⚠️ No wrangler config found"
|
||||
echo "Playwright will be configured, but Cloudflare bindings tests may not work."
|
||||
fi
|
||||
```
|
||||
|
||||
### 2. Install Playwright Dependencies
|
||||
|
||||
```bash
|
||||
# Install Playwright and dependencies
|
||||
pnpm add -D @playwright/test @axe-core/playwright
|
||||
|
||||
# Install browsers
|
||||
npx playwright install --with-deps chromium firefox webkit
|
||||
```
|
||||
|
||||
### 3. Create Playwright Configuration
|
||||
|
||||
**File**: `playwright.config.ts`
|
||||
|
||||
```typescript
|
||||
import { defineConfig, devices } from '@playwright/test'
|
||||
|
||||
export default defineConfig({
|
||||
testDir: './e2e',
|
||||
fullyParallel: true,
|
||||
forbidOnly: !!process.env.CI,
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
workers: process.env.CI ? 1 : undefined,
|
||||
|
||||
reporter: [
|
||||
['html'],
|
||||
['list'],
|
||||
process.env.CI ? ['github'] : ['list'],
|
||||
],
|
||||
|
||||
use: {
|
||||
baseURL: process.env.PLAYWRIGHT_TEST_BASE_URL || 'http://localhost:3000',
|
||||
trace: 'on-first-retry',
|
||||
screenshot: 'only-on-failure',
|
||||
video: 'retain-on-failure',
|
||||
},
|
||||
|
||||
projects: [
|
||||
{
|
||||
name: 'chromium',
|
||||
use: { ...devices['Desktop Chrome'] },
|
||||
},
|
||||
{
|
||||
name: 'firefox',
|
||||
use: { ...devices['Desktop Firefox'] },
|
||||
},
|
||||
{
|
||||
name: 'webkit',
|
||||
use: { ...devices['Desktop Safari'] },
|
||||
},
|
||||
{
|
||||
name: 'Mobile Chrome',
|
||||
use: { ...devices['Pixel 5'] },
|
||||
},
|
||||
{
|
||||
name: 'Mobile Safari',
|
||||
use: { ...devices['iPhone 12'] },
|
||||
},
|
||||
],
|
||||
|
||||
webServer: {
|
||||
command: 'pnpm dev',
|
||||
url: 'http://localhost:3000',
|
||||
reuseExistingServer: !process.env.CI,
|
||||
timeout: 120 * 1000,
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
### 4. Create Directory Structure
|
||||
|
||||
```bash
|
||||
mkdir -p e2e/{routes,server-functions,components,auth,accessibility,performance,visual,fixtures}
|
||||
```
|
||||
|
||||
### 5. Create Example Tests
|
||||
|
||||
**File**: `e2e/example.spec.ts`
|
||||
|
||||
```typescript
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('Example Tests', () => {
|
||||
test('home page loads', async ({ page }) => {
|
||||
await page.goto('/')
|
||||
|
||||
await expect(page).toHaveTitle(/.*/)
|
||||
await expect(page.locator('body')).toBeVisible()
|
||||
})
|
||||
|
||||
test('has no console errors', async ({ page }) => {
|
||||
const errors: string[] = []
|
||||
|
||||
page.on('console', msg => {
|
||||
if (msg.type() === 'error') {
|
||||
errors.push(msg.text())
|
||||
}
|
||||
})
|
||||
|
||||
await page.goto('/')
|
||||
|
||||
expect(errors).toHaveLength(0)
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
**File**: `e2e/accessibility/home.spec.ts`
|
||||
|
||||
```typescript
|
||||
import { test, expect } from '@playwright/test'
|
||||
import AxeBuilder from '@axe-core/playwright'
|
||||
|
||||
test.describe('Accessibility', () => {
|
||||
test('home page has no a11y violations', async ({ page }) => {
|
||||
await page.goto('/')
|
||||
|
||||
const accessibilityScanResults = await new AxeBuilder({ page })
|
||||
.analyze()
|
||||
|
||||
expect(accessibilityScanResults.violations).toEqual([])
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
**File**: `e2e/performance/metrics.spec.ts`
|
||||
|
||||
```typescript
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('Performance', () => {
|
||||
test('measures page load time', async ({ page }) => {
|
||||
const startTime = Date.now()
|
||||
await page.goto('/')
|
||||
await page.waitForLoadState('networkidle')
|
||||
const loadTime = Date.now() - startTime
|
||||
|
||||
console.log(`Page load time: ${loadTime}ms`)
|
||||
|
||||
// Cloudflare Workers should load fast
|
||||
expect(loadTime).toBeLessThan(1000)
|
||||
})
|
||||
|
||||
test('measures TTFB', async ({ page }) => {
|
||||
await page.goto('/')
|
||||
|
||||
const timing = await page.evaluate(() =>
|
||||
JSON.parse(JSON.stringify(
|
||||
performance.getEntriesByType('navigation')[0]
|
||||
))
|
||||
)
|
||||
|
||||
const ttfb = timing.responseStart - timing.requestStart
|
||||
console.log(`TTFB: ${ttfb}ms`)
|
||||
|
||||
// Time to First Byte should be fast on Workers
|
||||
expect(ttfb).toBeLessThan(200)
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### 6. Create Test Fixtures
|
||||
|
||||
**File**: `e2e/fixtures/test-users.ts`
|
||||
|
||||
```typescript
|
||||
export const testUsers = {
|
||||
admin: {
|
||||
email: 'admin@test.com',
|
||||
password: 'admin123',
|
||||
name: 'Admin User',
|
||||
},
|
||||
regular: {
|
||||
email: 'user@test.com',
|
||||
password: 'user123',
|
||||
name: 'Regular User',
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 7. Update package.json Scripts
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"test:e2e": "playwright test",
|
||||
"test:e2e:ui": "playwright test --ui",
|
||||
"test:e2e:debug": "playwright test --debug",
|
||||
"test:e2e:headed": "playwright test --headed",
|
||||
"test:e2e:report": "playwright show-report"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 8. Create .env.test for Cloudflare Bindings
|
||||
|
||||
**File**: `.env.test`
|
||||
|
||||
```bash
|
||||
# Cloudflare Test Environment
|
||||
CLOUDFLARE_ACCOUNT_ID=your-test-account-id
|
||||
CLOUDFLARE_API_TOKEN=your-test-api-token
|
||||
|
||||
# Test Bindings (separate from production)
|
||||
KV_NAMESPACE_ID=test-kv-namespace-id
|
||||
D1_DATABASE_ID=test-d1-database-id
|
||||
R2_BUCKET_NAME=test-r2-bucket
|
||||
|
||||
# Test Base URL
|
||||
PLAYWRIGHT_TEST_BASE_URL=http://localhost:3000
|
||||
```
|
||||
|
||||
### 9. Create GitHub Actions Workflow (Optional)
|
||||
|
||||
**File**: `.github/workflows/e2e.yml`
|
||||
|
||||
```yaml
|
||||
name: E2E Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
timeout-minutes: 60
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Install Playwright Browsers
|
||||
run: npx playwright install --with-deps
|
||||
|
||||
- name: Run Playwright tests
|
||||
run: pnpm test:e2e
|
||||
env:
|
||||
CLOUDFLARE_ACCOUNT_ID: ${ secrets.CLOUDFLARE_ACCOUNT_ID}
|
||||
CLOUDFLARE_API_TOKEN: ${ secrets.CLOUDFLARE_API_TOKEN}
|
||||
|
||||
- name: Upload Playwright Report
|
||||
uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: playwright-report
|
||||
path: playwright-report/
|
||||
retention-days: 30
|
||||
```
|
||||
|
||||
### 10. Create Testing Guide
|
||||
|
||||
**File**: `e2e/README.md`
|
||||
|
||||
```markdown
|
||||
# E2E Testing Guide
|
||||
|
||||
## Running Tests
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
pnpm test:e2e
|
||||
|
||||
# Run with UI mode
|
||||
pnpm test:e2e:ui
|
||||
|
||||
# Run specific test file
|
||||
pnpm test:e2e e2e/routes/home.spec.ts
|
||||
|
||||
# Run in headed mode (see browser)
|
||||
pnpm test:e2e:headed
|
||||
|
||||
# Debug mode
|
||||
pnpm test:e2e:debug
|
||||
```
|
||||
|
||||
## Test Organization
|
||||
|
||||
- `routes/` - Tests for TanStack Router routes
|
||||
- `server-functions/` - Tests for server functions
|
||||
- `components/` - Tests for shadcn/ui components
|
||||
- `auth/` - Authentication flow tests
|
||||
- `accessibility/` - Accessibility tests (axe-core)
|
||||
- `performance/` - Performance and load time tests
|
||||
- `visual/` - Visual regression tests
|
||||
- `fixtures/` - Test data and helpers
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Test user behavior, not implementation**
|
||||
- Focus on what users see and do
|
||||
- Avoid testing internal state
|
||||
|
||||
2. **Use data-testid for stable selectors**
|
||||
```tsx
|
||||
<button data-testid="submit-button">Submit</button>
|
||||
```
|
||||
|
||||
3. **Test with real Cloudflare bindings**
|
||||
- Use test environment bindings
|
||||
- Don't mock KV, D1, R2, DO
|
||||
|
||||
4. **Run accessibility tests on every page**
|
||||
- Zero violations policy
|
||||
- Use @axe-core/playwright
|
||||
|
||||
5. **Monitor performance metrics**
|
||||
- Cold start < 500ms
|
||||
- TTFB < 200ms
|
||||
- Bundle size < 200KB
|
||||
```
|
||||
|
||||
### 11. Add .gitignore Entries
|
||||
|
||||
```bash
|
||||
# Add to .gitignore
|
||||
cat >> .gitignore << 'EOF'
|
||||
|
||||
# Playwright
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
/playwright/.cache/
|
||||
EOF
|
||||
```
|
||||
|
||||
### 12. Validation
|
||||
|
||||
**Task playwright-testing-specialist(verify setup)**:
|
||||
- Confirm Playwright installed
|
||||
- Verify browser binaries downloaded
|
||||
- Check test directory structure
|
||||
- Validate configuration file
|
||||
- Run example test to ensure setup works
|
||||
|
||||
```bash
|
||||
# Run validation
|
||||
pnpm test:e2e --reporter=list
|
||||
|
||||
# Should see:
|
||||
# ✓ example.spec.ts:5:3 › Example Tests › home page loads
|
||||
# ✓ accessibility/home.spec.ts:6:3 › Accessibility › home page has no a11y violations
|
||||
# ✓ performance/metrics.spec.ts:6:3 › Performance › measures page load time
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
After running `/es-test-setup`, you will have:
|
||||
|
||||
✅ Playwright installed with all browsers
|
||||
✅ Test directory structure created
|
||||
✅ Configuration file (playwright.config.ts)
|
||||
✅ Example tests (routes, accessibility, performance)
|
||||
✅ Test fixtures and helpers
|
||||
✅ npm scripts for running tests
|
||||
✅ CI/CD workflow template
|
||||
✅ Testing guide documentation
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Run example tests**:
|
||||
```bash
|
||||
pnpm test:e2e
|
||||
```
|
||||
|
||||
2. **Generate tests for your routes**:
|
||||
```bash
|
||||
/es-test-gen /users/$id
|
||||
```
|
||||
|
||||
3. **Add tests to your workflow**:
|
||||
- Write tests as you build features
|
||||
- Run tests before deployment
|
||||
- Monitor test results in CI/CD
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Issue: "Cannot find module '@playwright/test'"
|
||||
|
||||
**Solution**:
|
||||
```bash
|
||||
pnpm install
|
||||
npx playwright install
|
||||
```
|
||||
|
||||
### Issue: "Browser not found"
|
||||
|
||||
**Solution**:
|
||||
```bash
|
||||
npx playwright install --with-deps
|
||||
```
|
||||
|
||||
### Issue: "Tests timing out"
|
||||
|
||||
**Solution**: Increase timeout in `playwright.config.ts`:
|
||||
```typescript
|
||||
export default defineConfig({
|
||||
timeout: 60 * 1000, // 60 seconds per test
|
||||
// ...
|
||||
})
|
||||
```
|
||||
|
||||
### Issue: "Accessibility violations found"
|
||||
|
||||
**Solution**: Fix the violations! Playwright will show you exactly what's wrong:
|
||||
```
|
||||
Expected: []
|
||||
Received: [
|
||||
{
|
||||
"id": "color-contrast",
|
||||
"impact": "serious",
|
||||
"description": "Ensures the contrast between foreground and background colors meets WCAG 2 AA contrast ratio thresholds",
|
||||
"nodes": [...]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
- **Playwright Docs**: https://playwright.dev
|
||||
- **Axe Accessibility**: https://github.com/dequelabs/axe-core-npm/tree/develop/packages/playwright
|
||||
- **Cloudflare Testing**: https://developers.cloudflare.com/workers/testing/
|
||||
- **Best Practices**: https://playwright.dev/docs/best-practices
|
||||
|
||||
## Success Criteria
|
||||
|
||||
✅ Playwright installed and configured
|
||||
✅ Example tests passing
|
||||
✅ Accessibility testing enabled
|
||||
✅ Performance monitoring setup
|
||||
✅ CI/CD workflow ready
|
||||
✅ Team trained on testing practices
|
||||
Reference in New Issue
Block a user