Querying with Find
The find
method ofPlaywrightContext
is your primary vechicle for querying elements within a page. As its base, it uses Playwright's built-in page.locator. This provides a very powerful way to query for an element on the page with various types of selectors.
Here is a basic example, using a CSS selector to pick a text box named password:
const passwordInput = context.find('input[name="password"]');
Supported selectors include:
- Simple Text -
context.find('"Hello World"')
- CSS -
context.find('h1.main')
- XPath -
context.find('xpath=//button')
- React
- Vue
You do not need to await
the find
method, and you can create the selector before the element is present on the page. It returns a PlaywrightValue
object, which contains an internal reference to the selector. This can be used later to do something with that element (like click it), query against for children, or make assertions about it.
Examples:
const searchInput = context.find('input[name="search_term"]');
const submitButton = context.find('button[type="submit"]');
const listItem = context.find("ui li");
You can also chain additional arguments within a find
query, which are considered sub-queries. For example:
const checkedInputs = context.find("input", ":checked");
This isn't actually different than simply using it as a single CSS selector like this:
const checkedInputs = context.find("input:checked");
However, the power of this chaining will become evident as you read further sections of this documentation.
Naming the Element
The PlaywrightValue
returned by find
not only contains the internal selector, but also has a name that will be used in any assertions against it. QA Flag will do its best to automatically give it a decent name. However, sometimes you may want to explicitly assign it a human-readable name so your logs make more sense.
For this we'll use the as
method:
const logo = context.find("img.logo").as("Site Logo");
const submitButton = context.find('button[type="submit"]').as("Search Button");
Matching multiple elements
It's important to note that the selector you pass to find
may returned multiple matches. So think of it like an array of matches. When you take an action or make an assertion it will do it against the first match... unless you specifically tell it otherwise.
Let's talk about ways to do that. We'll use this example:
// This may return multiple values that matched the <li> tag
const listItems = context.find("li");
// The click will happen against the first match
await listItems.mouse.click();
Getting the first, last, or nth item
Maybe you want to select only one of the items. Easy!
const firstItem = listItems.first;
const lastItem = listItems.last;
const fifthItem = listItems.nth(4); // Zero-based
This does not need to be awaited because it is just returning another locator. You don't necessarily need to save them to their own const
. You can simply assert against them directly like this.
await context.find("li").first.must.be.visible();
Or perform an action against the last one.
await context.find("li").last.mouse.click();
Count the matches
If you want to know how many matched, use count()
to give you a new NumericValue
with that result. This must be awaited since we must go to the browser to look it up.
const itemCount = await listItems.count();
So we can assert against the result.
itemCount.must.be.greaterThan(0);
Notice that I didn't have to await
this assertion. The count()
method returned a NumericValue
and not a PlaywrightValue
. We only need to await things that have to go to the browser do to work. Since we already awaited
the count on the previous example, now we're just asserting against that number.