Skip to content

test(core): the segmented slide's busy proof starts in time - #10315

Merged
cixzhang merged 3 commits into
meta:mainfrom
vjeux:test/segmented-slide-busy-start
Nov 7, 2026
Merged

cixzhang merged 3 commits into
meta:mainfrom
vjeux:test/segmented-slide-busy-start

Conversation

@vjeux

@vjeux vjeux commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

Stacked on #10286: only the last commit is this change. It stays a draft until #10286 lands.

Maintainer impact

SegmentedControl's "the slide keeps advancing every frame while the main thread is blocked" (Chromium) could start its block after the slide had settled. The test tapped, waited for the slide, painted the lens and then blocked: three round trips. Under the CI lane's CPU quota with load, that threw BusyWindowTooLateError. The case also counted frames against the frame rate (expectedFrames - 2), which a quota starves.

Intended invariant

Unchanged: the slide advances on the compositor through a main-thread block. No product code changes, and no timeout, retry or skip.

Change

  • The lens is painted in the marker colour before the tap. An important rule keeps that colour, since the tap's render writes the lens's own.
  • The page arms blockMainThread(…, {during: control.group}) before the tap. It blocks once the slide has run 16 ms, on the compositor.
  • The case judges against the harness's busy-window control (startBusyControl, trackControl), until the lens is within 1 px of rest.

Evidence

Every commit named here is evidence, not for landing.

  • Failure before / success after, in one container at the CI lane's profile (--cpus=4, CI=1, one worker) with eight busy loops: before, the case failed 1 of 10 on main (028e6ca19d) and 1 of 20 on test: watch before the action at 28 first-contact waits #10286's head, each with BusyWindowTooLateError. This change passed 10 of 10.
  • Mutants fail on the verdict, 3 of 3 without load and 3 of 3 loaded:
    • febffa35af: every animation runs on the main thread. The slide moved on 0 of the control's 27 frames.
    • 2fd7e98967: every animation holds its first keyframe. The slide moved on 0 of 27.
  • Product/runtime behavior verified unchanged: a test-only change.
  • CI impact: none; no workflow changes.

Scope

  • No intended public API, product behavior, visual direction, or policy change.
  • Product changes discovered during the work were removed or split.
  • Public text and artifacts contain no internal Meta context.

Testing

@vercel

vercel Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
astryx Ready Ready Preview Nov 7, 2026 10:50am UTC

Request Review

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Nov 6, 2026
@astracat-bot

astracat-bot Bot commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

AI review status for this pull request.

Review status Updated
🟢 Reviewed (for maintainers only) Nov 7, 2026, 11:05 AM UTC

@github-actions

github-actions Bot commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

🔎 Preview · 81551e8

Storybook · Sandbox · built from this PR's head

Modified components

Component Size LoC Visual · A11y · RTL
SegmentedControl 91.4 kB (0) · 6.8 kB CSS (0) — ✓ · ✓ · ✓
SegmentedControlItem 16.5 kB (0) · 4.3 kB CSS (0) — ✓ · ✓ · ✓

Package size: no published package changed; no new dependencies.

API changes: none in this pull request

Committed API report behind this build: cli 19 rows, core 25 rows; run pnpm api:report.

Touched components checked; add ci:run-visual, ci:run-a11y or ci:run-rtl to run the full suites.


Generated by PR Enrichment workflow | View full report

@cixzhang

cixzhang commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

/approve-spec 7818c09

@cixzhang cixzhang added the ci:run A maintainer lets this outside contributor's pull request run CI (AST-030 FR17) label Nov 6, 2026

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved pending CI: the SegmentedControl busy-main-thread case now arms its block in the page before the tap and judges the slide against the busy-window control, and the other changes only take watchAnimations before the action. This diff also carries #10286's commit, so it lands after #10286 or together with it.

  • Non-blocking: paintLensMarker (SegmentedControl.interaction.browser.spec.ts:389-408) no longer has a caller and adds a @typescript-eslint/no-unused-vars warning, so delete it or move the new !important rule into it and call it from the busy case.

CI has not run on this head yet because the pull request is a draft; it already carries ci:run, so marking it ready for review starts CI.

[Automated review]

// The lens has no element to carry the harness's marker chip, so the test
// paints the lens itself in the marker colour before the tap. The tap
// writes the lens's own colour, and an important rule keeps the marker's.
await control.group.evaluate((group, rgb) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking: this replaces paintLensMarker (line 394), which now has no caller and adds a @typescript-eslint/no-unused-vars warning. Delete the helper, or move this !important rule into it and call it here.

The block started after three round trips from the test, so on a loaded
machine the slide had settled when it began. The page now paints the
lens first and arms the block before the tap. The proof judges the slide
against the busy-window control, not against the frame rate.
@vjeux
vjeux force-pushed the test/segmented-slide-busy-start branch from 7818c09 to 2e7a318 Compare November 7, 2026 04:11
@cixzhang

cixzhang commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

/approve-spec 2e7a318

@cixzhang

cixzhang commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

/approve-spec 5e02c9e

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved pending CI: the SegmentedControl busy-main-thread case now arms its block in the page before the tap and judges the slide against the busy-window control, so the block no longer starts after the slide has settled on a loaded runner.

  • Regression (non-blocking): after main's rework of this file's other lens cases, the busy case was the last caller of waitForLens (SegmentedControl.interaction.browser.spec.ts:228-282), so the helper is now unused and adds a @typescript-eslint/no-unused-vars warning; delete it with the waitForAnimation and AnimationWatch imports that only it uses.
  • Non-blocking: paintLensMarker (SegmentedControl.interaction.browser.spec.ts:364-383) still has no caller and adds the same warning, so delete it too.

CI has not run on this head because the pull request is a draft. It carries ci:run, so marking it ready for review starts CI.

[Automated review]

});
await control.tapSegment('table');
// Running and composited before the block.
const [slide] = await waitForLens(control, {minProgressMs: 16, watch});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regression (non-blocking): main has since moved this file's other lens cases to holds from the slide's start, so this was the last call to waitForLens (now line 232 of the head). The helper is unused after this change and adds a second @typescript-eslint/no-unused-vars warning. Delete it, together with the waitForAnimation and type AnimationWatch imports (lines 60 and 66) that only it uses.

@vjeux
vjeux marked this pull request as ready for review November 7, 2026 07:59
@cixzhang

cixzhang commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

/approve-spec 81551e8

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved: the SegmentedControl busy-main-thread case now arms its block in the page before the tap and judges the slide against the busy-window control, so a loaded runner can no longer start the block after the slide has settled. On this head the case passes in CI's Chromium interaction lane with the lens moving on every frame the control moves, and CI is green.

Optional, non-blocking:

  • waitForLens and paintLensMarker have no callers after this change (noted inline); deleting them, with the waitForAnimation and AnimationWatch imports only waitForLens uses, clears two lint warnings.
  • Now that blockMainThread takes pseudoElement, passing pseudoElement: '::before' would let only the lens start the block, not another animation under the radiogroup such as a segment's press release.

[Automated review]

@cixzhang
cixzhang merged commit f1ad44f into meta:main Nov 7, 2026
73 checks passed
@vjeux
vjeux deleted the test/segmented-slide-busy-start branch November 7, 2026 12:41

This branch was successfully deployed

1 active deployment
Preview — 81551e85 Deployed Nov 7, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:run A maintainer lets this outside contributor's pull request run CI (AST-030 FR17) CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants