340 lines
7.7 KiB
Markdown
340 lines
7.7 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
|
|
|
|
### 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
|
|
```
|
|
|
|
### Run specific test file
|
|
```bash
|
|
npx playwright test tests/auth/login.spec.ts
|
|
```
|
|
|
|
### Run tests matching a pattern
|
|
```bash
|
|
npx playwright test --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
|
|
- Increase timeout in `playwright.config.ts`
|
|
- Check network speed
|
|
|
|
### Authentication fails
|
|
- Verify test credentials are correct
|
|
- Check if test user exists in database
|
|
- 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)
|
|
|
|
## 📚 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! 🎭
|