Skip to content

prasad291024/playwright-automation-framework

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

95 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Playwright Automation Framework

🎭 A Production-Grade End-to-End Testing Framework

Built with Playwright, TypeScript, and Industrial-Quality Automation

Playwright TypeScript Node.js

Features β€’ Quick Start β€’ Architecture β€’ Quality Gates β€’ CI/CD


πŸš€ Features

Core Framework

  • βœ… Page Object Model (POM) with TypeScript interfaces
  • βœ… Multi-browser support (Chromium, Firefox, WebKit)
  • βœ… Accessible selectors (role-based, test IDs)
  • βœ… Global setup/teardown and auth fixtures
  • βœ… API testing with JSON schema validation
  • βœ… Data-driven testing with external data files
  • βœ… Comprehensive reporting (HTML, JSON, videos, screenshots)

Quality & Reliability

  • βœ… TypeScript strict mode for type safety
  • βœ… ESLint + Prettier code quality enforcement
  • βœ… Husky + lint-staged pre-commit automation
  • βœ… GitHub Actions CI/CD multi-browser testing
  • βœ… Flaky test protection (retries, diagnostics)
  • βœ… Test tagging strategy (@smoke, @regression, @critical)
  • βœ… Production diagnostics (trace, video, screenshots)

Developer Experience

  • βœ… Docker & Docker Compose support
  • βœ… Visual Studio Code integration
  • βœ… Automated test execution
  • βœ… Branch protection rules
  • βœ… Environment-specific configs
  • βœ… Real-time test reporting
  • βœ… Comprehensive documentation

πŸ“ Project Structure

