Projects & Dependencies
Table of Contents
- Project Configuration
- Project Dependencies
- Setup Projects
- Filtering & Running Projects
- Sharing Configuration
- Advanced Patterns
Project Configuration
Basic Multi-Browser Setup
// playwright.config.ts
import { defineConfig, devices } from "@playwright/test";
export default defineConfig({
projects: [
{
name: "chromium",
use: { ...devices["Desktop Chrome"] },
},
{
name: "firefox",
use: { ...devices["Desktop Firefox"] },
},
{
name: "webkit",
use: { ...devices["Desktop Safari"] },
},
],
});Environment-Based Projects
export default defineConfig({
projects: [
{
name: "staging",
use: {
baseURL: "https://staging.example.com",
},
},
{
name: "production",
use: {
baseURL: "https://example.com",
},
},
{
name: "local",
use: {
baseURL: "http://localhost:3000",
},
},
],
});Test Type Projects
export default defineConfig({
projects: [
{
name: "e2e",
testDir: "./tests/e2e",
use: { ...devices["Desktop Chrome"] },
},
{
name: "api",
testDir: "./tests/api",
use: { baseURL: "http://localhost:3000" },
},
{
name: "visual",
testDir: "./tests/visual",
use: {
...devices["Desktop Chrome"],
viewport: { width: 1280, height: 720 },
},
},
],
});Project Dependencies
Setup Dependency
export default defineConfig({
projects: [
// Setup project runs first
{
name: "setup",
testMatch: /.*\.setup\.ts/,
},
// Browser projects depend on setup
{
name: "chromium",
use: {
...devices["Desktop Chrome"],
storageState: ".auth/user.json",
},
dependencies: ["setup"],
},
{
name: "firefox",
use: {
...devices["Desktop Firefox"],
storageState: ".auth/user.json",
},
dependencies: ["setup"],
},
],
});Multiple Auth States
export default defineConfig({
projects: [
// Auth setup projects
{
name: "setup-admin",
testMatch: /admin\.setup\.ts/,
},
{
name: "setup-user",
testMatch: /user\.setup\.ts/,
},
// Admin tests
{
name: "admin-tests",
testDir: "./tests/admin",
use: { storageState: ".auth/admin.json" },
dependencies: ["setup-admin"],
},
// User tests
{
name: "user-tests",
testDir: "./tests/user",
use: { storageState: ".auth/user.json" },
dependencies: ["setup-user"],
},
// Tests that need both
{
name: "integration-tests",
testDir: "./tests/integration",
dependencies: ["setup-admin", "setup-user"],
},
],
});Chained Dependencies
export default defineConfig({
projects: [
// Step 1: Database setup
{
name: "db-setup",
testMatch: /db\.setup\.ts/,
},
// Step 2: Auth setup (needs DB)
{
name: "auth-setup",
testMatch: /auth\.setup\.ts/,
dependencies: ["db-setup"],
},
// Step 3: Seed data (needs auth)
{
name: "seed-setup",
testMatch: /seed\.setup\.ts/,
dependencies: ["auth-setup"],
},
// Tests (need everything)
{
name: "tests",
testDir: "./tests",
dependencies: ["seed-setup"],
},
],
});Setup Projects
Authentication Setup
Setup projects are the recommended way to handle authentication. They run before your main test projects and can use Playwright fixtures.
For complete authentication patterns (storage state, multiple auth states, auth fixtures), see fixtures-hooks.md.
Data Seeding Setup
// seed.setup.ts
import { test as setup } from "@playwright/test";
setup("seed test data", async ({ request }) => {
// Create test data via API
await request.post("/api/test/seed", {
data: {
users: 10,
products: 50,
orders: 100,
},
});
});Cleanup Setup
// cleanup.setup.ts
import { test as setup } from "@playwright/test";
setup("cleanup previous run", async ({ request }) => {
// Clean up data from previous test runs
await request.delete("/api/test/cleanup");
});Filtering & Running Projects
Run Specific Project
# Run single project
npx playwright test --project=chromium
# Run multiple projects
npx playwright test --project=chromium --project=firefoxRun by Grep
# Run tests matching pattern
npx playwright test --grep @smoke
# Run project with grep
npx playwright test --project=chromium --grep @critical
# Exclude pattern
npx playwright test --grep-invert @slowProject-Specific Grep
export default defineConfig({
projects: [
{
name: "smoke",
grep: /@smoke/,
use: { ...devices["Desktop Chrome"] },
},
{
name: "regression",
grepInvert: /@smoke/,
use: { ...devices["Desktop Chrome"] },
},
],
});Sharing Configuration
Base Configuration
// playwright.config.ts
const baseConfig = {
timeout: 30000,
expect: { timeout: 5000 },
use: {
trace: "on-first-retry",
screenshot: "only-on-failure",
},
};
export default defineConfig({
...baseConfig,
projects: [
{
name: "chromium",
use: {
...baseConfig.use,
...devices["Desktop Chrome"],
},
},
{
name: "firefox",
use: {
...baseConfig.use,
...devices["Desktop Firefox"],
},
},
],
});Shared Project Settings
const sharedBrowserConfig = {
timeout: 60000,
retries: 2,
use: {
video: "on-first-retry",
trace: "on-first-retry",
},
};
export default defineConfig({
projects: [
{
name: "chromium",
...sharedBrowserConfig,
use: {
...sharedBrowserConfig.use,
...devices["Desktop Chrome"],
},
},
{
name: "firefox",
...sharedBrowserConfig,
use: {
...sharedBrowserConfig.use,
...devices["Desktop Firefox"],
},
},
],
});Advanced Patterns
Conditional Projects
const projects = [
{
name: "chromium",
use: { ...devices["Desktop Chrome"] },
},
];
// Add Firefox only in CI
if (process.env.CI) {
projects.push({
name: "firefox",
use: { ...devices["Desktop Firefox"] },
});
}
// Add mobile only for specific test dirs
if (process.env.TEST_MOBILE) {
projects.push({
name: "mobile",
use: { ...devices["iPhone 14"] },
});
}
export default defineConfig({ projects });Project Metadata
export default defineConfig({
projects: [
{
name: "chromium",
use: { ...devices["Desktop Chrome"] },
metadata: {
platform: "desktop",
browser: "chromium",
priority: "high",
},
},
],
});
// Access in test
test("example", async ({ page }, testInfo) => {
const { platform, priority } = testInfo.project.metadata;
console.log(`Running on ${platform} with ${priority} priority`);
});Teardown Projects
export default defineConfig({
projects: [
{
name: "setup",
testMatch: /.*\.setup\.ts/,
teardown: "teardown", // Run teardown after this completes
},
{
name: "teardown",
testMatch: /.*\.teardown\.ts/,
},
{
name: "tests",
dependencies: ["setup"],
},
],
});// cleanup.teardown.ts
import { test as teardown } from "@playwright/test";
teardown("cleanup", async ({ request }) => {
await request.delete("/api/test/data");
});Anti-Patterns to Avoid
| Anti-Pattern | Problem | Solution |
|---|---|---|
| Too many browser projects | Slow CI, expensive | Focus on critical browsers |
| Missing setup dependencies | Tests fail randomly | Declare all dependencies explicitly |
| Duplicated configuration | Hard to maintain | Extract shared config |
| Not using setup projects | Repeated auth in tests | Use setup project + storageState |
Related References
- Global Setup: See global-setup.md for globalSetup vs setup projects
- Fixtures: See fixtures-hooks.md for authentication patterns
- CI/CD: See ci-cd.md for running projects in CI