PageObject
PageObject is the base class for nested controls. Use it as the initializer for a decorated accessor:
@Selector("PromoCode")accessor PromoCode = new PageObject();For root-level page objects, use RootPageObject instead.
Instance members
Section titled “Instance members”.$
The raw Playwright Locator bound to this control’s resolved chain.
await checkout.PromoCode.$.fill("SAVE20");await checkout.PromoCode.$.click();Use whenever a built-in wait helper does not cover your case.
A getter that returns the underlying Page instance.
const page = checkout.PromoCode.page;await page.keyboard.press("Escape");.expect(options?)
Section titled “.expect(options?)”Returns Playwright’s assertion API on .$. Accepts the same options as Playwright’s expect:
await control.expect().toBeVisible();await control.expect({ soft: true }).toHaveText("Click me");await control.expect({ message: "Apply must be enabled" }).toBeEnabled();Wait helpers
Section titled “Wait helpers”| Method | Accepts |
|---|---|
waitVisible() | — |
waitHidden() | — |
waitText(text) | string | RegExp |
waitValue(value) | string | RegExp | number |
waitCount(count) | number |
waitChecked() | — |
waitUnChecked() | — |
await control.waitVisible();await control.waitText("Applied");await control.waitText(/applied/i);await control.waitValue(42); // coerced to "42"waitValue accepts number and coerces with String(value) for convenience. Pass a RegExp for pattern matching.
Subclassing
Section titled “Subclassing”For typed nested children, extend PageObject and add decorated accessors:
class CartItemControl extends PageObject { @Selector("Name") accessor Name = new PageObject();
@SelectorByRole("button", { name: "Remove" }) accessor RemoveButton = new PageObject();
async remove() { await this.RemoveButton.$.click(); }}Use the subclass as an initializer:
@Selector("CartItem_1")accessor FirstItem = new CartItemControl();cloneWithContext for custom constructors
Section titled “cloneWithContext for custom constructors”If your subclass has constructor arguments beyond the default, override cloneWithContext(root, selector). The library calls this on every access to bind the instance to its parent’s resolved scope.
class TimedItem extends PageObject { constructor(readonly timeout: number) { super(); }
cloneWithContext(root, selector) { const next = new TimedItem(this.timeout); return next.attach(root, selector); }}Most users do not need this — the default cloneWithContext covers the no-arg constructor case.
Static guards
Section titled “Static guards”| Static | Returns |
|---|---|
PageObject.isClass(v) | true if v is a class extending PageObject |
PageObject.isInstance(v) | true if v is an instance of PageObject |
Used internally and exposed for advanced use cases (e.g., generic helpers that inspect accessor types).
See also
Section titled “See also”- RootPageObject — the root variant.
- ListPageObject — for repeated children.
- Built-In POM guide — walkthrough.