ENG-1727: Tests 17/39 False Positive When muted Set via JS Property

Bug (ENG-1727): Access Engine tests 17 and 39 (autoplaying media must not produce sound — WCAG 1.4.2 Audio Control) decided "is this element muted?" by reading the HTML muted attribute only. When a page mutes media via the JavaScript IDL property (videoEl.muted = true), no muted attribute is added to the DOM. The engine saw no attribute, assumed the media was audible, and produced a false-positive autoplay violation even though the media was actually silent.

Impact: False positives on autoplay media that is muted via JavaScript — background hero videos, JS-driven video players, and framework-bound media all reported audio-control failures despite playing no sound.

Test Logic (tests 17 & 39):

Common Scenarios:

Fix: During DOM markdown, read the live .muted IDL property (not just the serialized muted attribute). When an element is muted via the property but has no muted attribute, stamp a marker attribute the test selectors can exclude:

if (n.muted === true && !n.hasAttribute("muted")) { n.setAttribute("data-ae_muted", "true"); }

The tests 17/39 base selector then excludes both the attribute and the marker:

video:not([muted]):not([data-ae_muted])[autoplay][data-ae_ar="null"][data-ae_vis]

Post-fix, autoplay media is treated as compliant (N/A) when the live .muted property is true, regardless of whether a muted attribute is serialized in the DOM. There is no .volume check — the engine does not consult volume.
N/A — out of scope
PASS — not flagged (correct)
FAIL — flagged (correct, regression guard)
BUG repro — pre-fix false positive

N/A Tests — Tests 17/39 Do Not Apply

Video without autoplay — user must press play no autoplay

No autoplay, so playback is user-initiated. Tests 17/39 apply only to auto-playing media. Should not be flagged.

Audio without autoplay — user must press play no autoplay

No autoplay means no automatic sound. Out of scope for tests 17/39. Should not be flagged.

autoplay video with display:none, NOT muted hidden

(Media element is present but hidden via display:none.)

Arguably a real WCAG 1.4.2 issue — display:none does not silence audio — but tests 17/39 only evaluate visible media: the base selector requires [data-ae_vis], and a display:none element is marked data-ae_invis instead. The engine therefore reports N/A (out of scope as not visible), not a flag, regardless of mute state.

PASS Tests — Correctly NOT Flagged After Fix

Baseline: <video autoplay muted> muted via ATTRIBUTE (control) attr muted

Muted via the serialized muted attribute. Worked before and after the fix. Should not be flagged.

<video autoplay> WITHOUT muted attribute, .muted = true set by JS JS muted

No muted attribute in the DOM, but the live .muted IDL property is true. Pre-fix this was a false positive; post-fix the engine reads .muted and does not flag it.

<audio autoplay> muted via JS .muted = true property JS muted

Autoplay audio with no muted attribute but .muted === true after JS runs. Post-fix the effective muted state is honored. Should not be flagged.

<video> with both muted attribute AND JS .muted = true (belt-and-braces) attr + JS muted

Attribute present and property re-set to true in JS — fully silent. Should not be flagged either way.

FAIL Tests — Correctly Flagged (Regression Guard)

<video autoplay> with sound — not muted at all audible

Autoplay with no muting via the muted attribute or the .muted property. Genuine WCAG 1.4.2 violation. Correctly flagged by tests 17/39 — the fix must not suppress this.

<audio autoplay> unmuted audible

Autoplaying audio with no mute and no control to stop it pre-emptively. Genuine violation. Correctly flagged.

Known Limitation — Out of Scope for ENG-1727

<video autoplay muted> whose JS later sets .muted = false (now audible) attr muted, JS unmutes

Known false negative — NOT addressed by ENG-1727. The muted attribute is present in the DOM, so the tests 17/39 selector :not([muted]) excludes the element and the engine reports N/A — even though JS has flipped the live .muted property to false and the media is actually audible. The ENG-1727 fix only adds a data-ae_muted marker when .muted === true && !hasAttribute("muted"); it never reads .muted === false to override a present muted attribute. Catching this (attribute present, property false) is the opposite-direction problem and remains out of scope.

BUG Reproduction — Pre-Fix False Positives

Autoplay video, muted via JS property only — muted attribute ABSENT JS muted

Pre-fix: flagged ❌ (engine saw no muted attribute). Post-fix: not flagged ✓ (engine reads .muted === true). This is the core ENG-1727 case.

Autoplay audio, muted via JS property only — muted attribute ABSENT JS muted

Pre-fix: flagged ❌. Post-fix: not flagged ✓. Test 39 audio equivalent of the false positive.

Real-World Scenarios

Background hero video muted in JS (silent looping banner) JS muted

Common framework/hero pattern: el.muted = true applied after mount, no muted attribute serialized. Pre-fix: false positive ❌. Post-fix: not flagged ✓.

Video carousel that mutes each slide via the player API (player.muted = true) JS muted

Player libraries mute through the IDL property, never the attribute. Pre-fix: every slide a false positive ❌. Post-fix: not flagged ✓.