--- description: Frontend testing standards using Playwright for end-to-end testing globs: **/*.{ts,js,svelte} --- When working on frontend features: 1. Test Coverage Requirements: - All new features must have e2e tests - Critical user flows must be tested - Test both success and error paths - Test responsive behavior for mobile/desktop - Test accessibility where applicable 2. Test Structure: - Use descriptive test names - Reset database state before each test - Group related tests in describe blocks - Keep tests focused and atomic - Add explicit waits and checks at key points 3. Testing Best Practices: - Test user interactions, not implementation - Use data-testid for test-specific selectors - Test across different viewport sizes - Test across multiple browsers - Verify visual and functional aspects 4. Reliable Test Execution: - Always reset database state with `/api/test/reset` - Wait for redirects with URL checks - Wait for content with `.waitForSelector()` - Check element visibility before interaction - Use specific selectors (id, role, exact text) - Add explicit waits after state changes - Store URLs after navigation for reliable returns 5. Required Test Cases: - Navigation flows - Form submissions - Error handling - Loading states - Responsive behavior - Cross-browser compatibility 6. Database Considerations: - Use single worker mode due to shared database - Reset database state before each test - Avoid parallel test execution - Consider test isolation needs 7. Running Tests: - Run tests before committing: `bun test` - Debug tests with UI: `bun test:ui` - Debug specific test: `bun test:debug` - Install browsers: `bun test:install` metadata: priority: high version: 1.1 examples: - input: | # Bad: Unreliable waiting await page.click('button'); await page.locator('h1').textContent(); output: | # Good: Explicit waits and checks await page.click('button'); await expect(page).toHaveURL(/\/expected-path/); await page.waitForSelector('h1'); await expect(page.locator('h1')).toBeVisible(); - input: | # Bad: No state reset test('creates item', async ({ page }) => { await page.goto('/items/new'); }); output: | # Good: Reset state first test('creates item', async ({ page }) => { await page.goto('/'); await page.request.post('/api/test/reset'); await page.goto('/items/new'); }); - input: | # Bad: No tests for new feature git commit -m "feat: add note search" output: | # Good: Feature with tests bun test git commit -m "feat: add note search with e2e tests Tests added: - Search functionality - Empty results handling - Error states - Mobile layout" - input: | # Bad: Testing implementation details test('internal state is correct', () => { expect(component.state.value).toBe(true) }) output: | # Good: Testing user interaction test('user can toggle feature', async ({ page }) => { await page.click('[data-testid=toggle]') await expect(page.locator('.status')).toHaveText('Enabled') })