.
β”œβ”€β”€ πŸ”§ Configuration & Setup
β”‚   β”œβ”€β”€ playwright.config.ts      # Playwright configuration (browsers, timeouts, retries)
β”‚   β”œβ”€β”€ tsconfig.json             # TypeScript strict mode configuration
β”‚   β”œβ”€β”€ .eslintrc.cjs             # ESLint rules and plugins
β”‚   β”œβ”€β”€ .prettierrc                # Prettier formatting rules
β”‚   └── .env.example              # Environment variables template
β”‚
β”œβ”€β”€ πŸ€– CI/CD & Automation
β”‚   β”œβ”€β”€ .github/workflows/
β”‚   β”‚   β”œβ”€β”€ ci.yml                # Staged CI pipeline (install, lint, typecheck, test, publish)
β”‚   β”‚   └── codeql.yml            # Security scanning
β”‚   β”œβ”€β”€ .husky/                   # Git hooks
β”‚   β”‚   β”œβ”€β”€ pre-commit            # Pre-commit validation (lint-staged)
β”‚   β”‚   β”œβ”€β”€ pre-push              # Pre-push quality checks
β”‚   β”‚   β”œβ”€β”€ pre-merge             # Pre-merge validation
β”‚   β”‚   └── post-merge            # Post-merge smoke tests
β”‚   β”œβ”€β”€ scripts/
β”‚   β”‚   β”œβ”€β”€ git-hooks/
β”‚   β”‚   β”‚   β”œβ”€β”€ pre-commit.ps1    # PowerShell pre-commit script
β”‚   β”‚   β”‚   └── pre-commit.sh     # Bash pre-commit script
β”‚   β”‚   β”œβ”€β”€ post-pull-checks.ps1  # Environment verification script
β”‚   β”‚   └── post-pull-checks.sh   # Bash environment check
β”‚   └── Dockerfile & docker-compose.yml
β”‚
β”œβ”€β”€ πŸ“ Source Code
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ pages/                # Page Object classes
β”‚   β”‚   β”‚   β”œβ”€β”€ BasePage.ts       # Abstract base with common methods
β”‚   β”‚   β”‚   β”œβ”€β”€ LoginPage.ts      # Example page objects
β”‚   β”‚   β”‚   β”œβ”€β”€ DashboardPage.ts
β”‚   β”‚   β”‚   └── infrastructure/
β”‚   β”‚   β”‚       β”œβ”€β”€ PageFactory.ts # Dynamic page object factory
β”‚   β”‚   β”‚       └── index.ts
β”‚   β”‚   β”‚
β”‚   β”‚   β”œβ”€β”€ interface/            # TypeScript contracts
β”‚   β”‚   β”‚   β”œβ”€β”€ pages.interface.ts # ILoginPage, IDashboardPage, etc.
β”‚   β”‚   β”‚   └── api.interface.ts  # API request/response types
β”‚   β”‚   β”‚
β”‚   β”‚   β”œβ”€β”€ utils/                # Utility functions
β”‚   β”‚   β”‚   β”œβ”€β”€ apiHelper.ts      # Type-safe API client
β”‚   β”‚   β”‚   β”œβ”€β”€ schemaValidator.ts # JSON schema validation (AJV)
β”‚   β”‚   β”‚   β”œβ”€β”€ selectors.ts      # Centralized selector definitions
β”‚   β”‚   β”‚   β”œβ”€β”€ assertions.ts     # Custom assertions
β”‚   β”‚   β”‚   β”œβ”€β”€ logger.ts         # Logging utilities
β”‚   β”‚   β”‚   └── [other utilities]
β”‚   β”‚   β”‚
β”‚   β”‚   β”œβ”€β”€ core/                 # Core framework
β”‚   β”‚   β”‚   β”œβ”€β”€ base/BasePage.ts  # Base page object class
β”‚   β”‚   β”‚   β”œβ”€β”€ fixtures/         # Playwright fixtures
β”‚   β”‚   β”‚   └── utils/            # Core utilities
β”‚   β”‚   β”‚
β”‚   β”‚   β”œβ”€β”€ fixture/              # Test data & fixtures
β”‚   β”‚   β”‚   β”œβ”€β”€ auth.fixture.ts   # Authentication fixture
β”‚   β”‚   β”‚   └── README.md
β”‚   β”‚   β”‚
β”‚   β”‚   └── config/               # Application configurations
β”‚   β”‚       β”œβ”€β”€ app.config.ts     # App registry and settings
β”‚   β”‚       └── [app-specific configs]
β”‚   β”‚
β”‚   β”œβ”€β”€ tests/                    # Test suites
β”‚   β”‚   β”œβ”€β”€ cura/                 # CURA suites (auth, smoke, regression, a11y, performance)
β”‚   β”‚   β”œβ”€β”€ orangehrm/            # OrangeHRM suites
β”‚   β”‚   β”œβ”€β”€ saucedemo/            # SauceDemo suites
β”‚   β”‚   β”œβ”€β”€ shared/               # Shared auth and API coverage
β”‚   β”‚   └── templates/            # Numbered template track (01-10)
β”‚   β”‚
β”‚   β”œβ”€β”€ test-data/                # Test data files
β”‚   β”‚   β”œβ”€β”€ fixtures/             # Shared test data (JSON)
β”‚   β”‚   β”œβ”€β”€ dev/                  # Development environment data
β”‚   β”‚   └── qa/                   # QA environment data
β”‚   β”‚
β”‚   β”œβ”€β”€ schemas/                  # JSON Schema definitions
β”‚   β”‚   β”œβ”€β”€ user.schema.json      # User response schema
β”‚   β”‚   β”œβ”€β”€ error.schema.json     # Error response schema
β”‚   β”‚   └── createUser.request.schema.json
β”‚   β”‚
β”‚   β”œβ”€β”€ globals/                  # Global test setup/teardown
β”‚   β”‚   β”œβ”€β”€ global-setup.ts       # Global authentication setup
β”‚   β”‚   └── global-teardown.ts    # Cleanup operations
β”‚   β”‚
β”‚   └── storage-state/            # Saved browser authentication state
β”‚
β”œβ”€β”€ πŸ“Š Reports & Results
β”‚   β”œβ”€β”€ playwright-report/        # HTML test report (interactive)
β”‚   β”œβ”€β”€ test-results/             # JSON test results
β”‚   └── screenshots/              # Failure screenshots
β”‚
β”œβ”€β”€ πŸ“š Documentation
β”‚   β”œβ”€β”€ docs/
β”‚   β”‚   β”œβ”€β”€ FRAMEWORK_INDEX.md          # Current framework overview
β”‚   β”‚   β”œβ”€β”€ FRAMEWORK_IMPLEMENTATION.md # Implementation guide
β”‚   β”‚   β”œβ”€β”€ PRODUCTION_FRAMEWORK_SUMMARY.md
β”‚   β”‚   β”œβ”€β”€ STRUCTURE_REFACTORING.md    # Structure history and migration notes
β”‚   β”‚   β”œβ”€β”€ PRODUCTION_READINESS.md     # Production checklist
β”‚   β”‚   β”œβ”€β”€ CONTRIBUTING.md             # Development guidelines
β”‚   β”‚   └── SECURITY.md                 # Security guidelines
β”‚
└── πŸ“¦ Dependencies & Configuration
    β”œβ”€β”€ package.json
    β”œβ”€β”€ package-lock.json
    β”œβ”€β”€ .gitignore
    └── README.md (this file)

