Skip to content

clampist/playwright-test-framework

Repository files navigation

Frontend Playwright Test Project

This is a complete project structure for frontend UI testing using Playwright, including best practices and common configurations.

Project Structure

├── core/                   # Generic Logic Layer - No business logic
│   ├── BasePage.ts         # Base page class, encapsulates Playwright core API
│   ├── helpers.ts          # Generic utility functions
│   └── test-data-factory.ts # Generic test data factory
├── tests/                  # Business Logic Layer - Contains business-related code
│   ├── pages/              # Page Layer - Page Object Model (POM)
│   │   ├── LoginPage.ts    # Login page object model
│   │   ├── DashboardPage.ts # Dashboard page object model
│   │   └── HomePage.ts     # Home page object model
│   ├── services/           # Business Layer - Business process encapsulation
│   │   ├── AuthService.ts  # Authentication service
│   │   └── UserService.ts  # User service
│   ├── dsl/                # DSL Layer - Custom test DSL
│   │   └── UserDSL.ts      # User domain-specific language
│   ├── data/               # Test Data Layer
│   │   └── test-data.ts    # Business-related test data
│   ├── config/             # Configuration Management Layer
│   │   ├── environment.ts  # Environment configuration
│   │   ├── test-config.ts  # Test configuration
│   │   └── index.ts        # Configuration unified export
│   ├── fixtures/           # Test fixtures
│   │   └── auth.fixture.ts # Authentication-related fixtures
│   ├── api/                # API testing
│   │   └── api.spec.ts     # API test examples
│   ├── examples/           # Test examples
│   │   ├── dsl-example.spec.ts      # DSL test examples
│   │   └── data-driven-example.spec.ts # Data-driven test examples
│   ├── example.spec.ts     # Basic test examples
│   └── auth.spec.ts        # Authentication test examples
├── playwright.config.ts    # Playwright configuration
├── package.json           # Project dependencies
├── tsconfig.json          # TypeScript configuration
├── .eslintrc.js          # ESLint configuration
├── .prettierrc           # Prettier configuration
├── .gitignore            # Git ignore file
├── env.example           # Environment variables example
└── README.md             # Project documentation

Features

  • âś… Layered Architecture - Base layer, page layer, business layer, DSL layer
  • âś… TypeScript Support - Complete type safety
  • âś… Page Object Model - Page Object Model pattern
  • âś… Business Process Encapsulation - Cross-page business operation encapsulation
  • âś… Custom DSL - Business-oriented test methods
  • âś… Data-Driven Testing - Test data factory and parameterized testing
  • âś… Test Fixtures - Reusable test setup
  • âś… Multi-Browser Support - Chrome, Firefox, Safari
  • âś… Mobile Testing - Mobile device viewport testing
  • âś… API Testing - HTTP request testing
  • âś… Environment Configuration - Multi-environment support
  • âś… Code Quality - ESLint + Prettier
  • âś… Test Reporting - HTML, JSON, JUnit reports
  • âś… MCP Server Integration - AI-powered test automation through Cursor IDE

🎭 MCP Server Integration (New!)

This framework now includes a built-in MCP (Model Context Protocol) Server that enables AI-powered test automation through IDE integrations like Cursor.

What is MCP?

MCP allows AI assistants to:

  • 🤖 Execute tests using natural language commands
  • 📊 Analyze results automatically
  • đź§Ş Generate tests based on your requirements
  • 🔍 Debug failures with intelligent assistance

Quick Start with MCP

  1. Start MCP Server:

    npm run mcp-server
  2. Configure Cursor IDE: Add to ~/.cursor/mcp.json:

    {
      "mcpServers": {
        "playwright-e2e": {
          "command": "node",
          "args": ["--loader", "ts-node/esm", "/path/to/your/project/core/mcp/server.ts"],
          "cwd": "/path/to/your/project",
          "env": {
            "BASE_URL": "http://localhost:3000"
          }
        }
      }
    }
  3. Use Natural Language:

    "Run all E2E tests"
    "Run login tests in headed mode"
    "Show me the latest test results"
    "Generate a test for the dashboard page"
    

