Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🎭 Playwright Multi-Site Automation

Production-grade end-to-end test framework for multi-brand dealer web apps — one codebase, any number of sites.


Playwright Node.js License PRs Welcome Allure


Features

Feature What it gives you
🏗️ Page Object Model with inheritance One base class (SitePage) shared by all pages — fix a nav locator once, every test benefits
🔌 Custom Playwright fixtures Page objects auto-injected into every test; no new MyPage(page) boilerplate in specs
🏷️ Tag-based prod safety @smoke tests run on production; @functional tests are dev-only — enforced in config, not convention
🌐 Multi-site switchable Swap the target site with SITE=brand-name — no code changes, no duplicated test files
🔗 Dynamic navigation Tests find and click into product pages at runtime — no hardcoded detail URLs
📊 Parameterized validation Data arrays in one file generate individually-named tests for every phone and email format
🧪 Allure TestOps integration Every test maps to a case ID for structured reporting and traceability
⚙️ Multi-project config dev and prod Playwright projects with independent base URLs and grep locks

Project Structure

playwright-multi-site-automation/
│
├── playwright.config.js        # Multi-project config (dev + prod, Allure reporter)
├── package.json
├── .gitignore
│
├── config/
│   ├── constants.js            # Shared timeout values (navigation, assert, test)
│   ├── env.js                  # Base URLs per environment (DEV_URL / PROD_URL)
│   └── site-config.js          # Per-brand config (name, address pattern, footer regex)
│
├── pages/                      # Page Object Model layer
│   ├── site.page.js            # Base class — header, footer, nav, goto(), assertShellLoaded()
│   ├── home.page.js            # Home page locators and helpers
│   ├── listing.page.js         # Inventory listing page (openFirstProduct, filters)
│   └── detail.page.js          # Product detail page (carousel, form, accordion, CTAs)
│
└── tests/
    ├── support/
    │   ├── testContext.js      # Custom test fixture — injects site/home/listing/detail
    │   ├── allureTestOps.js    # Allure TestOps case ID helper (brand / group / caseId)
    │   └── validation-data.js  # Phone and email test data arrays (valid + invalid)
    │
    └── acme/                   # Test suite for "Acme Dealer" (one folder per brand)
        ├── home.spec.js        # Home page smoke + functional tests
        ├── listing.spec.js     # Inventory listing tests
        └── detail.spec.js      # Product detail — 27 smoke + parameterized functional tests

Quick Start

npm install && npx playwright install --with-deps chromium
npm test                      # all tests on dev
npm run report                # open HTML report

Project Setup

Prerequisites

Requirement Version Notes
Node.js 18 or higher node --version to check
npm Bundled with Node npm --version to check
Playwright browsers Installed via CLI Chromium only by default
A Playwright-targeted site Any Configure the URL in config/env.js

Step 1 — Clone the repo

Mac / Linux

git clone https://github.com/YOUR_USERNAME/playwright-multisite-e2e.git
cd playwright-multisite-e2e

Windows (PowerShell)

git clone https://github.com/YOUR_USERNAME/playwright-multisite-e2e.git
cd playwright-multisite-e2e

Step 2 — Install dependencies

npm install

This installs @playwright/test, allure-playwright, and allure-js-commons as dev dependencies.


Step 3 — Install Playwright browsers

npx playwright install --with-deps chromium

--with-deps also installs OS-level browser dependencies. On CI or Docker you may need to run npx playwright install-deps separately.


Step 4 — Configure your site URLs

Edit config/env.js:

module.exports = {
  dev:  process.env.DEV_URL  || 'https://your-site-dev.example.com',
  prod: process.env.PROD_URL || 'https://your-site.example.com',
};

Or pass URLs inline without touching the file:

Mac / Linux

DEV_URL=https://staging.mysite.com npm test

Windows (PowerShell)

$env:DEV_URL="https://staging.mysite.com"; npm test

Windows (Command Prompt)

set DEV_URL=https://staging.mysite.com && npm test

Note: Never commit real credentials to env.js. Use a .env file (already in .gitignore) or CI secrets for sensitive values.


Step 5 — Configure your brand (optional)

Edit config/site-config.js to match your site's brand name and content patterns:

const SITE_CONFIGS = {
  acme: {
    brandName:           'Acme Dealer',
    footerDealerPattern: /Acme\s*Dealer|Primary\s*Location/i,
    addressPattern:      /123\s+Main\s+St|Anytown/i,
  },
  // Add your brand here:
  mybrand: {
    brandName:           'My Brand',
    footerDealerPattern: /My\s*Brand|Main\s*Location/i,
    addressPattern:      /456\s+Oak\s+Ave|Somecity/i,
  },
};

Expected Output

After npm test you should see:

Running 33 tests using 4 workers
  ✓  detail page loads with a valid URL and title (1.2s)
  ✓  H1 product title is visible and non-empty (0.9s)
  ✓  carousel has a next button and at least one thumbnail (1.1s)
  ...
  33 passed (28.4s)

An HTML report is generated at playwright-report/index.html. Open it with:

npm run report

Running Tests

Command What it does
npm test All tests against the dev project
npm run test:prod @smoke tests only against prod (grep-locked in config)
npm run test:smoke @smoke tests on dev
npm run test:func @functional tests on dev (form validation, state mutations)
npm run test:ui Playwright UI mode — step through tests visually
npm run report Open the last HTML report in your browser
npm run report:allure Serve the Allure report (requires Allure CLI installed)

Switch sites at runtime:

Mac / Linux

SITE=mybrand npm test

Windows (PowerShell)

$env:SITE="mybrand"; npm test

