Repository navigation
flaky(desktop): three intermittent WorkHub test failures on Linux CI (e2e closePopup crash, native smoke click, Storybook work filter) #5995
Description
Three WorkHub tests failed intermittently on Linux CI while I was landing #5961, and one of them recurred on main right after the merge. #5961 caused none of them. The three PR runs used byte-identical trees, and that tree had already passed the full CI before the rebase. Each run failed a different test, and none of the failing tests renders the retention notices #5961 added. Each failure below has its own mechanism and fix, so they can be fixed and closed separately.
1. workhub-layout e2e still crashes Electron at the guarded closePopup after #5918
apps/desktop/e2e/workhub-layout.spec.ts › "WorkHub uses its coordination model and shared attachment composer" crashed the Electron main process again in the Desktop e2e step, after #5918 had closed #5917.
Seen on: #5961, run 37728038123 attempt 2 (head 8d05fd7b3). Attempt 3 of the same tree passed.
Error: jsHandle.evaluate: Target page, context or browser has been closed
> 150 | await mainWindow.evaluate((window) => {
at apps/desktop/e2e/workhub-layout.spec.ts:150:20
Mechanism. The process dies inside the single main-process task that #5918 introduced:
if (probe.workbarMenuOpen) probe.workbarMenu.closePopup(window);The mainWindow.evaluate just before it (the container getVisible() check) succeeded, so the main process was alive when this task began. That leaves two possibilities, and CI logs cannot tell them apart:
- GTK has already torn the popup down, but
menu-will-closehas not reached JS yet, so the flag is stale. This is the test(desktop): workhub-layout e2e crashes Electron when the native menu auto-dismisses before closePopup #5917 race, narrowed but not closed. closePopup(window)can crash on Linux even for a live popup in this window setup.
Fix: stop opening a real native menu in this spec. Its assertions are about Maka state, not GTK: aria-expanded, the dock backdrop, and the native WorkHub view's visibility. Stub Menu.prototype.popup so it records the menu without calling the native implementation, then close by emitting menu-will-close. That removes closePopup from the test, and both crash paths with it. Product code never calls closePopup, so this is test-only.
2. WorkHub native browser smoke loses the CDP click sent right after Main closes
apps/desktop/scripts/workhub-browser-presentation-smoke.mjs (CI step "WorkHub native browser presentation smoke") fails at its last assertion:
AssertionError [ERR_ASSERTION]: background page must handle the native click after Main closes
'Test' !== 'Clicked'
at run (apps/desktop/scripts/workhub-browser-presentation-smoke.mjs:197:12)
Seen on:
mainatf10a74d8e, run 37731524494 attempt 1. Every earlier phase passed: docked, menu-overlay, menu-dismissed, floating-conversation, panel-hidden, background-restored and redocked.feature/chat-image-delivery, run 37588623379 (2026-10-07).
The smoke uses a synthetic fixture window and no AppShell renderer.
Mechanism (plausible; not reproduced locally). The test runs these steps back to back:
main.emit('close'), thenmain.destroy(). This reparents the live view into the floating window.- A fixed
wait(100). controller.navigate('…/page?main-closed').- One
Input.dispatchMouseEventpress/release pair.
The page may not yet have produced a compositor frame or hit-test data in its new window under Xvfb, and Chromium drops input it cannot route. The smoke deliberately sends only one click, so a dropped event fails the run.
Fix: wait until the page can receive input before dispatching, rather than retrying the click. For example:
- await
document.visibilityState === 'visible'and tworequestAnimationFramecallbacks viaexecuteJavaScript; or - force a frame with
webContents.capturePage().
Keep the single click, so a genuinely lost event still fails.
3. Storybook product-workhub--retry-while-work-filtered intermittently never shows the work filter
The Storybook smoke failed this story both under 4-way concurrency and when retried alone:
[product-workhub--retry-while-work-filtered (light/default)] console.error:
TestingLibraryElementError: Unable to find role="button" and name "显示全部对话"
Seen on: #5961, run 37728038123 attempt 1. The same tree passed the Storybook smoke on attempts 2 and 3. The story renders WorkHubRoot only.
Where it fails. In RetryWhileWorkFiltered.play (apps/desktop/stories/workhub.stories.tsx), the steps are:
- Send
FILTERED_RETRY_PROBE. - Wait for the
Temporary Host failurealert. - Click the first
.workhub-message-rail. waitFor(() => getByRole('button', { name: '显示全部对话' })), with the default 1 s timeout. This step times out.
Ruled out locally. I built Storybook at f10a74d8e and drove the story through the CI smoke's own smokeStory(). It passed 34/34 runs: 10 without throttling, 12 at 2× and 12 at 3× CDP CPU throttling. At 6× the story cannot finish in 15 s at all, which is a different failure. Instrumentation showed the click always landed on a connected rail with aria-pressed="false" and pointer-events: auto. That rules out a click on a detached node, and a click swallowed by the 1.2 s WorkHub reveal gate.
Open question. On the CI runner, either the filtered re-render takes longer than the 1 s waitFor, or something clears the selection after it was set. onSubmit clears it only at send time, before the failure. A CI trace or screenshot at the failure point would settle which.
Next step:
- Have the smoke capture a screenshot or trace on play-function errors.
- Check whether this story, unlike
SendWhileWorkFiltered, should wait for the composer to settle after the failed send before clicking the rail.
Activity
ggbdpq commentedon Oct 8, 2026
take
test(desktop): wait for a painted frame before the native smoke's CDP…
test(desktop): stub the workbar menu popup in the WorkHub layout e2e (#…
liugddx commentedon Oct 9, 2026
Status update:
workhub-layoute2eclosePopupcrash: fixed by test(desktop): stub the workbar menu popup in the WorkHub layout e2e #6008 (@ggbdpq, merged as6d53ca8e9). The workbar popup is now stubbed and closed through its ownmenu-will-close→callbackpath. One trade to record: the workbar add-panel is the only renderer caller ofwindow:popupMenu/popupNativeMenu, so no e2e now opens a real native menu next to the live WorkHubWebContentsView. That coverage can come back once there's a way to dismiss a GTK popup that doesn't crash the main process.retry-while-work-filtered: open, root cause unknown. The next step is still a screenshot or trace from the smoke when a play function errors.test(desktop): wait for a painted frame before the native smoke's CDP…
liugddx commentedon Oct 9, 2026
2. Native browser smoke losing the CDP click: fixed by #6007 (merged as
0af3d5adc). The smoke now waits for load plus two frames before its single click; on CI it logsBackground page input readiness: frames, visible. Items 1 and 2 are now fixed. Item 3 (Storybookretry-while-work-filtered) is still open; I'm running an instrumented repro on Linux CI to capture a failing timeline.ci(repro): verify the last-rail fix for apache#5995 under 4-way load
liugddx commentedon Oct 9, 2026
3. Storybook
retry-while-work-filtered: root cause found, fix in #6020.This is a race in the story, not a product bug. After the send fails, the play function clicks the first
.workhub-message-rail. The send follows the latest Turn, andChatView'svirtuavirtualizer (chat-view.tsx:959) unmounts Turns that scroll out; only focused or selected Turns are kept (:1155). Under CPU load, Turn 1's rail is still the first rail when the alert lands, and it detaches between user-event's hover and press. Thepointerdownandclickthen go to a node outside the document: nothing handles them and nothing throws, so the filter never appears.An instrumented repro on Linux CI in a fork measured this. With 4-way load on
main, the story failed 50/120; alone it failed 0/40. In 17 of 18 instrumented failures the hover reached Turn 1's rail but nopointerdownfollowed, and in the remaining one Turn 1's rail had already detached before the hover. With #6020, which clicks the newest linked Turn's rail, the same 4-way load gives 0/120. The earlier hypotheses are ruled out: the reveal animation'spointer-eventsgate never runs in Storybook, and the history is neverinert.Once #6020 merges, all three items are fixed, and its
Fixes #5995will close this issue.