Chapter 05Lesson 01~135 minutes

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.

WebElement stateAttributes / propertiesUser-like inputForm semanticsAssertions

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.

DevOps connection: UI tests become useful release evidence when they assert meaningful user-visible outcomes and preserve enough state to explain why an interaction could or could not happen.

2. From locator to application outcome

Element interaction is a state transition, not an API call

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"))
Why it matters: an assertion against only the original HTML attribute can miss the state the browser is actually using. In Selenium Python 4.47.0, use 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?

What is the practical difference between get_dom_attribute("value") and get_property("value") on a text input?

What does a successful click() prove?

Why should a custom div-based dropdown not use Selenium Select?

A button is displayed and enabled but click raises ElementClickInterceptedException. What should you inspect first?

Next lesson

Guided Hands-On Workflow

Build the loopback form fixture, inspect attributes/properties/state, perform native interactions, compare invalid and valid submissions, and capture an evidence packet.

Official references and version notes

Version and compatibility note

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.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.