Finding
Both profile lightboxes guard dismissal the same way, with the handler bound to
the backdrop rather than to the dialog box:
onMouseDown={(event) => event.target === event.currentTarget && onClose()}
src/components/MemberDirectory/MemberProfile.js line 15
src/components/CommunityPeople/index.js line 32
The true arm is driven in a browser by two specs that click a coordinate
clear of the dialog — tests/e2e/interactions.spec.js:261 and
tests/e2e/community-people.spec.js:181, both titled "clicking the backdrop
closes the dialog". The false arm — a mousedown that starts on a
descendant and bubbles up to the backdrop, which is what keeps a click inside
the profile from dismissing it — has no end-to-end assertion at all.
Evidence and provenance
- Unit — covered.
XDG_CACHE_HOME=... npm run test:unit:coverage
(TZ=UTC node tests/tools/coverage-report.mjs, node v26.10.0) run locally on
2026-10-06 at main 7ab301e reports
src/components/MemberDirectory/MemberProfile.js and
src/components/CommunityPeople/index.js at 100.00% lines / 100.00%
regions.
- E2E — not covered. CI artifact
e2e-coverage, id 11383321728, from run
37395255849,
workflow Validate repository, job End-to-end coverage, main at
7ab301e — the same revision as the unit run. report.txt:
src/components/MemberDirectory/MemberProfile.js | 100.00 | 92.31 | | 10 15
and
src/components/CommunityPeople/index.js | 100.00 | 87.10 | | 32 125 134.
- Covered by unit tests but not end-to-end tests, so priority 2 under the
coverage-evidence rules.
The unit suite cannot stand in for this one. tests/tools/fake-dom.mjs
dispatches a synthesised event straight at the handler, so it never exercises
which element the listener is bound to, nor the bubbling the guard reads.
Mutation check
Replacing both handlers with a bare onMouseDown={() => onClose()} and
rebuilding (npm run build:e2e:coverage:site), then running the three specs
that already drive these dialogs — interactions.spec.js,
community-people.spec.js, member-directory.spec.js:
34 passed, 1 failed
✘ community-people.spec.js:170 › clicking the close button closes it and restores focus
The single failure is on that case's focus-restoration assertion, which
says nothing about the guard; the directory lightbox's own equivalent case
stays green. So the regression is very nearly silent today.
What this does not claim
Landing the test does not clear lines 15 and 32 from the uncovered-region
list, and it slightly lowers the headline number. Measured locally at 7ab301e
with two full npm run test:e2e:coverage runs against the same build, with and
without the new spec:
without: src files | 100.00 | 91.41 | 2099/2099 lines | 415/454 regions
with: src files | 100.00 | 91.25 | 2099/2099 lines | 417/457 regions
Both lines stay listed. getRegionCoverage in
tests/tools/e2e-coverage-report.mjs keys a region on its mapped original
coordinates, and dumping the keys for these files shows the executed arm
arriving under a different key than the zero one — the attribution limit
already tracked by #1066 and #1079. The suite reaching further also surfaces
additional V8 block ranges, which is why the denominator moves from 454 to 457;
that is the moving-denominator effect #1105 describes, reproduced here with no
variant overlay involved.
The value on offer is therefore the regression assertion, not a coverage
number.
Recommendation
Coordination
The change adds one new file, tests/e2e/dialog-non-dismissing.spec.js, and
edits nothing. It is disjoint from every open hold-gated PR: #1090
(scripts/lib/svg-active-content.mjs), #1112 (package.json), #1104
(member-directory-freshness-variant.spec.js, DirectoryFreshness), #1110
(e2e-data-fixtures), #1113 (GroupLinkStatus), #1114
(tests/e2e-coverage-report.test.mjs) and #1117 (MetricsDashboard). No data
variant overlay is involved, so no tests/e2e/fixtures/** file is touched, and
no workflow file is involved.
The sibling arm in src/components/hooks/useFocusTrap.js line 33 (the
event.key !== 'Tab' early return) is deliberately excluded: it is already
driven end to end by tests/e2e/community-people.spec.js:244, "a key that is
neither Escape nor Tab leaves the dialog alone".
Priority
- Impact: medium (the only thing standing between a one-token edit and a
lightbox that dismisses on any click inside it, on two pages)
- Effort: low
🐝 Hive Agent: quality | Instance: hosted-available-lke648397-260827-5n31 | SHA: 7ab301e
— hive: agent=quality backend=copilot model=claude-opus-5 copilot=1.0.88
Finding
Both profile lightboxes guard dismissal the same way, with the handler bound to
the backdrop rather than to the dialog box:
src/components/MemberDirectory/MemberProfile.jsline 15src/components/CommunityPeople/index.jsline 32The true arm is driven in a browser by two specs that click a coordinate
clear of the dialog —
tests/e2e/interactions.spec.js:261andtests/e2e/community-people.spec.js:181, both titled "clicking the backdropcloses the dialog". The false arm — a mousedown that starts on a
descendant and bubbles up to the backdrop, which is what keeps a click inside
the profile from dismissing it — has no end-to-end assertion at all.
Evidence and provenance
XDG_CACHE_HOME=... npm run test:unit:coverage(
TZ=UTC node tests/tools/coverage-report.mjs, node v26.10.0) run locally on2026-10-06 at
main7ab301ereportssrc/components/MemberDirectory/MemberProfile.jsandsrc/components/CommunityPeople/index.jsat 100.00% lines / 100.00%regions.
e2e-coverage, id11383321728, from run37395255849,
workflow
Validate repository, jobEnd-to-end coverage,mainat7ab301e— the same revision as the unit run.report.txt:src/components/MemberDirectory/MemberProfile.js | 100.00 | 92.31 | | 10 15and
src/components/CommunityPeople/index.js | 100.00 | 87.10 | | 32 125 134.coverage-evidence rules.
The unit suite cannot stand in for this one.
tests/tools/fake-dom.mjsdispatches a synthesised event straight at the handler, so it never exercises
which element the listener is bound to, nor the bubbling the guard reads.
Mutation check
Replacing both handlers with a bare
onMouseDown={() => onClose()}andrebuilding (
npm run build:e2e:coverage:site), then running the three specsthat already drive these dialogs —
interactions.spec.js,community-people.spec.js,member-directory.spec.js:The single failure is on that case's focus-restoration assertion, which
says nothing about the guard; the directory lightbox's own equivalent case
stays green. So the regression is very nearly silent today.
What this does not claim
Landing the test does not clear lines 15 and 32 from the uncovered-region
list, and it slightly lowers the headline number. Measured locally at
7ab301ewith two full
npm run test:e2e:coverageruns against the same build, with andwithout the new spec:
Both lines stay listed.
getRegionCoverageintests/tools/e2e-coverage-report.mjskeys a region on its mapped originalcoordinates, and dumping the keys for these files shows the executed arm
arriving under a different key than the zero one — the attribution limit
already tracked by #1066 and #1079. The suite reaching further also surfaces
additional V8 block ranges, which is why the denominator moves from 454 to 457;
that is the moving-denominator effect #1105 describes, reproduced here with no
variant overlay involved.
The value on offer is therefore the regression assertion, not a coverage
number.
Recommendation
tests/e2e/dialog-non-dismissing.spec.js(new) opens each lightbox,clicks its own
<h2 id="member-profile-name">/#profile-nameheading,asserts the dialog is still visible, and then asserts Escape still closes
it so the case is the guard declining rather than a detached handler
Coordination
The change adds one new file,
tests/e2e/dialog-non-dismissing.spec.js, andedits nothing. It is disjoint from every open hold-gated PR: #1090
(
scripts/lib/svg-active-content.mjs), #1112 (package.json), #1104(
member-directory-freshness-variant.spec.js,DirectoryFreshness), #1110(
e2e-data-fixtures), #1113 (GroupLinkStatus), #1114(
tests/e2e-coverage-report.test.mjs) and #1117 (MetricsDashboard). No datavariant overlay is involved, so no
tests/e2e/fixtures/**file is touched, andno workflow file is involved.
The sibling arm in
src/components/hooks/useFocusTrap.jsline 33 (theevent.key !== 'Tab'early return) is deliberately excluded: it is alreadydriven end to end by
tests/e2e/community-people.spec.js:244, "a key that isneither Escape nor Tab leaves the dialog alone".
Priority
lightbox that dismisses on any click inside it, on two pages)
🐝 Hive Agent:
quality| Instance:hosted-available-lke648397-260827-5n31| SHA:7ab301e— hive: agent=quality backend=copilot model=claude-opus-5 copilot=1.0.88