Repository navigation
test(BottomSheet): check the handoff's scrim and focus with the handoff held - #9235
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
AI review status for this pull request.
|
PR Analysis Report🔎 Preview ·
|
| Component | Size | LoC |
|---|---|---|
| BottomSheet | 33.8 kB (0) · 7.4 kB CSS (0) | — |
| BottomSheetSwitcher | 14.9 kB (0) · 3.4 kB CSS (0) | — |
Package size: no published package changed; no new dependencies.
Not run on this PR: add ci:run-visual, ci:run-a11y or ci:run-rtl to run them.
Generated by PR Enrichment workflow | View full report
There was a problem hiding this comment.
Changes requested: holding the handoff phase by phase is the right fix for these flaky checks, but two parts need another pass.
- The scrim takeover after the retained dialog closes is still read once on the real clock (lines 577–578), so please hold or assert the dialogs'
::backdroptransitions through it, since a takeover that fades on the 410 ms scrim curve passes once that read lands about 160 ms late. - Please reuse
waitForRest,holdAnimations,seekAnimationsandreleaseAnimationsfrominternal/interaction-harness/src/curves.ts(extending them if pausing attransitionrunis needed) instead of the page-side versions, and update the harness's@positionand README now that an accessibility spec depends on it.
[Automated review]
| await expect(page.locator('dialog[open]')).toHaveCount(1); | ||
| const after = await combinedDim(); |
There was a problem hiding this comment.
This is the only read of the takeover, and it runs on the real clock: the dialogs' ::backdrop transition is neither held nor stretched (only .astryx-bottom-sheet is). If the takeover lost its 0 s pin, the entering backdrop would fade in over the 410 ms --duration-medium curve and be back above steady * 0.9 about 160 ms in, so this check catches it only when the read lands sooner. Could the takeover be held or stepped by progress too, or could the test assert that no ::backdrop transition is running on an open sheet dialog here?
| * transition by its progress, so its length doesn't change what they read. | ||
| * Also installs the page-side reads `nextHandoffPhase` and `combinedDim` use. | ||
| */ | ||
| async function holdHandoff(page: Page) { |
There was a problem hiding this comment.
@astryxdesign/interaction-harness already covers this flow: waitForRest, holdAnimations, seekAnimations (with END_INSET_MS) and releaseAnimations({finish: true}) in curves.ts. The harness hold also takes ::backdrop transitions, which this copy misses. Could the test call those helpers, and extend holdAnimations if pausing at transitionrun really is needed?
efdb459 to
c072a18
Compare
|
Both points are addressed at c072a18:
|
There was a problem hiding this comment.
Changes requested: holding the handoff phase by phase with the interaction harness makes both checks deterministic, and a double dim, a retained dialog without inert and an inert entering dialog now fail in both Chromium and WebKit. One gap remains: the takeover guard keeps only transitions whose pseudoElement is '::backdrop' (lines 314 and 549), but WebKit reports an empty pseudoElement for ::backdrop transitions, so in WebKit a takeover that fades still passes once the read at line 542 lands about 160 ms after the close. Please also count an opacity transition targeted at the sheet dialog in both the transitionrun listener and the getAnimations() scan; with that change a forced 410 ms takeover fade fails at every read delay in both engines.
[Automated review]
| document.addEventListener( | ||
| 'transitionrun', | ||
| event => { | ||
| if (event.pseudoElement === '::backdrop') { |
There was a problem hiding this comment.
WebKit dispatches a ::backdrop transition's transitionrun on the dialog with pseudoElement === '', so this never records it there: a forced 410 ms takeover fade passes in WebKit once the read at line 542 lands about 160 ms late. Counting the dialog's own opacity transition too closes it in both engines (these dialogs run no opacity transition of their own):
if (
event.pseudoElement === '::backdrop' ||
(event.target instanceof HTMLDialogElement && event.propertyName === 'opacity')
) {| ...(window as unknown as {__backdropRuns: string[]}).__backdropRuns, | ||
| ...document.getAnimations().flatMap(animation => { | ||
| const effect = animation.effect as KeyframeEffect | null; | ||
| return effect?.pseudoElement === '::backdrop' |
There was a problem hiding this comment.
Same in the scan: WebKit's KeyframeEffect.pseudoElement is '' for the running ::backdrop transition, so it is dropped here as well. Matching effect?.target instanceof HTMLDialogElement with transitionProperty === 'opacity' alongside the '::backdrop' check catches it.
…ff held The scrim and Tab checks for a switcher handoff in BottomSheetNativeModal.a11y.browser.spec.ts counted frames and Tab presses inside a handoff running in wall time. Both now hold each handoff phase with the interaction harness (sheet panel transitions stretched, held with holdAnimations and read with seekAnimations; the page's timers frozen) and read it at fixed points: the scrim at 0-100% of each phase in 5% steps, Tab six times per phase. The scrim check also fails if any backdrop transition runs through the handoff, so a takeover that fades can't pass between two reads. The harness's entry point and README say an accessibility spec may use its holds now.
c072a18 to
771358b
Compare
|
Fixed at 771358b. Both the With a takeover forced to fade over 410 ms, the check now fails in both Chromium and WebKit whether the read lands at once or 160, 200 or 250 ms late. At c072a18, WebKit passed the 160, 200 and 250 ms reads. The unmutated test still passes in both engines. |
There was a problem hiding this comment.
Approval recommended: holding the handoff phase by phase with the interaction harness makes both checks independent of machine speed, and the widened guard now fails a takeover that fades in WebKit as well as Chromium. A forced double dim, a fading takeover read up to 600 ms late, a retained dialog without inert and an inert entering dialog each fail the new tests in both engines, so no further changes are needed.
[Automated review]
Maintainer impact
Two handoff checks in
BottomSheetNativeModal.a11y.browser.spec.tsdepend on how fast the machine runs, even though the switcher is correct:On a slower machine fewer fit. In WebKit with 2 CPUs and 16 workers, the scrim check fails 2 of 6 runs on main (8 and 15 samples). This came up while stress-testing the scroll-lock change in #8098 (
spec:AST-094).Intended invariant
Unchanged: one steady scrim through a handoff (no dip, no double dim); focus only in the entering sheet's dialog; the retained dialog
inertandaria-hiddenuntil it closes.Change
Both tests hold the handoff phase by phase with the interaction harness instead of racing it:
waitForRest), panel transitions are stretched to 1000 s and the harness's timer gate freezes the page's timers, so the panels'transitionendbackstop can't advance the handoff. A hold sent from the test arrives a round trip after a transition starts, and a 300 ms one can end before then; a stretched one is still near its start. Held transitions are read by progress, so their length doesn't change the reading.watchAnimationson the panels that move in it and held withholdAnimations.releaseAnimations({finish: true})moves the flow on.seekAnimations, and once after the retained dialog closes. It also fails if any::backdroptransition ran or is running through the handoff, so a takeover that fades can't pass between two reads. WebKit reports such a transition on the dialog itself, with an emptypseudoElement, so anopacitytransition on a sheet dialog counts too.click()on Continue. A pointer press runs its own frames and timers, which the gate would hold.@positionand README now say an accessibility spec may use its holds and timer gate.The assertions are unchanged.
Evidence
CI=1, 1 worker, ×10): 40/40.body).inert(the slide's first Tab).Scope
Testing
Local gates at 771358b:
It merges cleanly with main.