# Configuration ## Full Configuration ```typescript // playwright.config.ts import { defineConfig, devices } from '@playwright/test'; export default defineConfig({ testDir: './tests', fullyParallel: true, forbidOnly: !!process.env.CI, retries: process.env.CI ? 2 : 0, workers: process.env.CI ? 1 : undefined, reporter: [ ['html'], ['json', { outputFile: 'results.json' }], ['junit', { outputFile: 'results.xml' }], ], use: { baseURL: 'http://localhost:3000', trace: 'retain-on-failure', screenshot: 'only-on-failure', video: 'retain-on-failure', testIdAttribute: 'data-testid', }, projects: [ { name: 'chromium', use: { ...devices['Desktop Chrome'] }, }, { name: 'firefox', use: { ...devices['Desktop Firefox'] }, }, { name: 'webkit', use: { ...devices['Desktop Safari'] }, }, { name: 'mobile-chrome', use: { ...devices['Pixel 5'] }, }, { name: 'mobile-safari', use: { ...devices['iPhone 13'] }, }, ], webServer: { command: 'npm run dev', url: 'http://localhost:3000', reuseExistingServer: !process.env.CI, timeout: 120000, }, }); ``` ## Authentication Setup ```typescript // global-setup.ts import { chromium, FullConfig } from '@playwright/test'; async function globalSetup(config: FullConfig) { const browser = await chromium.launch(); const page = await browser.newPage(); await page.goto('http://localhost:3000/login'); await page.getByLabel('Email').fill('user@test.com'); await page.getByLabel('Password').fill('password'); await page.getByRole('button', { name: 'Log in' }).click(); await page.waitForURL(/dashboard/); // Save auth state await page.context().storageState({ path: 'auth.json' }); await browser.close(); } export default globalSetup; // playwright.config.ts export default defineConfig({ globalSetup: require.resolve('./global-setup'), use: { storageState: 'auth.json', }, }); ``` ## Project Dependencies ```typescript projects: [ { name: 'setup', testMatch: /global.setup\.ts/, }, { name: 'chromium', use: { ...devices['Desktop Chrome'] }, dependencies: ['setup'], }, ], ``` ## Environment Variables ```typescript // playwright.config.ts export default defineConfig({ use: { baseURL: process.env.BASE_URL || 'http://localhost:3000', }, }); // .env BASE_URL=https://staging.example.com ``` ## CI Configuration ```yaml # .github/workflows/playwright.yml name: Playwright Tests on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 - run: npm ci - run: npx playwright install --with-deps - run: npx playwright test - uses: actions/upload-artifact@v4 if: always() with: name: playwright-report path: playwright-report/ ``` ## Quick Reference | Option | Purpose | |--------|---------| | `testDir` | Test files location | | `fullyParallel` | Run tests in parallel | | `retries` | Retry failed tests | | `trace` | Record trace on failure | | `webServer` | Start dev server | | `globalSetup` | Run before all tests | | `storageState` | Reuse auth state |