Search code examples
node.jsenvironment-variablesplaywrightdotenv

How do I use a different .env file when starting a webServer in Playwright?


I am introducing Playwright into my project. My current project structure has a separate backend and frontend in a single repo, and Playwright is installed in the frontend part of the project.

├ .git
├ frontend/                  
│    ├ ...          
│    ├ playwright.config.ts           
│    ├ .env                  
│    └ package.json 
└ backend/          
     ├ ...          
     ├ server.js    
     ├ .env         
     └ package.json  

When I run npx playwright test from within /frontend, I want both my frontend and backend services to start up.

// playwright.config.ts
webServer: [
  {
    // start frontend
    command: "npm run start",
    port: 3000,
    reuseExistingServer: !process.env.CI,
  },
  {
    // start backend
    command: "cd ../backend && node server",
    port: 3001,
    reuseExistingServer: !process.env.CI,
  },
]

However, the environment variables that are specified in /frontend/.env are the ones that are being passed to the backend, so the backend has an incomplete or faulty configuration when it attempts to start. I have tried using the env property and specifying the path to the backend .env file in dotenv.config(), but then it overrides the frontend environment variables, giving me the same but opposite problem.

How can I get /backend/.env to be used by the backend process, and /frontend/.env to be used by the frontend process?


Solution

  • You can force dotenv to read each of the .env files and then cache the value of process.env. Then I could pass the environment variables to each webserver with the env property. Since I want /frontend/.env to be loaded into process.env, I load /backend/.env first.

    override: true is required for the second call of dotenv.config() if you have conflicting environment variables, such as PORT. By default, dotenv will not set environment variables that already exist, so any variables with the same name will not get set.

    import type { PlaywrightTestConfig } from "@playwright/test";
    import dotenv from "dotenv";
    
    dotenv.config({ path: "../backend/.env", override: true });
    const backendEnv = { ...process.env } as { [key: string]: string };
    dotenv.config({ override: true });
    const frontendEnv = { ...process.env } as { [key: string]: string };
    
    const config: PlaywrightTestConfig = {
      // omitted config above...
      webServer: [
        {
          command: "npm run start",
          port: 3000,
          reuseExistingServer: !process.env.CI,
          env: frontendEnv,
        },
        {
          command: "cd ../backend && node server",
          port: 3001,
          reuseExistingServer: !process.env.CI,
          env: backendEnv,
        },
      ],
    }