playwright-page-object
API

createFixtures

Convert a map of page object classes into Playwright fixtures.

Signature

function createFixtures<T extends PageObjectConstructorsMap>(
  pageObjects: T,
): Fixtures<FixturesFromMap<T>, {}, {}, {}>;

type PageObjectEntry<T> =
  | (new (page: Page) => T)
  | ((page: Page) => T);

type PageObjectConstructorsMap = Record<string, PageObjectEntry<unknown>>;

Usage

import { test as base } from "@playwright/test";
import { createFixtures } from "playwright-page-object";

export const test = base.extend<{
  checkoutPage: CheckoutPage;
  authPage: AuthPage;
}>(
  createFixtures({
    checkoutPage: CheckoutPage,
    authPage: (page) => new AuthPage(page, authConfig),
  }),
);

The <{ ... }> generic on base.extend tells TypeScript the fixture types. createFixtures produces matching runtime wiring.

Class vs factory detection

For each entry, createFixtures decides whether to new-call or directly call:

const isConstructor =
  typeof entry === "function" &&
  entry.prototype !== undefined &&
  entry.prototype.constructor === entry;

const instance = isConstructor
  ? new entry(page)
  : entry(page);

This means:

Entry shapeDetected asCalled as
class Foo {} (ES class)constructornew entry(page)
function Foo() {} (regular function)constructornew entry(page)
(page) => new Foo(page, config) (arrow)factoryentry(page)

Use arrow functions for factories. Regular functions have a prototype and will be treated as constructors.

Type inference

FixturesFromMap<T> maps each entry to its instance type so that test.extend infers fixture types correctly:

createFixtures({
  homePage: HomePage,                     // homePage: HomePage
  authPage: (page) => new AuthPage(page), // authPage: AuthPage
});

You still pass the explicit generic to base.extend<{ homePage; authPage }> — Playwright's extend requires it for stricter type narrowing.

When to use it

  • Your suite already uses Playwright fixtures.
  • You want a single point of configuration for page-object setup.
  • You need factories for page objects with custom constructor arguments.

Manual instantiation (new CheckoutPage(page) inside each test) is equally valid. The library does not require fixtures.

See also

Last updated on

On this page