Playwright Monorepo Test Setup: Scalable TypeScript Architecture for Large Projects

1. Introduction: Why Monorepos Need a Scalable Playwright Test Setup

Modern organizations rarely have a single frontend application.

A product platform may contain:

Customer Portal

Admin Portal

Partner Portal

Internal Dashboard

Mobile Web

Shared Design System

API Services

Keeping all these applications in separate repositories can create duplicated test utilities, inconsistent Playwright versions, repeated fixtures, and difficult framework maintenance.

A Playwright monorepo test setup provides another approach.

A monorepo can keep application-specific tests isolated while sharing:

The architecture becomes:

                        Playwright Monorepo

                                |

             +——————+——————+

             |                  |                  |

       Customer Portal     Admin Portal      Partner Portal

             |                  |                  |

           Tests              Tests              Tests

             |                  |                  |

             +——————+——————+

                                |

                       Shared Test Packages

                                |

              +—————–+—————–+

              |                 |                 |

           Fixtures          Utilities          API

              |                 |                 |

              +—————–+—————–+

                                |

                            CI/CD

This approach is especially useful when multiple teams own related applications but need a consistent Playwright Automation Framework.

Playwright itself supports projects for different browsers, devices, environments, or logical test groups, making its test runner suitable for multi-application configurations.


2. What Is a Playwright Monorepo Test Setup?

A Playwright monorepo test setup is an automation architecture where multiple applications, test suites, and reusable testing packages are maintained inside one repository.

For example:

playwright-monorepo/

├── apps/

│   ├── customer-portal/

│   ├── admin-portal/

│   └── partner-portal/

├── packages/

│   ├── fixtures/

│   ├── utils/

│   ├── api/

│   └── test-data/

├── playwright.config.ts

├── package.json

└── pnpm-workspace.yaml

The important distinction is shared infrastructure without shared test ownership.

The customer portal should not accidentally execute admin tests.

Instead:

customer-portal

    ↓

customer tests

    ↓

shared fixtures/utilities

admin-portal

    ↓

admin tests

    ↓

shared fixtures/utilities

This creates separation at the application level while preserving reuse at the framework level.


3. Monorepo vs Single-Repository Playwright Architecture

AreaSingle applicationPlaywright monorepo
ApplicationsOneMultiple
Test ownershipSimplePackage/application based
Shared utilitiesLocalShared packages
CISimpleSelective/affected execution
Dependency managementEasyWorkspace-based
ReportingOne suiteAggregated or package-specific
ScalabilityModerateHigh
Initial setupEasierMore complex

A monorepo is not automatically better.

It becomes valuable when applications have meaningful relationships and teams benefit from shared infrastructure.

If you have one small application with 50 tests, a monorepo can add unnecessary complexity.

If you have five applications with thousands of tests and common authentication, API, data, and reporting needs, a Playwright TypeScript monorepo setup can significantly reduce duplication.


4. When Should Teams Use a Playwright Monorepo?

Consider a monorepo when:

  • Multiple applications share the same organization.
  • Applications use the same technology stack.
  • Tests share authentication infrastructure.
  • Teams need common fixtures.
  • APIs are shared.
  • CI pipelines need coordinated releases.
  • You maintain a shared design system.
  • Test utilities are duplicated across repositories.
  • Multiple teams need consistent Playwright versions.

Avoid forcing unrelated applications into the same test repository.

A good architecture follows:

Share infrastructure, not application-specific assumptions.


5. Playwright Monorepo Prerequisites and Project Setup

You need:

  • Node.js
  • TypeScript
  • Playwright
  • npm, pnpm, or Yarn
  • A workspace-capable package manager
  • Git
  • CI/CD platform

For a new Playwright project:

npm init playwright@latest

Playwright’s current installer supports TypeScript and can create configuration, tests, browser binaries, and optional CI workflow files.

For a larger organization, pnpm is a common workspace choice because it provides explicit workspace configuration and efficient dependency management.


