role=linkBug (ENG-1747): Access Engine test 925 (an A element must not carry an alt attribute) scoped its candidate set to a[data-ae_ar="null"][data-ae_vis][data-ae_avat] — 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" alt="should not be here">Testing this out</a> was silently skipped — a false negative.
Impact: alt is not a valid attribute on A. Authors add it expecting it to name the link, but browsers ignore it, so the link is often left with a misleading or missing accessible name. Those mistakes went unreported on any link that also spelled out role="link".
A elements without an ARIA-assigned role, or with role=link, not intentionally hidden in the DOM and available to assistive technologies.alt attribute, whether populated or empty — alt is not defined on A in HTML.role="button", role="img", …) remain out of scope — they are no longer being exposed as links.alt on a nested img is correct markup and is not what this test looks at.alt copied onto the anchor instead of the image it wraps.alt onto every element in a media block.role="link" alongside href, hiding the mistake from the test.data-ae_computed_role, the explicit-or-implicit ARIA role):
a[data-ae_ar="null"][data-ae_vis][data-ae_avat], a[data-ae_computed_role="link"][data-ae_vis][data-ae_avat]
[alt] appended to each branch for the failing set. The computed-role branch matches role="link" in any letter case, and a role list 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" and an alt attribute other roleThe anchor is exposed as a button, not a link, so test 925 does not apply. Only role=link (or no role) is in scope. Should not be flagged.
role="img" and an alt attribute other roleAn anchor exposed as an image is out of scope for this test, unchanged by ENG-1747. Should not be flagged.
role="link" hidden with display:none hidden(Anchor is present but hidden via display:none.)
Test 925 only evaluates elements that are not intentionally hidden: the selector requires [data-ae_vis]. Should not be flagged.
role="link" and aria-hidden="true" not exposedNot available to assistive technologies, so the selector's [data-ae_avat] requirement excludes it. Should not be flagged.
alt attribute no roleIn scope, carries no alt. Should not be flagged.
role="link" and no alt attribute role=linkNewly in scope after ENG-1747, and compliant. Should not be flagged.
role="link" wrapping an image that carries the alt alt on imgCorrect markup: the alt belongs to the img, not the anchor. Test 925 looks only at alt on the A itself. Should not be flagged.
role="link" anchor with a populated alt role=linkThe markup from ENG-1747. Pre-fix: not flagged ❌. Post-fix: flagged ✓.
role="link" anchor with an empty alt empty altAn empty alt is still an alt on an element that does not define it. Pre-fix: not flagged ❌. Post-fix: flagged ✓.
role="LINK" anchor with an alt 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 with an alt 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 — expected and unrelated to test 925.)
role="link" anchor with no href and an alt 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 ✓. (Test 1119 also flags this element for having neither href nor a tabindex — expected and unrelated to test 925.)
href and an alt 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 ✓. (Test 1119 also flags it for having neither href nor a tabindex — expected and unrelated to test 925.)
alt was put on the anchor instead of the image role=linkThe most common form of this mistake: the image is left without a name and the anchor carries an attribute browsers ignore. Pre-fix: not flagged ❌. Post-fix: flagged ✓. (Test 1386 flags the nested image separately for having no accessible name — that is the other half of the same authoring mistake.)
alt across the block role=linkA template applies the same alt to every element in the card, including the anchor. Pre-fix: not flagged ❌. Post-fix: flagged ✓.