⚑ Quick Start

Prerequisites

  • Node.js 20+
  • npm 10+
  • Git

Installation

# Clone the repository
git clone https://github.com/prasad291024/playwright-automation-framework.git
cd playwright-automation-framework

# Install dependencies
npm install

# Install Playwright browsers
npx playwright install

# Verify environment
npm run verify-env

Environment Setup

Create a .env file in the project root:

# Application Configuration
BASE_URL=https://your-app-url.com
APP_NAME=local  # or: saucedemo, cura, orangehrm

# Authentication
USERNAME=your_username
PASSWORD=your_password

# Logging
LOG_LEVEL=info  # debug, info, warn, error

# Timeouts (milliseconds)
ACTION_TIMEOUT=5000
NAVIGATION_TIMEOUT=30000

Running Tests

# Run all tests (headless)
npm test

# Run smoke tests only (@smoke tag)
npm run test:smoke

# Run with visible browser
npm run test:headed

# Run specific active test file
npx playwright test tests/saucedemo/smoke/login.spec.ts

# Run tests matching pattern
npx playwright test --grep "login"

# Debug a specific test
npx playwright test tests/auth.spec.ts --debug

# View HTML report
npx playwright show-report

πŸ—οΈ Architecture & Design Patterns

Page Object Model with Interfaces

TypeScript interfaces enforce contracts for page objects:

// Interface (contract)
export interface ILoginPage {
  navigate(): Promise<void>;
  fillUsername(username: string): Promise<void>;
  clickLoginButton(): Promise<void>;
  getErrorMessage(): Promise<string>;
}

// Implementation
export class LoginPage extends BasePage implements ILoginPage {
  async navigate(): Promise<void> {
    await this.goto('/login');
    await this.waitForPageLoad();
  }

  async fillUsername(username: string): Promise<void> {
    await this.getByTestId('username-input').fill(username);
  }

  async clickLoginButton(): Promise<void> {
    await this.getByRole('button', { name: /sign in/i }).click();
  }
}

Selector Strategy (Priority Order)

  1. Test ID β€” data-testid (explicit, maintainable)

    await this.getByTestId('submit-button').click();
  2. Role-based β€” getByRole (accessible, semantic)

    await this.getByRole('button', { name: /login/i }).click();
  3. Text/Placeholder β€” User-centric selectors

    await this.getByText('Submit').click();
  4. CSS/XPath β€” Last resort only (fragile, avoid when possible)

BasePage Abstract Class

All page objects inherit from BasePage for unified locator strategies:

export abstract class BasePage {
  constructor(protected page: Page) {}

  // Role-based selectors (preferred for accessibility)
  protected getByRole(role: AriaRole, options?: GetByRoleOptions) {
    return this.page.getByRole(role, options);
  }

  // Test ID selectors (explicit, maintainable)
  protected getByTestId(testId: string) {
    return this.page.getByTestId(testId);
  }

  // Navigation helpers
  async goto(path: string) { ... }
  async navigateTo(url: string) { ... }
  async waitForPageLoad() { ... }

  // Common assertions
  async waitForElement(selector: string) { ... }
  async isElementVisible(locator: Locator) { ... }
}

πŸ”Œ API Testing with Schema Validation

Type-Safe API Client

import { apiHelper } from '../src/utils/apiHelper';

// Automatically validates response against user.schema.json
const user = await apiHelper.getUser(1);
console.log(user.id, user.name, user.email);

// Create user with automatic validation
const newUser = await apiHelper.createUser({
  name: 'John Doe',
  email: 'john@example.com',
  phone: '555-1234',
});

// Validation error handling
try {
  const response = await apiHelper.getUser(999);
} catch (error) {
  console.error('API Error or validation failed:', error.message);
}

JSON Schema Validation with AJV

import { schemaValidator } from '../src/utils/schemaValidator';

// Validate data against schema
const result = schemaValidator.validate(userData, 'user.schema.json');
if (!result.isValid) {
  console.error('Validation errors:', result.errors);
}

// Validate or throw
schemaValidator.validateOrThrow(response, 'user.schema.json');

// Get human-readable errors
const messages = schemaValidator.getErrorMessages('user.schema.json', data);
messages.forEach((msg) => console.log(msg));

πŸ›‘οΈ Industrial-Grade Quality Gates

This framework implements four control points in the development lifecycle to ensure production-ready automation code.

1️⃣ Pre-Commit Checks (Local Developer Guard)

Purpose: Prevent bad code from entering the repository

Trigger: Automatic on git commit

Technology: Husky + lint-staged

Checks:

  • βœ… ESLint validation with auto-fix
  • βœ… Prettier formatting with auto-fix
  • βœ… TypeScript compilation (manual: npm run typecheck)
# Automatic on every commit
git commit -m "feat: my changes"
# β†’ Husky runs ESLint + Prettier automatically
# β†’ Commit succeeds if all checks pass
# β†’ Commit fails if checks cannot be auto-fixed

Files Modified:

  • .husky/pre-commit β€” Runs npx lint-staged
  • scripts/git-hooks/pre-commit.ps1 & .sh β€” Alternative implementation

2️⃣ Post-Pull Checks (Environment Health Verification)

Purpose: Verify developer environment consistency after repository updates

Trigger: Manual execution after git pull

Command: npm run verify-env

Checks:

  • βœ… Dependencies installation
  • βœ… Browser installation
  • βœ… Code quality validation
  • βœ… Smoke test execution (@smoke)
# After pulling new changes
git pull
npm run verify-env
# β†’ Installs dependencies
# β†’ Installs browsers
# β†’ Runs linting and type checking
# β†’ Executes smoke test suite

Implementation:

  • scripts/post-pull-checks.ps1 β€” PowerShell version
  • scripts/post-pull-checks.sh β€” Bash version
  • Package.json script: "verify-env"

3️⃣ Pre-Merge Checks (Pull Request Quality Gate)

Purpose: Validate code meets standards before merge to main

Trigger: Pull Request to main branch

Technology: GitHub Actions

Workflow: .github/workflows/ci.yml

Checks:

  • βœ… Install Dependencies β€” workspace/bootstrap stage
  • βœ… Lint β€” ESLint + Prettier validation
  • βœ… Type check β€” TypeScript compilation
  • βœ… Code Quality Checks β€” staged quality gate summary
  • βœ… Test β€” smoke scope on PR, broader suite coverage on push/manual runs
  • βœ… Publish Report β€” artifact and report summary stage

Each job appears as individual status check:

  • Install Dependencies βœ…
  • Lint βœ…
  • Type check βœ…
  • Code Quality Checks βœ…
  • Test βœ…
  • Publish Report βœ…
# Jobs run in stages after dependency installation
jobs:
  install:
    runs-on: ubuntu-latest
  lint:
    runs-on: ubuntu-latest
    needs: install
  typecheck:
    runs-on: ubuntu-latest
    needs: install
  code_quality:
    runs-on: ubuntu-latest
    needs: [lint, typecheck]
  test:
    runs-on: ubuntu-latest
    needs: [install, code_quality]
  publish_report:
    runs-on: ubuntu-latest
    needs: [install, test]

4️⃣ Post-Merge Checks (Main Branch Protection)

Purpose: Ensure main branch remains production-ready

Trigger: Push to main branch after merge

Workflow: .github/workflows/ci.yml

Checks:

  • βœ… Staged CI execution on main
  • βœ… Smoke/full scope selection based on event type
  • βœ… HTML, JSON, JUnit, and raw artifact upload
  • βœ… Published CI run summary

🏷️ Test Tagging Strategy

Tests are tagged for selective execution across the pipeline:

Tag Purpose When to Use
@smoke Core health checks, fast execution PR validation, smoke testing
@regression Full feature coverage Post-merge validation, nightly runs
@critical High-risk business flows Production-critical tests
@performance Performance benchmarks Performance testing pipeline
@accessibility A11y compliance checks Accessibility testing
@visual Visual regression tests Visual regression pipeline

Usage Example

// Smoke test (runs in PR validation)
test('@smoke - user can login', async ({ page }) => {
  // Test implementation
});

// Regression test (runs on main branch)
test('@regression - user can update profile', async ({ page }) => {
  // Test implementation
});

// Critical path test
test('@critical - payment processing', async ({ page }) => {
  // Test implementation
});

