npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

satya-qa-playwright-framework

v1.2.0

Published

A production-ready npm initializer CLI tool that scaffolds a hybrid UI + API test automation project using Playwright and TypeScript. v1.2.0 includes advanced wait strategies, retry patterns, enhanced error handling, and environment variable configuration

Downloads

31

Readme

satya-qa-playwright-framework

A production-ready npm initializer CLI tool that scaffolds a hybrid UI + API test automation project using Playwright and TypeScript.

Features

Core Framework (v1.0.0)

  • Hybrid Testing: Unified framework for both UI and API test automation
  • Page Object Model: BasePage class with reusable UI interaction helpers
  • Three-Tier API Architecture: BaseApi → BaseClient → ServiceClient hierarchy
  • Environment Switching: Switch between dev/uat/prod via TEST_ENV variable
  • Credential Management: Centralized user credentials keyed by environment and role
  • Allure Reporting: Auto-configured with rich metadata and screenshots
  • TypeScript: Fully typed with strict configuration
  • Fixtures & Hooks: Automatic dependency injection and lifecycle management
  • Artifact Cleanup: Automatic cleanup of stale test results before each run

Enhanced Reliability (v1.2.0)

  • Advanced Wait Strategies: Custom condition waits, API response waits, business logic waits, and element stability waits
  • Retry Patterns: Exponential backoff, custom retry conditions, circuit breaker pattern, and retry statistics
  • Enhanced Error Handling: Rich error context with automatic capture of page state, network requests, and recovery suggestions
  • Environment Variable Configuration: Override any configuration value via environment variables for flexible CI/CD integration
  • Backward Compatibility: 100% compatible with v1.0.0 - all existing tests work unchanged

Installation

Create a new test automation project:

npx satya-qa-playwright-framework <project-name>

Replace <project-name> with your desired project directory name.

Usage

1. Scaffold a New Project

npx satya-qa-playwright-framework my-test-project

This creates a new directory my-test-project/ with the complete framework structure.

2. Install Dependencies

Navigate into your project and run the setup script:

cd my-test-project
node setup.js

The setup script will:

  • Install all npm dependencies from package.json
  • Install Playwright browsers via npx playwright install

3. Run Tests

After setup completes, you can run tests:

# Run all tests (UI + API)
npm test

# Run only UI tests
npm run test:ui

# Run only API tests
npm run test:api

# Generate Allure report
npm run report

# Open Allure report in browser
npm run report:open

4. Switch Environments

Use the TEST_ENV environment variable to switch between environments:

# Run tests against UAT environment
TEST_ENV=uat npm run test:ui

# Run tests against production environment
TEST_ENV=prod npm run test:api

Supported environments: dev (default), uat, prod

5. Environment Variable Configuration (v1.2.0)

Override any configuration value using environment variables for flexible CI/CD integration:

# Environment-specific URL overrides
DEV_BASE_URL=https://dev-custom.example.com npm run test
UAT_BASE_URL=https://uat-custom.example.com npm run test
PROD_BASE_URL=https://prod-custom.example.com npm run test

# Global configuration overrides
BASE_URL=https://global-override.example.com npm run test
API_BASE_URL=https://api-override.example.com npm run test
TEST_TIMEOUT=60000 npm run test
TEST_RETRIES=5 npm run test

# Playwright-specific overrides
HEADLESS=false npm run test:ui
SLOW_MO=1000 npm run test:ui

All configuration values can be overridden without modifying code files.

Project Structure

The scaffolded project follows this structure:

