Skip to content

flaky(desktop): three intermittent WorkHub test failures on Linux CI (e2e closePopup crash, native smoke click, Storybook work filter) #5995

Description

@liugddx

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:

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:

  • main at f10a74d8e, 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:

  1. main.emit('close'), then main.destroy(). This reparents the live view into the floating window.
  2. A fixed wait(100).
  3. controller.navigate('…/page?main-closed').
  4. One Input.dispatchMouseEvent press/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 two requestAnimationFrame callbacks via executeJavaScript; 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:

  1. Send FILTERED_RETRY_PROBE.
  2. Wait for the Temporary Host failure alert.
  3. Click the first .workhub-message-rail.
  4. 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.

Refs #5917, #5918, #5961.

Activity

  1. ggbdpq commented on Oct 8, 2026

    @ggbdpq
    Contributor

    take

  2. liugddx commented on Oct 9, 2026

    @liugddx
    MemberAuthor

    Status update:

    • 1. workhub-layout e2e closePopup crash: fixed by test(desktop): stub the workbar menu popup in the WorkHub layout e2e #6008 (@ggbdpq, merged as 6d53ca8e9). The workbar popup is now stubbed and closed through its own menu-will-close → callback path. One trade to record: the workbar add-panel is the only renderer caller of window:popupMenu/popupNativeMenu, so no e2e now opens a real native menu next to the live WorkHub WebContentsView. That coverage can come back once there's a way to dismiss a GTK popup that doesn't crash the main process.
    • 2. Native browser smoke losing the CDP click: open, in test(desktop): wait for a painted frame before the native smoke's CDP click #6007. It waits for load plus two frames before the single click and is waiting for review.
    • 3. Storybook 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.
  3. liugddx commented on Oct 9, 2026

    @liugddx
    MemberAuthor

    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 logs Background page input readiness: frames, visible. Items 1 and 2 are now fixed. Item 3 (Storybook retry-while-work-filtered) is still open; I'm running an instrumented repro on Linux CI to capture a failing timeline.

  4. added a commit that references this issue on Oct 9, 2026
  5. liugddx commented on Oct 9, 2026

    @liugddx
    MemberAuthor

    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, and ChatView's virtua virtualizer (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. The pointerdown and click then 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 no pointerdown followed, 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's pointer-events gate never runs in Storybook, and the history is never inert.

    Once #6020 merges, all three items are fixed, and its Fixes #5995 will close this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions