Only reload the merge request page from the Changes tab

This fixes a reload triggered by Rapid Diffs' prepared event that could cancel an in-progress page navigation and strand users on the Overview tab instead of Changes. The page now only reloads when Changes is the active tab, since that is the only tab where the reload does anything useful. This is one of two causes behind the flaky revert_commit_spec.rb and cherry_pick_commit_spec.rb E2E tests; the other is fixed separately in !255351 (merged).

Detailed context for AI agents

What does this MR do and why?

Rapid Diffs renders a "Building your merge request..." empty state server side, but only on the Changes tab. The EVT_MR_PREPARED handler in page.js used to call window.location.reload() unconditionally, on whichever tab the user happened to be on, once the merge request finished preparing. On the Overview tab there is nothing to fix, so the reload was pointless there, and it had a real side effect.

Clicking Changes on a merge request that has no diff yet does a full page navigation to /diffs (clickTab in merge_request_tabs.js calls visitUrl(href) when #hasDiffRefs() is false). If the prepared broadcast lands while that navigation is in flight, which on the E2E environment typically takes 1 to 3 seconds, the unconditional reload requests the Overview URL and cancels the pending /diffs navigation. The user ends up back on Overview with no diff.

This is the second failure signature behind the flaky QA specs qa/specs/features/browser_ui/3_create/merge_request/revert/revert_commit_spec.rb and cherry_pick/cherry_pick_commit_spec.rb: "Wait for file tree button to load failed after 60 seconds". QA::Page::MergeRequest::Show#click_diffs_tab clicks the tab and then wait_until(reload: true) refreshes the current URL until a file tree toggle appears. After the cancelled navigation, the current URL is Overview, so the wait refreshes Overview for 60 seconds and times out. Job logs from failing runs show exactly that: "refreshing .../merge_requests/1" every 5 seconds right after "clicking :diffs-tab". 5 of 5 sampled failing jobs from September 14 matched this signature.

The first failure signature for these same specs, "expected ... to have file", is a separate bug (subscribing to the preparation channel after querying status) fixed in !255351 (merged). Both MRs share the same base commit and touch different files, so they can land independently.

Changes

  • app/assets/javascripts/pages/projects/merge_requests/page.js: the EVT_MR_PREPARED handler now checks mergeRequest.tabs.isDiffAction(mergeRequest.tabs.getCurrentAction()) and only reloads when the current tab is Changes.
  • spec/frontend/pages/projects/merge_requests/page_spec.js: three new tests covering reload on the Changes tab, no reload from another tab, and no reload when Rapid Diffs is off.

Alternatives considered

  • Fix only the QA page object (click_diffs_tab) to re-click the tab instead of refreshing the URL. Rejected as spec-only: real users hit the same cancelled navigation, not just the test harness. The page object could still be hardened separately as a defense in depth measure.
  • Detect an in-flight navigation before reloading. Not reliably possible from JavaScript, so not pursued.

References

How to set up and validate locally

  1. Ensure rapid_diffs_default_on_mr_show is enabled (default on).
  2. gdk stop rails-background-jobs so preparation stalls.
  3. Create a merge request via the API.
  4. Open its Overview page, click Changes, and hold or throttle the navigation to /diffs (for example with a DevTools network throttle or a paused request).
  5. gdk start rails-background-jobs so the merge request finishes preparing while the navigation is held.

Before this change, the page bounces back to Overview once preparation completes. After this change, the Changes page loads with the diff.

Live verification on GDK

Verified on GDK on 2026-09-15 using headless Chrome over CDP, with Sidekiq stopped and a merge request created via the API. Fetch.requestPaused held the /diffs document navigation triggered by clicking Changes from the Overview tab, then Sidekiq was started so the merge request prepared while the navigation was held.

  • Before this change (parent commit 70c3fc35): when the prepared broadcast arrived, window.location.reload() requested the Overview URL and cancelled the held /diffs navigation. Final state was the Overview tab with no diff files. The !255351 (merged) branch showed the same behavior, since it does not touch this reload.
  • After this change: no reload request fired during the hold. When the held navigation was released, the page landed on /diffs with the diff rendered.
  • Also verified on this branch: opening /diffs directly while the merge request is still preparing, then letting Sidekiq prepare it, still reloads the page and shows the diff. The Changes tab path is unchanged.

MR acceptance checklist

  • Frontend-only change
  • No database changes
  • No API changes
  • No security surface changes
  • Tests added for the new behavior

Merge request reports

Loading
Loading