🎬 Demo

See the MCP integration in action:

Using Cursor IDE to Run Tests

Run tests in Cursor

Simply ask in natural language: "Run tests in headed mode" and the AI executes the command for you.

Browser Test Execution

Run tests in Browser

The tests run in the browser with full visibility of the test execution process.

MCP Features

Available Tools

  • run_tests - Execute tests with various options (headed, debug, grep, etc.)
  • generate_test - Generate test code using Playwright codegen
  • view_report - View test reports in various formats
  • debug_test - Launch tests in debug mode with Playwright Inspector

Available Resources

  • e2e://test-results/latest - Latest test execution results (JSON)
  • e2e://test-reports/summary - Human-readable test summary
  • e2e://screenshots/list - List of failure screenshots

Documentation

Benefits

Traditional Approach:

# You need to remember commands
npm test auth/login.spec.ts --headed --project=chromium

With MCP:

"Run login tests in headed mode with Chrome"
→ AI understands and executes automatically

See MCP vs Direct Commands for detailed comparison.

Quick Start

1. Install Dependencies

npm install

2. Install Browsers

npm run install:browsers

3. Configure Environment Variables

cp env.example .env
# Edit .env file to set your application URL

4. Run Tests

# Run all tests
npm test

# Run tests with browser visible
npm run test:headed

# Run tests in UI mode
npm run test:ui

# Debug mode
npm run test:debug

# Generate test reports
npm run test:report

Test Commands

Command Description
npm test Run all tests
npm run test:headed Run tests with browser visible
npm run test:ui Run Playwright UI mode
npm run test:debug Run tests in debug mode
npm run test:report Show test reports
npm run test:codegen Generate test code
npm run install:browsers Install browsers

Writing Tests

Architecture Overview

Our test framework adopts a clear layered architecture designed for multi-team collaboration:

Core Layer (core/)

  • BasePage.ts - Encapsulates Playwright core API, provides unified element operations, waiting, and validation methods
  • helpers.ts - Generic utility functions with no business logic
  • test-data-factory.ts - Generic test data factory for dynamic data generation

Business Logic Layer (tests/)

  • Page Layer (pages/) - Page Object Model pattern, encapsulates page elements and operations
  • Service Layer (services/) - Business process encapsulation, provides cross-page business operations
  • DSL Layer (dsl/) - Custom domain-specific language, business-oriented test methods
  • Data Layer (data/) - Business-related test data
  • Config Layer (config/) - Test environment and test configuration management

Documentation

Core Framework Guide

For comprehensive information about using the core framework, see:

Team-Specific Documentation

For team-specific implementations and examples:

Multi-Team Collaboration

This framework is designed to support multiple teams using the same core functionality:

Core Framework Distribution

  • Core layer is published as an npm package: @your-org/playwright-test-core
  • Teams install the core framework as a dependency
  • Core updates are automatically available to all teams

Team Project Structure

Each team maintains their own test project with:

  • Team-specific page objects
  • Team-specific business services
  • Team-specific test data
  • Team-specific configuration
  • Team-specific test specifications

Benefits

  • Shared Core: All teams benefit from core framework improvements
  • Independent Development: Teams can work independently on their business logic
  • Consistent Standards: All teams follow the same patterns and conventions
  • Easy Updates: Core framework updates are automatically available
  • Reduced Duplication: Common functionality is shared across teams

Basic Test Example

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

test('should display correct title', async ({ page }) => {
  await page.goto('/');
  await expect(page).toHaveTitle(/My App/);
});

Using Page Object Model

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

test('should login successfully', async ({ page }) => {
  const loginPage = new LoginPage(page);
  await loginPage.navigateToLoginPage();
  await loginPage.login('testuser', 'password123');
  await loginPage.verifyLoginSuccess();
});

Using Business Process Encapsulation

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

test('should login as admin', async ({ page }) => {
  const authService = new AuthService(page);
  await authService.loginAsAdmin();
  await authService.verifyUserLoggedIn('admin');
});

Using Custom DSL

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

