fix: close and recreate macOS windows safely
This commit is contained in:
1 parent
f443f3bc66
commit
b5e6c663ef
19 files changed
+1079
-172
No files matched your search
@@ -0,0 +1,94 @@
|
||||
import { EventEmitter } from 'node:events';
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import { registerMainWindowClose } from '@electron/main/main-window-close';
|
||||
|
||||
class WindowStub extends EventEmitter {
|
||||
fullscreen = false;
|
||||
destroyed = false;
|
||||
hide = vi.fn();
|
||||
setFullScreen = vi.fn();
|
||||
isFullScreen = () => this.fullscreen;
|
||||
isDestroyed = () => this.destroyed;
|
||||
close = vi.fn(() => {
|
||||
const event = { defaultPrevented: false, preventDefault() { this.defaultPrevented = true; } };
|
||||
this.emit('close', event);
|
||||
if (!event.defaultPrevented) {
|
||||
this.destroyed = true;
|
||||
this.emit('closed');
|
||||
}
|
||||
});
|
||||
leaveFullscreen(): void {
|
||||
this.fullscreen = false;
|
||||
this.emit('leave-full-screen');
|
||||
}
|
||||
}
|
||||
|
||||
function setup(fullscreen = false) {
|
||||
const window = new WindowStub();
|
||||
window.fullscreen = fullscreen;
|
||||
let quitting = false;
|
||||
registerMainWindowClose(window as never, {
|
||||
platform: 'darwin', isQuitting: () => quitting, hideOnClose: false,
|
||||
});
|
||||
return { window, quit: () => { quitting = true; window.close(); } };
|
||||
}
|
||||
|
||||
describe('native main window close', () => {
|
||||
it('really destroys a normal macOS window instead of hiding it', () => {
|
||||
const { window } = setup();
|
||||
window.close();
|
||||
expect(window.destroyed).toBe(true);
|
||||
expect(window.hide).not.toHaveBeenCalled();
|
||||
expect(window.setFullScreen).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('waits for the fullscreen exit before closing, including repeated clicks', () => {
|
||||
const { window } = setup(true);
|
||||
const order: string[] = [];
|
||||
window.prependListener('leave-full-screen', () => order.push('left fullscreen'));
|
||||
window.on('closed', () => order.push('closed'));
|
||||
window.close();
|
||||
window.close();
|
||||
expect(window.destroyed).toBe(false);
|
||||
expect(window.hide).not.toHaveBeenCalled();
|
||||
expect(window.setFullScreen).toHaveBeenCalledExactlyOnceWith(false);
|
||||
window.leaveFullscreen();
|
||||
expect(window.destroyed).toBe(true);
|
||||
expect(order).toEqual(['left fullscreen', 'closed']);
|
||||
});
|
||||
|
||||
it('does not delay a real app quit while fullscreen exit is pending', () => {
|
||||
const { window, quit } = setup(true);
|
||||
window.close();
|
||||
quit();
|
||||
expect(window.destroyed).toBe(true);
|
||||
window.leaveFullscreen();
|
||||
expect(window.close).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('lets Cmd+Q close a fullscreen window without starting another transition', () => {
|
||||
const { window, quit } = setup(true);
|
||||
quit();
|
||||
expect(window.destroyed).toBe(true);
|
||||
expect(window.setFullScreen).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('cancels deferred closing if the window was destroyed externally', () => {
|
||||
const { window } = setup(true);
|
||||
window.close();
|
||||
window.destroyed = true;
|
||||
window.emit('closed');
|
||||
window.leaveFullscreen();
|
||||
expect(window.close).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('preserves existing close-to-tray behavior on other platforms', () => {
|
||||
const window = new WindowStub();
|
||||
registerMainWindowClose(window as never, {
|
||||
platform: 'win32', isQuitting: () => false, hideOnClose: true,
|
||||
});
|
||||
window.close();
|
||||
expect(window.destroyed).toBe(false);
|
||||
expect(window.hide).toHaveBeenCalledOnce();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user