3.4 KiB
page-object
(no submodules)
Purpose
PageObject is the abstract base class for Playwright Page Object Model implementations. It wires every subclass with a consistent navigate / waitForReady / findByRole / findByLabel / findByText surface so spec files stay declarative. Subclasses override the path and waitForReady specifics while inheriting the shared query conveniences.
Features
- Abstract
path: string— subclass declares the route navigate(options?)— delegates topage.gotowith the configured pathwaitForReady(options?)— subclass overrides to assert page-specific readiness- Query helpers:
findByRole,findByLabel,findByText— thin wrappers overpage.getBy* exactOptionalPropertyTypes-safe:timeoutis forwarded only when set
Usage: Basic Example
import { PageObject } from "@suaveplan/testing-e2e/page-objects";
class LoginPage extends PageObject {
public readonly path = "/login";
public async waitForReady(): Promise<void> {
await this.findByRole("heading", { name: /sign in/i });
}
}
// spec:
const login = new LoginPage(page);
await login.navigate();
await login.waitForReady();
Usage: Advanced Example
import { PageObject } from "@suaveplan/testing-e2e/page-objects";
import { expect } from "@playwright/test";
class CheckoutPage extends PageObject {
public readonly path = "/checkout";
public async waitForReady({ timeoutMs }: { timeoutMs?: number } = {}): Promise<void> {
const headingFinder = this.findByRole("heading", { name: /checkout/i });
await expect(headingFinder).toBeVisible({
...(timeoutMs !== undefined ? { timeout: timeoutMs } : {}),
});
}
public async enterCardNumber(number: string): Promise<void> {
await this.findByLabel("Card number").fill(number);
}
public async submit(): Promise<void> {
await this.findByRole("button", { name: /pay now/i }).click();
}
}
// spec:
const checkout = new CheckoutPage(page);
await checkout.navigate({ timeoutMs: 10_000 });
await checkout.waitForReady();
await checkout.enterCardNumber("4242 4242 4242 4242");
await checkout.submit();
API Reference
abstract class PageObject
abstract readonly path: stringconstructor(page: Page)navigate(options?: { timeoutMs?: number }): Promise<void>waitForReady(options?: { timeoutMs?: number }): Promise<void>— subclass overridefindByRole(role, options?)→LocatorfindByLabel(label)→LocatorfindByText(text)→Locator
Implementation Notes
navigate calls page.waitForLoadState("domcontentloaded", waitOptions) where waitOptions is undefined when no timeout is supplied and { timeout } when one is — this conditional construction is required by exactOptionalPropertyTypes which forbids passing { timeout: undefined }. The class deliberately stays small; subclass-specific assertions belong on the subclass, not baked into a common helper that tries to anticipate every scenario.
Base Class
PageObject is the minimal base class for Playwright page-object-model helpers. It carries a page: Page reference, a baseUrl: string, and exposes goto(path?) / expectVisible(locator) / expectUrlMatches(regex) helpers that every subclass uses. Subclasses narrow the locator surface to the page's specific components and keep tests focused on flows rather than selectors.