Running Tests by Tag

# Run only smoke tests
npx playwright test --grep @smoke

# Run regression tests
npx playwright test --grep @regression

# Run critical tests
npx playwright test --grep @critical

# Run all except smoke
npx playwright test --grep --invert @smoke

πŸ”„ Flaky Test Protection

The framework includes built-in strategies to reduce flakiness:

Automatic Retries

// playwright.config.ts
export default defineConfig({
  // Retry failed tests in CI, not locally
  retries: process.env.CI ? 2 : 0,

  // Detailed diagnostics on first retry
  trace: 'on-first-retry',
  video: 'retain-on-failure',
  screenshot: 'only-on-failure',
});

Wait Strategies

// Always wait for ready state
await page.goto(url, { waitUntil: 'networkidle' });

// Use Playwright's built-in waits
await page.waitForLoadState('networkidle');
await page.waitForSelector('.loaded', { timeout: 10000 });

Smart Assertions

// Playwright auto-waits for assertions
await expect(element).toBeVisible(); // Waits up to 5s
await expect(element).toHaveText('Expected text'); // Auto-waits

πŸ“Š Test Reports & Diagnostics

HTML Report (Interactive)

npx playwright show-report

Location: playwright-report/index.html

Shows:

  • βœ… Test execution timeline
  • βœ… Pass/fail breakdown
  • βœ… Screenshots of failures
  • βœ… Video playback
  • βœ… Execution traces for debugging

JSON Report (Machine Readable)

Location: test-results/results.json

Use for:

  • CI/CD integration
  • Dashboards
  • Custom analytics

Failure Diagnostics

Automatically captured for failed tests:

  • πŸ“Έ Screenshots
  • πŸŽ₯ Video recordings
  • πŸ“ Execution traces
  • πŸ” Network logs

πŸ” Branch Protection Rules

Configure the following in GitHub repository settings to protect the main branch:

Required Settings

βœ… Require status checks to pass before merging

  • Lint
  • Type check
  • Unit / smoke tests

βœ… Require branches to be up to date before merging

βœ… Require pull request reviews before merging

  • Minimum: 1 approval

βœ… Require conversation resolution before merging

βœ… Require linear history

Additional Protections

βœ… Block force pushes

βœ… Restrict who can push to matching branches

Configuration Steps

  1. Go to: Settings β†’ Branches
  2. Click "Add rule"
  3. Branch name pattern: main
  4. Enable protections above
  5. Click "Create"

See Framework Index and Contributing for current workflow guidance.


πŸ”§ NPM Scripts

Command Purpose
npm test Run all tests (headless)
npm run test:headed Run with visible browser
npm run test:debug Debug mode with inspector
npm run test:ui Interactive UI mode
npm run test:smoke Run @smoke tests only
npm run lint Check code style
npm run lint:fix Auto-fix linting issues
npm run format Format code
npm run format:check Check formatting
npm run typecheck Validate TypeScript
npm run verify-env Verify environment health
npm run pre-pull Pre-pull checks
npm run pre-merge Pre-merge checks
npm run pre-push Pre-push checks

🐳 Docker Support

Docker Compose

# Run tests in Docker
docker-compose up test

# Run specific browser
docker-compose up test -- --project=firefox

# Run with headed browser
docker-compose run --build test-headed

# Build image
docker-compose build

Manual Docker

# Build image
docker build -t playwright-tests .

# Run tests
docker run --rm \
  -v $(pwd)/test-results:/app/test-results \
  -v $(pwd)/playwright-report:/app/playwright-report \
  playwright-tests

πŸ’‘ Complete Test Example

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

test.describe('User Authentication @smoke', () => {
  let loginPage: LoginPage;
  let dashboardPage: DashboardPage;

  test.beforeEach(async ({ page }) => {
    loginPage = new LoginPage(page);
    dashboardPage = new DashboardPage(page);
  });

  test('should login with valid credentials', async () => {
    // Arrange
    const testUser = {
      username: 'test@example.com',
      password: 'SecurePassword123',
    };

    // Act
    await loginPage.navigate();
    await loginPage.fillUsername(testUser.username);
    await loginPage.fillPassword(testUser.password);
    await loginPage.clickLoginButton();

    // Assert
    await expect(dashboardPage.getWelcomeMessage()).toContainText(`Welcome, ${testUser.username}`);
  });

  test('should display error with invalid credentials', async () => {
    // Act
    await loginPage.navigate();
    await loginPage.fillUsername('invalid@example.com');
    await loginPage.fillPassword('wrong');
    await loginPage.clickLoginButton();

    // Assert
    await expect(loginPage.getErrorMessage()).toBeVisible();
  });

  test('should require username and password', async () => {
    // Act
    await loginPage.navigate();
    await loginPage.clickLoginButton();

    // Assert
    await expect(loginPage.getUsernameError()).toContainText('Username is required');
  });
});

