Skip to content

buttered-spuds/playwright-template

Repository files navigation

Playwright TypeScript Test Automation Template

A comprehensive, scalable, and reusable end-to-end test automation template built with Playwright and TypeScript. This template is designed to be application-agnostic and can be easily adapted for any web application testing needs.

πŸš€ Features

  • TypeScript - Full type safety and enhanced IDE support
  • Multi-Environment Support - Dynamic environment switching (dev/test/uat/prod) with CLI tools
  • Page Object Model - Scalable test architecture with reusable components
  • Cross-Browser Testing - Support for Chromium, Firefox, and Safari
  • Parallel Execution - Fast test execution with parallel test runs
  • Accessibility Testing - Built-in WCAG compliance testing with axe-core
  • API Testing - Comprehensive REST API testing capabilities
  • Visual Testing - Screenshot comparison and visual regression testing
  • Test Data Generation - Dynamic test data using Faker.js
  • Authentication Management - Multi-user session handling and storage state
  • Global Setup/Teardown - Environment preparation and cleanup
  • CI/CD Ready - Pre-configured pipelines for GitLab, Azure DevOps, Jenkins, and CircleCI
  • Reporting - Rich HTML reports with screenshots, videos, and traces
  • Code Quality - ESLint, Prettier, and Husky pre-commit hooks

πŸ“ Project Structure

playwright-template/
β”œβ”€β”€ .ci/                          # CI/CD pipeline configurations
β”‚   β”œβ”€β”€ azure-pipelines.yml       # Azure DevOps pipeline
β”‚   β”œβ”€β”€ gitlab-ci.yml             # GitLab CI pipeline
β”‚   β”œβ”€β”€ jenkins.yml               # Jenkins pipeline
β”‚   └── circleci.yml              # CircleCI pipeline
β”œβ”€β”€ .husky/                       # Git hooks configuration
β”œβ”€β”€ config/                       # Configuration management
β”‚   β”œβ”€β”€ environmentConfig.ts      # Environment configuration utility
β”‚   └── environments/             # Environment-specific configurations
β”‚       β”œβ”€β”€ dev.env               # Development environment
β”‚       β”œβ”€β”€ test.env              # Test environment
β”‚       β”œβ”€β”€ uat.env               # UAT environment
β”‚       └── prod.env              # Production environment
β”œβ”€β”€ global-setup/                 # Global setup and teardown
β”‚   β”œβ”€β”€ globalSetup.ts            # Authentication and environment setup
β”‚   └── globalTeardown.ts         # Cleanup and report generation
β”œβ”€β”€ helpers/                      # Utility classes and functions
β”‚   β”œβ”€β”€ authUtils.ts              # Authentication utilities
β”‚   └── testDataGenerator.ts     # Test data generation using Faker
β”œβ”€β”€ pages/                        # Page Object Model classes
β”‚   β”œβ”€β”€ BasePage.ts               # Base page with common utilities
β”‚   β”œβ”€β”€ LoginPage.ts              # Login page implementation
β”‚   └── DashboardPage.ts          # Dashboard page implementation
β”œβ”€β”€ scripts/                      # Utility scripts
β”‚   └── switch-env.js             # Environment switching utility
β”œβ”€β”€ storage/                      # Storage state and session files
β”œβ”€β”€ tests/                        # Test suites
β”‚   β”œβ”€β”€ api/                      # API test cases
β”‚   β”‚   └── api.spec.ts
β”‚   β”œβ”€β”€ accessibility/            # Accessibility test cases
β”‚   β”‚   └── accessibility.spec.ts
β”‚   β”œβ”€β”€ environment/              # Environment validation tests
β”‚   β”‚   β”œβ”€β”€ environment-config.spec.ts
β”‚   β”‚   └── environment-switching.spec.ts
β”‚   β”œβ”€β”€ performance/              # Performance test cases
β”‚   β”‚   └── performance.spec.ts
β”‚   └── ui/                       # UI test cases
β”‚       └── ui.spec.ts
β”œβ”€β”€ .env                          # Environment variables (auto-generated)
β”œβ”€β”€ .env.example                  # Environment template
β”œβ”€β”€ .eslintrc.js                  # ESLint configuration
β”œβ”€β”€ .gitignore                    # Git ignore rules
β”œβ”€β”€ .prettierrc                   # Prettier configuration
β”œβ”€β”€ package.json                  # Dependencies and scripts
β”œβ”€β”€ playwright.config.ts          # Playwright configuration
β”œβ”€β”€ tsconfig.json                 # TypeScript configuration
└── README.md                     # This file

