test(picker): de-flake both Windows switch-picker PTY tests - #3242
Conversation
`test_switch_picker_alt_x_keeps_cursor_sticky` drives the interactive skim picker in a PTY, removes a row with alt-x, presses Enter, and asserted the process exited 0. On Windows this intermittently failed with exit code 1 even though the switch verifiably succeeded — the captured screen shows the `--format=json` result and the "Switched to worktree for wt-keep" success message. The test's actual belief — alt-x keeps the cursor on the slid-up row, so Enter switches there rather than to the current worktree at the top — is fully verified by the screen assertions (the JSON result is emitted only after the switch pipeline ran, and it names the sticky landing row). The exit-code-0 pin coupled that belief to the interactive session's process exit code, which is a separate, racy signal on Windows (this file's `assert_valid_abort_exit_code` already treats skim PTY exit codes as non-deterministic: 0/1/130). Accept skim's selection/abort codes (0 or 1) rather than pinning to 0. A gross failure (panic, crash) still fails the screen assertions, which require the success output to be present. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
fix all the flakes please! (sorry for having introduced them) |
…n feature
`test_switch_picker_worktree_row_comments_tab_shows_thread` drove the
picker with a single blind `Down` (`("\x1b[B", None)`) to move the cursor
onto `feature`, then Alt-1 and waited for `feature`'s `diff --git`. On
Windows CI it timed out after 30s — the captured screen showed the `>`
pointer stranded on `main` ("○ main has no uncommitted changes" in the
HEAD± preview), so the awaited `diff --git` never appeared.
Root cause: `feature`'s row decorates asynchronously (primed CI status
resolves to "has PR" in the background). When that resolution lands it
refreshes skim's item list, which resets the cursor to the top — undoing
the `Down` and leaving the pointer on the primary worktree. The existing
preview-reissue nudge then re-ran Alt-1 against `main` forever.
Make `Down` cursor-confirmed: when a Up/Down arrow step carries expected
content, treat it as the target row name and re-issue the (idempotent)
arrow via `wait_for_stable_until`'s nudge until the `>` pointer lands on
that row and the screen settles — by which point the list has stopped
refreshing. The comments-tab step becomes `("\x1b[B", Some("feature"))`.
This mirrors the alt-digit preview re-issue added in #3238 and reuses
`wait_for_cursor_on_row`'s pointer predicate (factored out as
`cursor_points_at`). Arrow steps that pass `None` (every other test) are
unaffected — they still fall through to a plain stability wait.
Refs #3241
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Done — pushed a fix for the second flake so this PR now covers both Windows picker PTY tests that blocked #3241. I pulled the failing run's logs to confirm the root causes from the captured screens rather than guess:
Those were the only two failures across the run's attempts. The full |
|
✅ CI is green on |
|
This flake just recurred on So this is reproducing on the default branch too, not just on #3241's PR CI — adding a data point for the cursor-reset root cause this PR fixes. No separate ci-fix PR; #3242 already covers it. |
|
@worktrunk-bot resolve conflicts |
Resolves the conflict in tests/integration_tests/switch_picker.rs. main (#3247) added PreviewNotifier, which auto-repaints a late preview when its background compute lands, and removed the test-side Alt-<digit> keystroke re-issue that #3238 used to paper over stranded "Loading…" placeholders. The two de-flakes in this PR are orthogonal to that: - Flake #1 (alt-x sticky exit code) — a separate region, auto-merged cleanly. - Flake #2 (comments-tab cursor reset) — kept. PreviewNotifier re-runs only the *preview* for the selected row (notify_row_changed); it does not stop on_update's request_render from resetting skim's cursor to the top after an async row decoration lands. So the cursor-confirmed Down is still needed. Resolution keeps the cursor-arrow re-issue (restored wait_for_stable_until's nudge param, now scoped to cursor recovery and renamed PREVIEW_REISSUE_INTERVAL -> CURSOR_REISSUE_INTERVAL) and drops the obsolete Alt-<digit> re-issue branch (is_alt_digit_tab deleted) in favor of main's PreviewNotifier path. Full switch_picker suite passes locally on Linux. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Resolved the conflict and pushed the merge ( The only conflict was in
So the resolution keeps the cursor-arrow re-issue (restored The full |
|
✅ CI is green on |
What
De-flakes both Windows
switch_picker.rsPTY tests that intermittently blocked #3241'stest (windows)job. Attempt 1 of that run failed ontest_switch_picker_alt_x_keeps_cursor_sticky; attempt 2 failed ontest_switch_picker_worktree_row_comments_tab_shows_thread. Both are addressed here.Flake 1 —
alt_x_keeps_cursor_sticky: racy process exit codeThe test drives the interactive skim picker in a PTY, removes a row with alt-x, presses Enter, and asserted the
wtprocess exited0. On Windows it intermittently failed with exit code 1 even though the switch verifiably succeeded — the captured screen shows both the structured result and the success message:The cursor-stickiness belief is fully verified by the screen assertions: the
--format=jsonresult reaches stdout only after the switch pipeline ran, and it names the sticky landing row. Theexit_code == 0pin coupled that belief to the interactive session's process exit code, a separate racy signal on Windows (this file'sassert_valid_abort_exit_codealready treats skim PTY exit codes as non-deterministic: 0/1/130). The fix keeps the screen-based success verification and accepts skim's selection/abort codes (0 or 1) instead of pinning to 0.Flake 2 —
comments_tab_shows_thread: cursor reset by async row decorationThe test moved the cursor onto
featurewith a single blindDown, then opened the HEAD± tab and waited forfeature'sdiff --git. On Windows it timed out after 30s. The captured failing screen shows the>pointer stranded onmain, with the preview reading "○ main has no uncommitted changes" — so the awaiteddiff --gitnever appeared:Root cause:
feature's row decorates asynchronously — the primed CI status resolves to "has PR" in the background. When that resolution lands it refreshes skim's item list, which resets the cursor to the top, undoing theDown. The preview re-issue nudge from #3238 then re-ran Alt-1 againstmainforever.Fix: make
Downcursor-confirmed. When a Up/Down arrow step carries expected content, it now names the target row, and the wait re-issues the (idempotent) arrow until the>pointer lands on that row and the screen settles — by which point the list has stopped refreshing. The step becomes("\x1b[B", Some("feature")). This mirrors the alt-digit preview re-issue and reuseswait_for_cursor_on_row's pointer predicate (factored out ascursor_points_at). Arrow steps that passNone(every other test) are unaffected.Verification
Both flakes are Windows-specific PTY races I could not reproduce on the Linux CI runner, so the fixes mirror this file's established de-flake patterns rather than root-causing platform exit-code / scheduling behavior. The full
switch_pickersuite (35 tests) passes locally on Linux, including both changed tests and every consumer of the shared helpers (wait_for_cursor_on_row,send_input_awaiting_content). The Windows CI on this PR exercises both on the affected platform.Refs #3241