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();
}
