role=linkBug (ENG-1745): Access Engine test 22 (an A element must not contain nested interactive content) scoped its candidate set to a[data-ae_vis][data-ae_ar="null"] — anchors with no ARIA role at all. Any role attribute took the anchor out of scope, including role="link", which does not change what the element is. Markup such as <a href="foo" role="link">Testing this out<button>bad</button></a> was silently skipped: the nested button went unreported — a false negative.
Impact: Real nested-interactive violations were missed on any link that spells out its role. This is common in design systems and framework component libraries, which frequently emit a redundant role="link" on anchors.
A elements without an ARIA-assigned role, or with role=link, that are not intentionally hidden in the DOM.input (without an assigned ARIA role and not type=hidden), keygen, select, textarea or button element, each without an assigned ARIA role.role="button", role="presentation", …) remain out of scope — they are no longer being exposed as links.role="link" alongside href.data-ae_computed_role, the explicit-or-implicit ARIA role):
a[data-ae_vis][data-ae_ar="null"], a[data-ae_vis][data-ae_computed_role="link"]
role="link" as well as case variations and multi-token role lists whose first valid token is link (role="foo link"), mirroring browser behaviour. The original data-ae_ar="null" branch is retained so a role-less A without an href (implicit role "") stays in scope exactly as before — the change only adds coverage, it never removes it.
role="button" containing a button other roleThe anchor is exposed as a button, not a link, so test 22 does not apply. Only role=link (or no role) is in scope. Should not be flagged.
role="presentation" containing a button other roleAn explicit presentational role removes the link semantics the test is about. Out of scope, unchanged by ENG-1745. Should not be flagged.
role="link" hidden with display:none hidden(Anchor is present but hidden via display:none.)
Test 22 only evaluates elements that are not intentionally hidden: the selector requires [data-ae_vis], and a display:none element is marked data-ae_invis instead. Should not be flagged.
In scope, contains no interactive element. Should not be flagged.
role="link" and text only role=linkNewly in scope after ENG-1745, but there is nothing nested to report. Should not be flagged.
role="link" containing input type="hidden" role=linkA hidden input is not an interactive control; the test explicitly excludes type=hidden. That exclusion applies on the new role=link branch too. Should not be flagged.
role="link" containing a button that has its own ARIA role role=linkNested elements with an assigned ARIA role are out of the test's descendant set, both before and after ENG-1745. Should not be flagged.
role="link" anchor containing a button role=linkThe exact markup from ENG-1745. Pre-fix: not flagged ❌. Post-fix: flagged ✓.
role="link" anchor containing a text input role=linkPre-fix: not flagged ❌. Post-fix: flagged ✓.
role="link" anchor containing a select role=linkPre-fix: not flagged ❌. Post-fix: flagged ✓.
role="link" anchor containing a textarea role=linkPre-fix: not flagged ❌. Post-fix: flagged ✓.
role="LINK" anchor containing a button caseARIA role tokens are case-insensitive and the computed role is normalised to lower case. Pre-fix: not flagged ❌. Post-fix: flagged ✓.
role="foo link" anchor containing a button token listBrowsers skip unknown tokens and use the first valid one, so this element is a link. The computed role resolves to link even though the recorded data-ae_ar is foo. Pre-fix: not flagged ❌. Post-fix: flagged ✓. (Tests 37 and 412 also flag this element for the invalid foo token — that is expected and unrelated to test 22.)
role="link" anchor with no href containing an input no hrefWithout href the anchor has no implicit link role, but the explicit role="link" makes it one. Pre-fix: not flagged ❌. Post-fix: flagged ✓.
button no roleThe original test 22 case. Must stay flagged ✓.
href containing a button no role, no hrefIts computed role is empty (no href), so it is only in scope through the retained data-ae_ar="null" branch. This case guards against narrowing the selector to the computed role alone. Must stay flagged ✓.
role="link" anchor with an "Add to cart" button role=linkCard-as-link pattern: the button is unreachable as a separate control inside the link. Pre-fix: not flagged ❌. Post-fix: flagged ✓.
role="link" around a filter select role=linkComponent libraries routinely add a redundant role="link" to their anchor components, which used to hide every nested-control violation they contained. Pre-fix: not flagged ❌. Post-fix: flagged ✓.