diff --git a/spec/api-debugger.spec.ts b/spec/api-debugger.spec.ts index a3f17794ee..5e92c7718f 100644 --- a/spec/api-debugger.spec.ts +++ b/spec/api-debugger.spec.ts @@ -235,27 +235,28 @@ describe('debugger module', () => { }); it('does not crash for invalid unicode characters in message', async () => { - w.webContents.debugger.attach(); - - const loadingFinished = new Promise((resolve) => { - w.webContents.debugger.on('message', (event, method) => { - // loadingFinished indicates that page has been loaded and it did not - // crash because of invalid UTF-8 data - if (method === 'Network.loadingFinished') { - resolve(); - } - }); - }); - server = http.createServer((req, res) => { res.setHeader('Content-Type', 'text/plain; charset=utf-8'); res.end('\uFFFF'); }); const { url } = await listen(server); - w.webContents.debugger.sendCommand('Network.enable'); - w.loadURL(url); + // Network.enable only reaches the renderer once it exists. On a fresh + // window that is during the first navigation, which can then finish + // before the renderer reports Network.loadingFinished. Load a page + // first and wait for Network.enable before the real navigation. + await w.loadURL('about:blank'); + w.webContents.debugger.attach(); + await w.webContents.debugger.sendCommand('Network.enable'); + // loadingFinished indicates that page has been loaded and it did not + // crash because of invalid UTF-8 data + const loadingFinished = emittedUntil( + w.webContents.debugger, + 'message', + (_event: any, method: string) => method === 'Network.loadingFinished' + ); + await w.loadURL(url); await loadingFinished; }); diff --git a/spec/fixtures/pages/beforeunload-false.html b/spec/fixtures/pages/beforeunload-false.html index 0b71b07c83..6626f38a31 100644 --- a/spec/fixtures/pages/beforeunload-false.html +++ b/spec/fixtures/pages/beforeunload-false.html @@ -2,10 +2,11 @@ diff --git a/spec/webview.spec.ts b/spec/webview.spec.ts index 383c10d186..1929232a9d 100644 --- a/spec/webview.spec.ts +++ b/spec/webview.spec.ts @@ -230,37 +230,48 @@ describe(' tag', () => { }); }); - ifdescribe(process.platform !== 'win32')('document.visibilityState/hidden', () => { + // The guest's visibility follows whether the embedder window is actually on + // screen, so this needs the screen to itself (see the BrowserWindow + // visibilityState specs): on macOS a window from another spec worker can + // occlude this one and hide the guest. + ifdescribe(process.platform !== 'win32')('document.visibilityState/hidden', { tags: ['serial'] }, () => { afterEach(() => { ipcMain.removeAllListeners('pong'); }); afterEach(closeAllWindows); + // The guest reports its state when its script runs and on every + // visibilitychange. Wait for the expected state rather than taking the + // next report: the guest can run its script while it is still being + // attached, before the embedder has shown it, and report 'hidden' first. + const guestVisibility = (state: 'visible' | 'hidden') => + emittedUntil(ipcMain, 'pong', (_event: unknown, visibilityState: string) => visibilityState === state); + it('follows the embedder window when it is hidden and shown again', async () => { const w = new BrowserWindow({ width: 100, height: 100, webPreferences: { webviewTag: true, nodeIntegration: true, contextIsolation: false } }); + const initiallyVisible = guestVisibility('visible'); w.loadFile(path.join(fixtures, 'pages', 'webview-visibilitychange.html')); { - const [, visibilityState, hidden] = await once(ipcMain, 'pong'); - expect(visibilityState).toBe('visible'); + const [, , hidden] = await initiallyVisible; expect(hidden).toBe(false); } + const hiddenState = guestVisibility('hidden'); w.hide(); { - const [, visibilityState, hidden] = await once(ipcMain, 'pong'); - expect(visibilityState).toBe('hidden'); + const [, , hidden] = await hiddenState; expect(hidden).toBe(true); } + const visibleState = guestVisibility('visible'); w.show(); { - const [, visibilityState, hidden] = await once(ipcMain, 'pong'); - expect(visibilityState).toBe('visible'); + const [, , hidden] = await visibleState; expect(hidden).toBe(false); } });