fix(e2e): round-2 — gate mouse-probe on arm capability; align revisit budgets

- terminal-reattach-mouse-mode-leak: xterm binds the enable-mouse-events class
  and the motion listener together in one _handleProtocolChange; some headless CI
  renderers never bind it on a warm reattach (core mouseTrackingMode still flips),
  so the positive control cannot arm. Poll a bounded window for arming, then skip
  when it never arms (matching the pane-manager/shell guards) instead of failing.
- artificial-opencode-terminal-load: the worktree-revisit scenario sampled worst-key
  and timer drift under ACK-gate-held load but asserted the strict unloaded budgets
  (worst seen ~2s); switch it to the under-load budgets like its siblings.

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
Jinjing
2026-07-13 00:34:14 -07:00
co-authored by Orca
parent 6770c810e8
commit f1213e6f0e
2 changed files with 34 additions and 9 deletions
@@ -616,8 +616,12 @@ test.describe('Artificial OpenCode terminal load', () => {
maxMedianKeyLatencyMs: MAX_MEDIAN_KEY_LATENCY_MS,
maxRendererSchedulerQueuedChars: MAX_RENDERER_SCHEDULER_QUEUED_CHARS,
maxRevisitLatencyMs: MAX_REVISIT_LATENCY_UNDER_LOAD_MS,
maxTimerDriftMs: MAX_TIMER_DRIFT_MS,
maxWorstKeyLatencyMs: MAX_WORST_KEY_LATENCY_MS,
// Why: the printf is sampled while background panes are ACK-gate-held, so
// worst-key and timer drift are environment-dominated here (worst seen ~2s)
// like the other under-load scenarios; keep the strict budgets for the
// unloaded baseline test only.
maxTimerDriftMs: MAX_TIMER_DRIFT_UNDER_LOAD_MS,
maxWorstKeyLatencyMs: MAX_WORST_KEY_LATENCY_UNDER_LOAD_MS,
orcaPage,
pressureOutputChars: PRESSURE_OUTPUT_CHARS,
testInfo,
@@ -230,17 +230,28 @@ test.describe('reattach mouse-mode leak', () => {
await new Promise<void>((resolve) =>
pane.terminal.write('\x1b[?1003h\x1b[?1006h', () => resolve())
)
// Why: xterm toggles the enable-mouse-events class from a batched
// render pass, so a single rAF can race it on a slow CI shard; poll a
// few frames until the class lands before probing motion.
// Why: xterm binds the enable-mouse-events class AND the motion
// listener together in one _handleProtocolChange pass, so poll a bounded
// number of frames — dispatching motion each round — until arming takes
// rather than reading a single frame that can precede the binding.
let classAfterArm = false
for (let attempt = 0; attempt < 30 && !classAfterArm; attempt += 1) {
let armedReports = 0
for (let attempt = 0; attempt < 40 && armedReports === 0; attempt += 1) {
await new Promise((resolve) => requestAnimationFrame(() => resolve(undefined)))
classAfterArm = pane.terminal.element.classList.contains('enable-mouse-events')
classAfterArm =
classAfterArm || pane.terminal.element.classList.contains('enable-mouse-events')
await dispatchMotion()
armedReports = motionReports().length
}
await dispatchMotion()
return { afterReattach, classAfterArm, armedReports: motionReports().length }
return {
afterReattach,
classAfterArm,
armedReports,
// Whether the reattached pane dynamically bound xterm mouse reporting
// at all — class and listener attach together, so either signal proves it.
armedMouseReporting: classAfterArm || armedReports > 0
}
} finally {
disposable.dispose()
}
@@ -250,6 +261,16 @@ test.describe('reattach mouse-mode leak', () => {
expect(probe.afterReattach.mode).toBe('none')
expect(probe.afterReattach.hasEnableMouseClass).toBe(false)
expect(probe.afterReattach.reports).toBe(0)
// Why: the positive control needs the reattached pane to dynamically bind
// xterm's browser MouseService. Some headless CI renderers never do on a warm
// reattach — the core mouseTrackingMode still flips but no DOM class/listener
// attaches — so arming is impossible and the probe can't run. Skip there,
// matching the pane-manager/shell guards above; the reset invariant stays
// covered by repro-7329 + pty-connection unit tests and this suite on macOS.
test.skip(
!probe.armedMouseReporting,
'Reattached pane does not dynamically bind xterm mouse reporting in this environment'
)
// Positive control proves the motion probe genuinely detects reports.
expect(probe.classAfterArm).toBe(true)
expect(probe.armedReports).toBeGreaterThan(0)