test('User login and update profile', async ({ page }) => {
  const user = new UserDSL(page);
  await user.loginAs('testuser');
  await user.updateProfile({
    firstName: 'John',
    lastName: 'Doe',
    email: 'johndoe@example.com'
  });
  await user.verifyProfile({
    firstName: 'John',
    lastName: 'Doe',
    email: 'johndoe@example.com'
  });
});

Using Data-Driven Testing

import { test, expect } from '@playwright/test';
import { UserDSL } from './dsl/UserDSL';
import { TestDataFactory } from '../../core/test-data-factory';

test('Data-driven user registration test', async ({ page }) => {
  const user = new UserDSL(page);
  const registrationData = TestDataFactory.createRegistrationFormData({
    username: 'newuser',
    email: 'newuser@example.com'
  });
  
  await user.registerAndLogin(registrationData);
  await user.verifyProfile({
    firstName: registrationData.firstName,
    lastName: registrationData.lastName,
    email: registrationData.email
  });
});

Using Test Fixtures

import { test, expect } from './fixtures/auth.fixture';

test('should access protected page', async ({ authenticatedPage }) => {
  await authenticatedPage.goto('/profile');
  await expect(authenticatedPage).toHaveURL('/profile');
});

Configuration

Playwright Configuration

  • Multi-browser Support: Chrome, Firefox, Safari
  • Mobile Testing: Pixel 5, iPhone 12
  • Parallel Execution: Support for parallel testing
  • Retry Mechanism: Automatic retry in CI environment
  • Report Generation: HTML, JSON, JUnit formats

Environment Configuration

Support for multiple environments:

  • development - Development environment
  • staging - Staging environment
  • production - Production environment

Best Practices

Layered Architecture Best Practices

Core Layer (core/)

  1. BasePage.ts - Encapsulate Playwright core API, provide unified element operations, waiting, and validation methods
  2. helpers.ts - Provide generic utility functions with no business logic
  3. test-data-factory.ts - Provide generic data generation capabilities for various data types

Business Logic Layer (tests/)

  1. Page Layer (pages/) - Use Page Object Model to encapsulate page elements and operations in classes
  2. Service Layer (services/) - Encapsulate cross-page business processes, provide high-level business operations
  3. DSL Layer (dsl/) - Create business-oriented test methods to make test code more readable
  4. Data Layer (data/) - Include business-related test data
  5. Config Layer (config/) - Manage test environment configuration and test configuration parameters

Multi-Team Best Practices

Core Framework Management

  1. Version Control: Use semantic versioning for core framework releases
  2. Backward Compatibility: Maintain backward compatibility when possible
  3. Migration Guides: Provide clear migration guides for breaking changes
  4. Testing: Thoroughly test core framework changes before release

Team Project Organization

  1. Naming Conventions: Use team prefixes for page objects, services, and DSL
  2. Module Organization: Group related functionality in subdirectories
  3. Configuration: Each team maintains their own environment configuration
  4. Documentation: Each team maintains their own README and documentation

Test Writing Best Practices

  1. Unified Locator Encapsulation - Use semantic getter methods, avoid hardcoded selectors
  2. Test Fixtures - Use fixtures to set up test environment, reduce duplicate code
  3. Data-Driven - Use test data factory to separate test data from test logic
  4. Wait Strategy - Use smart wait mechanisms, avoid hardcoded wait times
  5. Error Handling - Add appropriate error handling and retry mechanisms
  6. Test Isolation - Ensure tests are independent of each other
  7. Business Language - Use test method names and comments that are close to business language

FAQ

Q: How to add new browsers?

A: Add new browser configuration in the projects array in playwright.config.ts.

Q: How to set up different test environments?

A: Use environment variables NODE_ENV and BASE_URL to configure different environments.

Q: How to generate test code?

A: Run npm run test:codegen to start the Playwright code generator.

Contributing

  1. Fork the project
  2. Create a feature branch
  3. Commit your changes
  4. Push to the branch
  5. Create a Pull Request

License

MIT License

About

Multi-team Playwright test automation framework with core layer and example team implementation

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published