How to grab an element with dynamic data
  • 20 Jun 2022
  • 2 Minutes to read
  • Contributors
  • Dark
    Light

How to grab an element with dynamic data

  • Dark
    Light

This is a troubleshooting guide for "Element not found" errors where the target element has data/text that is different from when the scenario was recorded.

On this page, you'll learn how to stabilize your test execution against dynamic data.

Cause

During test execution, the test execution engine sees the element's inner text to check if the element is the same as the recorded one.
Although the element's identity is not solely determined by the text or data within it, dynamic data such as dates, names, and email addresses can cause an "Element not found" error.

Solutions

1. Use a CSS selector

Using a CSS selector is the quickest workaround.
Let's take a look at an example.
In the screenshot below, we can see that the latest article is displayed at the top half of the page. When a new article is created, the title, date, and author will change, and older articles are moved down to the card-like list on the bottom half of the page.

newest-title

To make sure that the title of the newest article was clicked, you can specify it like this:

div.LatestPost h1

dynamic-data-css-selector-example

(To learn CSS selector basics, please see Using CSS selectors effectively)

2. Update your website's structure

The test execution engine uses information in HTML to identify elements.
You can make your tests more stable by making each element more unique.
The most common fix is replacing general-purpose elements such as span, div with something more meaningful ("semantic" in technical terms).

Here are two examples:

❌ HTML structure with less clues

<div>
    <div>
        <div class="bold big">This is the page title</div>
        <div>
            Date: <span class="gray small">Jan 1, 2021</span>
        </div>
        <div>John</div>
    </div>
</div>

✅ HTML structure with more clues

<main>
    <article>
        <h1>This is the page title</h1>
        <p id="posted-at" aria-label="date" >
            Date: <time datetime="2021-01-01">Jan 1, 2021</time>
        </p>
        <p id="written-by" aria-label="author">John</p>
    </article>
</main>

Going back to the first example of our blog page, you can grab the title of the latest article without a CSS selector, even if a new article comes up.
The title of the latest article is h1, i.e., the top-level header of the page, whereas the titles of older articles are h3. The test execution engine can use this difference to distinguish which title is that of the latest article.

no-css-selector.png

It may not be a low-cost solution to improve the structure of your website to make it more meaningful. However, it's worth trying, especially if you cannot find an effective CSS selector.

Use a JS Step

You can query an element that has expected text like below:

const expectedText = "Dec 15, 2021";
const allSpanElementsInPage = document.querySelectorAll("span");

// You need to convert the NodeList returned by querySelector to an Array
// to use the filter method.
const filteredElements = Array.from(allSpanElementsInPage).filter(
    (el) => {
        return el.innerText === expectedText;
    }
);

if (filteredElements.length === 1) {
    // Perform action as needed. For example, clicking.
    filteredElements[0].click();
} else if (filteredElements.length === 0) {
   throw new Error("No elements found with JS")
} else {
   throw new Error(`Could not determine single element. ${filteredElements.length} found.`)
}

First name must have atleast 2 characters. Numbers and special characters are not allowed.
Last name must have atleast 1 characters. Numbers and special characters are not allowed.
Enter a valid email
Enter a valid password
Your profile has been successfully updated.