PRACTICAL GUIDE / Selenium WebElement state

WebElement State Semantics: Displayed, Enabled, Selected, and ARIA

Assert Selenium WebElement state correctly across displayed, enabled, selected, computed ARIA role, accessible name, and product-level readiness.

By The Testing AcademyUpdated July 11, 20269 min read
All field guides
In this guide13 sections
  1. Map Each Method to Its Contract
  2. Interpret isDisplayed as a Visibility Approximation
  3. Apply isEnabled to Native Enabled Semantics
  4. Restrict isSelected to Selectable Controls
  5. Assert Computed Role and Accessible Name
  6. Wait for a Domain-Specific Ready State
  7. Distinguish State from Interactability
  8. Compose State with Product Meaning
  9. Diagnose State Mismatches with a Snapshot
  10. Weigh Focused Helpers Against Hidden Assertions
  11. Cross-Binding Notes
  12. Operational Checklist
  13. Conclusion: Assert the State You Mean

What you will learn

  • Map Each Method to Its Contract
  • Interpret isDisplayed as a Visibility Approximation
  • Apply isEnabled to Native Enabled Semantics
  • Restrict isSelected to Selectable Controls

Selenium exposes several WebElement state methods, but they do not answer the same question. isDisplayed() estimates rendered visibility, isEnabled() follows enabled-state rules, isSelected() applies to selectable form controls, and computed ARIA methods describe accessibility semantics. A reliable assertion chooses the method that matches the product claim instead of treating all booleans as generic readiness.

The final business expectation usually needs more than one signal. A checkout button may need to be visible, enabled, named "Place order," and capable of producing an order. State checks establish the precondition; the user action and persistent outcome prove the workflow.

Map Each Method to Its Contract

The official Selenium element information guide documents displayed, enabled, and selected observations. It also notes that displayedness requires Selenium to make approximations rather than relying on a simple fully defined driver primitive. The WebDriver standard separately defines selection, enabled state, computed role, and computed label endpoints.

Use the narrowest question available. "Is the control rendered?" calls for displayedness. "Is this native form control disabled?" calls for enabled state. "Is this checkbox checked?" calls for selection. "What role and name are exposed to accessibility APIs?" calls for getAriaRole() and getAccessibleName().

Animated field map

WebElement State Assertion Flow

A located element is observed through rendered, interaction, and accessibility semantics before a product-specific assertion is made.

  1. 01 / web element

    Web Element

    Resolve the intended element from the current DOM and browsing context.

  2. 02 / rendered state

    Rendered State

    Observe displayedness and geometry relevant to the visible interface.

  3. 03 / interaction state

    Interaction State

    Check native enabled or selected semantics for the control type.

  4. 04 / accessibility state

    Accessibility State

    Read computed role, accessible name, and authored ARIA state.

  5. 05 / business assertion

    Business Assertion

    Act through the UI and verify the durable user-visible outcome.

Interpret isDisplayed as a Visibility Approximation

isDisplayed() answers whether Selenium considers the connected element displayed in the current browsing context. It accounts for more than one CSS declaration and is useful for waits and assertions about rendered UI. It does not prove that a user can perceive meaningful content, that the element has a useful hit area, or that another element is not covering its click point.

An element can return true while transparent content, clipping, animation, or an overlay makes interaction fail. Conversely, a hidden input associated with a styled label can be intentionally non-visible while the user-facing control is the label. Assert the element the user experiences, not whichever node is convenient to locate.

Displayedness is also momentary. If a component fades in and rerenders, a cached reference can become stale after returning true. Re-locate during a bounded wait and perform the action on the element returned by that same successful poll.

Apply isEnabled to Native Enabled Semantics

isEnabled() is most meaningful for HTML form controls whose disabled state is defined by the platform. A native button with the disabled state should report false. Ordinary elements generally report true because they do not participate in native disabled semantics.

A custom control such as <div role="button" aria-disabled="true"> can still report enabled from WebDriver's native-state perspective. aria-disabled communicates an accessibility state but does not automatically suppress click handlers or keyboard behavior. A strong test checks the authored ARIA state, verifies that activation is blocked, and asks why a native button was not used.

CSS classes such as .disabled are application conventions. Reading the class can support a narrow visual assertion, but the behavioral contract remains more important: the prohibited operation must not occur.

Restrict isSelected to Selectable Controls

The WebDriver selection command applies to checkbox and radio inputs and to option elements. On those controls, isSelected() reflects checkedness or selectedness. Use it after a user interaction and, where relevant, verify the associated application result.

