August 14, 2026

How Playwright Frameworks get configured with playwright.config.ts

When we installed bun, a new package manager owned by Anthropic, then ran "bun create playwright", a new automation framework was stood up, along with sample tests, and a Playwright configuration file. In this post, we will be examining the file generated: playwright.config.ts.  

Personally, I find the pre-generated file very hard to scan... there are so many options and documentation in the comments, it is difficult for me to focus on the code. Let's examine just the code generated below. If you need to see the whole file, you can see it here: https://playwright.dev/docs/test-configuration

Playwright.dev / Configuration mentions, "Playwright has many options to configure how your tests are run. You can specify these options in the configuration file". 


What is Configured By Default? 


import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: './tests',
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 1 : undefined,
  reporter: 'html',
 
    // baseURL: 'http://localhost:3000',

    /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
    trace: 'on-first-retry',
  },

  /* Configure projects for major browsers */
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },

    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },

    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },
});

I know what you are thinking ...  What the heck is process.env.CI ? 2 : 0?
  • This is know as a ternary operator. It is a shorthand for: "If A then B, else C". 
  • You can run tests two ways: Locally, on your local machine, or through a CI / CD Pipeline like Jenkins, GitHub Actions, or GitLab. 
  • If you are running tests on CI / CD, the process.env.CI would automatically get set. Since A is true, the value of retries would be "2". 
  • If you are running tests locally, the process.env.CI would NOT get set. Since A is false, the value "0" would be selected. 
  • CI / CD pipelines would get two retries. Locally, it would get no retries and a failed test would remain failed. 
Now that that is cleared up, let's examine the properties:
  • testDir: Points to the home of the tests.
  • fullyParallel: Allows you to set the tests to run all at once across many workers, or by one worker, tests lined up single file. By default, all tests are run all at once with multiple workers. 
  • forbidOnly
    • Developers debugging a test, will mark that test they are working on "test.only()". It's okay to have "test.only()" locally, but you want it to complain, loudly, if you have any test still marked "test.only()" in a CI/CD pipeline. 
    • If you are running the test locally, the test run wouldn't pick up a process.env.CI. The CI/ CD variable would not be set, which means that the variable would be "undefined" which would resolves to false. forbidOnly would be false. No alert would be thrown if an "only" was seen, which is exactly what you wanted. 
    • If you were running this in a CI/CD pipeline, you do not want test.only() to appear. Since process.env.CI would fill in a string, or set it to true, this equation would evaluate to "forbidOnly=true". An alert would be thrown if a test running in the CI/ CD pipeline saw an "only".
  • retries: Tests can be fragile when running on a CI/ CD platform. If it is CI/ CD, the process.env.CI would be set, by default retrying a failed test twice. If it is not set, because the test is running locally, we have the second default, which is "0", meaning failing tests would not be rerun. 
  • workers: How many workers would you like to execute tests for you?
    • By default, if you are on a CI / CD pipeline running a test it will run two workers to execute a test. Playwright recommends setting the workers to "1". 
    • Running a test locally? "Undefined" means that Playwright will detect your machines hardware and boot up a number of workers equal to half your logical CPU cores without freezing your operating system.  
    • Note: GitHub Actions free tier give you virtual machines with limited resources. If you have just one worker tests will run one after another making logs and failures easier to trace. 
    • Read Playwright.dev docs about running jobs in parallel, and dividing tests into shards
  • reporter: How would you like your output? Basic "html", with a standalone webpage? A "list" printing a detailed line per test showing pass or fail? A "line" displaying execution progress on a single terminal line? A "dot" report where passed tests are dots and failures are "F"? A "json" report? An xml "junit" style? A "blob" of a binary file that can be later merged from multiple machines? Or "github" which creates annotations in GitHub Actions? See Playuwright.dev / Reporter, and a list of reporters on The Testing Academy
By default, it has set up to run the Playwright version of Chrome, Firefox, and WebKit Safari. 

But What About Dot Env?


If you looked in the pre-generated configuration file, there is code that looks like: 
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// import dotenv from 'dotenv';
// import path from 'path';
// dotenv.config({ path: path.resolve(__dirname, '.env') });
Dotenv reads custom variables from a plain text file, injecting them into a Node.js application. 

Sometimes, settings change depending where your code is running, such as on your local machine vs a production environment. 

It is a good practice to set up one .env file per environment. .env for your local. .env.production. .env.staging, etc. 

There are things such as database passwords, third party API keys, server port numbers. 

With Dotenv you can create an .env file in the root folder of your project, and write configurations like:
  • PORT=3000
  • DATABASE_URL=mongodb://localhost:27817/myapp
  • STRIPE_API_KEY=
Make sure to add the .env file into .gitignore else you might accidently push these secrets into GitLab! ... Or you can encrypt it using https://github.com/dotenvx/dotenvx 


What about the Mobile Viewports and Branded Browsers? 


You also may have seen in the boilerplate playwright.config.ts file:


/* Test against mobile viewports. */
// {
// name: 'Mobile Chrome',
// use: { ...devices['Pixel 5'] },
// },
// {
// name: 'Mobile Safari',
// use: { ...devices['iPhone 12'] },
// },

/* Test against branded browsers. */
// {
// name: 'Microsoft Edge',
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
// },
// {
// name: 'Google Chrome',
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
// },

If you want Playwright to simulate how your website looks and behaves on mobile devices, you can comment out the mobile viewport section. Mobile Chrome simulates a Google Pixel 5 using Chromium, and Mobile Safari simulates an iPhone 12 using Apple's WebKit engine. ( See the ThinkSys article, Cross Browser Testing with Playwright in 2026 )

Sometimes, emulations are not enough, and you want to actually test on Microsoft Edge or Google Chrome. With this setup, you can launch the actual browsers. 

... The next post, we will dive into setting up actual test and page objects.


Happy Testing!

-T.J. Maher
Software Engineer in Test

BlueSky | YouTubeLinkedIn | Articles

No comments:

Post a Comment