WebElement State, Interactions, Forms, and Validation: Core Concepts and Mental Model
Build a precise WebElement mental model: presence, displayed/enabled/selected state, attributes versus DOM properties, user-like interaction commands, form-control semantics, and observable application outcomes.
Learning objectives
- Distinguish element presence from displayed, enabled, selected, and application-valid state.
- Explain why a WebElement is a session-scoped reference to a current DOM node rather than a durable copy of markup.
- Differentiate declared HTML attributes, runtime DOM properties, and Selenium’s convenience get_attribute behavior.
- Explain click, send_keys, clear, checkbox/radio/select, and form submission as browser-mediated interactions with preconditions.
- Separate “Selenium issued a command” from “the application reached the intended observable outcome.”
- Record read-only session, URL, capability, element-state, and form-state evidence before mutation.
1. The command is not the outcome
Chapter 04 established how a locator produces a WebElement reference. Chapter 05 asks the next operational question: what does that element mean right now, and what should happen when a user-like interaction is applied? A located input can be present but hidden, visible but disabled, enabled but covered by another element, selected but invalid for the business rule, or replaced by a rerender after you captured its reference.
Reliable UI tests therefore separate three layers:
element state,
browser interaction semantics, and
application outcome. A passing
click() only proves that WebDriver completed the click
command. It does not prove that inventory changed, a form was
accepted, a confirmation appeared, or a release requirement was
satisfied.
2. From locator to application outcome
The following diagram visualizes the relationships described in From locator to application outcome. Read the nodes in sequence and use the arrows to connect the conceptual state changes to the explanation around the diagram.
flowchart TD L[Locator] --> E[WebElement reference] E --> S[Current element state] S --> C[WebDriver interaction command] C --> B[Browser event + default behavior] B --> A[AUT state transition] A --> O[Observable outcome] O --> V[Assertion + evidence]
The locator selects a node. The WebElement is a protocol-backed reference to that node in one WebDriver session. State queries read the node as it exists now. Interaction commands ask the browser to perform user-like actions subject to WebDriver preconditions such as interactability. Browser events and native form behavior then drive the application. The final assertion should observe the state that expresses test intent.
This model also explains why stale references exist. If a framework rerenders the control and replaces the DOM node, the old WebElement still identifies the old node reference. The correct action is usually to reacquire the element from the current DOM, not to retry an obsolete reference blindly.
3. Presence, displayed, enabled, selected, and valid are different facts
The following table organizes the key choices and evidence for Presence, displayed, enabled, selected, and valid are different facts. Use it together with the surrounding prose so the rows serve as a comparison aid rather than standalone rules.
| Question | Selenium/browser signal | What it does not prove |
|---|---|---|
| Does a node match the locator? |
find_element / find_elements
|
That the user can see or operate it |
| Is it displayed? | is_displayed() |
That it is enabled, unobscured, or business-valid |
| Is it enabled? | is_enabled() |
That a click target is unobscured or that submission will succeed |
| Is it selected? | is_selected() |
That the overall form/application state is valid |
| Is the control HTML-valid? | DOM property such as validity.valid |
That the server/application accepted the request |
| Did the application succeed? | Status text, resulting page/state, backend test fixture evidence | That every intermediate UI state was ideal |
These facts are intentionally independent. A checkbox can be displayed and enabled but not selected. A required email field can be displayed and enabled but invalid. A submit button can be enabled while a client-side validator later blocks submission. Treating “element exists” as a proxy for all other state collapses the evidence you need for diagnosis.
4. Attributes and runtime DOM properties are not interchangeable
HTML attributes are values declared in markup, such
as value="seed" or checked. DOM
properties are runtime JavaScript-facing values
such as an input element’s current value or
checked boolean. User input commonly changes the
property without rewriting the original HTML attribute.
<input id="nickname" value="seed">
<input id="terms" type="checkbox" checked>
The following example makes the Attributes and runtime DOM properties are not interchangeable behavior concrete. Read it with the stated assumptions, then compare its observable output or state changes with the explanation that follows.
nickname = driver.find_element(By.ID, "nickname")
print("declared value attribute:", nickname.get_dom_attribute("value"))
print("runtime value property:", nickname.get_property("value"))
nickname.clear()
nickname.send_keys("Ada")
print("after typing, DOM attribute:", nickname.get_dom_attribute("value"))
print("after typing, property:", nickname.get_property("value"))
# get_attribute() is a convenience API: property first, then attribute.
print("convenience value:", nickname.get_attribute("value"))
get_dom_attribute() or get_property() when
you need an exact distinction.
5. WebDriver interaction commands are browser-mediated
Selenium documents a small set of high-level element interactions: click, send keys, clear, form submission behavior, and select-list support. These are deliberately closer to user behavior than assigning JavaScript properties directly. WebDriver may scroll an element into view and checks whether an element is interactable before performing an action.
A click targets the element center. If another element obscures that
point, WebDriver can raise
ElementClickInterceptedException. Sending keys requires
a keyboard-interactable/editable target; an unsuitable element can
produce invalid-element-state behavior. Those errors are valuable
evidence because they tell you the browser could not perform the
user action as modeled.
name = driver.find_element(By.ID, "name")
name.clear()
name.send_keys("Ava Example")
newsletter = driver.find_element(By.ID, "newsletter")
if not newsletter.is_selected():
newsletter.click()
submit = driver.find_element(By.ID, "submit")
assert submit.is_displayed() and submit.is_enabled()
submit.click()
6. Form controls have semantics worth preserving
Checkboxes, radio buttons, text inputs, and native select lists are
not generic clickable rectangles. Their browser semantics carry
state and accessibility information. Use
is_selected() for selection state, normal click for
checkboxes/radios, and Selenium’s Select helper only
for a real HTML <select>. A custom JavaScript
dropdown made from <div> or
<li> elements must be automated according to its
actual DOM and interaction contract.
from selenium.webdriver.support.ui import Select
role = Select(driver.find_element(By.ID, "role"))
role.select_by_value("developer")
assert role.first_selected_option.get_attribute("value") == "developer"
terms = driver.find_element(By.ID, "terms")
assert not terms.is_selected()
terms.click()
assert terms.is_selected()
7. Inspect before mutation
Before changing form state, record enough read-only evidence to distinguish an environment problem from an interaction problem. The following inspection does not type, click, submit, or alter storage.
import selenium
from selenium.webdriver.common.by import By
print("selenium", selenium.__version__)
print("session", driver.session_id)
print("browser", driver.capabilities.get("browserName"), driver.capabilities.get("browserVersion"))
print("url", driver.current_url)
print("title", driver.title)
email = driver.find_element(By.ID, "email")
print("displayed", email.is_displayed())
print("enabled", email.is_enabled())
print("selected", email.is_selected())
print("declared-required", email.get_dom_attribute("required"))
print("runtime-value", email.get_property("value"))
If the wrong URL or fixture build is loaded, fix that boundary before changing element code. If the element is present but disabled or hidden, preserve that fact. If it is interactable but the application outcome is wrong, the failure belongs farther downstream in the model.
8. Production rule: assert the outcome, keep the state evidence
A durable browser test normally uses element-state assertions as preconditions and diagnostics, then asserts a meaningful application-visible result after interaction. This keeps failures precise without confusing “the button was enabled” with “the business operation succeeded.”
Knowledge check
Why is “the element exists” insufficient before interaction?
Presence does not prove displayed, enabled, unobscured, editable, selected, or business-valid state.
What is the practical difference between get_dom_attribute("value") and get_property("value") on a text input?
The DOM attribute reflects the value declared in markup, while the property reflects the runtime value the browser currently uses; user typing can change the property without changing the declared attribute.
What does a successful click() prove?
It proves WebDriver completed the click command under its interaction semantics. The test must separately verify the intended application outcome.
Why should a custom div-based dropdown not use Selenium Select?
Select is designed for real HTML select/option elements. A custom widget has different DOM and interaction semantics.
A button is displayed and enabled but click raises ElementClickInterceptedException. What should you inspect first?
Preserve evidence and inspect what obscures the clickable center—such as an overlay—rather than forcing a JavaScript click.
Official references and version notes
- Selenium 4.47 release — current pinned Selenium release baseline for this chapter.
- Interacting with web elements — click, send keys, clear, interactability checks, and click-interception semantics.
- Information about web elements — displayed, enabled, selected, text, CSS, and attribute/property inspection.
-
Python WebElement API 4.47.0
— current
get_dom_attribute,get_property,get_attribute, interaction, and state-query APIs. -
Working with select list elements
— current support-library semantics for real HTML
<select>controls.
Version-sensitive behavior was rechecked against Selenium primary documentation on 2026-08-28. Mandatory examples pin Selenium Python 4.47.0 on Python 3.10+, use a supported locally installed Chromium-family browser, ordinary Selenium Manager resolution, and loopback-only fixtures. Grid, browser clouds, enterprise identity, and WebDriver BiDi are not required in this chapter.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.