ARIA widgets require different semantics. A tab may expose role="tab" and aria-selected="true", while a custom switch uses aria-checked. Calling isSelected() on a generic element does not convert those ARIA states into native selection. Read the correct ARIA attribute and verify the computed role so the assertion remains type-aware.

Java
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

static void assertSelectionSemantics(WebDriver driver) {
  WebElement newsletter = driver.findElement(By.id("newsletter"));
  assertTrue(newsletter.isSelected());
  assertEquals("checkbox", newsletter.getAriaRole());
  assertEquals("Email updates", newsletter.getAccessibleName());

  WebElement billingTab = driver.findElement(By.id("billing-tab"));
  assertEquals("tab", billingTab.getAriaRole());
  assertEquals("Billing", billingTab.getAccessibleName());
  assertEquals("true", billingTab.getDomAttribute("aria-selected"));
}

The native checkbox and custom tab deliberately use different selected-state assertions. That difference documents the platform contract instead of hiding it behind a generic helper called isActive.

Assert Computed Role and Accessible Name

getAriaRole() returns the computed WAI-ARIA role. A plain <button> can therefore report button without an explicit role attribute. getAccessibleName() returns the result of the accessible-name computation, which may derive from text, a label, aria-label, or referenced content.

This makes computed methods stronger for user-facing semantics than reading only role or aria-label. A test can verify that an icon-only control is exposed as a button named "Close dialog" regardless of which valid naming technique the component uses.

Do not over-specify implementation. If the requirement is that assistive technology receives the correct name, assert the computed name rather than demanding a particular aria-label string. If the requirement specifically concerns label wiring or attribute output, read that attribute separately.

Computed role and name are focused signals, not a replacement for an accessibility test strategy. They do not prove focus order, keyboard activation, live-region announcements, contrast, or screen-reader usability.

Wait for a Domain-Specific Ready State

Generic elementToBeClickable conditions are convenient but may not include the semantic identity your action requires. A domain wait can re-locate the button and check displayed, enabled, role, and accessible name in one poll. It should return the element that satisfied the contract.

Java
import java.time.Duration;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.support.ui.WebDriverWait;

static WebElement waitForPlaceOrder(WebDriver driver) {
  By buttonBy = By.cssSelector("[data-testid='place-order']");

  return new WebDriverWait(driver, Duration.ofSeconds(8)).until(current -> {
    try {
      WebElement button = current.findElement(buttonBy);
      boolean ready = button.isDisplayed()
          && button.isEnabled()
          && "button".equals(button.getAriaRole())
          && "Place order".equals(button.getAccessibleName());
      return ready ? button : null;
    } catch (NoSuchElementException | StaleElementReferenceException changingDom) {
      return null;
    }
  });
}

After click, wait for an order confirmation tied to the submitted data. Do not use the precondition checks as the final assertion. A button can be ready and a backend request can still fail.

Distinguish State from Interactability

WebDriver's click command performs additional work, including scrolling and hit testing. That means isDisplayed() && isEnabled() is not a complete prediction of click success. An overlay can intercept the pointer, a layout shift can move the control, or the browsing context can close between check and action.

Avoid implementing an elaborate client-side "clickable" calculation that races with the browser anyway. Establish the meaningful precondition, invoke the normal WebDriver action, and classify any interaction exception using screenshot, geometry, overlay, and DOM evidence. JavaScript click bypasses user-like interaction and should not be a default recovery.

For keyboard workflows, visible and enabled still do not prove focusability or correct key handling. Send keys through the intended focus path and assert focus and outcome separately.

Compose State with Product Meaning

A state assertion should explain why the state matters. On a consent form, a checkbox selected state proves the user's choice, while the enabled submit button proves validation has accepted required inputs. The subsequent server response or confirmation proves the choice was processed.

Avoid page objects that expose only raw booleans such as buttonIsDisplayed. Prefer domain observations like canSubmitOrder only when the method's combined contract is documented and failures report every contributing signal. Otherwise, keep direct assertions in the scenario so the expected behavior remains readable.

Negative assertions need equal care. "Delete is unavailable" may mean absent, hidden, natively disabled, aria-disabled, or blocked by authorization. Choose the one required by the design and add a behavior check for sensitive operations.

Diagnose State Mismatches with a Snapshot

When a state assertion fails, capture more than the expected boolean. Record locator, tag name, displayed, enabled, selected only when applicable, computed role, accessible name, relevant ARIA attributes, rectangle, URL, frame, and screenshot. Avoid logging sensitive input values.

