Repository navigation
test(desktop): stub the workbar menu popup in the WorkHub layout e2e - #6008
Conversation
The spec opened a real native menu for the workbar's add-panel button and then closed it with a scripted closePopup guarded by a main-process workbarMenuOpen flag. On Linux CI the GTK popup can already be torn down (e.g. after a window resize) while menu-will-close has not reached JS, so the stale flag still holds and closePopup crashes the Electron main process; closePopup could also crash on a live popup in that window setup. This intermittently killed the "Desktop e2e" step on byte-identical trees that had already passed CI (apache#5995, failure 1). Every assertion in this segment is Maka state — aria-expanded, the dock backdrop, and the WorkHub WebContentsView's native visibility — none of which needs a real GTK menu. Stub Menu.prototype.popup so it records the probe and restores itself immediately (the later task-action menu keeps the real popup), simulate the close through the menu's own menu-will-close lifecycle event, and drive the popup callback from it so the renderer's request resolves and aria-expanded drops through the same path a real menu uses. This removes closePopup, and both crash paths, from the test. Product code never calls closePopup, so the change is test-only. Verified on macOS arm64: the spec passes before (14.8s) and after (12.0s single / 28.2s full file, 3 passed) the change, with biome check and check:asf-headers clean. The crash itself is Linux-only and was not reproduced locally; the fix removes the native popup/closePopup path the crash rides on. Addresses apache#5995 (failure 1 of 3; the issue asks for the three failures to be fixed and closed separately). Generated-by: GLM-5.3-Flash (ZCode)
Astro-Han
left a comment
There was a problem hiding this comment.
Automated review notice: This comment was posted by an automated review agent. It is not an independent human review and does not replace one.
Full review of 364b5955 (+23/-15, apps/desktop/e2e/workhub-layout.spec.ts, test-only).
The one-shot Menu.prototype.popup stub records the menu, restores the prototype, and returns without opening a native popup. Its menu-will-close listener calls options.callback, and the close step emits menu-will-close in the main process instead of calling closePopup. This matches popupNativeMenu in src/main/native-menu.ts, which clears openMenus and resolves the renderer request only from the popup callback. So aria-expanded drops through the real product path, and the closePopup crash site is removed. The mechanics are correct. The workbarMenuOpen guard is now always true at the close step, but it is harmless.
P3: inaccurate comment and lost native-popup coverage. The comment at line 132 says restoring the prototype "keeps the later task-action menu on the real native popup", and the PR body says the same. The later "任务操作" menu in this spec is a DOM role=menuitem menu and never calls Menu.popup. The workbar add-panel is the only renderer caller of window:popupMenu/popupNativeMenu. So after this change no e2e opens a real native menu, including next to the live WorkHub WebContentsView, which was this segment's original purpose. Removing the crash is worth that trade, but the comment should be corrected and the coverage loss noted in #5995.
Overlap with #6007. #6007 (liugddx) makes the same fix to the same hunks of workhub-layout.spec.ts: stub the popup, drive the callback from menu-will-close, drop closePopup. The two PRs will conflict textually, and only one should land. #6007 is a superset: it also fixes the #5995 §2 CDP-click flake in workhub-browser-presentation-smoke.mjs and asserts that the stub captured a menu with items. Landing #6007 and closing this PR is the simpler path. If this PR lands first, #6007 needs to drop its spec hunk.
No protocol files are touched, so there is no epoch impact. The PR is MERGEABLE. CI test passes on 364b5955, and Desktop e2e (which included the changed spec) passed 34/34.
No P0-P2 findings.
| probe.workbarMenuOpen = true; | ||
| // Track the popup's own lifetime in the main process: Linux may | ||
| // auto-dismiss it (e.g. after a resize) at any moment. | ||
| // Restoring immediately keeps the later task-action menu on the real |
There was a problem hiding this comment.
P3: The later task-action menu ("任务操作") in this spec is a DOM role=menuitem menu and never calls Menu.popup. The workbar add-panel is the only popupNativeMenu caller. Restoring the prototype is still good hygiene, but this comment (and the PR body) overstate the remaining coverage: after this change no e2e opens a real native popup.
liugddx
left a comment
There was a problem hiding this comment.
Approving exact head 364b5955a. This is the right fix for #5995 failure 1. The stub drives the popup's options.callback from menu-will-close, and that callback is what popupNativeMenu (src/main/native-menu.ts:47-48) waits on before resolving the renderer request and dropping aria-expanded. So the assertions still go through the real product path, and closePopup, the crash site, is gone from the test. CI passes on this head.
I've reduced #6007 to the native-smoke fix (failure 2) only, so the two PRs no longer overlap. You had already taken #5995.
Two non-blocking notes, either fine as a follow-up:
- The comment "Restoring immediately keeps the later task-action menu on the real native popup" overstates it. The workbar add-panel is the only renderer caller of
window:popupMenu/popupNativeMenu(workbar-surface.tsx:226), and the later "任务操作" menu is a DOMrole=menuitemmenu. After this change, no e2e opens a real native menu next to the live WorkHubWebContentsView. That's a reasonable trade for removing a main-process crash, and I've recorded it in #5995. - An assertion that the stub actually captured the workbar menu (for example
probe.workbarMenu.items.length > 0) would catch a future change that stops routing this button throughMenu.popup, which would otherwise silently skip the close path.
Thanks @ggbdpq.
Summary
workhub-layout.spec.tsopened a real native menu for the workbar's add-panel button and closed it with a scriptedclosePopup(window), guarded by a main-processworkbarMenuOpenflag. On Linux CI the GTK popup can already be torn down (for example right after a window resize) whilemenu-will-closehas not reached JS; the flag then still holds andclosePopupcrashes the Electron main process, killing the whole "Desktop e2e" step on byte-identical trees that had already passed CI.closePopupmay also crash on a live popup in this window setup. This is failure 1 of #5995.Every assertion in this segment is Maka state —
aria-expanded, the dock backdrop, and the WorkHub WebContentsView's native visibility — none of which needs a real GTK menu. The change stubsMenu.prototype.popupso it records the probe and restores itself immediately (the later task-action menu in the same spec keeps the real popup), then simulates the close through the menu's ownmenu-will-closelifecycle event, driving the popupcallbackfrom it so the renderer's request resolves andaria-expandeddrops through the same path a real menu uses. This removesclosePopup, and both crash paths with it. Product code never callsclosePopup, so the change is test-only.Refs #5995 (the issue asks for the three failures to be fixed and closed separately, so this intentionally does not use a close keyword; failures 2 and 3 remain open there).
Verification
workhub-layout.spec.tson macOS arm64, before the change (baseline onupstream/main)npx biome check apps/desktop/e2e/workhub-layout.spec.tsnpm run typecheck(desktop workspace, 4 tsconfigs)npm run check:asf-headersclosePopuppath the crash rides onAI use
Tool(s) and scope: GLM-5.3-Flash (ZCode) — analyzed the crash path from #5995, implemented the stub, ran the local verification matrix, and drafted this PR.
Checklist
(The first box is intentionally unchecked: the change is the test — a test-only flaky fix has no separate product behavior for another test to cover. The before/after runs above are the evidence that the spec still passes with the stubbed popup.)
Does this PR entail a change in behavior?