πŸ› οΈ Quick Start

Prerequisites

  • Node.js 18+
  • npm or yarn
  • Git

1. Clone and Setup

# Clone the repository
git clone <your-repo-url>
cd v1-playwright-template

# Install dependencies
npm install  

#TODO //Some depreciated modules.. - lets work out if we need them.

# npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
# npm warn deprecated @humanwhocodes/config-array@0.13.0: Use @eslint/config-array instead
# npm warn deprecated rimraf@3.0.2: Rimraf versions prior to v4 are no longer supported
# npm warn deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported
# npm warn deprecated @humanwhocodes/object-schema@2.0.3: Use @eslint/object-schema instead
# npm warn deprecated eslint@8.57.1: This version is no longer supported. Please see https://eslint.org/version-support for other options.

# Install Playwright browsers
npx playwright install --with-deps

# Copy environment template
cp .env.example .env

2. Configure Environment

The base url will be set in the .env file (See .env.example) globalSetup.ts will perform your login, so add the appropriate endpoint to the base url in the login steps e.g. /login

await page.goto(`${urls.base}/login`, { waitUntil: 'domcontentloaded' });

Edit the .env file with your application-specific settings:

# Base URLs
BASE_URL=https://*insert-your-app*.com   
API_BASE_URL=https://*insert-api.your-app*.com

# Test Credentials - Use TEST_USERNAME to avoid conflict with Windows USERNAME
TEST_USERNAME=testuser@example.com
TEST_PASSWORD=testpassword123
ADMIN_USERNAME=admin@example.com
ADMIN_PASSWORD=adminpassword123
USER_USERNAME=user@example.com
USER_PASSWORD=userpassword123

# Test Configuration
HEADLESS=true
TIMEOUT=30000
RETRIES=2
WORKERS=4

Once .env file is configured move it to config\environments

3. Run Tests

# Run all tests
npm test  

# Run specific test suites
npm run test:ui          # UI tests only
npm run test:api         # API tests only
npm run test:accessibility # Accessibility tests only

# Run tests in specific browsers
npm run test:chrome      # Chrome only
npm run test:firefox     # Firefox only
npm run test:safari      # Safari only

# Run tests in headed mode (visible browser)
npm run test:headed

# Run tests in debug mode
npm run test:debug                                

🌍 Multi-Environment Configuration

The template supports dynamic environment switching with dedicated configurations for different environments (dev/test/uat/prod). Each environment has its own settings for URLs, credentials, timeouts, and test behaviors.

Environment Setup

Each environment has its own configuration file in config/environments/:

  • dev.env - Development environment
  • test.env - Test environment
  • uat.env - User Acceptance Testing environment
  • prod.env - Production environment

Environment Switching

Switch environments easily using CLI commands:

# Switch to different environments
npm run switch:dev     # Switch to development
npm run switch:test    # Switch to test
npm run switch:uat     # Switch to UAT
npm run switch:prod    # Switch to production

# Check current environment
npm run env:current

Environment-Specific Test Execution

Run tests in specific environments:

# Run all tests in specific environments
npm run test:dev       # Development environment
npm run test:uat       # UAT environment
npm run test:prod      # Production environment

# Run specific test suites by environment
npm run test:dev:ui         # UI tests in dev
npm run test:uat:api        # API tests in UAT
npm run test:prod:smoke     # Smoke tests in production

# Run with different modes
npm run test:dev:headed     # Development with visible browser
npm run test:uat:debug      # UAT in debug mode

Environment Configuration

Each environment can be configured with:

# Environment: dev.env
BASE_URL=https://dev.*insert-your-app-url*.com         
API_BASE_URL=https://dev-api.*insert-your-app-url*.com

# Credentials
TEST_USERNAME=dev-user@example.com
TEST_PASSWORD=devpassword123
ADMIN_USERNAME=dev-admin@example.com
ADMIN_PASSWORD=devadminpass

# Test Configuration
HEADLESS=false
TIMEOUT=30000
RETRIES=1
WORKERS=2
DEBUG=true

Programmatic Environment Access

Use the EnvironmentConfig utility in your tests:

