From f612dcfea8d6e9e6f396af8562173dd51a2e40ab Mon Sep 17 00:00:00 2001 From: Pushpak Jaiswal <149317014+PUSHPAK-JAISWAL@users.noreply.github.com> Date: Wed, 28 Oct 2026 15:10:51 +0530 Subject: [PATCH 1/8] docs(why): add Why accessibility-first locators? page --- .../why/why-accessibility-first-locators.md | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 docs-site/docs/why/why-accessibility-first-locators.md diff --git a/docs-site/docs/why/why-accessibility-first-locators.md b/docs-site/docs/why/why-accessibility-first-locators.md new file mode 100644 index 0000000..b092512 --- /dev/null +++ b/docs-site/docs/why/why-accessibility-first-locators.md @@ -0,0 +1,134 @@ +--- +description: "Why accessibility-first locators: targeting the accessibility tree (getByRole, getByLabel, getByText) survives CSS rewrites and markup refactors without hiding Selenium." +id: why-accessibility-first-locators +title: Why accessibility-first locators? +sidebar_label: Why accessibility-first locators? +sidebar_position: 4 +--- + +# Why accessibility-first locators? + +Automated tests break for two reasons: real regressions, and brittle selectors. The second kind is wasted time. + +Most Selenium test suites are packed with CSS selectors and XPath expressions tied directly to DOM hierarchies or styling hooks: + +```java +// Brittle: bound to exact tag hierarchy and volatile utility classes +driver.findElement(By.cssSelector("form.auth-form div.input-group > input.email-input")) + .sendKeys("user@example.com"); +driver.findElement(By.cssSelector("form.auth-form div.actions button.btn-primary")) + .click(); +``` + +When frontend developers restructure a component, migrate CSS frameworks (e.g. from Bootstrap to Tailwind), or wrap a field in an extra `
`, the application still works perfectly for end users. But the test suite turns red. + +--- + +## What accessibility-first locators do + +Users and assistive technologies (like screen readers) do not interact with CSS class names or DOM parent-child nesting. They interact with **accessible roles** and **names**: + +- A button labeled **"Sign In"** +- A text input labeled **"Email address"** +- A heading at **Level 1** reading **"Dashboard"** + +Selenium Boot introduces accessibility-first locators (`getByRole`, `getByLabel`, `getByText`, `getByPlaceholder`, `getByTestId`) available directly in `BaseTest` and `BasePage`: + +```java +// Resilient: targets what the user sees and perceives +getByLabel("Email address").type("user@example.com"); +getByRole(Role.BUTTON).withName("Sign In").click(); +``` + +--- + +## Surviving real markup refactors + +Consider a button that goes through common frontend iterations across three sprints: + +```html + + + + +Sign In + + + +``` + +Here is how different locator strategies hold up: + +| Locator Strategy | Sprint 1 | Sprint 2 | Sprint 3 | Why | +|---|---|---|---|---| +| `By.cssSelector("button.btn-primary")` | Pass | **Fail** | **Fail** | Tag changed to ``, class changed | +| `By.xpath("//button[text()='Sign In']")` | Pass | **Fail** | **Fail** | `button` tag is gone | +| `getByRole(Role.BUTTON).withName("Sign In")` | **Pass** | **Pass** | **Pass** | All 3 expose the accessible role `button` and name `"Sign In"` | + +`Role.BUTTON` targets both native HTML elements with implicit roles (`