Search code examples
playwright

Playwright nested projects


I have a need to build the following nested projects using Playwright

  projects: [ // this would be the root for all projects
    {
      name: 'Global Setup',
      testDir: 'global-setup',
      teardown: 'Global Teardown'
    },
    projects: [ // project A
      {
        name: 'Setup Project A',
        testDir: 'setup-proj-a',
        dependencies: ['Global Setup'],
        teardown: 'teardown-proj-a'
      },
      {
        name: 'Feature 1',
        testDir: 'proj-a/feature-1',
        dependencies: ['Setup Project A'],
        use: {
          ...devices['Desktop Chrome'],
          storageState: STORAGE_STATE
        }
      },
      {
        name: 'Feature 2',
        testDir: 'proj-a/feature-2',
        dependencies: ['Setup Project A'],
        use: {
          ...devices['Desktop Chrome']
        },
        fullyParallel: true
      },
      {
        name: 'Teardown Project A',
        testDir: 'teardown-proj-a'
      }

    projects: [ // project B
      {
        name: 'Setup Project B',
        testDir: 'setup-proj-b',
        dependencies: ['Global Setup'],
        teardown: 'teardown-proj-b'
      },
      {
        name: 'Feature 2',
        testDir: 'proj-b/feature-2',
        dependencies: ['Setup Project B'],
        use: {
          ...devices['Desktop Chrome'],
          storageState: STORAGE_STATE
        }
      },
      {
        name: 'Teardown Project B',
        testDir: 'teardown-proj-b'
      }
    {
      name: 'Global Teardown',
      testDir: 'global-teardown'
    }

Does Playwright support such an approach? Or is there a way to achieve this structure with Playwright?

And on the same topic, is it possible to have a generic playwright.config.ts file at root level, that can be extended by playwright.config.ts files in each project folder?

Currently I have one full playwright.config.ts file in each folder, with 70% of the options being identical for all projects


Solution

  • Either method will work. Here's the process...

    Single config file (recommended)

    You should be able to use a single playwright.config.ts for all of your projects. Remember that within a project config, you have access to the following properties:

    export default defineConfig({
      projects: [{
        // for selecting test files
        testDir, testMatch, testIgnore, 
        // for configuring project-specific settings:
        use,
      }],
    });
    

    In one shared file, it's easy to share config:

    export default defineConfig({
      projects: [{
        ...defaultConfig,
        name: 'Project A',
      }, {
        ...defaultConfig,
        name: 'Project B',
      }],
    });
    

    Perhaps the only gotcha is that you may want to match sure each project had a dedicated browser state (e.g. login, cookies, etc) for use across each of that project's features.

    Playwright has a good article about sharing state. The only caveat is that you will want to match sure each project stores it's state in a different location from the other.

    Multiple config files (for monorepo)

    Of course, you can use multiple playwright.config.ts files, but I would only recommend it if you're in a monorepo, where the projects are legitimately separate.

    If you wanted to go this route, you can import the values from your base config file and extend them.

    // ./playwright.config.ts
    export default defineConfig({});
    
    // ./packages/project-a/playwright.config.ts
    import baseConfig from '../../playwright.config.ts';
    
    export default defineConfig({
      ...baseConfig,
      // etc
    });
    

    I hope that helps.