E2E Testing with Playwright
Overview
This project uses Playwright for end-to-end testing.
Quick Start
Running Tests Locally
# Install dependencies (if not already done)
pnpm install
# Install Playwright browsers
npx playwright install
# Start development server (in a separate terminal)
pnpm dev
# Run all e2e tests
pnpm test:e2e
# Run tests with UI (interactive mode)
pnpm test:e2e:ui
# Run tests in debug mode
pnpm test:e2e:debug
# View test report
pnpm test:e2e:report
Development Server: Choosing the Best Mode for E2E Testing
By default, Playwright tests run against http://localhost:3000. Before running tests, ensure your development server is up and running. You can start it in development mode with:
pnpm dev
Note: Running in dev mode (pnpm dev) is convenient for rapid iteration, but it can be significantly slower than production builds. As a result, you may encounter Playwright timeout errors if pages take too long to load or build on demand.
Tips to Avoid Timeout Issues
- Preload pages: Manually visit the routes you plan to test in your browser before running the tests. This triggers Next.js to build those pages ahead of time, reducing load times during testing.
- Increase Playwright timeouts: If you must use dev mode, consider increasing Playwright's default timeouts to accommodate slower builds (see Playwright config docs).
- Use a production build for reliability: For the fastest and most stable E2E test runs, use a production build. This ensures all pages are prebuilt and served at optimal speed:
pnpm build
pnpm start
This will serve your app at http://localhost:3000 in production mode, minimizing the risk of timeouts and making your tests more reliable.
Summary:
- Use
pnpm devfor quick local development and debugging, but expect slower performance and possible timeouts.- For CI or full test runs, prefer
pnpm build && pnpm startfor best results.
Directory Layout
tests/
├── __results__/ # Test results (gitignored)
├── __report__/ # HTML reports (gitignored)
└── e2e/
├── fixtures/ # Test data and fixtures
├── pages/ # Page Object Model classes
├── *.spec.ts # Test files
└── .gitignore
Writing Tests
Best Practices
1. Use Page Object Model
Create reusable page objects for common interactions. For more details, see the Playwright Page Object Model documentation:
// pages/HomePage.ts
export class HomePage {
constructor(private page: Page) {}
async goto() {
await this.page.goto("/")
}
async searchFor(query: string) {
const isMobile = await this.isMobileViewport()
if (isMobile) {
await this.page.getByTestId("search-button").first().click()
} else {
await this.page.getByTestId("search-input-button").first().click()
}
await this.page.getByPlaceholder("Search").fill(query)
}
private async isMobileViewport() {
const viewport = this.page.viewportSize()
return viewport && viewport.width <= 768
}
}
2. Robust Selectors
Prefer data-testid attributes over CSS selectors:
// Good
await page.getByTestId("search-button")
// Better for accessibility
await page.getByRole("button", { name: "Search" })
// Avoid fragile selectors
await page.locator(".search-btn-class") // Fragile
3. Responsive Testing
Handle different viewport sizes appropriately:
test("search functionality", async ({ page }) => {
const viewport = page.viewportSize()
const isMobile = viewport && viewport.width <= breakpointAsNumber.md
if (isMobile) {
// Mobile-specific logic
} else {
// Desktop-specific logic
}
})
4. Visual Testing
Visual regression testing is handled separately via Storybook + Chromatic. E2E tests focus on functional assertions rather than visual snapshots.