If the element is stale, note that the component replaced it and capture a freshly located snapshot. If no element exists, do not report false for every state; absence is a separate condition. Good diagnostic models use not found, stale, and observed values distinctly.

Cross-browser mismatches in displayedness need controlled viewport, fonts, zoom, and animation inputs. Computed accessibility differences should be checked against valid platform semantics before forcing identical markup.

Weigh Focused Helpers Against Hidden Assertions

Small helpers can standardize repeated role-and-name checks and produce rich messages. Broad helpers that assert visibility, selection, ten ARIA attributes, CSS classes, and business output for every control create noisy failures and couple tests to implementation.

Keep immediate control contracts near component methods and scenario outcomes in the test. Use native methods for native semantics, computed methods for user-facing accessibility semantics, and raw attributes only when authored state is itself relevant.

Cross-Binding Notes

Java exposes isDisplayed, isEnabled, isSelected, getAriaRole, and getAccessibleName. Python, JavaScript, .NET, and Ruby use binding-specific naming and asynchronous patterns, but the protocol semantics are shared. Check current binding support for computed role and label rather than replacing them with raw JavaScript.

Boolean attributes may be represented as strings or null when read as DOM attributes. Keep method return types visible in assertions and avoid language truthiness that turns the string "false" into an unintended success.

Operational Checklist

  • Name the product claim before choosing a state method.
  • Use displayedness for rendered presence, not guaranteed clickability.
  • Use enabled state primarily for native form semantics.
  • Use selected state only for checkbox, radio, and option controls.
  • Read ARIA widget states through their correct attributes.
  • Assert computed role and accessible name for user-facing semantics.
  • Re-locate changing elements inside a bounded explicit wait.
  • Act on the element returned by the successful wait.
  • Verify a durable outcome after the interaction.
  • Capture distinct not-found, stale, and observed-state evidence.

Conclusion: Assert the State You Mean

WebElement state becomes reliable when every method is tied to its actual semantic boundary. Do not call visibility clickability, do not call ARIA disabledness native disabledness, and do not call a custom tab selected because isSelected() returned a boolean. Combine the right observations, perform the real user action, and close with the business outcome. Precise language in the test produces precise failures in the report.

// LIVE COURSE / THE TESTING ACADEMY

Playwright Automation Mastery

Go beyond Selenium. Master Playwright with JS/TS in 90 days.

From the instructor behind this guide.

Playwright jobs are growing 8x faster than Selenium. 90 days / 75+ live hrs / Tue-Thu-Sat 7 AM IST.

Code PROMODE / 10% offJoin the batch

The Testing Academy editorial desk

Practical QA guidance built around test evidence, production tradeoffs, and interview-ready explanations.

Published July 11, 2026 / Reviewed July 11, 2026

PRIMARY REFERENCES

Verify the details at the source

QABattle guides are practical explanations. Product behavior, standards, and APIs can change, so use these primary references for the canonical details.

  1. 01
    Selenium documentation

    Selenium Project

    Canonical WebDriver, Grid, waits, element, and browser automation guidance.

  2. 02
    WebDriver standard

    W3C

    The browser automation protocol specification behind WebDriver implementations.

  3. 03
    Web Content Accessibility Guidelines 2.2

    W3C

    The normative accessibility success criteria and conformance requirements.

  4. 04
    Evaluating web accessibility

    W3C Web Accessibility Initiative

    Official evaluation methods, tool guidance, and human review practices.

FAQ / QUICK ANSWERS

Questions testers ask

Does isDisplayed mean a Selenium element can be clicked?

No. Displayedness is one observation. The element can still be covered, outside a usable hit target, moving, or rejected by WebDriver's interaction checks.

Does aria-disabled make isEnabled return false?

Not necessarily. isEnabled follows WebDriver and HTML form-control semantics. A custom control with aria-disabled needs a separate accessibility-state assertion and behavior check.

Which elements should use isSelected?

Use it for checkbox and radio inputs and option elements. ARIA widgets such as tabs or listbox options expose selected state through ARIA attributes and require role-aware assertions.

What is the difference between getAriaRole and the role attribute?

getAriaRole returns the computed WAI-ARIA role, which can include native semantics. Reading the role attribute returns only the authored content attribute when present.

How should Selenium wait for a control to become ready?

Re-locate it inside a bounded explicit wait and check the exact contract needed by the action, such as displayed, enabled, expected role, and accessible name.