import { EnvironmentConfig } from '@/config/environmentConfig';

test('Environment-aware test', async ({ page }) => {
  const config = EnvironmentConfig.getInstance();
  
  // Get environment-specific values
  const baseUrl = config.get('BASE_URL');
  const timeout = config.getNumber('TIMEOUT');
  const isDebug = config.getBoolean('DEBUG');
  
  // Environment-specific test logic
  if (config.getCurrentEnvironment() === 'prod') {
    // Production-specific assertions
  }
});

For detailed environment configuration documentation, see ENVIRONMENTS.md.

πŸ“‹ Available Scripts

The template includes 28+ environment-specific npm scripts:

Test Execution Scripts

{
  "test": "playwright test",
  "test:ui": "playwright test tests/ui --project=chromium",
  "test:api": "playwright test tests/api",
  "test:accessibility": "playwright test tests/accessibility",
  
  // Environment-specific test execution
  "test:dev": "cross-env TEST_ENV=dev playwright test",
  "test:test": "cross-env TEST_ENV=test playwright test", 
  "test:uat": "cross-env TEST_ENV=uat playwright test",
  "test:prod": "cross-env TEST_ENV=prod playwright test",
  
  // Environment + Test Suite combinations
  "test:dev:ui": "cross-env TEST_ENV=dev playwright test tests/ui",
  "test:dev:api": "cross-env TEST_ENV=dev playwright test tests/api",
  "test:dev:smoke": "cross-env TEST_ENV=dev playwright test tests/smoke",
  "test:uat:ui": "cross-env TEST_ENV=uat playwright test tests/ui",
  "test:uat:api": "cross-env TEST_ENV=uat playwright test tests/api", 
  "test:uat:smoke": "cross-env TEST_ENV=uat playwright test tests/smoke",
  "test:prod:smoke": "cross-env TEST_ENV=prod playwright test tests/smoke",

  // Environment + Mode combinations
  "test:dev:headed": "cross-env TEST_ENV=dev playwright test --headed",
  "test:dev:debug": "cross-env TEST_ENV=dev playwright test --debug",
  "test:uat:headed": "cross-env TEST_ENV=uat playwright test --headed",
  "test:uat:debug": "cross-env TEST_ENV=uat playwright test --debug",
  
  // Browser-specific tests
  "test:chrome": "playwright test --project=chromium",
  "test:firefox": "playwright test --project=firefox",
  "test:safari": "playwright test --project=webkit",
  
  // Test modes
  "test:headed": "playwright test --headed",
  "test:debug": "playwright test --debug",
  "test:cross-browser": "playwright test --project=chromium --project=firefox --project=webkit",
  
  // Environment switching
  "switch:dev": "node scripts/switch-env.js dev",
  "switch:test": "node scripts/switch-env.js test", 
  "switch:uat": "node scripts/switch-env.js uat",
  "switch:prod": "node scripts/switch-env.js prod",
  "env:current": "node scripts/switch-env.js current",
  
  // Utilities
  "report": "playwright show-report",
  "lint": "eslint . --ext .ts,.js",
  "lint:fix": "eslint . --ext .ts,.js --fix",
  "format": "prettier --write .",
  "type-check": "tsc --noEmit",
  "prepare": "husky install",
  "cleanup": "node/cleanup.js"
}

Once you are ready to write your tests, running "cleanup.js" will remove all default template files. NOTE: the cleanup script will also delete the cleanup script. Once it has been successfully ran you should see logs like this:

--Cleared contents of tests folder--
--Deleted ENVIRONMENTS.md--
--Deleted MULTI-USER-ROLES.md--
--Deleted SETUP.md--
--Deleting cleanup file--
--Cleanup completed--

πŸ—οΈ Template Architecture

Base Page Class example

The BasePage class provides 40+ utility methods for common web interactions:

import { BasePage } from '../pages/BasePage';

class MyPage extends BasePage {
  async performAction() {
    await this.clickElement('#button');
    await this.fillInput('#input', 'value');
    await this.waitForLoadState();
    await this.assertElementVisible('#result');
  }
}

Test Data Generation example

Generate realistic test data using Faker.js:

import { TestDataGenerator } from '../helpers/testDataGenerator';

const testData = new TestDataGenerator();
const user = testData.generateUser();
const company = testData.generateCompany();
const form = testData.generateFormData();

Authentication Management example

