In a component library's interaction tests, why should a test find controls by role and accessible name instead of internal class names or test IDs?
answer
- test the way users find things
- the accessibility tree as the locator
- a missing name fails loudly
- internals the library may refactor
- test IDs only as a fallback
basics
~10 sRole and accessible name are what assistive-technology users and consuming teams rely on, so querying by them tests the public contract, fails when a control loses its name, and survives internal refactors.
solid answer
~40 sA shared library's interaction tests should drive components the way their users do. Finding the control as 'a button named Move to stage' asserts two things at once: it behaves correctly, and it exposes the role and accessible name that screen-reader and voice-control users need - what WCAG 4.1.2 Name, Role, Value requires. If someone removes the label, the test cannot even find the control, so the regression fails loudly. Class names and test IDs are internals: a query by them passes even when the control is unnamed, and breaks when the library refactors markup it is entitled to change. Test IDs stay a documented fallback for elements with no meaningful role, not the default.
code
pseudocode · 11 linesrender ActionMenu(label = "Move to stage", items = ["Phone screen", "Onsite", "Offer"])
trigger = locate(role = "button", name = "Move to stage")
assert trigger.expanded == false
focus(trigger)
press("Enter")
menu = locate(role = "menu")
assert focusedElement() == menu.items[0]
press("Escape")
assert menu.isHidden
assert trigger.expanded == false
assert focusedElement() == triggergo deeper
Recall that a good library test finds controls the way users and assistive technology do - by role and accessible name - and name one regression that approach catches.
Explain why a role-and-name query doubles as a WCAG 4.1.2 check while a test ID does not, and when a test ID is still the honest choice.
Show how you would pin a pattern's keyboard contract, such as a menu button's open and Escape behavior, and where role queries stop and manual review begins.
Argue for role-and-name queries as a library-wide testing standard across web and native, and weigh the cost of migrating an existing test-ID-based suite.
## What an interaction test is for in a library An **interaction test** renders a component, performs user actions - clicks, key presses, typing - and asserts on what a user would perceive afterwards. In a **component library** consumed by many product teams, those tests guard the library's promises: this menu opens, this dialog returns focus, this field reports its error. How the test *finds* each control decides what it really checks. The **accessible name** is the text assistive technology announces for a control; the **role** says what kind of control it is (button, menu, tab). Both live in the **accessibility tree**, the structure the platform exposes to screen readers, voice control and switch access. WCAG 2.2 success criterion **4.1.2 Name, Role, Value** (Level A) requires that the name and role of user interface components can be programmatically determined. ## Two ways to find the same control Take a recruiting tool's candidate card with a 'Move to stage' action menu: | Locator | Survives an internal refactor | Fails if the name is lost | Mirrors how users find it | |---|---|---|---| | Role button, name 'Move to stage' | Yes | Yes | Yes | | An internal class name | No | No | No | | A test ID attribute | Yes | No | No | The role-and-name query is the only one that doubles as an accessibility assertion. The class-name query couples the test to styling internals the library must stay free to change. The test ID survives refactors, but an icon-only button that lost its label would still be found by its ID and the test would stay green. ## Example: an action menu in a recruiting tool The WAI-ARIA Authoring Practices **menu button** pattern defines a keyboard contract a test can pin: 1. Locate the button by role and name. 2. Assert it reports collapsed. 3. Focus it and press Enter; the pattern says the menu opens and focus moves to the first item. Space does the same. 4. Press Escape; the menu closes and focus returns to the menu button. 5. Assert the button reports collapsed again. Every step uses the same vocabulary a screen-reader user hears, so a regression in naming, state or focus fails the test. ## Where role-and-name queries fall short - **Meaning is not checked.** A button named 'Click here' is found just as easily as one named 'Move to stage'; whether the name makes sense is a human judgment. - **Keyboard behavior must be exercised explicitly.** Finding a control by role proves it is exposed, not that its keys work; the test has to press them. - **Visual properties are invisible** - contrast, focus visibility, layout. Those belong to visual diffs and manual review. - **Role-less elements** such as layout regions or a canvas-drawn chart have nothing to query; a documented test ID is the honest fallback there. - **Several identical controls** - one 'Move to stage' per card - need scoping to the containing card, which is itself found by its role and name. ## The same idea on native mobile Native platforms expose the same model: an accessibility label, a role or trait, and a value. Their UI test tools can also locate elements by accessibility label, so a design system shipping to web and native can state one contract - 'a button named Move to stage that opens a menu' - and verify it on each platform with the same intent. ## The payoff for the library Tests written this way outlive refactors, fail on the regressions users would notice, and document the component's public behavior in plain terms. They do not replace manual testing with assistive technology, but they make the most common accessibility regression - a control that silently loses its name - impossible to ship unnoticed.
- When is a test ID the right way to find an element in a library test?When the element has no meaningful role or name - a layout region, a decorative container, a canvas-drawn chart. Use it as a documented fallback, never for an interactive control, because a test ID lets the test keep passing after the control loses its accessible name.
- If a test finds a control by role and name, does that prove the component is accessible?No. It proves the control exposes that role and name in the accessibility tree. It does not prove the name is meaningful in context, that the keyboard contract works, that focus is visible, or that contrast is sufficient. Those need explicit key-press assertions, visual checks and manual testing with assistive technology.
- How does this approach carry over to native mobile components?Native platforms expose the same model - an accessibility label, a role or trait, a value - and their UI test tools can locate elements by accessibility label. A system shipping to web and native can express one contract, such as 'a button named Move to stage', and verify it on each platform.
saying these in an interview costs you the question
- Test IDs on every element make library tests the most robust.
- Class-name locators are fine because the library owns its markup.
- Finding a control by role and name proves it is fully accessible.
- A control with visible text always has an accessible name.
- Accessible names matter to screen readers, not to automated tests.