Dynamic content and waiting
IntermediateElements that appear late, disappear, or are replaced after a refresh, plus an element whose id changes on every load.
Practice area
1. Loading, then result
The result is not in the page until about 3 seconds after you click.
2. Element that appears after a random delay (1 to 4 s)
3. A list that is replaced on refresh
The whole list is re-created, so references to old items go stale.
- Alpha
- Bravo
- Charlie
4. An id that changes on every page load
Tasks to automate
- Click Start and wait for the loaded message to appear without using a fixed sleep.
- Wait for the spinner to disappear, then assert the result.
- Click Refresh list, keep a reference to an item from before, and see the stale element error. Then fix the test.
- Find the element with the changing id using its data-testid instead.
- Assert that the delayed element appears within 5 seconds, and fails the test if it takes longer.
Model solutions
Try the tasks first. These show one good way, not the only way.
Selenium (Java)
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(8));
driver.findElement(By.id("pg-start")).click();
String text = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("pg-loaded"))).getText();
// Stale element: locate again after the list is re-rendered
driver.findElement(By.id("pg-refresh")).click();
wait.until(d -> d.findElements(By.cssSelector("li.pg-item")).size() == 3);
String first = driver.findElement(By.cssSelector("li.pg-item:first-child")).getText();
// The id changes on every load; the test id does not
driver.findElement(By.cssSelector("[data-testid='pg-random-id']")).click();
Playwright (TypeScript)
await page.locator('#pg-start').click();
await expect(page.locator('#pg-loaded')).toBeVisible({ timeout: 8000 });
await page.locator('#pg-refresh').click();
await expect(page.locator('li.pg-item')).toHaveCount(3); // locators re-query on every use, so no stale elements
await page.getByTestId('pg-random-id').click();
Element IDs on this page are stable and will not change. Nothing you do here is sent to a server.
