Skip to content

chore(deps): hold jsdom at 25 for the accname whitespace regression - #426

Merged
saquibrashid merged 1 commit into
mainfrom
chore/hold-jsdom-30
Oct 8, 2026
Merged

saquibrashid merged 1 commit into
mainfrom
chore/hold-jsdom-30

Conversation

@saquibrashid

Copy link
Copy Markdown
Owner

What

Holds jsdom at 25 and records why, closing #405.

Why — and it is not the reason the red PR first suggested

PR #405 (jsdom 25.0.1 → 30.1.2) failed twice with the same surface symptom — "jobs 4 and 6 are red" — from two completely unrelated causes.

Round 1 — TypeError: Cannot read properties of undefined (reading '_bytes') — FIXED, not held. jsdom 30.1 moved Blob internals behind private fields while vitest's jsdom-compat shim still read _bytes. Resolved upstream by vitest@5.0.3 ("Support Blob on jsdom 30.1", vitest-dev/vitest#11379), taken in #420. All 10 of those failures are gone.

Round 2 — accessible-name whitespace — this is the hold. With vitest 5.0.3 in place, 5 different tests fail with one root cause:

Expected element to have accessible name:
  Filters 4 active
Received:
  Filters4 active

jsdom >= 28 drops the separator space between a text node and an adjacent inline element, so All<span className="sr-only"> statuses</span> (FilterBar.tsx, three sites) computes as Allstatuses. accname 1.2 step 2I says to append with a space, and Chrome, Firefox and Safari all do.

The markup is correct, and the same CI run proves it

On the identical commit where 4 · test:unit + coverage and 6 · test:web went red (T-PHONE-005a, T-PHONE-005b, T-UX-145c, T-TOOLBAR-002b, T-AVREV-009a), the job 9 · test:a11y passed — that suite is Playwright driving real browsers.

A split of that exact shape — jsdom red, real browsers green, one commit — is evidence that the test engine is wrong. Reshaping FilterBar.tsx to satisfy jsdom would make the real-browser accessible name worse in order to make a non-conformant simulation agree, so it was rejected.

No dependency bump clears this

The space logic lives in dom-accessibility-api, not jsdom. Its latest release (0.7.1, 2025-11-27) is a trusted-publishing change with no fix, and @testing-library/dom@10.4.1 pins dom-accessibility-api@^0.5.9, so 0.7.x is unreachable from this tree. Bumping testing-library will not help.

Upstream jsdom/jsdom#4091 is closed not_planned, but on process grounds — the repro used a third-party library, which that project declines to investigate — not on the merits. The behaviour is unadjudicated, so a clean no-third-party repro remains a live path to reopening it.

Changes

  • .github/dependabot.yml — adds jsdom capped at versions: ['>=28'], with the evidence and a named exit criterion. Capped by version rather than by update-type, the same way @types/node is: 26 is known good (the upstream report reproduces clean on 26.1.0), so the cap stays as small as the evidence supports.
  • .github/dependabot.yml — the existing RELEASED comment claimed jsdom "carries no ignore now", which this change makes false. Corrected in place with the superseded sentence struck through below it, per the repo's F-001 supersession rule for machine-executed instructions.
  • docs/runbooks/update-dependencies.md §5 — a held-bump entry alongside Prisma 7 and Vitest 5, carrying both rounds so the next person does not re-litigate the _bytes half. Per §5: "a bump that was tried and rejected is more valuable written down than a bump nobody looked at."

Unblocked by: jsdom restoring accname 1.2 step 2I space separation, or dom-accessibility-api no longer depending on the old display default and @testing-library/dom widening its pin. To re-test: raise the cap, let Dependabot rebase, and watch those five named tests.

Validation

Command Result
npm run format:check passed — "All matched files use Prettier code style!"
npm run check:test-locations passed — "385 spec files, 354 collected by Vitest, 31 owned by Playwright"
python -c "yaml.safe_load(...)" on .github/dependabot.yml parses; ignore list resolves to @types/node >=23, typescript >=7.0.0 <7.1.0, jsdom >=28, plus the four Prisma/mssql major holds

No source or lockfile change, so the test suites are unaffected; CI runs them anyway. T-INFRA-018d reads package.json/.nvmrc/Dockerfile only and is not sensitive to the new ignore entry.

Closes #405

jsdom >= 28 drops the separator space between a text node and an
adjacent inline element when computing an accessible name, so
`All<span class="sr-only"> statuses</span>` in FilterBar.tsx is named
"Allstatuses" and the filters trigger is named "Filters4 active".
accname 1.2 step 2I says to append with a space, and Chrome, Firefox
and Safari all do.

The markup is correct and CI proves it: on the same commit where
`4 - test:unit + coverage` and `6 - test:web` went red (T-PHONE-005a,
T-PHONE-005b, T-UX-145c, T-TOOLBAR-002b, T-AVREV-009a), the Playwright
real-browser job `9 - test:a11y` passed. Reshaping FilterBar.tsx to
satisfy jsdom would make the real accessible name worse in order to
make a non-conformant simulation agree.

No dependency bump clears this. The space logic lives in
dom-accessibility-api, not jsdom; its latest release (0.7.1) contains
no fix, and @testing-library/dom pins ^0.5.9 so 0.7.x is unreachable.
Upstream jsdom#4091 is closed not_planned on process grounds (the
repro used a third-party library), not on the merits.

Capped by version at >=28 rather than by update-type, like @types/node:
26 is known good, so the cap stays as small as the evidence supports.

Also corrects in place the now-false dependabot.yml comment claiming
jsdom carries no ignore, keeping the superseded text struck through
below it.

Note: the separate `_bytes` failure that first blocked PR #405 was a
real vitest/jsdom incompatibility and is FIXED, not held - vitest 5.0.3
(#420) resolved it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c372e6ba-4c3f-419a-9f77-b9e23adfc874
@saquibrashid saquibrashid added the dependencies Dependency updates (referenced by .github/dependabot.yml) label Oct 8, 2026
@saquibrashid
saquibrashid merged commit 85f3b10 into main Oct 8, 2026
13 checks passed
@saquibrashid
saquibrashid deleted the chore/hold-jsdom-30 branch October 8, 2026 17:27
saquibrashid added a commit that referenced this pull request Oct 8, 2026
The jsdom hold landed in #426 with `versions: ['>=28']`, on the assumption
that the accname whitespace regression began in 28. That assumption was
wrong and the cap let Dependabot raise #427 (25.0.1 -> 27.4.0).

#427 failed jobs 4 and 6 with EXACTLY the same five tests as the jsdom 30
PR did - T-UX-145c, T-AVREV-009a, T-PHONE-005a, T-PHONE-005b and
T-TOOLBAR-002b - while the other ten jobs, including 9 . test:a11y
(Playwright, real browsers), passed. Same signature, same conclusion: the
markup is right and jsdom is wrong, from 27 onward.

26 remains known good, so the cap stays as small as the evidence supports.
The runbook paragraph is corrected in place with the superseded sentence
struck through below it, per the F-001 rule.

Closes #427

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c372e6ba-4c3f-419a-9f77-b9e23adfc874
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Dependency updates (referenced by .github/dependabot.yml)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant