LocatorQueryBuilder
getLocatorSchema(path) returns a LocatorQueryBuilder: a private copy of the path’s chain that you change for one
use and then resolve. Its methods change this query and return it; the registry never changes.
The examples on this page use this registry:
import type { LocatorRegistry } from "pomwright";
export type Paths = "main" | "main.list" | "main.list.item" | "main.button@save";
export function defineLocators(registry: LocatorRegistry<Paths>) { registry.add("main").locator("main"); registry.add("main.list").locator("ul").filter({ hasText: "Orders" }); registry.add("main.list.item").locator("li").nth(0); registry.add("main.button@save").getByRole("button", { name: "Save", exact: true });}const lastOpenOrder = registry .getLocatorSchema("main.list.item") .clearSteps() .filter({ hasText: "Open" }) .nth("last") .getNestedLocator();// locator('main').locator('ul').filter({ hasText: 'Orders' }).locator('li').filter({ hasText: 'Open' }).last()A method that takes a subPath works on that segment of the query’s chain: the path itself or one of its registered
ancestors. Without one it works on the path itself. Guide: queries.
Methods
Section titled “Methods”clearSteps()
Section titled “clearSteps()”Removes the filter and nth steps of a segment in this query; its definition and description stay.
Usage
registry.getLocatorSchema("main.list.item").clearSteps().getNestedLocator();// locator('main').locator('ul').filter({ hasText: 'Orders' }).locator('li')
registry.getLocatorSchema("main.list.item").clearSteps("main.list").getNestedLocator();// locator('main').locator('ul').locator('li').first()Arguments
-
subPathstring (optional)The segment. Defaults to the query’s path.
Returns
- LocatorQueryBuilder
describe()
Section titled “describe()”Sets the description of the resolved locator for this query; "" removes it. See
the description.
Usage
registry.getLocatorSchema("main.list.item").describe("First order").getNestedLocator();Arguments
-
descriptionstringApplies to the path itself; ancestors’ descriptions never show.
Returns
- LocatorQueryBuilder
filter()
Section titled “filter()”Adds a locator.filter() step to a segment, after
its registered steps.
Usage
registry.getLocatorSchema("main.list.item").filter({ hasText: "#1042" }).getNestedLocator();registry.getLocatorSchema("main.list.item").filter("main.list", { hasText: "Open" }).getNestedLocator();Arguments
-
subPathstring (optional)The segment. Defaults to the query’s path.
-
filterFilterDefinitionPlaywright’s filter options.
hasandhasNotalso take a registered path, resolved to that path’s own locator, without its ancestors.
Returns
- LocatorQueryBuilder
Throws
On a frameLocator() without a selector, which has no element:
filter() cannot apply to "anyFrame": frameLocator() without a selector has no element to filter, index or describe; resolve a path inside it.getLocator()
Section titled “getLocator()”Resolves the query’s path alone, with its steps and description, as
LocatorRegistry.getLocator() does; changes to ancestors and
skipped ancestors make no difference to it.
Usage
registry.getLocatorSchema("main.list.item").nth("last").getLocator();// locator('li').first().last()Returns
getNestedLocator()
Section titled “getNestedLocator()”Resolves the query’s chain: every registered segment that is not skipped, first to last, each with its steps, as
LocatorRegistry.getNestedLocator() does.
Usage
registry.getLocatorSchema("main.list.item").getNestedLocator();// locator('main').locator('ul').filter({ hasText: 'Orders' }).locator('li').first()Returns
Adds an index step to a segment, after its registered steps: "first" and "last" become
first() and
last(), a number goes to
nth() as given (-1 is the last element).
Usage
registry.getLocatorSchema("main.list.item").clearSteps().nth(2).getNestedLocator();// locator('main').locator('ul').filter({ hasText: 'Orders' }).locator('li').nth(2)The registered nth(0) stays unless cleared; see steps.
Arguments
-
subPathstring (optional)The segment. Defaults to the query’s path.
-
indexnumber | “first” | “last”
Returns
- LocatorQueryBuilder
Throws
On a frameLocator() without a selector, which has no element:
nth() cannot apply to "anyFrame": frameLocator() without a selector has no element to filter, index or describe; resolve a path inside it.replace()
Section titled “replace()”Replaces a segment’s definition for this query with one of any strategy, with Playwright’s arguments; its steps and description stay. Returns an update builder. See a new definition.
Usage
registry.getLocatorSchema("main.list.item").replace("main.list").getByRole("list", { name: "Orders" }).getNestedLocator();// locator('main').getByRole('list', { name: 'Orders' }).filter({ hasText: 'Orders' }).locator('li').first()Arguments
-
subPathstring (optional)The segment. Defaults to the query’s path.
Returns
Throws
getByRole requires a role value for "main.button@save".replace() cannot apply to "main.list": it has filter or nth steps, and frameLocator() without a selector takes none; call clearSteps("main.list") first.The first from JavaScript, where a missing first argument is not a compile error; the second for frameLocator()
without a selector on a segment that has steps.
skip()
Section titled “skip()”Leaves an ancestor out of the chain when this query resolves; unskip() brings it back as it was. See
leaving an ancestor out.
Usage
registry.getLocatorSchema("main.list.item").skip("main.list").getNestedLocator();// locator('main').locator('li').first()Arguments
-
subPathstringA registered ancestor of the query’s path; the path itself cannot be skipped.
Returns
- LocatorQueryBuilder
Throws
A change to a skipped segment and a second skip of it throw at the call, and so does skipping the query’s own path
(from JavaScript):
filter() cannot apply to "main.list": it is skipped in this query; call unskip("main.list") first.skip() cannot skip "main.list": it is already skipped in this query.skip() cannot skip "main.list.item": it is the path this query resolves; skip one of its ancestors.unskip()
Section titled “unskip()”Puts a segment left out with skip() back into the chain, with everything it had.
Usage
const query = registry.getLocatorSchema("main.list.item").skip("main.list");query.unskip("main.list").getNestedLocator();// locator('main').locator('ul').filter({ hasText: 'Orders' }).locator('li').first()Arguments
-
subPathstringA segment skipped in this query.
Returns
- LocatorQueryBuilder
Throws
unskip() cannot unskip "main.list": it is not skipped in this query.update()
Section titled “update()”Patches a segment’s definition for this query and keeps its strategy; its steps and description stay. Returns an update builder. See patching a definition.
Usage
registry.getLocatorSchema("main.button@save").update().getByRole({ name: "Cancel" }).getNestedLocator();// locator('main').getByRole('button', { name: 'Cancel', exact: true })
registry.getLocatorSchema("main.button@save").update().getByRole("button", null).getNestedLocator();// locator('main').getByRole('button')Arguments
-
subPathstring (optional)The segment. Defaults to the query’s path.
Returns
Throws
update("main.button@save") cannot change the strategy from "role" to "locator"; use replace("main.button@save").locator(…) instead.Errors of every method
Section titled “Errors of every method”A subPath outside the query’s chain, or a segment of it without a locator, throws at the call:
"main.button@save" is not a valid sub-path of "main.list.item"."main.form" is not a valid sub-path of "main.form.button@save". It is a segment of that path, but no locator schema is registered for it.