Handle multiple user sessions and storage states:

import { AuthUtils } from '../helpers/authUtils';

const auth = new AuthUtils(page);
await auth.loginAsUser('admin');
await auth.saveStorageState('admin-state.json');

πŸ§ͺ Writing Tests

UI Tests example

import { test, expect } from '@playwright/test';
import { LoginPage } from '../pages/LoginPage';
import { DashboardPage } from '../pages/DashboardPage';

test('User can login and view dashboard', async ({ page }) => {
  const loginPage = new LoginPage(page);
  const dashboardPage = new DashboardPage(page);

  await loginPage.navigate();
  await loginPage.login('user@example.com', 'password');
  await dashboardPage.waitForPageLoad();
  
  await expect(dashboardPage.welcomeMessage).toBeVisible();
});

API Tests example

import { test, expect } from '@playwright/test';

test('API - Create and retrieve user', async ({ request }) => {
  // Create user
  const response = await request.post('/api/users', {
    data: { name: 'John Doe', email: 'john@example.com' }
  });
  
  expect(response.status()).toBe(201);
  const user = await response.json();
  
  // Retrieve user
  const getResponse = await request.get(`/api/users/${user.id}`);
  expect(getResponse.status()).toBe(200);
});

Accessibility Tests example

import { test } from '@playwright/test';
import { AxeBuilder } from '@axe-core/playwright';

test('Homepage should be accessible', async ({ page }) => {
  await page.goto('/');
  
  const accessibilityScanResults = await new AxeBuilder({ page })
    .withTags(['wcag2a', 'wcag2aa', 'wcag21aa'])
    .analyze();
      expect(accessibilityScanResults.violations).toEqual([]);
});

🎯 Template Sample Tests

The template includes sample tests in tests/ that demonstrate template capabilities and validate setup. These are NOT application-specific tests but rather examples to show how a test should be structured:

Purpose of Sample Tests

  • Learning Examples: Show how to use template features
  • Reference Implementation: Demonstrate best practices

πŸ”§ Configuration

Playwright Configuration

The playwright.config.ts file includes:

  • Multiple browsers: Chromium, Firefox, Safari
  • Parallel execution: Configurable worker threads
  • Global setup/teardown: Authentication and cleanup
  • Reporting: HTML, JUnit, and JSON reporters
  • Screenshots and videos: On failure capture
  • Retry logic: Automatic test retries

TypeScript Configuration

  • Path mapping: Clean imports with @/ prefix
  • Strict mode: Enhanced type safety
  • Modern ES features: Latest JavaScript features

ESLint and Prettier

  • Playwright-specific rules: Best practices enforcement
  • Code formatting: Consistent style across the codebase
  • Pre-commit hooks: Automatic linting and formatting

πŸ“Š Reporting

HTML Reports

Rich interactive reports with:

  • Test results overview
  • Screenshots and videos on failures
  • Execution traces for debugging
  • Performance metrics
# Generate and view reports
npm run report

CI/CD Integration

Pre-configured pipelines for:

  • GitLab CI: .ci/gitlab-ci.yml
  • Azure DevOps: .ci/azure-pipelines.yml
  • Jenkins: .ci/jenkins.yml
  • CircleCI: .ci/circleci.yml

Each pipeline includes:

  • Multi-stage testing (lint, unit, e2e)
  • Cross-browser execution
  • Environment-specific test execution
  • Artifact publishing
  • Test result reporting
  • Notification systems

Environment-Specific CI/CD Examples

# Azure DevOps Pipeline Example
- stage: TestEnvironments
  jobs:
  - job: TestDev
    steps:
    - script: npm run test:dev:smoke
      displayName: 'Run Dev Smoke Tests'
  
  - job: TestUAT
    steps:
    - script: npm run test:uat
      displayName: 'Run UAT Tests'
  
  - job: TestProd
    condition: eq(variables['Build.SourceBranch'], 'refs/heads/main')
    steps:
    - script: npm run test:prod:smoke
      displayName: 'Run Production Smoke Tests'

For detailed CI/CD setup with environment configuration, see ENVIRONMENTS.md.

🎯 Best Practices

Page Objects

  • Single Responsibility: One page per class
  • Reusable Methods: Common actions in base class
  • Type Safety: Full TypeScript support
  • Locator Strategy: Use data-testid for stable selectors

