← Back to libraryQuestion 183 of 273
🎭PlaywrightIntermediate

playwright.config & Projects (Cross-Browser & Devices)

📌 Definition:

playwright.config is the single source of truth for how tests run: timeouts, retries, reporters, the shared use options (baseURL, trace, viewport), and projects — named run configurations that let one suite execute across browsers, devices, and setup dependencies.

📖 Detailed Explanation:

Projects are the key concept. Each project is a named configuration with its own use options and can depend on other projects. This is how you run the same tests on Desktop Chrome, Firefox, WebKit and emulated mobile devices (devices['Pixel 7'], devices['iPhone 14']) from one command, and how you wire an auth 'setup' project as a dependency so login runs first. Shared options live under top-level use (baseURL so tests navigate with relative paths, trace/screenshot policies, default viewport, locale, timezone). Because config is code, you can branch on process.env.CI for retries and reporters. Good config is a large part of a suite's quality: it encodes cross-browser coverage, artifact capture, and environment targeting in one reviewable file.

🔑 Key Points:
  • Projects = named run configs; run cross-browser and emulated-device coverage from one suite
  • Project dependencies wire setup (e.g. auth) to run before dependent projects
  • Shared use options: baseURL, trace, screenshot, viewport, locale, timezone
  • baseURL enables relative navigation (page.goto('/login'))
  • Config is code — branch on process.env.CI for retries/reporters/workers
🌍 Real-World Example:

One command must cover desktop Chrome/Firefox/Safari plus emulated iPhone and Pixel, all starting authenticated. The config defines a 'setup' project for login and five browser/device projects that depend on it and load storageState — so npx playwright test runs the whole matrix, authenticated, with per-project traces.

📎 Code Example:
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  use: { baseURL: process.env.BASE_URL ?? 'https://www.qapractice.com', trace: 'on-first-retry' },
  reporter: process.env.CI ? [['blob'], ['github']] : [['html']],
  projects: [
    { name: 'setup', testMatch: /auth\.setup\.ts/ },
    { name: 'chromium', use: { ...devices['Desktop Chrome'], storageState: 'auth/user.json' }, dependencies: ['setup'] },
    { name: 'firefox',  use: { ...devices['Desktop Firefox'], storageState: 'auth/user.json' }, dependencies: ['setup'] },
    { name: 'webkit',   use: { ...devices['Desktop Safari'],  storageState: 'auth/user.json' }, dependencies: ['setup'] },
    { name: 'mobile-chrome', use: { ...devices['Pixel 7'], storageState: 'auth/user.json' }, dependencies: ['setup'] },
  ],
});
🎯 Scenario-Based Interview Question:

Scenario: The team wants the same suite to run against local (localhost:3000), staging and production, across three browsers, without duplicating test files. How do you structure playwright.config to do this cleanly?