Skip to content

Clear the report's six axe-core accessibility violations and close the gate (fixes #462) - #467

Merged
tylervick merged 1 commit into
tylervick/escape-attachment-htmlfrom
tylervick/a11y-template-fixes
Aug 14, 2026
Merged

tylervick merged 1 commit into
tylervick/escape-attachment-htmlfrom
tylervick/a11y-template-fixes

Conversation

@tylervick

Copy link
Copy Markdown
Member

Closes #462. Stacked on #466 — both touch HTMLTemplates.swift and both invalidate the same two goldens, so they cannot be reviewed against main independently. Retarget to main once #466 merges.

HTMLTemplates.swift contained zero alt= and zero title= attributes anywhere in the file, which was the whole cause of both gating findings. All six violations are fixed.

rule impact fix
image-alt critical, 6 nodes every <img> carries alt
frame-title serious #text-attachment and #logs-iframe are named
heading-order moderate #device-header h4 → h2, so levels no longer skip h1→h4
landmark-one-main moderate #main-content div → <main>
region moderate sidebars → <nav> / <aside> with aria-labels
empty-heading minor #file-attachment h2 → p

axe now reports zero violations at any impact, not just zero gating ones.

Choices worth a second look

Alt text is the display name, not the file name. A real .xcresult names its payloads with an 80-character opaque id; reading that aloud is worse than the missing alt it replaces. TestScreenshotFlow gained a NAME placeholder for this. The two preview panes ship alt="" — how a decorative placeholder declares itself — and inherit the name of whatever showScreenshot/showGif puts in them.

#file-attachment is a p now. It holds a download link, not a section heading; it was empty at load because its text is set by JS. The two CSS rules that centred it as a heading name it directly instead, so it looks identical, and querySelector("#right-sidebar h2") still resolves to the placeholder.

Landmarks changed elements, nothing else. Every CSS rule and script hook involved is id- or class-based.

The gate

GATING_IMPACTS goes back to ['critical', 'serious'], so a new critical or serious finding fails the build. Left at [] the expectation was expect([]).toEqual([]), which cannot fail. Moderate and minor stay informational — the level #462 prescribed, and it keeps the failure mode proportionate. The test's name asserts what it checks again.

The two rules that survive without a browser are also restated as AccessibilitySeamTests, so they hold in the test jobs and not only in visual, which is a separate workflow.

One knock-on worth flagging

alt puts the attachment display name in a second place, and that name is a divergence the modern reader already declares. DifferentialTests caught it immediately. The attachmentDisplayNames allow-list entry now masks both sites; masking only the text line would have let alt reintroduce a difference already accounted for. No new allow-list entry, and testEveryAllowListEntryStillMasksARealDivergence still passes.

Verified locally: 129 Swift tests, 0 failures; 11 Playwright tests, 0 failures. Goldens refreshed and read.

🤖 Generated with Claude Code

…462)

`HTMLTemplates.swift` contained zero `alt=` and zero `title=` attributes,
which was the whole cause of both gating findings: image-alt (critical, six
nodes) and frame-title (serious). Four more were moderate or minor. All six
are fixed here.

- Every `<img>` carries an `alt`. Attachment and screenshot-flow images take
  the attachment's display name; the two preview panes ship `alt=""`, which
  is how a decorative placeholder declares itself, and inherit the name of
  whatever is put in them.
- Both frames are named: `#text-attachment` and the run's `#logs-iframe`.
- `#device-header` becomes an `h2`, so heading levels no longer skip h1 to h4.
- `#left-sidebar`, `#main-content` and `#right-sidebar` become `nav`, `main`
  and `aside`, which answers landmark-one-main and region together. Every
  rule and script hook is id- or class-based, so nothing else moves.
- `#file-attachment` stops being an empty `h2`. It holds a download link, not
  a section heading, so it is a `p` — and the two rules that centred it as a
  heading now name it directly.

The gate goes back to `['critical', 'serious']`, so a new critical or serious
finding fails the build; moderate and minor stay informational, which is the
level #462 prescribed. The test's name says what it asserts again.

The two rules that survive without a browser — every image has alt text,
every frame has a name — are also restated as `AccessibilitySeamTests`, so
they hold in the `test` jobs and not only in `visual`.

One knock-on: `alt` puts the attachment display name in a second place, and
that name is a divergence the modern reader already declares. The
`attachmentDisplayNames` allow-list entry now masks both sites; masking only
the text line would have let `alt` reintroduce a difference already accounted
for.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 14, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: fec78631-12ce-4997-be34-3e251729a035

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@tylervick
tylervick merged commit fe58bcd into tylervick/escape-attachment-html Aug 14, 2026
8 checks passed
@tylervick
tylervick deleted the tylervick/a11y-template-fixes branch August 14, 2026 03:52
tylervick added a commit that referenced this pull request Aug 14, 2026
…462) (#467)

`HTMLTemplates.swift` contained zero `alt=` and zero `title=` attributes,
which was the whole cause of both gating findings: image-alt (critical, six
nodes) and frame-title (serious). Four more were moderate or minor. All six
are fixed here.

- Every `<img>` carries an `alt`. Attachment and screenshot-flow images take
  the attachment's display name; the two preview panes ship `alt=""`, which
  is how a decorative placeholder declares itself, and inherit the name of
  whatever is put in them.
- Both frames are named: `#text-attachment` and the run's `#logs-iframe`.
- `#device-header` becomes an `h2`, so heading levels no longer skip h1 to h4.
- `#left-sidebar`, `#main-content` and `#right-sidebar` become `nav`, `main`
  and `aside`, which answers landmark-one-main and region together. Every
  rule and script hook is id- or class-based, so nothing else moves.
- `#file-attachment` stops being an empty `h2`. It holds a download link, not
  a section heading, so it is a `p` — and the two rules that centred it as a
  heading now name it directly.

The gate goes back to `['critical', 'serious']`, so a new critical or serious
finding fails the build; moderate and minor stay informational, which is the
level #462 prescribed. The test's name says what it asserts again.

The two rules that survive without a browser — every image has alt text,
every frame has a name — are also restated as `AccessibilitySeamTests`, so
they hold in the `test` jobs and not only in `visual`.

One knock-on: `alt` puts the attachment display name in a second place, and
that name is a divergence the modern reader already declares. The
`attachmentDisplayNames` allow-list entry now masks both sites; masking only
the text line would have let `alt` reintroduce a difference already accounted
for.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant