Mental Model & Core Concepts
Relevant source files
The following files were used as context for generating this wiki page:
The playwright-page-object library provides a decorator-driven layer for Playwright that transforms raw page.locator() chains into a typed, composable control graph. Its primary purpose is to centralize selector logic, reduce duplication, and allow for incremental adoption of the Page Object Model (POM) within existing Playwright test suites.
Sources: README.md:1-12, package.json:4-6
The core mental model treats the library as a locator composition layer rather than a mandatory inheritance framework. It relies on three primary pillars: establishing locator context via root decorators, resolving relative selectors via child decorators, and determining the result shape based on accessor types.
Sources: skills/playwright-page-object/SKILL.md:15-20, README.md:65-80
Architecture & Data Flow
The system operates as a lazy control graph. Locators are not resolved when the class is instantiated; instead, they are built dynamically when an accessor is first called. This ensures that the selector chain always reflects the current state of the DOM and the hierarchy of the page objects.
The diagram above shows how decorators establish a hierarchy where child selectors are always resolved relative to their nearest parent root.
Sources: README.md:19-25, skills/playwright-page-object/SKILL.md:38-45
Key Components
1. Root Decorators
Root decorators bind a class to a top-level locator context. For plain classes, the decorator expects the first constructor argument to be a Playwright Page. For classes extending the built-in RootPageObject, this context is handled automatically.
Sources: README.md:82-88, src/tests/decorators/rootSelectors.spec.ts:50-60
2. Child Decorators
Child decorators resolve locators relative to the context provided by the root. Common variants include @Selector (test ID based), @SelectorByRole, and @SelectorByText. These decorators use the ECMAScript accessor keyword.
Sources: README.md:118-125, src/tests/decorators/selectors.spec.ts:80-95
3. Result Shapes
The library is "output agnostic," meaning a decorated accessor can return different types based on how it is declared or initialized:
| Result Type | Implementation | Best Use Case |
|---|---|---|
Locator | Declared as accessor name!: Locator | Direct Playwright API access with no abstraction. |
| External Control | Constructor/Factory passed to decorator | Custom logic without library inheritance. |
PageObject | Initialized as new PageObject() | Access to built-in waits, assertions, and $ helper. |
ListPageObject | Initialized as new ListPageObject() | Collections, async iteration, and filtering. |
Sources: README.md:105-115, skills/playwright-page-object/SKILL.md:22-30
Control Composition & Nesting
When nesting controls, specifically when using the built-in PageObject classes, the library uses a "cloning" mechanism. When a decorated property is accessed, the child object is cloned with the current root and selector context.
This sequence ensures that even if a child control is defined once as a property, every access provides a fresh instance correctly bound to its parent's current locator state.
Sources: src/page-objects/PageObject.ts:114-124, src/tests/page-objects/PageObject.spec.ts:106-120
Built-in POM Helpers
The PageObject and RootPageObject classes provide a set of convenience methods to simplify common testing tasks.
Wait Helpers and Assertions
Instead of writing manual expect(locator).toBeVisible(), the PageObject class encapsulates these into methods that leverage Playwright's web-first assertions.
- Wait Methods:
waitVisible(),waitHidden(),waitText(text),waitCount(n),waitProp(name, value). - Assertions: The
.expect()method returns the standard Playwrightexpect(locator)object, allowing for full assertion chains. It also supports soft assertions via.expect({ soft: true }).
Sources: src/page-objects/PageObject.ts:130-221, README.md:188-210
List Handling
The ListPageObject is specifically designed for repeated elements. It provides a proxy through the .items property to support array-like access and async iteration.
Summary
The playwright-page-object framework centers on a decorator-driven locator context. By establishing a root and resolving children relatively, it creates a typed tree of components. This architecture allows developers to choose their level of abstraction—ranging from raw locators to complex, self-contained page objects—while maintaining a clean, lazy-loading data flow that integrates directly with Playwright's native locator system.
Sources: README.md:14-30, skills/playwright-page-object/SKILL.md:10-20