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: theEVT_MR_PREPAREDhandler now checksmergeRequest.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
- Related work item: https://gitlab.com/gitlab-org/quality/test-failure-issues/-/work_items/44546
- Related work item: https://gitlab.com/gitlab-org/quality/test-failure-issues/-/work_items/44547
- Companion fix for the other failure signature: !255351 (merged)
- Flaky specs:
qa/specs/features/browser_ui/3_create/merge_request/revert/revert_commit_spec.rb,qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_commit_spec.rb
How to set up and validate locally
- Ensure
rapid_diffs_default_on_mr_showis enabled (default on). gdk stop rails-background-jobsso preparation stalls.- Create a merge request via the API.
- 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). gdk start rails-background-jobsso 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/diffsnavigation. 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
/diffswith the diff rendered. - Also verified on this branch: opening
/diffsdirectly 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