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 ​