mirror of
https://github.com/electron/electron.git
synced 2026-10-28 11:44:46 +08:00
test: fix retry-reliant macOS fullscreen BrowserWindow specs (#55230)
"should be able to load a URL while transitioning to fullscreen" and "transparent option > correctly returns isMaximized() when the window is maximized then minimized" time out on their first attempt on macOS and pass on retry. Each runs right after a test that ends with two windows sharing fullscreen (a borderless child of a fullscreen parent, and "multiple windows inherit correct fullscreen state"). Those tests' reported durations, which include the afterEach hook, are too short to contain a fullscreen exit in the failing runs, so closeAllWindows() destroyed a window that was still animating out of fullscreen, and AppKit ignored the next test's first window request. closeWindow() only waited when isFullScreen() was true, which it no longer is while a window is being taken out of fullscreen along with another one. Track which BrowserWindows have entered fullscreen and not yet left it, wait for their 'leave-full-screen' too, and warn when that does not arrive within the existing 5s bound. "does not exit simpleFullScreen when requestFullscreen is called" still spent its first attempt's whole 10s focus wait without the page getting focus on macOS arm64, and passed on the retry, which requested app activation again. Request activation on every poll instead of once. Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
0240841b24
commit
6408a0c6bb
2 files changed
+41
-11
No files matched your search
@@ -48,7 +48,6 @@ import {
|
||||
ifit,
|
||||
ifdescribe,
|
||||
defer,
|
||||
focusWebContents,
|
||||
listen,
|
||||
waitUntil,
|
||||
isWayland,
|
||||
@@ -8025,9 +8024,20 @@ describe('BrowserWindow module', () => {
|
||||
// the page is focused after entering simple fullscreen.
|
||||
// webContents.focus() only activates the app when no other app is
|
||||
// active, and the earlier fullscreen specs can leave another app
|
||||
// frontmost, so take activation explicitly first.
|
||||
app.focus({ steal: true });
|
||||
await focusWebContents(w.webContents);
|
||||
// frontmost, so take activation explicitly. One request is not
|
||||
// always enough: on macOS arm64 CI the first attempt sometimes
|
||||
// spent the whole wait without the page getting focus, while the
|
||||
// retry, which requested activation again, passed at once. So ask
|
||||
// again on every poll until the page has focus.
|
||||
await waitUntil(
|
||||
async () => {
|
||||
if (await w.webContents.executeJavaScript('document.hasFocus()')) return true;
|
||||
app.focus({ steal: true });
|
||||
w.webContents.focus();
|
||||
return false;
|
||||
},
|
||||
{ rate: 100 }
|
||||
);
|
||||
|
||||
const enterHtmlFS = once(w.webContents, 'enter-html-full-screen');
|
||||
await w.webContents.executeJavaScript('document.getElementById("div").requestFullscreen()', true);
|
||||
|
||||
@@ -1,17 +1,37 @@
|
||||
import { BaseWindow, BrowserWindow, webContents } from 'electron/main';
|
||||
import { app, BaseWindow, BrowserWindow, webContents } from 'electron/main';
|
||||
|
||||
import { expect } from 'vitest';
|
||||
|
||||
import { once } from 'node:events';
|
||||
|
||||
// BrowserWindows that have emitted 'enter-full-screen' but not yet
|
||||
// 'leave-full-screen'.
|
||||
const inFullScreen = new WeakSet<BaseWindow>();
|
||||
if (process.platform === 'darwin') {
|
||||
app.on('browser-window-created', (_event, window) => {
|
||||
window.on('enter-full-screen', () => inFullScreen.add(window));
|
||||
window.on('leave-full-screen', () => inFullScreen.delete(window));
|
||||
});
|
||||
}
|
||||
|
||||
// On macOS, destroying a fullscreen window animates it out of its Space, and
|
||||
// AppKit ignores fullscreen requests from other windows until that finishes.
|
||||
// Leave fullscreen first so the next test doesn't start inside the animation.
|
||||
// AppKit ignores fullscreen and other window state requests from other
|
||||
// windows until that finishes. Leave fullscreen first so the next test
|
||||
// doesn't start inside the animation.
|
||||
//
|
||||
// isFullScreen() is not enough to tell: a window can already be on its way
|
||||
// out, for example when another window in the same fullscreen Space left
|
||||
// fullscreen and took it along. isFullScreen() is then false, but the window
|
||||
// still emits 'leave-full-screen' once the animation ends, so wait for that.
|
||||
async function leaveFullScreen(window: BaseWindow) {
|
||||
if (process.platform !== 'darwin' || !window.isFullScreen()) return;
|
||||
const left = once(window, 'leave-full-screen');
|
||||
window.setFullScreen(false);
|
||||
await Promise.race([left, new Promise((resolve) => setTimeout(resolve, 5000))]);
|
||||
if (process.platform !== 'darwin') return;
|
||||
if (!window.isFullScreen() && !inFullScreen.has(window)) return;
|
||||
const left = once(window, 'leave-full-screen').then(() => true);
|
||||
if (window.isFullScreen()) window.setFullScreen(false);
|
||||
const timeout = new Promise<boolean>((resolve) => setTimeout(() => resolve(false), 5000));
|
||||
if (!(await Promise.race([left, timeout]))) {
|
||||
console.warn(`closeWindow(): window ${window.id} did not leave fullscreen within 5s, destroying it anyway`);
|
||||
}
|
||||
}
|
||||
|
||||
async function ensureWindowIsClosed(window: BaseWindow | null) {
|
||||
|
||||
Reference in new issue
Block a user