label[for=""] Must Not Match input[id=""]Bug (ENG-1719): When a <label for=""> and an <input id=""> both had empty string values, the explicit for/id comparison (for === id) was true because "" === "". This caused every label[for=""] on the page to associate with every input[id=""], producing a spurious concatenated accessible name.
Impact: Test 374 violations (missing accessible name on radio) were hidden because the engine reported a (wrong) accessible name instead of no name.
for and id to be non-empty and equalid="" must never be matched by any label[for=""]id=""id="" as a default fallbacknode.id && guard before the for/id comparison:
(node.id && labels[i].getAttribute("for") === node.id)
node.id is "" (falsy), the comparison short-circuits and no explicit association is made.
id=""for=""id attribute at all (attribute absent) — id="na-radio-no-id"No empty id involved — fix irrelevant. aria-label provides name so Test 374 does not fire. Should not be flagged.
id="" (display:none) — id="", excluded by visibilityHidden element — data-ae_vis absent, excluded from all tests. Should not be flagged.
id="" — same fix, different test rule — id=""Fix blocks label[for=""] matching checkbox[id=""]. aria-label provides name so checkbox accessible-name test does not fire. Should not be flagged.
id="" and sibling label[for=""] — no accessible name assigned — all id=""AFTER FIX: No accessible name from labels. Test 374 correctly fires on all three. Should be flagged.
id + label[for] — still named correctly (regression)Valid non-empty for/id pairs still associate correctly. No regression from the fix.
<label> (implicit association) — id="plan-monthly", id="plan-annual"Implicit label unaffected by fix. Accessible names: "Monthly", "Annual". Should not be flagged.
id="good-option" (named) / id="" (no name)id="good-option": accessible name "Good option" — should not be flagged. id="": no name — should be flagged.
id="" alongside unrelated label[for=""] — search id="" / radios id=""Search field (unrelated to radio group):
Search: aria-label provides name — should not be flagged. Radios: no name after fix — should be flagged. No cross-contamination from the search label.
id="", should be flaggedPre-fix, each radio would receive an accessible name of "Whitewash Chambray North Pole" (all label texts concatenated). The engine treated every label[for=""] as associated with every input[id=""] on the page.
Pre-fix accessible name (each radio): "Whitewash Chambray North Pole" ❌
Post-fix accessible name (each radio): null ✓ (Test 374 correctly fires)
id="real-id" should not be flagged / id="" should be flaggedPre-fix: the radio below would inherit "Pick me" as its accessible name from the unrelated label above it, because both use empty id/for.
Pre-fix: second radio accessible name = "Pick me Should not bleed" (all empty-for labels) ❌
Post-fix: second radio accessible name = null ✓
id="", should be flaggedProduct: Classic T-Shirt
Accessible name: null (no name on any radio). Test 374 fires — radios need accessible names. Developer fix: add unique id per radio + matching for on label, OR wrap each input in its label.
id="color-white/blue/offwhite/gray", should not be flaggedProduct: Classic T-Shirt
Each radio wrapped in its label — implicit association. Accessible names: "Whitewash", "Chambray", "North Pole", "Pewter". Test 374 passes.
id="", should be flaggedCMS template emits id="" as placeholder. Pre-fix: each radio got "Daily Weekly Monthly" as name (hiding the bug). Post-fix: no name — Test 374 fires, exposing the real problem. Developer must fix the CMS template to emit unique IDs.
id="rate-1/rate-2/rate-3", should not be flaggedAll radios have unique, non-empty ids. Explicit for/id associations work correctly. Accessible names: "1 — Poor", "2 — Fair", "3 — Good".