my-test-project/
├── setup.js                          # Dependency installation script
├── package.json                      # npm dependencies and scripts
├── playwright.config.ts              # Playwright configuration
├── tsconfig.json                     # TypeScript configuration
│
├── src/
│   ├── api/
│   │   ├── base.api.ts               # HTTP transport layer (enhanced v1.2.0)
│   │   └── clients/
│   │       ├── base.client.ts        # Shared client utilities
│   │       └── service.client.ts     # Service-specific endpoints
│   │
│   ├── config/
│   │   ├── config.ts                 # Environment switching (enhanced v1.2.0)
│   │   └── users.json                # Credentials by env + role
│   │
│   ├── fixtures/
│   │   └── base.fixture.ts           # Playwright fixtures
│   │
│   ├── hooks/
│   │   └── base.hook.ts              # Lifecycle hooks
│   │
│   ├── pages/
│   │   └── base.page.ts              # BasePage for POM (enhanced v1.2.0)
│   │
│   ├── specs/
│   │   ├── spec.base.ts              # Unified test + step export
│   │   ├── specs-ui/                 # UI test specs
│   │   └── specs-api/                # API test specs
│   │
│   ├── types/                        # Type definitions (v1.2.0)
│   │   ├── config.types.ts           # Configuration types
│   │   ├── error.types.ts            # Error handling types
│   │   ├── retry.types.ts            # Retry pattern types
│   │   └── wait.types.ts             # Wait strategy types
│   │
│   └── utils/
│       ├── cleanup.util.ts           # Artifact cleanup utility
│       ├── config.util.ts            # Configuration validation (v1.2.0)
│       ├── error.util.ts             # Enhanced error context (v1.2.0)
│       ├── retry.util.ts             # Retry patterns (v1.2.0)
│       └── wait.util.ts              # Advanced wait strategies (v1.2.0)
│
├── test-results/                     # Screenshots, videos (auto-generated)
├── allure-results/                   # Raw Allure data (auto-generated)
└── allure-report/                    # HTML report (auto-generated)

Writing Tests

UI Tests (Page Object Model)

  1. Create a page object in src/pages/:
import { Page } from '@playwright/test';
import { BasePage } from './base.page';

export class LoginPage extends BasePage {
  private usernameInput = this.getByTestId('username');
  private passwordInput = this.getByTestId('password');
  private loginButton = this.getByRole('button', { name: 'Login' });

  constructor(page: Page) {
    super(page);
  }

  async open() {
    await this.navigate('/login');
  }

  async login(username: string, password: string) {
    await this.fill(this.usernameInput, username);
    await this.fill(this.passwordInput, password);
    await this.click(this.loginButton);
  }
}
  1. Create a spec in src/specs/specs-ui/:
import { test, step } from '../spec.base';
import { expect } from '@playwright/test';
import { LoginPage } from '../../pages/login.page';

test('User can log in', async ({ page }) => {
  const loginPage = new LoginPage(page);

  await step('Given user opens login page', async () => {
    await loginPage.open();
  });

  await step('When user enters valid credentials', async () => {
    await loginPage.login('admin', 'password');
  });

  await step('Then dashboard should appear', async () => {
    await expect(page).toHaveURL(/dashboard/);
  });
});

API Tests (Service Client)

  1. Create a service client in src/api/clients/:
import { BaseClient } from './base.client';
import { APIResponse } from '@playwright/test';

export class UserServiceClient extends BaseClient {
  async getUser(userId: string): Promise<APIResponse> {
    return this.get(`/api/users/${userId}`);
  }

  async createUser(payload: object): Promise<APIResponse> {
    return this.post('/api/users', payload);
  }
}
  1. Create a spec in src/specs/specs-api/:
import { test, step } from '../spec.base';
import { expect } from '@playwright/test';
import { UserServiceClient } from '../../api/clients/user.client';

test('API: Create and retrieve user', async ({ request, config }) => {
  const client = new UserServiceClient(request, config.apiBaseUrl);

  let userId: string;

  await step('When creating a new user', async () => {
    const res = await client.createUser({ name: 'John Doe' });
    expect(res.status()).toBe(201);
    userId = (await res.json()).id;
  });

  await step('Then user can be retrieved', async () => {
    const res = await client.getUser(userId);
    expect(res.status()).toBe(200);
    expect((await res.json()).name).toBe('John Doe');
  });
});

v1.2.0 Enhanced Features

Retry Patterns

Use retry patterns for flaky interactions and API calls:

// UI interactions with retry
import { BasePage } from '../pages/base.page';

const loginPage = new LoginPage(page);

// Click with exponential backoff retry
await loginPage.clickWithRetry('#flaky-button', { 
  maxAttempts: 5, 
  initialDelay: 500 
});

// Fill input with retry
await loginPage.fillWithRetry('#dynamic-input', 'value', { 
  maxAttempts: 3,
  initialDelay: 1000 
});

// API requests with retry
import { UserServiceClient } from '../api/clients/user.client';

const client = new UserServiceClient(request, config.apiBaseUrl);

// GET with retry
const response = await client.getWithRetry('/api/users', {}, { 
  maxAttempts: 3,
  initialDelay: 1000 
});

// POST with retry
const createResponse = await client.postWithRetry('/api/users', payload, { 
  maxAttempts: 5,
  initialDelay: 500 
});

Advanced Wait Strategies

Use advanced wait utilities for complex scenarios:

import { 
  waitForCondition, 
  waitForApiResponse, 
  waitForBusinessLogic,
  waitForElementStable 
} from '../utils/wait.util';

// Wait for custom business logic
await waitForCondition(() => {
  return someBusinessLogic() === 'completed';
}, { timeout: 30000, pollInterval: 1000 });

// Wait for API response with specific conditions
await waitForApiResponse(() => fetch('/api/status'), {
  status: 200,
  bodyContains: { ready: true },
  timeout: 15000
});

// Wait for business process completion
await waitForBusinessLogic(page, {
  type: 'data-loading',
  loadingIndicator: '.spinner',
  completionIndicator: '.data-ready',
  timeout: 20000
});

// Wait for element to stop moving (animations)
await waitForElementStable(page.locator('#animated-element'), {
  stableFor: 1000,
  timeout: 10000
});

Enhanced Error Context

Automatic error enhancement provides rich debugging information:

// Errors automatically include:
// - Action context ('clicking element #login-button')
// - Page URL and title
// - Screenshot (if available)
// - Network request logs
// - Console error logs
// - Recovery suggestions

try {
  await basePage.click('#problematic-element');
} catch (error) {
  // Error now contains rich context for debugging
  console.log(error.context); // Page state, network logs, etc.
  console.log(error.suggestions); // Recovery suggestions
}

Configuration Validation

Validate and debug configuration issues:

import { 
  validateCurrentConfig, 
  getFullConfig, 
  getEnvMappings 
} from '../config/config';

// Validate current configuration
const validation = validateCurrentConfig();
if (!validation.isValid) {
  console.log('Config errors:', validation.errors);
}

// Get full configuration with all overrides applied
const fullConfig = getFullConfig();
console.log('Current config:', fullConfig);

// See environment variable mappings
const mappings = getEnvMappings();
console.log('Available env vars:', mappings);

Configuration

Environment Configuration

Edit src/config/config.ts to add or modify environments:

const environments: Record<Environment, EnvConfig> = {
  dev: {
    baseURL: 'https://dev.example.com',
    apiBaseUrl: 'https://api.dev.example.com'
  },
  uat: {
    baseURL: 'https://uat.example.com',
    apiBaseUrl: 'https://api.uat.example.com'
  },
  prod: {
    baseURL: 'https://prod.example.com',
    apiBaseUrl: 'https://api.prod.example.com'
  }
};

Credential Management

Edit src/config/users.json to add test credentials:

{
  "dev": {
    "admin": {
      "username": "[email protected]",
      "password": "dev-password"
    }
  },
  "uat": {
    "admin": {
      "username": "[email protected]",
      "password": "uat-password"
    }
  }
}

Retrieve credentials in tests:

import { getUser } from '../config/config';

const user = getUser('admin');
// user.username, user.password

Requirements

  • Node.js >= 18.0.0
  • npm >= 9.0.0

License

MIT

Support

For issues and questions, please refer to the inline usage guides in each scaffolded file.