Run a specific spec file:

npx playwright test tests/acme/detail.spec.js

Run tests by tag:

npx playwright test --grep "@smoke"
npx playwright test --grep "@functional"

Architecture

Page Object Model with inheritance

All page objects extend SitePage (pages/site.page.js), which owns shared shell locators — header, navigation, footer — and the goto() and assertShellLoaded() helpers. Individual page classes only define what's unique to that page.

This means a change to the nav selector fixes every test at once. It also means the base class can evolve independently of the page-specific logic.

class ListingPage extends SitePage {
  get firstViewDetailsLink() {
    return this.page.getByRole('main').getByRole('link', { name: /view details/i }).first();
  }

  async openFirstProduct() {
    await expect(this.firstViewDetailsLink).toBeVisible();
    await this.firstViewDetailsLink.scrollIntoViewIfNeeded();
    await this.firstViewDetailsLink.click();
  }
}
Custom fixtures — zero boilerplate in specs

tests/support/testContext.js extends Playwright's base test with four fixtures: site, home, listing, and detail. Every spec imports test from testContext and receives page objects automatically — no new MyPage(page) in tests.

// tests/support/testContext.js
const test = base.test.extend({
  home:    async ({ page }, use) => { await use(new HomePage(page));    },
  listing: async ({ page }, use) => { await use(new ListingPage(page)); },
  detail:  async ({ page }, use) => { await use(new DetailPage(page));  },
});
// In any spec file
const { test, expect } = require('../support/testContext');

test('product detail page loads', async ({ listing, detail }) => {
  await listing.openFirstProduct();
  await expect(detail.titleH1).toBeVisible();
});

To add a new page object: create the class, import it in testContext.js, add one fixture entry. No changes needed in individual spec files.

Tag-based prod safety

Every test suite is tagged at the describe level:

// Safe to run on production — read-only, no side effects
test.describe('Acme — Detail', { tag: ['@ui', '@smoke'] }, () => { ... });

// Dev only — submits forms, mutates state
test.describe('Acme — Detail (Functional)', { tag: ['@ui', '@functional'] }, () => {
  test.fixme(true, 'Re-enable once form bug is resolved on dev');
  ...
});

playwright.config.js locks the prod project to @smoke via a grep filter, checked at startup:

const prodSafeMode = process.env.PLAYWRIGHT_GREP_OVERRIDE !== 'true';
// ...
{ name: 'prod', grep: prodSafeMode ? /@smoke/ : undefined }

No one has to remember to add a flag — production is safe by default.

Parameterized validation tests

Phone and email test data lives in one file (tests/support/validation-data.js). A for loop over the array generates a distinctly-named test per entry — so 6 invalid phone formats becomes 6 test results, each clearly labeled in the report.

for (const [phone, reason] of INVALID_PHONES) {
  test(`invalid phone: ${reason} — "${phone}" shows error`, async ({ detail }) => {
    await detail.phoneInput.fill(phone);
    await detail.submitButton.click();
    await expect(detail.formErrorBanner).toBeVisible();
  });
}

Adding a new validation case means adding one entry to the data array — the test is generated automatically.

Multi-site architecture

The framework is designed to test multiple brands from one codebase. The SITE environment variable selects the active brand at runtime. playwright.config.js auto-discovers site folders under tests/ and scopes test matching to the selected brand:

const siteKey = (process.env.SITE || 'acme').toLowerCase().trim();
const hasDedicatedFolder = fs.existsSync(path.join(testsDir, siteKey));

module.exports = defineConfig({
  testMatch: hasDedicatedFolder ? `${siteKey}/**/*.spec.js` : undefined,
  ...
});

config/site-config.js stores per-brand patterns (brand name, footer regex, address regex) so page objects can use flexible locators without hardcoding brand-specific strings.

To add a new brand: create tests/mybrand/, add its config to site-config.js, and run SITE=mybrand npm test. Page objects require no changes unless the new site has a different UI structure.


Configuration

Environment Variables

Variable Default Description
DEV_URL https://acme-dealer-dev.example.com Base URL for the dev Playwright project
PROD_URL https://acme-dealer.example.com Base URL for the prod Playwright project
BASE_URL Override both projects with a single URL (useful in CI)
SITE acme Selects the active brand folder under tests/
PLAYWRIGHT_GREP_OVERRIDE false Set to true to run functional tests on prod (use with caution)
CI When set, enables 1 retry per test

Timeout Defaults

All timeouts are defined in config/constants.js:

const TIMEOUTS_MS = {
  navigation: 30_000,   // page.goto() and waitForURL()
  assert:     15_000,   // expect() and actionTimeout
  test:       90_000,   // overall test timeout
};

Allure Reporting

Allure results are written to allure-results/ after each run. To view them:

# Install Allure CLI once
npm install -g allure-commandline

# Serve the report
npm run report:allure

Each test includes a structured case ID set via applyAllureTestOpsMapping():

await applyAllureTestOpsMapping({
  brand:  'Acme',
  group:  'Acme-Detail',
  caseId: 'Acme-Detail-012',   // 001-099: smoke, 100+: functional
});

Tech Stack

Tool Version Purpose
Playwright v1.56+ Browser automation and test runner
Allure Playwright v3.0+ Rich test reporting with case traceability
allure-js-commons v3.0+ Allure label/annotation helpers
Node.js 18+ Runtime
CommonJS modules No build step or transpilation required

Built with Playwright  ·  Reported with Allure  ·  Structured for real-world scale

About

Production-grade Playwright E2E framework for multi-site dealer apps — Page Object Model, custom fixtures, tag-based prod/dev separation, and Allure reporting.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages