Skip to content

test(terminal): a drag in the copy regression waits for its own viewport position - #573

Merged
devswha merged 1 commit into
mainfrom
fix/terminal-copy-flake
Oct 7, 2026
Merged

devswha merged 1 commit into
mainfrom
fix/terminal-copy-flake

Conversation

@devswha

@devswha devswha commented Oct 7, 2026

Copy link
Copy Markdown
Owner

Change

scripts/terminal-copy-regression.ts raced the page in its drag steps (#551).

A press in the desktop terminal asks herdr where the pane's viewport sits (GET /api/pane/scroll). A release that comes before that answer has no history row to map the selection to. It still copies the visible text with the native copy (PaneTerminal.tsx copySelection, document.execCommand("copy")), shows "copied to clipboard", and returns before it reserves the async navigator.clipboard.write (onMouseUp, if (!range) return). The script's recorder counts only navigator.clipboard.write/writeText, so under load (a slow scroll answer) clipboardGesture.writes stayed [] and the assertion at line 86 failed. The clipboard and the banner were already right. This matches the CI failure in #551.

The product behaves as intended: copying the visible text when the position is not known yet is the documented fallback. So the fix is in the test. Each press now waits for its own scroll position instead of racing it: the init script counts the /pane/scroll reads the page asked for and the ones still open, and a press waits until its read was asked for and none is open, so an answer to an earlier press cannot stand in for it. The three steps that guessed with waitForTimeout(200) ("the viewport position arrives") use the same wait.

Fixes #551

Validation

On a herdr of the run's own (bun run check run), with a scratch runner that runs checkTerminalCopy alone and can hold GET /api/pane/scroll (not committed):

  • Before, unchanged script: 3 of 3 normal runs passed; with the scroll answer held 600 ms, 1 of 1 failed with the Flaky test: terminal-copy-regression.ts finds no clipboard write inside mouseup after a plain drag #551 assertion (drag copy must begin inside mouseup, + []).
  • After: with the scroll answer held 600 ms, 3 of 3 passed; 5 of 5 normal runs passed. A first draft that counted any scroll response failed 3 of 3 under the hold at a later step (first selection response held), because a double-click's late answer released the next press; counting asked and open reads fixed that.
  • bun run check fast: passed (1699 pass, 4 skip, 0 fail), run before the final wait change; it does not cover scripts/, which the runs above exercise.

No CHANGELOG entry: the change is test-only and nothing a user notices.

…ort position

A release that arrives before the press's GET /api/pane/scroll answer copies
the visible text natively and never calls navigator.clipboard.write, so the
recorder saw no write and the plain drag step failed under load (#551).
Each press now waits until its scroll read was asked for and none is open.
@coderabbitai

coderabbitai Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: devswha/herdr-web-ui/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 34f94b39-a196-4854-9796-19ad5372b4cc
📥 Commits

Reviewing files that changed from the base of the PR and between f8f09d1 and 7b343b1.

📒 Files selected for processing (1)
  • scripts/terminal-copy-regression.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 4 remain after this review.


📝 Summary

Summary by CodeRabbit

  • Tests
    • Improved reliability of drag-and-scroll regression checks by waiting for scroll-position requests to complete before continuing drag interactions. Coverage for bottom-edge, wheel-scrolled, and top-edge drags now uses this synchronization instead of fixed delays.

Walkthrough

The terminal copy regression script now tracks /pane/scroll requests and waits for the press-triggered request to complete before continuing drag tests. Bottom-edge, wheel-scrolled, and top-edge drag cases use this synchronization instead of fixed delays.

Changes

Terminal copy drag synchronization

Layer / File(s) Summary
Track scroll requests and synchronize drags
scripts/terminal-copy-regression.ts
The script tracks open GET requests to /pane/scroll. The press helper waits for a newer request to complete before the drag continues. Bottom-edge, wheel-scrolled, and top-edge cases use the helper instead of fixed delays.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Other · Severity of issue fixed: Low

Merge Risk: ⚪ Minimal · up to 7b343

The drag regression now waits for the scroll-position request before continuing. No merge-blocking issue was identified.

Architecture Summary

Architecture risk: 🟡 Medium · up to 7b343

The change affects 1 system.

Changed systems: scripts

Architecture concerns
No architecture-level concerns identified.

Review details

Systems and components

  • observed — scripts (service) was modified; 1 changed file maps to changed impact.

Before / after behavior

  • observed — Modified behavior in scripts/terminal-copy-regression.ts: The clipboard test state now tracks scroll requests asked for and still open. A fetch wrapper counts only GET requests to /pane/scroll, and closes each request’s open count after a failed response, JSON consumption, or fetch error.
  • observed — Modified behavior in scripts/terminal-copy-regression.ts: Adds press, which records the current request count, presses the mouse, and waits until a newer scroll request has completed before allowing the drag to continue.
  • observed — Modified behavior in scripts/terminal-copy-regression.ts: The drag helper replaces its direct mouse-down with press, so drag input waits for the press-triggered scroll-position request to complete.
  • observed — Modified behavior in scripts/terminal-copy-regression.ts: The bottom-edge drag now uses press instead of mouse-down followed by a fixed 200 ms wait.

Reliability and maintainability

  • inferred — Risk-relevant change factors for scripts: blast_radius_1; direct_dependents_1
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the test change: the drag now waits for its own viewport position. It is concise and directly matches the primary changeset objective.
Description check ✅ Passed The description includes the required Change and Validation sections. It explains the race condition, the test fix, linked issue, validation results, and why no changelog entry is needed. The reported…
Linked Issues check ✅ Passed Issue #551 requires resolving the flaky terminal copy regression test. The diff updates scripts/terminal-copy-regression.ts to count requested and open /pane/scroll reads. The new press helper w…
Out of Scope Changes check ✅ Passed The pull request changes only scripts/terminal-copy-regression.ts. The changes add test instrumentation and synchronization for the linked flaky test. No unrelated product code or unrelated behavior…
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 1 files.
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@devswha devswha left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Independent review (merge-own lane).

Classification: test-only fix for a flaky required check (#551). It merges because the "Integration and browser" check is required on main, so a race in it blocks every PR.

What I checked:

  • Diff: scripts/terminal-copy-regression.ts wraps window.fetch in the init script and counts GET .../pane/scroll reads as asked and open. A press waits until its own read was asked and none is open. The product reads the position through getJson (src/lib/api.ts:111), which always calls response.json(), so the counter closes every read. A non-OK answer closes at once. A read that never answers makes waitForFunction time out loudly rather than pass. The three waitForTimeout(200) guesses after a press are replaced by the same wait.
  • Root cause matches PaneTerminal.tsx: a release before the scroll answer copies the visible text natively and returns before the async clipboard write, so the recorder saw [].
  • No product code changed, and there is no CHANGELOG entry, matching earlier test-only PRs.

What I ran, on head 7b343b1 in a separate worktree:

  • bun run check fast: 1699 pass, 0 fail.
  • bun run build then bun run check run bun scripts/ui-regression.ts: every step passed, including the three terminal-copy steps ("plain drag copies...", "a selecting drag scrolls herdr...", "drag copy starts in the gesture...").
  • Fast checks and Integration and browser are green on this head, the branch is up to date with main, and there are no review threads. CodeRabbit had no actionable comments.

@devswha
devswha merged commit c41fe02 into main Oct 7, 2026
4 checks passed
@devswha
devswha deleted the fix/terminal-copy-flake branch October 7, 2026 19:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Flaky test: terminal-copy-regression.ts finds no clipboard write inside mouseup after a plain drag

1 participant