</>

Technology

Page Object Model

Difficulty

Intermediate

Interview Question

How do you handle dynamic elements and StaleElementReferenceException in POM?

Answer

Handling Dynamic Elements in POM

Problem: Dynamic IDs / Attributes

HTML
<!-- ID changes every page load — unusable locator -->
<button id="btn-29xk7q">Submit</button>

<!-- Use stable attributes instead -->
<button data-testid="submit-btn" class="btn-primary">Submit</button>

Stable Locator Strategies

Java
// ❌ Fragile — dynamic ID
By fragile = By.id("btn-29xk7q");

// ✅ Stable alternatives
By byTestId  = By.cssSelector("[data-testid='submit-btn']");
By byClass   = By.className("btn-primary");
By byText    = By.xpath("//button[text()='Submit']");
By contains  = By.xpath("//button[contains(text(),'Submit')]");
By startsWith = By.xpath("//button[starts-with(@id,'btn-')]");
By ancestor  = By.xpath("//div[@class='form-footer']//button");
By following = By.xpath("//label[text()='Name']/following-sibling::input");

Dynamic Table Row Locator

Java
// Find row containing specific text
public WebElement getTableRowByName(String name) {
    return driver.findElement(
        By.xpath("//table//tr[td[text()='" + name + "']]")
    );
}

// Find delete button in a specific row
public void deleteUser(String username) {
    String xpath = "//tr[td[text()='" + username + "']]//button[@data-action='delete']";
    click(By.xpath(xpath));
}

StaleElementReferenceException

Occurs when the DOM is refreshed/updated after you found an element but before you interacted with it.

Common Causes

  • Page refreshes or redirects
  • AJAX updates part of the DOM
  • Angular/React re-renders the component

Fix 1 — Re-find Element

Java
protected void clickWithRetry(By locator) {
    int attempts = 0;
    while (attempts < 3) {
        try {
            driver.findElement(locator).click();
            return;
        } catch (StaleElementReferenceException e) {
            attempts++;
            if (attempts == 3) throw e;
        }
    }
}

Fix 2 — ExpectedConditions.refreshed()

Java
protected WebElement waitForRefreshed(By locator) {
    return wait.until(
        ExpectedConditions.refreshed(
            ExpectedConditions.elementToBeClickable(locator)
        )
    );
}

// Usage
waitForRefreshed(By.id("save-btn")).click();

Fix 3 — Don't Store WebElements (Re-find Every Time)

Java
// ❌ Storing element — goes stale after DOM update
WebElement btn = driver.findElement(By.id("save-btn"));
doSomethingThatUpdatesDOM();
btn.click();   // StaleElementReferenceException!

// ✅ Find fresh every time
By saveBtn = By.id("save-btn");
driver.findElement(saveBtn);   // fresh find each time

Handling Loading Spinners / Overlays

Java
// Wait for spinner to disappear before interacting
protected void waitForSpinner() {
    By spinner = By.cssSelector(".loading-spinner");
    try {
        // Wait for spinner to appear (might miss it if fast)
        new WebDriverWait(driver, Duration.ofSeconds(2))
            .until(ExpectedConditions.visibilityOfElementLocated(spinner));
    } catch (TimeoutException ignored) {}

    // Wait for spinner to disappear
    wait.until(ExpectedConditions.invisibilityOfElementLocated(spinner));
}

// Usage in BasePage before any click
protected void click(By locator) {
    waitForSpinner();   // ensure overlay is gone
    waitForClickable(locator).click();
}

Dynamic Dropdowns (Angular/React)

Java
public void selectFromCustomDropdown(String containerSelector, String optionText) {
    // Click trigger
    click(By.cssSelector(containerSelector));

    // Wait for options panel to appear
    By options = By.cssSelector(containerSelector + " .dropdown-option");
    waitForVisible(options);

    // Click the right option
    driver.findElements(options).stream()
        .filter(el -> el.getText().trim().equals(optionText))
        .findFirst()
        .orElseThrow(() -> new NoSuchElementException("Option not found: " + optionText))
        .click();
}

Follow AutomateQA

Related Topics