Test Organisation

  • Descriptive Names: Clear test and suite naming
  • Independent Tests: No test dependencies
  • Data Isolation: Clean test data for each run
  • Proper Cleanup: Global teardown for environment reset

Error Handling

  • Retry Logic: Automatic retries for flaky tests
  • Meaningful Assertions: Clear failure messages
  • Screenshot Capture: Visual debugging on failures
  • Trace Recording: Full execution traces

πŸš€ Extending the Template

Adding New Page Objects

// pages/NewPage.ts
import { BasePage } from './BasePage';

export class NewPage extends BasePage {
  // Page-specific locators
  readonly submitButton = this.page.locator('[data-testid="submit"]');
  
  // Page-specific methods
  async submitForm(data: FormData) {
    await this.fillForm(data);
    await this.clickElement(this.submitButton);
    await this.waitForResponse('/api/submit');
  }
}

Adding Custom Utilities

// helpers/customHelper.ts
export class CustomHelper {
  constructor(private page: Page) {}
  
  async customAction() {
    // Implementation
  }
}

Environment-Specific Configuration

Create environment-specific config files in config/environments/:

# config/environments/production.env
BASE_URL=https://prod.*example*.com
API_BASE_URL=https://prod-api.*example*.com
HEADLESS=true
TIMEOUT=60000
RETRIES=3
WORKERS=1
DEBUG=false

The template automatically detects the environment using this priority order:

  1. Command line arguments (--env=prod)
  2. Environment variables (TEST_ENV=prod)
  3. NODE_ENV environment variable
  4. Default environment (test)

Environment Validation

The template includes comprehensive environment validation tests in tests/environment/environment-config.spec.ts that verify:

  • Environment detection and switching
  • Configuration loading from environment files
  • Credential management per environment
  • Storage state isolation
  • Playwright configuration integration

Run environment validation tests:

# Test environment configuration
npm run test tests/environment/environment-config.spec.ts

# Test all environments
npm run test:dev tests/environment/
npm run test:uat tests/environment/
npm run test:prod tests/environment/

πŸ› Troubleshooting

Common Issues

  1. Browser Installation

    npx playwright install --with-deps
  2. Permission Issues

    # Windows (Run as Administrator)
    npx playwright install-deps
  3. Environment Configuration Issues

    # Check current environment
    npm run env:status
    
    # Validate environment configuration
    npm run test tests/environment/environment-config.spec.ts
    
    # Reset to test environment
    npm run switch:test
  4. Test Flakiness

    • Increase timeouts in environment configuration files
    • Add explicit waits in page objects
    • Use stable locators with data-testid
    • Check environment-specific settings
  5. Storage State Issues

Clear storage states

Remove-Item storage/authState*.json

Regenerate storage states

npm run test tests/environment/environment-config.spec.ts


6. **CI/CD Failures**
- Check browser dependencies
- Verify environment variables are set correctly
- Review test parallelization settings per environment
- Ensure environment files are available in CI

### Environment-Specific Debugging

```bash
# Debug environment detection
cross-env TEST_ENV=dev DEBUG=true npm test

# Debug specific environment
npm run test:dev:debug tests/environment/

# Check environment configuration loading
node -e "const {EnvironmentConfig} = require('./config/environmentConfig'); console.log(EnvironmentConfig.getInstance().getCurrentEnvironment());"

Debug Mode

# Run specific test in debug mode
npx playwright test tests/example.spec.ts --debug

# Run tests with browser visible
npx playwright test --headed --slowmo=1000

πŸ“ˆ Performance Optimization

  • Parallel Execution: Configure workers based on CI environment
  • Browser Context Reuse: Share contexts for faster test execution
  • Strategic Waits: Use efficient waiting strategies
  • Resource Management: Proper cleanup of browser resources

🀝 Contributing

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/new-feature
  3. Make changes and add tests
  4. Run linting: npm run lint:fix
  5. Run tests: npm test
  6. Commit changes: git commit -m 'Add new feature'
  7. Push to branch: git push origin feature/new-feature
  8. Create Pull Request

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ™‹β€β™‚οΈ Support

For questions and support:

  • Documentation: Check this README and code comments
  • Issues: Create GitHub issues for bugs and feature requests
  • Discussions: Use GitHub discussions for questions

πŸ“š Additional Resources


Happy Testing! 🎭

About

TypeScript Template for Playwright

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors