Configuring multiple environments in Playwright

Irfan Pasha
2 min readJun 27, 2023

Playwright is emerging as the go-to UI/E2E automation tool for those who want to start automation from scratch. I have been watching the tool’s progress and the features offered to it for a while, and I should say the playwright team has done a great job.

While working on one of our new projects with playwright, we had a case where we must define a set of configuration properties in addition to the baseUrl for each environment in playwright config, and I did not see a straightforward answer for that, and I was seeing more than one solution to solve this problem, which seems to be a little complicated.

I was able to solve that by creating an interface from PlaywrightTestConfig and adding all my customer properties.

import { PlaywrightTestConfig } from '@playwright/test';

// Config to hold extra properties
interface TestConfig extends PlaywrightTestConfig {
baseUrl: string;
apiURL: string;
}

// default configuration you expect to have for every environment
const defaultConfig: PlaywrightTestConfig = {
timeout: 6000,
expect: {
timeout: 2000
},
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 0 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: [['html', { open: 'never' }], ['junit', { outputFile: 'results.xml' }]],
use: {
actionTimeout: 0,
trace: 'on',
},
projects: [
{
name: 'login',
testMatch: '**/*.setup.ts',
},
{
name: 'tests',
testDir: './tests',
dependencies: ['login'],
use: {
storageState: 'storageState.json'
},
}
],
};

// set config for dev
const devConfig: TestConfig = {
baseUrl: 'https://dev.example.com',
apiUrl: 'https://dev.api.example.com'
};

// set config for stage
const stageConfig: TestConfig = {
baseUrl: 'https://stage.example.com',
apiUrl: 'https://stage.api.example.com'
};

// set config for prod
const prodConfig: TestConfig = {
baseUrl: 'https://prod.example.com',
apiUrl: 'https://prod.api.example.com'
};

// get the environment type from command line. If none, set it to dev
const environment = process.env.TEST_ENV || 'dev';

// config object with default configuration and environment specific configuration
const config: TestConfig = {
...defaultConfig,
...(environment === 'stage' ? stageConfig : environment === 'prod' ? prodConfig : devConfig)
};

export default config;

In my test, I get access to baseUrl and apiUrl from the config object.

import { test, expect } from '@playwright/test';
import config from '../playwright.config';


test('get started link', async ({ page }) => {

console.log(config.baseUrl);
console.log(config.apiUrl);

});

If one has to execute the test in a staging environment, then he can set the environment variable “TEST_ENV” to “stage” and execute the command as below.

TEST_ENV=stage npx playwright test 

Running 1 test using 1 worker
[tests] › tests/example.spec.ts:5:5 › get started link
https://stage.example.com
https://stage.api.example.com

If you do not provide any environment variables, it will use “dev” environment by default.

TEST_ENV=dev npx playwright test 

Running 1 test using 1 worker
[tests] › tests/example.spec.ts:5:5 › get started link
https://dev.example.com
https://dev.api.example.com

Thought it could be useful for someone who might come across similar scenario.

Have fun !!!

--

--

Irfan Pasha

QA Architect at Progress Software. 16+ years of experience in Software testing. Expert in automation, performance, CI/CD and cloud.