πŸ“š Documentation

Comprehensive guides available in docs/:

Document Purpose
FRAMEWORK_INDEX.md Current framework overview
TEST_STRATEGY.md Active suite ownership and CI scope
FRAMEWORK_IMPLEMENTATION.md Implementation details
PRODUCTION_FRAMEWORK_SUMMARY.md Architecture summary
STRUCTURE_REFACTORING.md Structure changes and migration notes
PRODUCTION_READINESS.md Production checklist
CONTRIBUTING.md Development guidelines
SECURITY.md Security guidance
tests/README.md Current active and template suites

🀝 Contributing

We follow strict quality and contribution guidelines.

Development Workflow

  1. Sync and verify environment

    git pull
    npm run verify-env
  2. Create feature branch

    git checkout -b feature/your-feature-name
  3. Develop and test

    npm test  # Run tests locally
  4. Commit with pre-commit hooks

    git add .
    git commit -m "feat: your feature"
    # β†’ Pre-commit hooks run automatically
  5. Push feature branch

    git push origin feature/your-feature-name
  6. Create Pull Request

    • PR validation runs automatically
    • Must pass all checks: Lint, Type check, Smoke tests
  7. Merge to main

    • Requires 1 approval
    • All status checks must pass
    • Post-merge regression suite runs

See CONTRIBUTING.md for detailed guidelines.


🌐 Resources


🎯 Next Steps


πŸ“„ License

ISC


Made with ❀️ by Prasad β€” Test Automation Engineer

⭐ Star on GitHub if you find this useful!

Create a .env file in the project root:

BASE_URL=https://your-app-url.com
USERNAME=your_username
PASSWORD=your_password
LOG_LEVEL=info

Running Tests

# Run all tests (headless)
npm test

# Run tests with visible browser
npm run test:headed

# Run specific test file
npx playwright test tests/auth.api.spec.ts

# Run tests matching pattern
npx playwright test --grep "login"

# View HTML report
npx playwright show-report

πŸ—οΈ Architecture

Page Object Model with Interfaces

This framework uses a modern POM pattern with TypeScript interfaces:

// Interface contract
export interface ILoginPage {
  navigate(): Promise<void>;
  fillUsername(username: string): Promise<void>;
  fillPassword(password: string): Promise<void>;
  clickLoginButton(): Promise<void>;
}

// Implementation extending BasePage
export class LoginPage extends BasePage implements ILoginPage {
  async navigate(): Promise<void> {
    await this.goto('/login');
    await this.waitForPageLoad();
  }

  async fillUsername(username: string): Promise<void> {
    // Prefer testId over CSS selectors
    await this.getByTestId(SELECTORS_BY_TESTID.login.usernameInput).fill(username);
  }

  // ... more methods
}

BasePage Class

All page objects inherit from BasePage, providing unified locator strategies:

export abstract class BasePage {
  // Preferred: Role-based selectors (accessible, resilient)
  protected getByRole(role: AriaRole, options?: GetByRoleOptions) {}

  // Preferred: Test ID selectors (explicit data-testid attributes)
  protected getByTestId(testId: string) {}

  // Navigation helpers
  async goto(path: string) {}
  async navigateTo(url: string) {}
  async waitForPageLoad() {}
}

Selector Strategy (Priority Order)

  1. Test ID β€” data-testid attributes (explicit, maintainable)
  2. Role-based β€” getByRole('button', { name: /label/i }) (accessible)
  3. Text/Placeholder β€” getByText(), getByPlaceholder() (user-centric)
  4. CSS/XPath β€” Last resort only (brittle, avoid)

πŸ”Œ API Testing with Schema Validation

Type-Safe API Helper

import { apiHelper } from '../src/utils/apiHelper';

// Automatically validates response against user.schema.json
const user = await apiHelper.getUser(1);

