430 lines
10 KiB
Markdown
430 lines
10 KiB
Markdown
# Playwright E2E Testing Guide for Bakery-IA
|
|
|
|
This directory contains end-to-end (E2E) tests for the Bakery-IA SaaS application using [Playwright](https://playwright.dev).
|
|
|
|
## 📁 Project Structure
|
|
|
|
```
|
|
tests/
|
|
├── auth/ # Authentication tests (login, register, logout)
|
|
├── onboarding/ # Onboarding wizard tests
|
|
├── dashboard/ # Dashboard and main page tests
|
|
├── operations/ # Business operations tests
|
|
├── analytics/ # Analytics page tests (to be added)
|
|
├── settings/ # Settings page tests (to be added)
|
|
├── fixtures/ # Test data files (CSV, images, etc.)
|
|
├── helpers/ # Utility functions and helpers
|
|
│ ├── auth.ts # Authentication helpers
|
|
│ └── utils.ts # General utilities
|
|
├── .auth/ # Stored authentication states (gitignored)
|
|
├── .gitignore # Files to ignore in git
|
|
└── auth.setup.ts # Global authentication setup
|
|
```
|
|
|
|
## 🚀 Getting Started
|
|
|
|
### Prerequisites
|
|
|
|
- Node.js 20+
|
|
- npm installed
|
|
- Playwright browsers installed
|
|
|
|
### Installation
|
|
|
|
Playwright is already installed in this project. If you need to reinstall browsers:
|
|
|
|
```bash
|
|
npx playwright install
|
|
```
|
|
|
|
## 🎯 Running Tests
|
|
|
|
### Testing Against Local Dev Server (Default)
|
|
|
|
These commands test against the Vite dev server running on `localhost:5173`:
|
|
|
|
#### Run all tests (headless)
|
|
```bash
|
|
npm run test:e2e
|
|
```
|
|
|
|
#### Run tests with UI (interactive mode)
|
|
```bash
|
|
npm run test:e2e:ui
|
|
```
|
|
|
|
#### Run tests in headed mode (see browser)
|
|
```bash
|
|
npm run test:e2e:headed
|
|
```
|
|
|
|
#### Run tests in debug mode (step through tests)
|
|
```bash
|
|
npm run test:e2e:debug
|
|
```
|
|
|
|
### Testing Against Local Kubernetes/Tilt Environment
|
|
|
|
These commands test against your Tilt-managed Kubernetes cluster on `localhost`:
|
|
|
|
#### Prerequisites
|
|
- Tilt must be running: `tilt up`
|
|
- Frontend service must be accessible at `http://localhost` (via ingress)
|
|
- All services should be healthy (check with `tilt status` or the Tilt UI)
|
|
|
|
#### Run all tests against K8s (headless)
|
|
```bash
|
|
npm run test:e2e:k8s
|
|
```
|
|
|
|
#### Run tests with UI (interactive mode)
|
|
```bash
|
|
npm run test:e2e:k8s:ui
|
|
```
|
|
|
|
#### Run tests in headed mode (see browser)
|
|
```bash
|
|
npm run test:e2e:k8s:headed
|
|
```
|
|
|
|
#### Run tests in debug mode
|
|
```bash
|
|
npm run test:e2e:k8s:debug
|
|
```
|
|
|
|
#### Record tests against K8s environment
|
|
```bash
|
|
npm run test:e2e:k8s:codegen
|
|
```
|
|
|
|
#### Custom base URL
|
|
If your K8s ingress uses a different URL (e.g., `bakery-ia.local`):
|
|
```bash
|
|
PLAYWRIGHT_BASE_URL=http://bakery-ia.local npm run test:e2e:k8s
|
|
```
|
|
|
|
### General Test Commands
|
|
|
|
#### Run specific test file
|
|
```bash
|
|
npx playwright test tests/auth/login.spec.ts
|
|
# Or against K8s:
|
|
npx playwright test --config=playwright.k8s.config.ts tests/auth/login.spec.ts
|
|
```
|
|
|
|
#### Run tests matching a pattern
|
|
```bash
|
|
npx playwright test --grep "login"
|
|
# Or against K8s:
|
|
npx playwright test --config=playwright.k8s.config.ts --grep "login"
|
|
```
|
|
|
|
#### View test report
|
|
```bash
|
|
npm run test:e2e:report
|
|
```
|
|
|
|
## 🎬 Recording Tests (Codegen)
|
|
|
|
Playwright has a built-in test generator that records your actions:
|
|
|
|
```bash
|
|
npm run test:e2e:codegen
|
|
```
|
|
|
|
This opens a browser where you can interact with your app. Playwright will generate test code for your actions.
|
|
|
|
## 🔐 Authentication
|
|
|
|
Tests use a global authentication setup to avoid logging in before every test.
|
|
|
|
### How it works:
|
|
1. `auth.setup.ts` runs once before all tests
|
|
2. Logs in with test credentials
|
|
3. Saves authentication state to `tests/.auth/user.json`
|
|
4. Other tests reuse this state
|
|
|
|
### Test Credentials
|
|
|
|
Set these environment variables (or use defaults):
|
|
|
|
```bash
|
|
export TEST_USER_EMAIL="test@bakery.com"
|
|
export TEST_USER_PASSWORD="test-password-123"
|
|
```
|
|
|
|
### Creating authenticated tests
|
|
|
|
```typescript
|
|
import { test, expect } from '@playwright/test';
|
|
|
|
test.describe('My Test Suite', () => {
|
|
// Use saved auth state
|
|
test.use({ storageState: 'tests/.auth/user.json' });
|
|
|
|
test('my test', async ({ page }) => {
|
|
// Already logged in!
|
|
await page.goto('/app/dashboard');
|
|
});
|
|
});
|
|
```
|
|
|
|
## 📝 Writing Tests
|
|
|
|
### Basic Test Structure
|
|
|
|
```typescript
|
|
import { test, expect } from '@playwright/test';
|
|
|
|
test.describe('Feature Name', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
// Setup before each test
|
|
await page.goto('/your-page');
|
|
});
|
|
|
|
test('should do something', async ({ page }) => {
|
|
// Your test code
|
|
await page.getByRole('button', { name: 'Click me' }).click();
|
|
await expect(page).toHaveURL('/expected-url');
|
|
});
|
|
});
|
|
```
|
|
|
|
### Using Helpers
|
|
|
|
```typescript
|
|
import { login, logout, TEST_USER } from '../helpers/auth';
|
|
import { waitForLoadingToFinish, expectToastMessage } from '../helpers/utils';
|
|
|
|
test('my test with helpers', async ({ page }) => {
|
|
await login(page, TEST_USER);
|
|
await waitForLoadingToFinish(page);
|
|
await expectToastMessage(page, 'Success!');
|
|
});
|
|
```
|
|
|
|
### Best Practices
|
|
|
|
1. **Use semantic selectors**
|
|
```typescript
|
|
// ✅ Good
|
|
page.getByRole('button', { name: 'Submit' })
|
|
page.getByLabel('Email')
|
|
|
|
// ❌ Avoid
|
|
page.locator('.btn-primary')
|
|
page.locator('#email-input')
|
|
```
|
|
|
|
2. **Wait for elements properly**
|
|
```typescript
|
|
// ✅ Good - Auto-waits
|
|
await page.getByText('Hello').click();
|
|
|
|
// ❌ Avoid - Manual waits
|
|
await page.waitForTimeout(3000);
|
|
```
|
|
|
|
3. **Use data-testid for complex elements**
|
|
```typescript
|
|
// In your component
|
|
<div data-testid="product-card">...</div>
|
|
|
|
// In your test
|
|
await page.getByTestId('product-card').click();
|
|
```
|
|
|
|
4. **Reuse authentication**
|
|
```typescript
|
|
// ✅ Good - Reuse saved state
|
|
test.use({ storageState: 'tests/.auth/user.json' });
|
|
|
|
// ❌ Avoid - Login in every test
|
|
test.beforeEach(async ({ page }) => {
|
|
await login(page);
|
|
});
|
|
```
|
|
|
|
## 🔍 Debugging Tests
|
|
|
|
### 1. Use Playwright Inspector
|
|
```bash
|
|
npm run test:e2e:debug
|
|
```
|
|
|
|
### 2. Use console.log
|
|
```typescript
|
|
test('debug test', async ({ page }) => {
|
|
console.log('Current URL:', page.url());
|
|
});
|
|
```
|
|
|
|
### 3. Take screenshots
|
|
```typescript
|
|
await page.screenshot({ path: 'screenshot.png' });
|
|
```
|
|
|
|
### 4. View trace
|
|
When tests fail, check the trace viewer:
|
|
```bash
|
|
npx playwright show-trace test-results/trace.zip
|
|
```
|
|
|
|
## 🎨 Test Reports
|
|
|
|
After running tests, view the HTML report:
|
|
|
|
```bash
|
|
npm run test:e2e:report
|
|
```
|
|
|
|
This shows:
|
|
- ✅ Passed tests
|
|
- ❌ Failed tests
|
|
- 📸 Screenshots on failure
|
|
- 🎥 Videos on failure
|
|
- 📊 Traces for debugging
|
|
|
|
## 🌐 Multi-Browser Testing
|
|
|
|
Tests run on multiple browsers automatically:
|
|
- Chromium (Chrome/Edge)
|
|
- Firefox
|
|
- WebKit (Safari)
|
|
- Mobile Chrome
|
|
- Mobile Safari
|
|
|
|
Configure in `playwright.config.ts`.
|
|
|
|
## 📱 Mobile Testing
|
|
|
|
Tests automatically run on mobile viewports. To test specific viewport:
|
|
|
|
```typescript
|
|
test('mobile test', async ({ page }) => {
|
|
await page.setViewportSize({ width: 375, height: 667 });
|
|
// Your test
|
|
});
|
|
```
|
|
|
|
## 🔄 CI/CD Integration
|
|
|
|
Tests run automatically on GitHub Actions:
|
|
|
|
- ✅ On every push to `main` or `develop`
|
|
- ✅ On every pull request
|
|
- ✅ Uploads test reports as artifacts
|
|
- ✅ Comments on PRs with results
|
|
|
|
### GitHub Secrets Required
|
|
|
|
Set these in your repository settings:
|
|
- `TEST_USER_EMAIL`: Test user email
|
|
- `TEST_USER_PASSWORD`: Test user password
|
|
|
|
## 🧪 Test Coverage
|
|
|
|
Current test coverage:
|
|
|
|
- ✅ Authentication (login, register, logout)
|
|
- ✅ Onboarding wizard
|
|
- ✅ Dashboard smoke tests
|
|
- ✅ Purchase order management
|
|
- ✅ Product/Recipe creation
|
|
- 🔜 Analytics pages
|
|
- 🔜 Settings pages
|
|
- 🔜 Team management
|
|
- 🔜 Payment flows
|
|
|
|
## 🚨 Common Issues
|
|
|
|
### Tests fail with "timeout exceeded"
|
|
- Check if dev server is running (for regular tests)
|
|
- For K8s tests: Verify Tilt is running and services are healthy
|
|
- Increase timeout in `playwright.config.ts` or `playwright.k8s.config.ts`
|
|
- Check network speed
|
|
|
|
### Authentication fails
|
|
- Verify test credentials are correct
|
|
- Check if test user exists in database
|
|
- For K8s tests: Ensure the database is seeded with test data
|
|
- Clear `.auth/user.json` and re-run
|
|
|
|
### "Element not found"
|
|
- Check if selectors match your UI
|
|
- Add `await page.pause()` to inspect
|
|
- Use Playwright Inspector
|
|
|
|
### Tests work locally but fail in CI
|
|
- Check environment variables
|
|
- Ensure database is seeded with test data
|
|
- Check for timing issues (add explicit waits)
|
|
|
|
### K8s-Specific Issues
|
|
|
|
#### Cannot connect to http://localhost
|
|
```bash
|
|
# Check if ingress is running
|
|
kubectl get ingress -n bakery-ia
|
|
|
|
# Verify services are up
|
|
tilt status
|
|
|
|
# Check if you can access the frontend manually
|
|
curl http://localhost
|
|
```
|
|
|
|
#### Ingress returns 404 or 503
|
|
- Verify all Tilt resources are healthy in the Tilt UI
|
|
- Check frontend pod logs: `kubectl logs -n bakery-ia -l app=frontend`
|
|
- Restart Tilt: `tilt down && tilt up`
|
|
|
|
#### Tests are slower in K8s than dev server
|
|
- This is expected due to ingress routing overhead
|
|
- The K8s config has increased `navigationTimeout` to 30 seconds
|
|
- Consider running fewer browsers in parallel for K8s tests
|
|
|
|
#### Authentication state doesn't work
|
|
- Test credentials must match what's seeded in K8s database
|
|
- Check orchestrator logs for auth issues: `kubectl logs -n bakery-ia -l app=orchestrator`
|
|
- Delete `.auth/user.json` and re-run setup
|
|
|
|
#### Using custom ingress host (e.g., bakery-ia.local)
|
|
```bash
|
|
# Add to /etc/hosts
|
|
echo "127.0.0.1 bakery-ia.local" | sudo tee -a /etc/hosts
|
|
|
|
# Run tests with custom URL
|
|
PLAYWRIGHT_BASE_URL=http://bakery-ia.local npm run test:e2e:k8s
|
|
```
|
|
|
|
## 📚 Resources
|
|
|
|
- [Playwright Documentation](https://playwright.dev)
|
|
- [Best Practices](https://playwright.dev/docs/best-practices)
|
|
- [API Reference](https://playwright.dev/docs/api/class-playwright)
|
|
- [Selectors Guide](https://playwright.dev/docs/selectors)
|
|
|
|
## 🤝 Contributing
|
|
|
|
When adding new features:
|
|
|
|
1. Write E2E tests for critical user flows
|
|
2. Use existing helpers and utilities
|
|
3. Follow the established test structure
|
|
4. Add test data to `fixtures/` if needed
|
|
5. Update this README if adding new patterns
|
|
|
|
## 💡 Tips
|
|
|
|
- Use `test.only()` to run a single test during development
|
|
- Use `test.skip()` to temporarily disable a test
|
|
- Group related tests with `test.describe()`
|
|
- Use `test.beforeEach()` for common setup
|
|
- Keep tests independent and isolated
|
|
- Name tests descriptively: "should [action] when [condition]"
|
|
|
|
---
|
|
|
|
Happy Testing! 🎭
|