Skip to content

Test Structure

This page explains the generated file tree, the purpose of each directory, and when to add new files.

Generated File Tree

After running the generator, your project gains this structure:

your-project/
├── playwright.config.js              # Playwright configuration
├── tests/
│   ├── config/                       # Test configuration
│   │   ├── index.js                  # Barrel export
│   │   ├── experiment.config.js      # Experiment settings
│   │   └── qa-links.config.js        # Market URLs
│   ├── fixtures/                     # Custom Playwright fixtures
│   │   └── test-fixtures.js          # Experiment context, Adobe preview
│   ├── utils/                        # Reusable test helpers
│   │   └── test-helpers.js           # Wait, scroll, screenshot, retry
│   └── e2e/                          # Test specs
│       └── <experiment-name>/
│           ├── <experiment-name>.spec.js       # Live URL tests
│           └── experiment-test.spec.js          # Bundle injection test

Directory Reference

tests/config/

All test configuration lives here. The barrel index.js re-exports everything so tests have a single import path.

FilePurpose
index.jsBarrel export - import everything from here
experiment.config.jsExperiment name, markets, variants, timeouts, Adobe preview token
qa-links.config.jsControl/experiment URL resolution per market

When to add files: Add new config files here when your experiment needs additional configuration (e.g., feature flags, A/B platform tokens, content mappings). Always re-export from index.js.

tests/fixtures/

Custom Playwright fixtures that extend the base test object with experiment-specific context.

FilePurpose
test-fixtures.jsexperimentContext fixture (config access, URL builder), adobePreview fixture

When to add files: Add new fixtures when you need shared setup that multiple test files use. For example, a cookie-fixtures.js for tests that need consent cookies, or a mobile-fixtures.js for mobile viewport tests.

tests/utils/

Reusable helper functions that don't depend on Playwright's test runner. These are pure utility functions.

FilePurpose
test-helpers.jswaitForNetworkIdle, waitForStable, getComputedStyle, isInViewport, scrollIntoView, takeScreenshot, waitForText, retryWithBackoff

When to add files: Add new utility files for domain-specific helpers. For example:

  • selector-helpers.js - functions that build complex selectors from config
  • data-helpers.js - functions that generate test data
  • assertion-helpers.js - custom assertion wrappers

tests/e2e/

Test spec files, organized by experiment name.

FilePurpose
<name>/<name>.spec.jsLive URL tests with control and experiment describe blocks
<name>/experiment-test.spec.jsBundle injection smoke test

When to add files: Add new spec files within the experiment folder for additional test scenarios:

  • <name>/visual-regression.spec.js - screenshot comparison tests
  • <name>/accessibility.spec.js - a11y checks on the experiment
  • <name>/performance.spec.js - performance metrics collection

tests/performance/ (Optional)

Not generated by default. Create this directory for performance-focused tests.

tests/performance/
└── selector-performance.spec.js    # Measure selector resolution time

Import Conventions

Config Imports

Always import config from the barrel file:

js
// Correct
import { experimentConfig, qaLinksConfig, validateUrls } from '../../config/index.js';

// Avoid importing individual config files directly

Fixture Imports

Import the extended test and expect from your fixtures file instead of from @playwright/test:

js
// When using custom fixtures
import { test, expect } from '../fixtures/test-fixtures.js';

// When not using custom fixtures
import { test, expect } from '@playwright/test';

Helper Imports

Import individual functions from utils:

js
import { waitForNetworkIdle, scrollIntoView } from '../utils/test-helpers.js';

Scaling the Structure

As your experiment test suite grows, the structure scales naturally:

tests/
├── config/
│   ├── index.js
│   ├── experiment.config.js
│   ├── qa-links.config.js
│   └── content.config.js           # Added: market-specific content expectations
├── fixtures/
│   ├── test-fixtures.js
│   └── consent-fixtures.js          # Added: cookie consent setup
├── utils/
│   ├── test-helpers.js
│   └── selector-helpers.js          # Added: dynamic selector builders
└── e2e/
    └── my-experiment/
        ├── my-experiment.spec.js
        ├── experiment-test.spec.js
        ├── multi-market.spec.js     # Added: cross-market sweep
        └── mobile.spec.js           # Added: mobile-specific tests

What's Next