Repository navigation
test(core): the swipe spring-back read stops the scene at the lift - #10432
Conversation
The spring-back proof read the row 60 ms after its lift, from a timer the test process started after the lift. That read comes a round trip late, and on a loaded runner the spring back was over. The proof now freezes the scene in the lift's own task, moves it on 60 ms by its own clock, reads, and thaws.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
PR Analysis Report🔎 Preview ·
|
| Component | Size | LoC | Visual · A11y · RTL |
|---|---|---|---|
| Item · Storybook | 16.3 kB (0) · 5.5 kB CSS (0) | 1,697 (0) | ✓ · ✓ · — |
Package size: measured; main has no measurement of the merge base to compare yet.
API changes: cli +14 · ~5 · −0 (against the merge base's committed report)
Committed API report behind this build: cli 19 rows, core 24 rows; run pnpm api:report.
19 API changes (advisory)
| Package | Where | Signature | Usage | |
|---|---|---|---|---|
| + | cli |
./api · Types · type SearchResultEntry |
deprecated?: ComponentDeprecation | undefined |
import type {SearchResultEntry} from '@astryxdesign/cli/api'; const x: SearchResultEntry = {deprecated: …} |
| + | cli |
./authoring · Types · interface ComponentDeprecation |
interface ComponentDeprecation |
import type {ComponentDeprecation} from '@astryxdesign/cli/authoring' |
| + | cli |
./authoring · Types · interface ComponentIconSlotDoc |
interface ComponentIconSlotDoc |
import type {ComponentIconSlotDoc} from '@astryxdesign/cli/authoring' |
| + | cli |
./authoring · Types · interface ComponentIconSlotStateDoc |
interface ComponentIconSlotStateDoc |
import type {ComponentIconSlotStateDoc} from '@astryxdesign/cli/authoring' |
| + | cli |
./authoring · Types · interface MultiComponentDoc |
deprecated?: ComponentDeprecation |
import type {MultiComponentDoc} from '@astryxdesign/cli/authoring'; const x: MultiComponentDoc = {deprecated: …} |
| + | cli |
./authoring · Types · interface SingleComponentDoc |
deprecated?: ComponentDeprecation |
import type {SingleComponentDoc} from '@astryxdesign/cli/authoring'; const x: SingleComponentDoc = {deprecated: …} |
| + | cli |
./doc · Types · interface ComponentBaseDoc |
deprecated?: ComponentDeprecation |
import type {ComponentBaseDoc} from '@astryxdesign/cli/doc'; const x: ComponentBaseDoc = {deprecated: …} |
| + | cli |
./doc · Types · interface SubComponentDoc |
deprecated?: ComponentDeprecation |
import type {SubComponentDoc} from '@astryxdesign/cli/doc'; const x: SubComponentDoc = {deprecated: …} |
| + | cli |
./doc · Also exported from an earlier entry point · ComponentDeprecation |
ComponentDeprecation (./authoring) |
import {ComponentDeprecation} from '@astryxdesign/cli/doc' |
| + | cli |
./doc · Also exported from an earlier entry point · ComponentIconSlotDoc |
ComponentIconSlotDoc (./authoring) |
import {ComponentIconSlotDoc} from '@astryxdesign/cli/doc' |
| + | cli |
./doc · Also exported from an earlier entry point · ComponentIconSlotStateDoc |
ComponentIconSlotStateDoc (./authoring) |
import {ComponentIconSlotStateDoc} from '@astryxdesign/cli/doc' |
| + | cli |
./template · Also exported from an earlier entry point · ComponentDeprecation |
ComponentDeprecation (./authoring) |
import {ComponentDeprecation} from '@astryxdesign/cli/template' |
| + | cli |
./template · Also exported from an earlier entry point · ComponentIconSlotDoc |
ComponentIconSlotDoc (./authoring) |
import {ComponentIconSlotDoc} from '@astryxdesign/cli/template' |
| + | cli |
./template · Also exported from an earlier entry point · ComponentIconSlotStateDoc |
ComponentIconSlotStateDoc (./authoring) |
import {ComponentIconSlotStateDoc} from '@astryxdesign/cli/template' |
| ~ | cli |
./api · Functions · function search |
function search: (query: string, options?: { cwd?: string | undefined; type?: "template" | "component" | "hook" | "theme" | "doc" | undefined; limit?: number | undefined }) => Promise<SearchResponse> → function search: (query: string, options?: { cwd?: string | undefined; type?: "template" | "component" | "doc" | "theme" | "hook" | undefined; limit?: number | undefined }) => Promise<SearchResponse> |
import {search} from '@astryxdesign/cli/api'; search(…) |
| ~ | cli |
./authoring · Types · interface MultiComponentDoc |
theming?: { container?: boolean; targets: ComponentThemingTarget[]; vars?: ComponentThemingVar[]; derived?: ComponentThemingDerivedVar[] } → theming?: { container?: boolean; targets: ComponentThemingTarget[]; vars?: ComponentThemingVar[]; derived?: ComponentThemingDerivedVar[]; componentIcons?: ComponentIconSlotDoc[] } |
import type {MultiComponentDoc} from '@astryxdesign/cli/authoring'; const x: MultiComponentDoc = {theming: …} |
| ~ | cli |
./authoring · Types · interface SingleComponentDoc |
theming?: { container?: boolean; targets: ComponentThemingTarget[]; vars?: ComponentThemingVar[]; derived?: ComponentThemingDerivedVar[] } → theming?: { container?: boolean; targets: ComponentThemingTarget[]; vars?: ComponentThemingVar[]; derived?: ComponentThemingDerivedVar[]; componentIcons?: ComponentIconSlotDoc[] } |
import type {SingleComponentDoc} from '@astryxdesign/cli/authoring'; const x: SingleComponentDoc = {theming: …} |
| ~ | cli |
./doc · Types · interface ComponentBaseDoc |
theming?: { container?: boolean; targets: ComponentThemingTarget[]; vars?: ComponentThemingVar[]; derived?: ComponentThemingDerivedVar[] } → theming?: { container?: boolean; targets: ComponentThemingTarget[]; vars?: ComponentThemingVar[]; derived?: ComponentThemingDerivedVar[]; componentIcons?: ComponentIconSlotDoc[] } |
import type {ComponentBaseDoc} from '@astryxdesign/cli/doc'; const x: ComponentBaseDoc = {theming: …} |
| ~ | cli |
./doc · Types · interface SubComponentDoc |
theming?: { container?: boolean; targets: ComponentThemingTarget[]; vars?: ComponentThemingVar[]; derived?: ComponentThemingDerivedVar[] } → theming?: { container?: boolean; targets: ComponentThemingTarget[]; vars?: ComponentThemingVar[]; derived?: ComponentThemingDerivedVar[]; componentIcons?: ComponentIconSlotDoc[] } |
import type {SubComponentDoc} from '@astryxdesign/cli/doc'; const x: SubComponentDoc = {theming: …} |
Touched components checked; add ci:run-visual or ci:run-rtl to run the full suites.
Generated by PR Enrichment workflow | View full report
|
AI review status for this pull request.
|
There was a problem hiding this comment.
Approved pending CI: CI has not run on this head yet. The pull request is a draft from a fork, so CI starts once it is marked ready for review and a maintainer adds the ci:run label (it takes effect on the next push or a close and reopen).
The spring-back read now runs on the scene's clock: with 150 ms of runner lag after the lift, the old read failed in all five runs and the new one passed in all five, about 60 ms into the spring back as intended.
Non-blocking suggestion:
- The comment above
freezePageOn(page, 'touchend')says the scene stops before the row hears the lift, but the row hearspointerupfirst and the read relies on that; arming onpointerupinstead reads at 0 ms and passes without checking the panel, so please reword the comment (suggestion inline) and the matching sentence in the description.
[Automated review]
| // The scene stops in the lift's own task, before the row hears the lift, | ||
| // and moves on 60 ms by its own clock. A read sent after the lift comes a | ||
| // round trip late, and a loaded runner can find the spring back over. |
There was a problem hiding this comment.
Non-blocking: the row hears the lift before this freeze. It handles pointerup (useSwipeAction.ts:672), and Chromium dispatches pointerup before touchend, so settle() has already written the duration and travel when the freeze lands; the freeze's style flush then starts the transitions and holds them at their start. Armed on pointerup, as this comment reads, the freeze runs before settle(), nothing is held, and the read lands at 0 ms with the row and the panel both at 30 px, so the check passes without testing the panel. Suggested wording:
| // The scene stops in the lift's own task, before the row hears the lift, | |
| // and moves on 60 ms by its own clock. A read sent after the lift comes a | |
| // round trip late, and a loaded runner can find the spring back over. | |
| // The row hears the lift first, on pointerup, and writes its settle. The | |
| // freeze lands on touchend in the same task, before the settle's | |
| // transitions start, and holds them at their start. A read sent after the | |
| // lift comes a round trip late, and a loaded runner can find the spring | |
| // back over. |
The spring-back check in
ItemSwipeActions.a11y.chromium.spec.tsnow reads the row 60 ms after its lift on the scene's own clock, by stopping the scene at the lift, instead of from a timer the test process starts after it. This is a test-only change onmain.Maintainer impact
"Paints no panel at rest, keeps the panel fixed while the row moves, rests open on a real button, and springs back with the panel" reads the row mid-flight, 60 ms into its spring back. The test process started that 60 ms timer only once its read reached the page, a round trip after the lift. On a loaded runner the spring back was over by then, and the check failed with nothing wrong.
Intended invariant
60 ms after the lift, the row is still on its way home and the panel is as wide as the gap the row has not yet covered, as before. The assertions are unchanged.
Change
freezePageOn(page, 'touchend')before it lifts the finger. The scene freezes in the lift's own task, before the row hears the lift, andadvanceFrozenPage(page, 60)moves it on 60 ms by its own clock. The test reads the row and the panel, then thaws.Evidence
Scope
Testing
ItemSwipeActions.a11y.chromium.spec.ts: 3 of 3 in Chromium (the spec is Chromium-only: it drives touch through the browser's protocol).