lecture 10 of 160 completed

Configuration across environments

Selenium gives you no config file, so the structure is yours to design. Here is the shape that works.

Cypress has cypress.config.js. Playwright has playwright.config.ts. Selenium has nothing, because it is a library rather than a framework.

That is not a gap to complain about, it is a design decision you have to make yourself. Here is the shape most teams arrive at.

Keep every environment-specific value in one module.

// config.js
const environments = {
  local:   { baseUrl: 'http://localhost:3000' },
  staging: { baseUrl: 'https://staging.example.com' },
};

const name = process.env.TEST_ENV || 'local';

module.exports = {
  ...environments[name],
  browser: process.env.BROWSER || 'chrome',
  headless: process.env.HEADLESS === 'true',
  timeout: Number(process.env.TIMEOUT) || 10000,
};

Then run:

TEST_ENV=staging BROWSER=firefox HEADLESS=true npm test

Same tests, different target, nothing edited.

Build the driver in one place too. A shared factory keeps browser options consistent across the suite:

// driver-factory.js
async function createDriver() {
  const options = new chrome.Options();
  if (config.headless) options.addArguments('--headless=new');
  options.addArguments('--window-size=1920,1080');

  return new Builder()
    .forBrowser(config.browser)
    .setChromeOptions(options)
    .build();
}

Every test calls createDriver(). When you need to add a browser flag, you add it once.

The rule from the other tracks holds here too, and it is the one that decays first without a config file to enforce it.

⚠️ Tests must not know which environment they are in.

The moment a test contains if (config.env === 'staging'), you have started building a suite that only really passes in one place while appearing to cover all of them. Those branches multiply quietly.

Configuration decides where. Tests decide what. If a test really cannot run somewhere, exclude it from that run rather than branching inside it.

Secrets never go in the repository. Read them from environment variables, and store them in your CI system's secret storage:

password: process.env.TEST_USER_PASSWORD,

If a credential reaches Git, treat it as public and rotate it. The history keeps it after you delete the line.

Timeouts belong in config, not scattered through tests. A suite with 5000 typed in ninety places cannot be tuned for a slower environment. One value, imported everywhere, can.

Remember this: one config module, one driver factory, environment through variables, and no environment names inside tests.

Reference: Driver options.