// Create user with type validation
const newUser = await apiHelper.createUser({
  name: 'John Doe',
  email: 'john@example.com',
  phone: '555-1234',
});

// Error handling with schema validation
try {
  const response = await apiHelper.getUser(999);
} catch (error) {
  console.error('Validation failed:', error.message);
}

Schema Validation with AJV

import { schemaValidator } from '../src/utils/schemaValidator';

// Validate against schema
const result = schemaValidator.validate(userData, 'user.schema.json');
if (!result.valid) {
  console.error('Validation errors:', result.errors);
}

// Throw on validation failure
schemaValidator.validateOrThrow(response, 'user.schema.json');

// Get human-readable error messages
const messages = schemaValidator.getErrorMessages('user.schema.json', data);

πŸ”’ Code Quality & Pre-commit Hooks

Quality Checks

# Check code style
npm run lint

# Auto-fix linting issues
npm run lint:fix

# Format code
npm run format

# Validate TypeScript
npm run typecheck

Husky + lint-staged

Automatically runs on every git commit:

  1. ESLint checks and fixes *.ts files
  2. Prettier formats code
  3. Commit rejected if checks fail

No manual intervention neededβ€”hooks run automatically.


πŸ€– GitHub Actions CI/CD

Multi-Browser Testing

Runs on every push and pull request:

  • Browsers: Chromium, Firefox, WebKit
  • Platforms: Ubuntu, Windows, macOS
  • Quality: ESLint, Prettier, TypeScript checks
  • Reports: HTML + JSON artifacts
# View workflows
.github/workflows/ci.yml        # Main staged CI pipeline
.github/workflows/codeql.yml    # Security scanning

🐳 Docker Support

Docker Compose

# Run tests in Docker
docker-compose up test

# Run with headed browser
docker-compose --profile headed up test-headed

# Build image
docker-compose build

Manual Docker Commands

# Build image
docker build -t playwright-tests .

# Run tests
docker run --rm \
  -v $(pwd)/test-results:/app/test-results \
  -v $(pwd)/playwright-report:/app/playwright-report \
  playwright-tests

# Run specific browser
docker run --rm playwright-tests npm test -- --project=firefox

πŸ“¦ NPM Scripts

Script Purpose
npm test Run all tests (headless)
npm run test:headed Run tests with visible browser
npm run lint Check code style
npm run lint:fix Auto-fix linting errors
npm run format Format code with Prettier
npm run typecheck Validate TypeScript

πŸ“Š Test Reports

  • HTML Report: playwright-report/index.html β€” Interactive test results
  • JSON Report: test-results/results.json β€” Machine-readable results
  • Screenshots: screenshots/ β€” Failure screenshots
  • Videos: Captured for failed tests (configurable)
# View HTML report
npx playwright show-report

🧱 Example: Complete Test with Modern Patterns

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

test.describe('User Authentication Flow', () => {
  let loginPage: LoginPage;
  let dashboardPage: DashboardPage;

  test.beforeEach(async ({ page }) => {
    loginPage = new LoginPage(page);
    dashboardPage = new DashboardPage(page);
    await loginPage.navigate();
  });

  test('should login with valid credentials', async () => {
    // Arrange
    const testUser = {
      username: 'user@example.com',
      password: 'SecurePassword123',
    };

    // Act
    await loginPage.fillUsername(testUser.username);
    await loginPage.fillPassword(testUser.password);
    await loginPage.clickLoginButton();

    // Assert
    await expect(dashboardPage.getWelcomeMessage()).toContainText('Welcome');
  });

  test('should reject invalid credentials', async () => {
    // Act
    await loginPage.fillUsername('invalid@example.com');
    await loginPage.fillPassword('wrong');
    await loginPage.clickLoginButton();

    // Assert
    await expect(loginPage.getErrorMessage()).toBeVisible();
  });
});

πŸ”— Contributing

See CONTRIBUTING.md for:

  • Development setup
  • Git workflow and commit conventions
  • Testing guidelines
  • Code style requirements
  • Pull request process

πŸ“š Resources


πŸ‘€ Author

Developed by Prasad β€” Software Test Engineer, passionate about test automation, framework design, and engineering excellence.


πŸ“„ License

ISC


Ready to contribute? See CONTRIBUTING.md for guidelines!

About

End-to-end testing framework using Playwright, TypeScript, and environment-driven configuration. Includes global setup, multi-browser support, and data-driven testing.

Resources

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors