216 lines
5.9 KiB
Markdown
216 lines
5.9 KiB
Markdown
---
|
|
description: Generate end-to-end browser tests for user workflows
|
|
shortcut: e2e
|
|
---
|
|
|
|
# End-to-End Test Generator
|
|
|
|
Generate comprehensive browser-based E2E tests for complete user workflows using Playwright, Cypress, or Selenium.
|
|
|
|
## Purpose
|
|
|
|
Create automated tests that simulate real user interactions:
|
|
- Complete user journeys (signup → login → purchase)
|
|
- Multi-page workflows
|
|
- Form interactions and validations
|
|
- Navigation flows
|
|
- Browser-specific behaviors
|
|
- Mobile responsive testing
|
|
|
|
## Supported Frameworks
|
|
|
|
**Playwright** (Recommended)
|
|
- Multi-browser support (Chromium, Firefox, WebKit)
|
|
- Auto-wait for elements
|
|
- Network interception
|
|
- Mobile emulation
|
|
- Parallel execution
|
|
|
|
**Cypress**
|
|
- Time-travel debugging
|
|
- Real-time reloads
|
|
- Automatic waiting
|
|
- Network stubbing
|
|
- Screenshot/video capture
|
|
|
|
**Selenium WebDriver**
|
|
- Mature ecosystem
|
|
- Cross-browser support
|
|
- Remote execution (Selenium Grid)
|
|
- Mobile testing (Appium)
|
|
|
|
## Test Generation
|
|
|
|
When invoked, generate E2E tests with:
|
|
|
|
1. **User workflow analysis**
|
|
- Identify key user journeys
|
|
- Map page interactions
|
|
- Define success criteria
|
|
|
|
2. **Page Object Model**
|
|
- Create page classes
|
|
- Define selectors
|
|
- Implement action methods
|
|
|
|
3. **Test scenarios**
|
|
- Happy path workflows
|
|
- Error handling paths
|
|
- Edge cases
|
|
|
|
4. **Assertions**
|
|
- URL validation
|
|
- Element presence
|
|
- Content verification
|
|
- State changes
|
|
|
|
## Example: Playwright Test
|
|
|
|
```typescript
|
|
import { test, expect } from '@playwright/test';
|
|
|
|
test.describe('User Registration Flow', () => {
|
|
test('should complete full registration workflow', async ({ page }) => {
|
|
// Navigate to signup
|
|
await page.goto('https://example.com/signup');
|
|
|
|
// Fill registration form
|
|
await page.fill('[name="email"]', '[email protected]');
|
|
await page.fill('[name="password"]', 'SecurePass123!');
|
|
await page.fill('[name="confirmPassword"]', 'SecurePass123!');
|
|
await page.check('[name="terms"]');
|
|
|
|
// Submit and wait for navigation
|
|
await page.click('button[type="submit"]');
|
|
await page.waitForURL('**/verify-email');
|
|
|
|
// Verify success message
|
|
await expect(page.locator('.success-message')).toContainText(
|
|
'Please check your email'
|
|
);
|
|
});
|
|
|
|
test('should show validation errors for invalid data', async ({ page }) => {
|
|
await page.goto('https://example.com/signup');
|
|
|
|
// Submit empty form
|
|
await page.click('button[type="submit"]');
|
|
|
|
// Verify error messages
|
|
await expect(page.locator('.error-email')).toBeVisible();
|
|
await expect(page.locator('.error-password')).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test.describe('E-commerce Purchase Flow', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
// Login before each test
|
|
await page.goto('https://example.com/login');
|
|
await page.fill('[name="email"]', '[email protected]');
|
|
await page.fill('[name="password"]', 'password123');
|
|
await page.click('button[type="submit"]');
|
|
await page.waitForURL('**/dashboard');
|
|
});
|
|
|
|
test('should complete product purchase', async ({ page }) => {
|
|
// Browse products
|
|
await page.goto('https://example.com/products');
|
|
await page.click('text=Add to Cart').first();
|
|
|
|
// Verify cart badge
|
|
await expect(page.locator('.cart-badge')).toHaveText('1');
|
|
|
|
// Go to checkout
|
|
await page.click('.cart-icon');
|
|
await page.click('text=Checkout');
|
|
|
|
// Fill shipping info
|
|
await page.fill('[name="address"]', '123 Main St');
|
|
await page.fill('[name="city"]', 'San Francisco');
|
|
await page.fill('[name="zip"]', '94102');
|
|
await page.click('text=Continue');
|
|
|
|
// Enter payment (test mode)
|
|
await page.fill('[name="cardNumber"]', '4242424242424242');
|
|
await page.fill('[name="expiry"]', '12/25');
|
|
await page.fill('[name="cvc"]', '123');
|
|
await page.click('text=Place Order');
|
|
|
|
// Verify success
|
|
await page.waitForURL('**/order/confirmation');
|
|
await expect(page.locator('.order-success')).toBeVisible();
|
|
await expect(page.locator('.order-number')).toContainText('ORDER-');
|
|
});
|
|
});
|
|
```
|
|
|
|
## Example: Cypress Test
|
|
|
|
```javascript
|
|
describe('User Dashboard Workflow', () => {
|
|
beforeEach(() => {
|
|
cy.login('[email protected]', 'password123');
|
|
});
|
|
|
|
it('should load dashboard with user data', () => {
|
|
cy.visit('/dashboard');
|
|
cy.get('.welcome-message').should('contain', 'Welcome, John');
|
|
cy.get('.user-stats').should('be.visible');
|
|
});
|
|
|
|
it('should create new project', () => {
|
|
cy.visit('/dashboard');
|
|
cy.get('[data-testid="new-project"]').click();
|
|
|
|
cy.get('[name="projectName"]').type('My New Project');
|
|
cy.get('[name="description"]').type('Project description here');
|
|
cy.get('button[type="submit"]').click();
|
|
|
|
cy.url().should('include', '/projects/');
|
|
cy.get('.project-title').should('contain', 'My New Project');
|
|
});
|
|
});
|
|
```
|
|
|
|
## Page Object Model
|
|
|
|
```typescript
|
|
// pages/LoginPage.ts
|
|
export class LoginPage {
|
|
constructor(private page: Page) {}
|
|
|
|
async goto() {
|
|
await this.page.goto('/login');
|
|
}
|
|
|
|
async login(email: string, password: string) {
|
|
await this.page.fill('[name="email"]', email);
|
|
await this.page.fill('[name="password"]', password);
|
|
await this.page.click('button[type="submit"]');
|
|
}
|
|
|
|
async getErrorMessage() {
|
|
return this.page.locator('.error-message').textContent();
|
|
}
|
|
}
|
|
|
|
// Test using Page Object
|
|
test('login with page object', async ({ page }) => {
|
|
const loginPage = new LoginPage(page);
|
|
await loginPage.goto();
|
|
await loginPage.login('[email protected]', 'password123');
|
|
await expect(page).toHaveURL('/dashboard');
|
|
});
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
- **Use data-testid attributes** - Stable selectors
|
|
- **Implement Page Objects** - Reusable page interactions
|
|
- **Handle waits properly** - Auto-wait or explicit waits
|
|
- **Test realistic scenarios** - Actual user workflows
|
|
- **Parallelize tests** - Faster execution
|
|
- **Capture screenshots on failure** - Debugging aid
|
|
- **Use fixtures** - Consistent test data
|
|
- **Test across browsers** - Chrome, Firefox, Safari
|