6. Creating a Playwright Monorepo Folder Structure

A practical enterprise structure is:

playwright-monorepo/

├── apps/

│   ├── customer-portal/

│   │   ├── tests/

│   │   ├── pages/

│   │   ├── test-data/

│   │   ├── playwright.config.ts

│   │   └── package.json

│   │

│   ├── admin-portal/

│   │   ├── tests/

│   │   ├── pages/

│   │   ├── test-data/

│   │   ├── playwright.config.ts

│   │   └── package.json

│   │

│   └── partner-portal/

│       ├── tests/

│       ├── pages/

│       └── playwright.config.ts

├── packages/

│   ├── fixtures/

│   ├── utils/

│   ├── api/

│   ├── test-data/

│   └── auth/

├── playwright.config.ts

├── package.json

├── pnpm-workspace.yaml

└── tsconfig.json

Responsibilities

DirectoryResponsibility
apps/Application-specific tests
pages/Application-specific Page Objects
fixtures/Shared Playwright fixtures
utils/Generic utilities
api/Reusable API clients
test-data/Shared data builders
auth/Authentication helpers
reports/Generated artifacts

This separation prevents a common enterprise problem: putting everything into one enormous tests/ directory.


7. Configuring pnpm Workspaces

At the repository root:

# pnpm-workspace.yaml

