Extract values from the DOM

Read data out of the page so you can assert on values you don't know up front.

The matchers from the last two lessons cover the common case: locate something, assert on it directly. They compare against something you already know: a fixed string, a count, a role.

Often you don't know the value up front. You click a random product and need to confirm that same product shows up in the cart. You sort by price and need to verify the order. The value only exists at runtime, so read it off the page first, then assert on it.

Extract a single value

locator.innerText() reads the visible text of a single element. It's the one I reach for most often.

const productHeading = page.getByRole("heading", { level: 2 });const productName = await productHeading.innerText();const cartContainer = page.getByTestId("cart");await expect(cartContainer.getByText(`1x, ${productName}`)).toBeVisible();

productName carries the value across pages so you don't have to hard-code it.

Warning

Unlike web-first assertions, innerText() and friends do not auto-wait. They snapshot the DOM at the moment you call them. Make sure the elements are settled first (typically by awaiting an assertion on the parent or by awaiting a navigation).

Three more readers handle values innerText doesn't see. textContent returns everything in the source: hidden text, raw whitespace, etc. Given const heading = page.getByRole("heading", { name: "Online" }):

<h3>
Online
<span hidden>(maintenance soon)</span>
</h3>
heading.innerText()
"Online"

Visible text only, whitespace collapsed.

heading.textContent()
"\nOnline\n(maintenance soon)\n"

Raw markup, hidden text and whitespace included.

Form fields don't have inner text. Reach for inputValue to read what's currently in the field. Given const search = page.getByLabel("Search"):

<input aria-label="Search" value="snowboards" />
search.inputValue()
"snowboards"

Reflects what's typed, not the static `value` attribute.

Use getAttribute for anything stored in an attribute: href, data-*, aria-label, alt, etc. Given const link = page.getByRole("link", { name: "Snowboard X" }):

<a href="/products/snowboard-x">
Snowboard X
</a>
link.getAttribute("href")
"/products/snowboard-x"

Any attribute by name. Returns null if it isn't set.

Extract many values

For locators that match multiple elements, use allInnerTexts or allTextContents.

// grab every price on the page
const allPrices = await page.getByTestId("price").allInnerTexts();
// ["100.00", "250", "1234", ...]

Let's see what we can extract!


Hands on

Practice extracting values

Exercise 1 of 2

Verify price sorting works

sorting

  1. Click on the top-left Products link.
  2. Sort the products by price (ascending, then descending).
  3. Read all visible prices and assert the order is correct using the helpers above.

Here are some helper methods:

const isSortedAsc = (arr) =>
  arr.every((element, index, array) => !index || +array[index - 1] <= +element);
const isSortedDesc = (arr) =>
  arr.every((element, index, array) => !index || +array[index - 1] >= +element);
Exercise 2 of 2

Validate your add-to-cart flow

  1. Take your previously recorded add to cart test.
  2. Read each product's name and price from the product detail page using innerText.
  3. Assert the cart contains the correct items by name.
  4. Tip: look out for data-testid attributes. They make extraction easier.