Implementation:SeleniumHQ Selenium WebElement Interaction API
| Knowledge Sources | |
|---|---|
| Domains | Test_Design, Design_Patterns, Browser_Automation |
| Last Updated | 2026-02-11 00:00 GMT |
Overview
Concrete tool for interacting with DOM elements within Page Objects provided by the WebElement interface and ThreadGuard utility.
Description
The WebElement interface (in package org.openqa.selenium) extends SearchContext and TakesScreenshot, providing the core interaction methods used within Page Object method implementations. All method calls perform a freshness check to verify the element is still attached to the DOM; if not, a StaleElementReferenceException is thrown. The interface includes action methods (click(), submit(), sendKeys(), clear()), query methods (getText(), getAttribute(), getDomAttribute(), getDomProperty(), getTagName(), getCssValue(), getAriaRole(), getAccessibleName()), state methods (isDisplayed(), isEnabled(), isSelected()), geometry methods (getLocation(), getSize(), getRect()), and search methods inherited from SearchContext (findElement(), findElements()). It also provides getShadowRoot() for accessing shadow DOM.
ThreadGuard.protect() wraps a WebDriver in a JDK dynamic proxy (via java.lang.reflect.Proxy) that validates all method calls come from the thread that created the guard. The WebDriverInvocationHandler stores the creating thread's ID and name, and on every invocation checks Thread.currentThread().getId() against the stored ID. If they differ, a WebDriverException is thrown with a descriptive message identifying both threads.
Usage
Use WebElement methods within Page Object method implementations. Use ThreadGuard when running tests in parallel with shared driver instances to catch accidental cross-thread access early.
Code Reference
Source Location
- Repository: Selenium
- File: java/src/org/openqa/selenium/WebElement.java (L32-335)
- File: java/src/org/openqa/selenium/support/ThreadGuard.java (L42-102)
Signature
public interface WebElement extends SearchContext, TakesScreenshot {
// Action methods
void click();
void submit();
void sendKeys(CharSequence... keysToSend);
void clear();
// Query methods
String getTagName();
@Nullable String getAttribute(String name);
default @Nullable String getDomAttribute(String name);
default @Nullable String getDomProperty(String name);
String getText();
String getCssValue(String propertyName);
default @Nullable String getAriaRole();
default @Nullable String getAccessibleName();
// State methods
boolean isSelected();
boolean isEnabled();
boolean isDisplayed();
// Geometry methods
Point getLocation();
Dimension getSize();
Rectangle getRect();
// Search methods (inherited from SearchContext)
WebElement findElement(By by);
List<WebElement> findElements(By by);
// Shadow DOM
default SearchContext getShadowRoot();
}
public class ThreadGuard {
public static WebDriver protect(WebDriver actualWebDriver);
// Returns proxy that throws WebDriverException if called from wrong thread
}
Import
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ThreadGuard;
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| keysToSend | CharSequence... | Yes (for sendKeys) | Text to type or Keys enum values; throws IllegalArgumentException if null |
| name | String | Yes (for getAttribute/getDomAttribute/getDomProperty) | Attribute or property name to retrieve |
| propertyName | String | Yes (for getCssValue) | CSS property name (use longhand, not shorthand) |
| by | By | Yes (for findElement/findElements) | Locator strategy for sub-element search |
| actualWebDriver | WebDriver | Yes (for ThreadGuard.protect) | WebDriver instance to wrap with thread-safety proxy |
Outputs
| Name | Type | Description |
|---|---|---|
| getText() | String | Visible text of the element (not hidden by CSS), including sub-elements |
| getAttribute() | String or null | Value of attribute/property; returns null if not set |
| getDomAttribute() | String or null | Value of the DOM attribute only (not JavaScript property) |
| getDomProperty() | String or null | Value of the DOM property only (not HTML attribute) |
| getTagName() | String | HTML tag name (e.g., "input", "div", "button") |
| getCssValue() | String | Computed CSS value (e.g., "rgba(0, 255, 0, 1)") |
| isDisplayed() | boolean | Whether element is visible on the page |
| isEnabled() | boolean | Whether element is interactable (not disabled) |
| isSelected() | boolean | Whether checkbox/radio/option is selected |
| getLocation() | Point | Top-left corner coordinates |
| getSize() | Dimension | Width and height |
| getRect() | Rectangle | Combined location and size |
| ThreadGuard.protect() | WebDriver | Proxied WebDriver with thread-safety enforcement |
Exceptions
| Exception | Condition |
|---|---|
| StaleElementReferenceException | Element is no longer attached to the DOM |
| NoSuchElementException | Element not found (for findElement) or form not found (for submit) |
| IllegalArgumentException | keysToSend is null (for sendKeys) |
| WebDriverException | ThreadGuard detects cross-thread access |
Usage Examples
Page Object with Interaction Methods
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
public class LoginPage {
private WebDriver driver;
@FindBy(id = "username")
private WebElement usernameInput;
@FindBy(id = "password")
private WebElement passwordInput;
@FindBy(css = "button[type='submit']")
private WebElement submitButton;
@FindBy(css = ".error-message")
private WebElement errorMessage;
public LoginPage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
// Domain-specific method returning another Page Object
public DashboardPage login(String username, String password) {
usernameInput.clear();
usernameInput.sendKeys(username);
passwordInput.clear();
passwordInput.sendKeys(password);
submitButton.click();
return new DashboardPage(driver);
}
// Query method returning data for test assertions
public String getErrorMessage() {
return errorMessage.getText();
}
// State query method
public boolean isSubmitEnabled() {
return submitButton.isEnabled();
}
}
ThreadGuard for Parallel Tests
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ThreadGuard;
// Wrap driver creation with ThreadGuard
WebDriver driver = ThreadGuard.protect(new ChromeDriver());
// Any call from a different thread will throw WebDriverException:
// "Thread safety error; this instance of WebDriver was constructed on
// thread main (id 1) and is being accessed by thread Thread-2 (id 15)
// This is not permitted and *will* cause undefined behaviour"
public class CartPage {
private WebDriver driver;
@FindBy(id = "checkout-btn")
private WebElement checkoutButton;
@FindBy(css = ".cart-item")
private List<WebElement> cartItems;
public CartPage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
public CheckoutPage proceedToCheckout() {
checkoutButton.click();
return new CheckoutPage(driver);
}
public int getItemCount() {
return cartItems.size();
}
public String getItemName(int index) {
return cartItems.get(index).getText();
}
}