packages:

  – ‘apps/*’

  – ‘packages/*’

Root package.json:

{

  “name”: “playwright-monorepo”,

  “private”: true,

  “scripts”: {

    “test”: “playwright test”,

    “test:customer”: “pnpm –filter customer-portal test”,

    “test:admin”: “pnpm –filter admin-portal test”,

    “test:all”: “pnpm -r test”

  },

  “devDependencies”: {

    “@playwright/test”: “^1.60.0”,

    “typescript”: “^5.0.0”

  }

}

An application package can declare:

{

  “name”: “customer-portal”,

  “private”: true,

  “scripts”: {

    “test”: “playwright test”

  },

  “dependencies”: {

    “@company/test-fixtures”: “workspace:*”

  }

}

The important architectural principle is that shared packages should expose stable interfaces.

For example:

packages/fixtures

    ↓

authenticatedPage()

apiClient()

testUser()

The customer application consumes those capabilities without knowing how they are internally implemented.


8. Creating Separate Playwright Projects for Multiple Applications

Playwright projects are logical groups of tests with shared configuration. They can represent browsers, environments, devices, or test groups.

A root configuration can orchestrate applications:

// playwright.config.ts

import { defineConfig } from ‘@playwright/test’;

export default defineConfig({

  fullyParallel: true,

  reporter: [

    [‘list’],

    [‘html’, {

      outputFolder: ‘reports/root’

    }]

  ],

  projects: [

    {

      name: ‘customer’,

      testDir: ‘./apps/customer-portal/tests’,

      use: {

        baseURL:

          process.env.CUSTOMER_URL ??

          ‘http://localhost:3001’

      }

    },

    {

      name: ‘admin’,

      testDir: ‘./apps/admin-portal/tests’,

      use: {

        baseURL:

          process.env.ADMIN_URL ??

          ‘http://localhost:3002’

      }

    },

    {

      name: ‘partner’,

      testDir: ‘./apps/partner-portal/tests’,

      use: {

        baseURL:

          process.env.PARTNER_URL ??

          ‘http://localhost:3003’

      }

    }

  ]

});

Run one application:

npx playwright test –project=customer

Run everything:

npx playwright test

Playwright’s –project option allows teams to select individual projects instead of running every configured project.


9. Shared Page Objects in a Playwright Monorepo

Not every Page Object belongs in packages/.

A useful rule is:

Generic/shared page → packages/

Application-specific page → apps/<app>/pages/

For example:

// packages/utils/src/navigation.ts

import { Page } from ‘@playwright/test’;

export class Navigation {

  constructor(

    private readonly page: Page

  ) {}

  async openProfile() {

    await this.page

      .getByRole(‘link’, {

        name: ‘Profile’

      })

      .click();

  }

}

Application-specific Page Object:

// apps/customer-portal/pages/customer-home.page.ts

import { Page } from ‘@playwright/test’;

export class CustomerHomePage {

  constructor(

    private readonly page: Page

  ) {}

  async openOrders() {

    await this.page

      .getByRole(‘link’, {

        name: ‘Orders’

      })

      .click();

  }

}

This prevents Page Objects from becoming overly generic.


10. Shared Playwright Fixtures Across Applications

Shared fixtures are one of the biggest benefits of a Playwright monorepo testing framework.

Example:

// packages/fixtures/src/base.ts

import {

  test as base,

  expect

} from ‘@playwright/test’;

type Fixtures = {

  testUser: {

    email: string;

    role: string;

  };

};

export const test =

  base.extend<Fixtures>({

    testUser: async ({}, use) => {

      await use({

        email:

          ‘automation@example.com’,

        role: ‘customer’

      });

    }

  });

export { expect };

Then:

import {

  test,

  expect

} from ‘@company/test-fixtures’;

test(‘customer profile’, async ({

  page,

  testUser

}) => {

  await page.goto(‘/profile’);

  await expect(

    page.getByText(testUser.email)

  ).toBeVisible();

});

The fixture becomes a reusable contract.

Application tests don’t need to recreate the same user object.


11. Authentication and Storage State Across Monorepo Projects

Authentication is often shared across applications.

Playwright supports storageState for pre-authenticated browser contexts.

A setup project can create authentication state:

// apps/customer-portal/tests/auth.setup.ts

import {

  test as setup,

  expect

} from ‘@playwright/test’;

setup(

  ‘authenticate customer’,

  async ({ page }) => {

    await page.goto(‘/login’);

    await page.getByLabel(‘Email’)

      .fill(

        process.env.CUSTOMER_USER!

      );

    await page.getByLabel(‘Password’)

      .fill(

        process.env.CUSTOMER_PASSWORD!

      );

    await page.getByRole(‘button’, {

      name: ‘Sign in’

    }).click();

    await expect(

      page.getByText(‘Dashboard’)

    ).toBeVisible();

    await page.context()

      .storageState({

        path:

          ‘playwright/.auth/customer.json’

      });

  }

);

Then configure:

{

  name: ‘customer-authenticated’,

  testDir:

    ‘./apps/customer-portal/tests’,

  use: {

    baseURL:

      process.env.CUSTOMER_URL,

    storageState:

      ‘playwright/.auth/customer.json’

  }

}

For larger frameworks, use project dependencies for setup workflows. Playwright recommends project dependencies over a traditional globalSetup approach because dependencies integrate with reporting, tracing, fixtures, retries, and normal project behavior.


12. Project Dependencies for Monorepo Setup

A useful architecture is:

Customer Auth Setup

        |

        v

Customer Chromium

Customer Firefox

Configuration:

projects: [

  {

    name: ‘customer-auth’,

    testMatch:

      /customer\.auth\.setup\.ts/

  },

  {

    name: ‘customer-chromium’,

    testDir:

      ‘./apps/customer-portal/tests’,

    use: {

      browserName: ‘chromium’,

      baseURL:

        process.env.CUSTOMER_URL,

      storageState:

        ‘playwright/.auth/customer.json’

    },

    dependencies: [

      ‘customer-auth’

    ]

  }

]

The dependency runs first, then dependent projects can execute. Playwright also supports teardown projects for cleanup workflows.


13. Environment and Configuration Management

Never hard-code environment-specific URLs throughout tests.

Use:

export const environment = {

  customerUrl:

    process.env.CUSTOMER_URL ??

    ‘http://localhost:3001’,

  adminUrl:

    process.env.ADMIN_URL ??

    ‘http://localhost:3002’,

  apiUrl:

    process.env.API_URL ??

    ‘http://localhost:4000’

};

Then:

await page.goto(

  `${environment.customerUrl}/orders`

);

A better architecture uses Playwright’s baseURL:

use: {

  baseURL:

    process.env.CUSTOMER_URL

}

Then:

await page.goto(‘/orders’);

Playwright supports baseURL specifically to allow relative navigation and centralize target environment configuration.


14. API and UI Testing Across Multiple Applications

Shared API clients can live in:

packages/api/

Example:

import {

  APIRequestContext

} from ‘@playwright/test’;

export class UserApi {

  constructor(

    private readonly request:

      APIRequestContext

  ) {}

  async createUser(

    email: string

  ) {

    return this.request.post(

      ‘/users’,

      {

        data: { email }

      }

    );

  }

}

Test:

test(‘created user appears in UI’,

  async ({ page, request }) => {

    const api = new UserApi(request);

    await api.createUser(

      ‘qa@example.com’

    );

    await page.goto(‘/users’);

    await expect(

      page.getByText(

        ‘qa@example.com’

      )

    ).toBeVisible();

  }

);

This is a strong enterprise pattern:

API

 ↓

Create deterministic state

 ↓

UI

 ↓

Validate user behavior

It avoids unnecessarily creating test data through long UI workflows.


15. Test Data Management in a Playwright Monorepo

Shared test data should be reusable but configurable.

Example:

export function createUser(

  overrides = {}

) {

  return {

    firstName: ‘Test’,

    lastName: ‘User’,

    email:

      `qa-${Date.now()}@example.com`,

    role: ‘customer’,

    …overrides

  };

}

Usage:

const admin =

  createUser({

    role: ‘admin’

  });

For parallel execution, avoid fixed shared identifiers.

Bad:

test-user@example.com

Better:

test-user-workerIndex-{timestamp}

Or use server-generated IDs.

The objective is:

Worker 1 → isolated data

Worker 2 → isolated data

Worker 3 → isolated data

rather than:

Worker 1 ─┐

Worker 2 ─┼→ SAME DATABASE RECORD

Worker 3 ─┘


16. Parallel Execution and Test Isolation

Playwright supports worker processes for parallel test execution, and workers controls the maximum number of concurrent workers. fullyParallel can enable broader parallel execution.

Root configuration:

export default defineConfig({

  fullyParallel: true,

  workers:

    process.env.CI

      ? 4

      : undefined,

  retries:

    process.env.CI

      ? 2

      : 0,

  use: {

    trace: ‘on-first-retry’

  }

});

Parallel execution works well only when tests are isolated.

Avoid:

Test A modifies global user

Test B expects original user

Instead:

Test A → User A

Test B → User B

For large suites, test isolation is more important than simply increasing worker count.


17. Browser and Application Project Configuration

A monorepo can combine application and browser dimensions.

For example:

projects: [

  {

    name: ‘customer-chromium’,

    testDir:

      ‘./apps/customer-portal/tests’,

    use: {

      browserName: ‘chromium’,

      baseURL:

        process.env.CUSTOMER_URL

    }

  },

  {

    name: ‘customer-firefox’,

    testDir:

      ‘./apps/customer-portal/tests’,

    use: {

      browserName: ‘firefox’,

      baseURL:

        process.env.CUSTOMER_URL

    }

  },

  {

    name: ‘admin-chromium’,

    testDir:

      ‘./apps/admin-portal/tests’,

    use: {

      browserName: ‘chromium’,

      baseURL:

        process.env.ADMIN_URL

    }

  }

]

Playwright projects are explicitly designed for running the same tests under different browsers, devices, environments, or configurations.

Run only customer Chromium:

npx playwright test \

  –project=customer-chromium


18. Application-Specific Playwright Configuration

Large organizations may prefer separate configs rather than one massive root file.

For example:

apps/

├── customer-portal/

│   └── playwright.config.ts

└── admin-portal/

    └── playwright.config.ts

Customer config:

import { defineConfig } from ‘@playwright/test’;

export default defineConfig({

  testDir: ‘./tests’,

  use: {

    baseURL:

      process.env.CUSTOMER_URL

  },

  reporter: [

    [‘list’],

    [‘html’, {

      outputFolder:

        ‘reports/customer’

    }]

  ]

});

Run:

npx playwright test \

  –config=apps/customer-portal/playwright.config.ts

This is often preferable when application teams need independent ownership.

A centralized root config is preferable when the automation architecture is tightly standardized.


19. Multiple Web Servers in a Playwright Monorepo

A local monorepo may need:

Customer → localhost:3001

Admin    → localhost:3002

API      → localhost:4000

Playwright supports multiple webServer entries.

webServer: [

  {

    command:

      ‘pnpm –filter customer-portal dev’,

    url:

      ‘http://localhost:3001’,

    name:

      ‘Customer Portal’

  },

  {

    command:

      ‘pnpm –filter admin-portal dev’,

    url:

      ‘http://localhost:3002’,

    name:

      ‘Admin Portal’

  },

  {

    command:

      ‘pnpm –filter api dev’,

    url:

      ‘http://localhost:4000’,

    name:

      ‘API’

  }

]

This makes local execution much closer to the CI architecture.


20. Reporting and Test Artifact Management

Reporting becomes more complicated in a monorepo.

You may have:

reports/

├── customer/

├── admin/

├── partner/

└── combined/

Playwright supports multiple reporters in one configuration.

Example:

reporter: [

  [‘list’],

  [‘html’, {

    outputFolder:

      ‘reports/customer’

  }],

  [‘json’, {

    outputFile:

      ‘reports/customer/results.json’

  }]

]

Keep artifacts application-specific when teams need independent ownership.

For organization-wide dashboards, generate a standardized JSON format and aggregate it later.


21. Debugging Playwright Monorepo Tests

Debugging becomes easier when artifact paths contain project information.

Example:

outputDir:

  `test-results/${process.env.APP_NAME ?? ‘unknown’}`

Configure:

use: {

  screenshot: ‘only-on-failure’,

  video: ‘on-first-retry’,

  trace: ‘on-first-retry’

}

Then a failed test might produce:

test-results/

└── customer/

    └── chromium/

        └── login-test/

            ├── trace.zip

            ├── screenshot.png

            └── video.webm

Playwright’s project configuration also provides project-specific output directories and ensures unique output locations for parallel test execution.


22. Playwright Monorepo CI/CD With GitHub Actions

A simple matrix can run application suites independently:

name: Playwright Monorepo Tests

on:

  pull_request:

  push:

    branches:

      – main

jobs:

  test:

    runs-on: ubuntu-latest

    strategy:

      fail-fast: false

      matrix:

        app:

          – customer

          – admin

          – partner

    steps:

      – uses: actions/checkout@v6

      – uses: actions/setup-node@v6

        with:

          node-version: lts/*

          cache: pnpm

      – uses: pnpm/action-setup@v4

        with:

          version: 10

      – run: pnpm install –frozen-lockfile

      – run: pnpm exec playwright install –with-deps chromium

      – name: Run tests

        run: pnpm test:${{ matrix.app }}

      – name: Upload report

        if: !cancelled()uses:actions/upload-artifact@v5with:name:playwright-{{ matrix.app }}

          path: |

            reports/

            test-results/

This creates:

GitHub Actions

       |

       +—- Customer

       |

       +—- Admin

       |

       +—- Partner

Each job gets independent resources.


23. Running Only Affected Playwright Tests

This is one of the biggest advantages of a monorepo—but also one of the hardest problems.

Suppose a pull request changes:

apps/customer-portal/

There is little value in automatically running every partner test.

A mature CI system can determine:

Changed files

     ↓

Affected application

     ↓

Affected shared package?

     ↓

Test selection

Example:

apps/customer-portal/**

        ↓

customer tests

packages/api/**

        ↓

customer + admin + partner tests

Shared package changes should generally trigger dependent applications.

For example:

packages/fixtures/

       |

       +—- customer

       +—- admin

       +—- partner

The critical architectural task is maintaining dependency ownership.

Don’t simply assume that directory-based filtering is sufficient.


24. Real-World Enterprise Playwright Monorepo Project

Imagine a SaaS company with:

Customer Portal

Admin Console

Partner Portal

All three use:

OAuth

REST APIs

Shared design system

Common identity service

Architecture:

                  Monorepo

                      |

        +————-+————-+

        |             |             |

    Customer        Admin        Partner

        |             |             |

      Tests         Tests         Tests

        |             |             |

        +————-+————-+

                      |

              Shared Playwright

                Infrastructure

                      |

       +————–+————–+

       |              |              |

   Fixtures          API          Test Data

       |              |              |

       +————–+————–+

                      |

                    CI/CD

The teams own:

Customer team → customer tests

Admin team    → admin tests

Partner team  → partner tests

Platform team → shared packages

This creates clear boundaries.


25. Common Playwright Monorepo Setup Errors

ErrorCauseSolution
Tests run twiceRoot and package configs overlapDefine ownership clearly
Wrong application URLEnvironment variable collisionUse project-specific config
Shared fixture breaks one appFixture assumes application-specific UIKeep shared fixtures generic
CI runs everythingNo affected-test strategyAdd dependency-aware filtering
Reports overwrite each otherSame output folderUse project-specific paths
Auth state conflictsShared storage fileCreate application/role-specific states
Parallel tests failShared test dataGenerate isolated data
Browser missing in CIBrowser not installedRun Playwright browser install
Local app unavailableMissing webServerConfigure server startup
Workspace package not foundIncorrect workspace dependencyUse workspace:* and install from root

26. Playwright Monorepo Best Practices

1. Define ownership

Every application and shared package should have clear owners.

2. Keep application tests local

Don’t put customer-specific tests in a global shared package.

3. Share infrastructure

Share:

  • Fixtures
  • API clients
  • Data builders
  • Authentication utilities
  • Generic helpers

4. Avoid over-sharing Page Objects

A Customer Portal page should not become a generic framework abstraction just because another application has a similarly named page.

5. Standardize configuration

Use common defaults:

timeouts

retries

traces

screenshots

reporters

workers

Then override only when necessary.

6. Isolate authentication

Use separate storage states for:

customer

admin

partner

7. Make test data parallel-safe

Never rely on one mutable shared record.

8. Use project dependencies carefully

They are useful for setup and teardown workflows and integrate with Playwright’s reporting and fixtures.

9. Keep reports separate

A failed admin test should not be hidden inside a huge organization-wide report.

10. Optimize CI

Use:

  • Matrix jobs
  • Affected-test detection
  • Parallel workers
  • Sharding for very large suites

11. Standardize versions

One Playwright version across the workspace reduces inconsistent browser behavior.

12. Treat shared packages as APIs

Breaking a fixture package can break hundreds of tests.


27. Playwright Monorepo Architecture Interview Questions

1. Why use a Playwright monorepo?

To manage multiple application test suites while sharing common automation infrastructure and dependencies.

2. Should all tests be in one Playwright configuration?

Not necessarily.

Centralized projects work well for standardized organizations. Separate application configs work better when teams require independent ownership.

3. What should be shared?

Good candidates include:

Fixtures

API clients

Data builders

Authentication utilities

Generic helpers

Reporting utilities

4. What should remain application-specific?

Usually:

Page Objects

Business workflows

Application test data

Application-specific assertions

Application configuration

5. How do you prevent test duplication?

Move reusable infrastructure into packages and keep application tests focused on business behavior.

6. How do you handle authentication?

Use dedicated setup projects and storageState, with separate states for different applications or roles.

7. How do you handle parallel execution?

Ensure each test has isolated browser state and independent test data. Configure workers based on CI resources.

8. How do you run one application?

Use:

npx playwright test \

  –project=customer

or a workspace command such as:

pnpm test:customer

9. How do you handle reports?

Give each project its own output directory, then aggregate results only when organization-wide reporting is required.

10. What is the biggest monorepo risk?

Creating a shared framework so tightly coupled that a change for one application breaks every application.

The goal is controlled reuse, not maximum reuse.


28. Playwright Monorepo Learning Roadmap

Level 1: Playwright TypeScript

Learn:

  • Locators
  • Assertions
  • Fixtures
  • Projects
  • Authentication
  • Reporting

Level 2: Workspace Management

Learn:

  • npm workspaces
  • pnpm workspaces
  • Yarn workspaces
  • Package dependencies
  • Workspace filtering

Level 3: Framework Architecture

Learn:

Level 4: Enterprise CI/CD

Learn:

  • GitHub Actions
  • Matrix execution
  • Affected tests
  • Parallel execution
  • Test sharding
  • Artifact management

Level 5: Automation Architecture

Learn:

  • Ownership boundaries
  • Shared package design
  • Test isolation
  • Dependency graphs
  • Framework governance
  • Reporting architecture

Related topics include Advanced Playwright Automation Techniques, Playwright Test Architecture for Large Projects, Playwright Multi-Tenant Testing Strategy, Playwright Custom Fixtures Advanced, Playwright Test Sharding Advanced, Playwright Network Mocking Advanced, Playwright Custom Reporter Development, Playwright Component Testing Advanced, Playwright Accessibility Testing Advanced, Playwright Performance Testing Techniques, Playwright Authentication Tutorial, Playwright API Testing, Playwright Page Object Model, Playwright Fixtures Tutorial, Playwright Parallel Execution Tutorial, Playwright Reporting Tutorial, Playwright CI/CD Tutorial, Playwright GitHub Actions Tutorial, Playwright Docker Tutorial, Playwright TypeScript Tutorial, Playwright Framework Design, Playwright Best Practices, and Playwright Interview Questions.


29. FAQs: Playwright Monorepo Test Setup

What is a Playwright monorepo test setup?

It is a repository architecture that manages multiple applications and their Playwright test suites while sharing reusable automation packages.

Can Playwright work in a monorepo?

Yes. Playwright’s project model can organize tests into logical groups, and workspace package managers can manage application-specific and shared dependencies.

How do I set up Playwright in a pnpm monorepo?

Create a root pnpm-workspace.yaml, place applications under apps/, shared testing libraries under packages/, and define Playwright configurations at either the root or application level.

Should each application have its own Playwright config?

It depends.

Use separate configs when applications have independent ownership and environments. Use one root config with projects when consistent centralized orchestration is more important.

How do I share Playwright fixtures across applications?

Create a workspace package such as:

packages/fixtures/

and import its exported fixtures from application-specific test suites.

How do I share Page Objects?

Only share Page Objects when the underlying UI and behavior are genuinely common. Application-specific Page Objects should remain within their application’s package.

How do I handle authentication?

Create authentication setup projects and save role/application-specific storage states. Playwright’s storageState can then initialize authenticated browser contexts.

How do I run only one application?

With centralized projects:

npx playwright test –project=customer

With workspace scripts:

pnpm test:customer

Can Playwright monorepos run tests in parallel?

Yes. Configure Playwright workers and parallel execution while ensuring test data and application state are isolated.

Can different applications use different browsers?

Yes. Playwright projects can represent different browsers, devices, environments, or application configurations.

Can a monorepo run multiple local applications?

Yes. Playwright’s webServer supports one or multiple development servers.

How should monorepo reports be organized?

Keep application-specific reports separate and aggregate them only when a central dashboard or organization-wide report is required.

Leave a Comment

Your email address will not be published. Required fields are marked *