diff --git a/spec/api-browser-view-spec.ts b/spec/api-browser-view-spec.ts index ec4d5a38aa4..76e86adb738 100644 --- a/spec/api-browser-view-spec.ts +++ b/spec/api-browser-view-spec.ts @@ -300,18 +300,14 @@ describe('BrowserView module', () => { }).to.not.throw(); }); - it('can be called on a BrowserView with a destroyed webContents', (done) => { + it('can be called on a BrowserView with a destroyed webContents', async () => { view = new BrowserView(); w.addBrowserView(view); - - view.webContents.on('destroyed', () => { - w.removeBrowserView(view); - done(); - }); - - view.webContents.loadURL('data:text/html,hello there').then(() => { - view.webContents.close(); - }); + await view.webContents.loadURL('data:text/html,hello there'); + const destroyed = once(view.webContents, 'destroyed'); + view.webContents.close(); + await destroyed; + w.removeBrowserView(view); }); }); diff --git a/spec/api-browser-window-spec.ts b/spec/api-browser-window-spec.ts index 4b5c752404c..540ad42d14e 100644 --- a/spec/api-browser-window-spec.ts +++ b/spec/api-browser-window-spec.ts @@ -589,7 +589,7 @@ describe('BrowserWindow module', () => { describe('will-frame-navigate event', () => { let server = null as unknown as http.Server; let url = null as unknown as string; - before((done) => { + before(async () => { server = http.createServer((req, res) => { if (req.url === '/navigate-top') { res.end('navigate _top'); @@ -609,10 +609,7 @@ describe('BrowserWindow module', () => { res.end(''); } }); - server.listen(0, '127.0.0.1', () => { - url = `http://127.0.0.1:${(server.address() as AddressInfo).port}/`; - done(); - }); + url = (await listen(server)).url; }); after(() => { @@ -683,7 +680,7 @@ describe('BrowserWindow module', () => { resolve(e.url); }); }); - expect(navigatedTo).to.equal(url); + expect(navigatedTo).to.equal(url + '/'); expect(w.webContents.getURL()).to.match(/^file:/); }); @@ -696,7 +693,7 @@ describe('BrowserWindow module', () => { resolve(e.url); }); }); - expect(navigatedTo).to.equal(url); + expect(navigatedTo).to.equal(url + '/'); expect(w.webContents.getURL()).to.equal('about:blank'); }); @@ -883,7 +880,7 @@ describe('BrowserWindow module', () => { 'did-frame-navigate', 'did-navigate' ]; - before((done) => { + before(async () => { server = http.createServer((req, res) => { if (req.url === '/navigate') { res.end('navigate'); @@ -899,10 +896,7 @@ describe('BrowserWindow module', () => { res.end(''); } }); - server.listen(0, '127.0.0.1', () => { - url = `http://127.0.0.1:${(server.address() as AddressInfo).port}/`; - done(); - }); + url = (await listen(server)).url; }); it('for initial navigation, event order is consistent', async () => { const firedEvents: string[] = []; @@ -929,7 +923,7 @@ describe('BrowserWindow module', () => { 'did-frame-navigate', 'did-navigate' ]; - w.loadURL(`${url}navigate`); + w.loadURL(url + '/navigate'); await once(w.webContents, 'did-navigate'); await setTimeout(2000); Promise.all(navigationEvents.map(event => @@ -972,7 +966,7 @@ describe('BrowserWindow module', () => { 'did-frame-navigate', 'did-navigate' ]; - w.loadURL(`${url}redirect`); + w.loadURL(url + '/redirect'); await once(w.webContents, 'did-navigate'); await setTimeout(2000); Promise.all(navigationEvents.map(event => @@ -1010,7 +1004,7 @@ describe('BrowserWindow module', () => { 'did-start-navigation', 'did-navigate-in-page' ]; - w.loadURL(`${url}in-page`); + w.loadURL(url + '/in-page'); await once(w.webContents, 'did-navigate'); await setTimeout(2000); Promise.all(navigationEvents.map(event => @@ -4729,7 +4723,7 @@ describe('BrowserWindow module', () => { expect(c.isVisible()).to.be.true('child is visible'); }); - it('closes a grandchild window when a middle child window is destroyed', (done) => { + it('closes a grandchild window when a middle child window is destroyed', async () => { const w = new BrowserWindow(); w.loadFile(path.join(fixtures, 'pages', 'base-page.html')); @@ -4739,12 +4733,12 @@ describe('BrowserWindow module', () => { const childWindow = new BrowserWindow({ parent: window }); await setTimeout(); - window.close(); - childWindow.on('closed', () => { - expect(() => { BrowserWindow.getFocusedWindow(); }).to.not.throw(); - done(); - }); + const closed = once(childWindow, 'closed'); + window.close(); + await closed; + + expect(() => { BrowserWindow.getFocusedWindow(); }).to.not.throw(); }); }); diff --git a/spec/api-menu-spec.ts b/spec/api-menu-spec.ts index a6a6243a608..019f5b43a2e 100644 --- a/spec/api-menu-spec.ts +++ b/spec/api-menu-spec.ts @@ -813,15 +813,17 @@ describe('Menu module', function () { }).to.not.throw(); }); - it('should emit menu-will-show event', (done) => { - menu.on('menu-will-show', () => { done(); }); + it('should emit menu-will-show event', async () => { + const menuWillShow = once(menu, 'menu-will-show'); menu.popup({ window: w }); + await menuWillShow; }); - it('should emit menu-will-close event', (done) => { - menu.on('menu-will-close', () => { done(); }); + it('should emit menu-will-close event', async () => { + const menuWillClose = once(menu, 'menu-will-close'); menu.popup({ window: w }); menu.closePopup(); + await menuWillClose; }); it('returns immediately', () => { diff --git a/spec/api-protocol-spec.ts b/spec/api-protocol-spec.ts index 72dfe18fe89..1bb267c2810 100644 --- a/spec/api-protocol-spec.ts +++ b/spec/api-protocol-spec.ts @@ -263,7 +263,7 @@ describe('protocol module', () => { expect(r.headers).to.have.property('x-great-header', 'sogreat'); }); - it('can load iframes with custom protocols', (done) => { + it('can load iframes with custom protocols', async () => { registerFileProtocol('custom', (request, callback) => { const filename = request.url.substring(9); const p = path.join(__dirname, 'fixtures', 'pages', filename); @@ -278,8 +278,9 @@ describe('protocol module', () => { } }); + const loaded = once(ipcMain, 'loaded-iframe-custom-protocol'); w.loadFile(path.join(__dirname, 'fixtures', 'pages', 'iframe-protocol.html')); - ipcMain.once('loaded-iframe-custom-protocol', () => done()); + await loaded; }); it('sends object as response', async () => { diff --git a/spec/api-tray-spec.ts b/spec/api-tray-spec.ts index a5a0b2aed1a..067d529330c 100644 --- a/spec/api-tray-spec.ts +++ b/spec/api-tray-spec.ts @@ -3,6 +3,7 @@ import { Menu, Tray } from 'electron/main'; import { nativeImage } from 'electron/common'; import { ifdescribe, ifit } from './lib/spec-helpers'; import * as path from 'node:path'; +import { setTimeout } from 'node:timers/promises'; describe('tray module', () => { let tray: Tray; @@ -74,12 +75,11 @@ describe('tray module', () => { }); describe('tray.popUpContextMenu()', () => { - ifit(process.platform === 'win32')('can be called when menu is showing', function (done) { + ifit(process.platform === 'win32')('can be called when menu is showing', async function () { tray.setContextMenu(Menu.buildFromTemplate([{ label: 'Test' }])); - setTimeout(() => { - tray.popUpContextMenu(); - done(); - }); + const timeout = setTimeout(); + tray.popUpContextMenu(); + await timeout; tray.popUpContextMenu(); }); @@ -115,14 +115,13 @@ describe('tray module', () => { }); describe('tray.closeContextMenu()', () => { - ifit(process.platform === 'win32')('does not crash when called more than once', function (done) { + ifit(process.platform === 'win32')('does not crash when called more than once', async function () { tray.setContextMenu(Menu.buildFromTemplate([{ label: 'Test' }])); - setTimeout(() => { - tray.closeContextMenu(); - tray.closeContextMenu(); - done(); - }); + const timeout = setTimeout(); tray.popUpContextMenu(); + await timeout; + tray.closeContextMenu(); + tray.closeContextMenu(); }); }); diff --git a/spec/api-web-contents-spec.ts b/spec/api-web-contents-spec.ts index b440ef2b3ea..089523c9537 100644 --- a/spec/api-web-contents-spec.ts +++ b/spec/api-web-contents-spec.ts @@ -1218,8 +1218,7 @@ describe('webContents module', () => { res.end(); }); }); - server.listen(0, '127.0.0.1', () => { - const url = 'http://127.0.0.1:' + (server.address() as AddressInfo).port; + listen(server).then(({ url }) => { const content = ``; w.webContents.on('did-frame-finish-load', (e, isMainFrame) => { if (!isMainFrame) { @@ -1591,8 +1590,9 @@ describe('webContents module', () => { default: done('unsupported endpoint'); } - }).listen(0, '127.0.0.1', () => { - serverUrl = 'http://127.0.0.1:' + (server.address() as AddressInfo).port; + }); + listen(server).then(({ url }) => { + serverUrl = url; done(); }); }); @@ -1721,11 +1721,10 @@ describe('webContents module', () => { } res.end('link'); }); - server.listen(0, '127.0.0.1', () => { - const url = 'http://127.0.0.1:' + (server.address() as AddressInfo).port + '/'; + listen(server).then(({ url }) => { w.webContents.once('did-finish-load', () => { w.webContents.setWindowOpenHandler(details => { - expect(details.referrer.url).to.equal(url); + expect(details.referrer.url).to.equal(url + '/'); expect(details.referrer.policy).to.equal('strict-origin-when-cross-origin'); return { action: 'allow' }; }); @@ -1748,11 +1747,10 @@ describe('webContents module', () => { } res.end(''); }); - server.listen(0, '127.0.0.1', () => { - const url = 'http://127.0.0.1:' + (server.address() as AddressInfo).port + '/'; + listen(server).then(({ url }) => { w.webContents.once('did-finish-load', () => { w.webContents.setWindowOpenHandler(details => { - expect(details.referrer.url).to.equal(url); + expect(details.referrer.url).to.equal(url + '/'); expect(details.referrer.policy).to.equal('strict-origin-when-cross-origin'); return { action: 'allow' }; }); diff --git a/spec/api-web-request-spec.ts b/spec/api-web-request-spec.ts index f3091b579a2..3d29cc61428 100644 --- a/spec/api-web-request-spec.ts +++ b/spec/api-web-request-spec.ts @@ -7,7 +7,7 @@ import * as fs from 'node:fs'; import * as url from 'node:url'; import * as WebSocket from 'ws'; import { ipcMain, protocol, session, WebContents, webContents } from 'electron/main'; -import { AddressInfo, Socket } from 'node:net'; +import { Socket } from 'node:net'; import { listen, defer } from './lib/spec-helpers'; import { once } from 'node:events'; import { ReadableStream } from 'node:stream/web'; @@ -60,10 +60,7 @@ describe('webRequest module', () => { before(async () => { protocol.registerStringProtocol('cors', (req, cb) => cb('')); defaultURL = (await listen(server)).url + '/'; - await new Promise((resolve) => { - h2server.listen(0, '127.0.0.1', () => resolve()); - }); - http2URL = `https://127.0.0.1:${(h2server.address() as AddressInfo).port}/`; + http2URL = (await listen(h2server)).url + '/'; console.log(http2URL); }); diff --git a/spec/chromium-spec.ts b/spec/chromium-spec.ts index c1ccab48bd5..9216038dfdf 100644 --- a/spec/chromium-spec.ts +++ b/spec/chromium-spec.ts @@ -13,6 +13,7 @@ import { ifit, ifdescribe, defer, itremote, listen } from './lib/spec-helpers'; import { PipeTransport } from './pipe-transport'; import * as ws from 'ws'; import { setTimeout } from 'node:timers/promises'; +import { AddressInfo } from 'node:net'; const features = process._linkedBinding('electron_common_features'); @@ -56,12 +57,12 @@ describe('reporting api', () => { res.end(''); }); - await new Promise(resolve => server.listen(0, '127.0.0.1', resolve)); + await listen(server); const bw = new BrowserWindow({ show: false }); try { const reportGenerated = once(reporting, 'report'); - await bw.loadURL(`https://localhost:${(server.address() as any).port}/a`); + await bw.loadURL(`https://localhost:${(server.address() as AddressInfo).port}/a`); const [reports] = await reportGenerated; expect(reports).to.be.an('array').with.lengthOf(1); diff --git a/spec/guest-window-manager-spec.ts b/spec/guest-window-manager-spec.ts index 8e4cffee3b2..21011a32c4e 100644 --- a/spec/guest-window-manager-spec.ts +++ b/spec/guest-window-manager-spec.ts @@ -200,29 +200,21 @@ describe('webContents.setWindowOpenHandler', () => { }); // Linux and arm64 platforms (WOA and macOS) do not return any capture sources - ifit(process.platform === 'darwin' && process.arch === 'x64')('should not make child window background transparent', (done) => { + ifit(process.platform === 'darwin' && process.arch === 'x64')('should not make child window background transparent', async () => { browserWindow.webContents.setWindowOpenHandler(() => ({ action: 'allow' })); - - browserWindow.webContents.once('did-create-window', async (childWindow) => { - const display = screen.getPrimaryDisplay(); - childWindow.setBounds(display.bounds); - await childWindow.webContents.executeJavaScript("const meta = document.createElement('meta'); meta.name = 'color-scheme'; meta.content = 'dark'; document.head.appendChild(meta); true;"); - await setTimeoutAsync(1000); - const screenCapture = await captureScreen(); - const centerColor = getPixelColor(screenCapture, { - x: display.size.width / 2, - y: display.size.height / 2 - }); - - try { - // color-scheme is set to dark so background should not be white - expect(areColorsSimilar(centerColor, HexColors.WHITE)).to.be.false(); - done(); - } catch (err) { - done(err); - } - }); - + const didCreateWindow = once(browserWindow.webContents, 'did-create-window'); browserWindow.webContents.executeJavaScript("window.open('about:blank') && true"); + const [childWindow] = await didCreateWindow; + const display = screen.getPrimaryDisplay(); + childWindow.setBounds(display.bounds); + await childWindow.webContents.executeJavaScript("const meta = document.createElement('meta'); meta.name = 'color-scheme'; meta.content = 'dark'; document.head.appendChild(meta); true;"); + await setTimeoutAsync(1000); + const screenCapture = await captureScreen(); + const centerColor = getPixelColor(screenCapture, { + x: display.size.width / 2, + y: display.size.height / 2 + }); + // color-scheme is set to dark so background should not be white + expect(areColorsSimilar(centerColor, HexColors.WHITE)).to.be.false(); }); }); diff --git a/spec/lib/spec-helpers.ts b/spec/lib/spec-helpers.ts index a94964f9361..e814c5a4539 100644 --- a/spec/lib/spec-helpers.ts +++ b/spec/lib/spec-helpers.ts @@ -2,6 +2,7 @@ import * as childProcess from 'node:child_process'; import * as path from 'node:path'; import * as http from 'node:http'; import * as https from 'node:https'; +import * as http2 from 'node:http2'; import * as net from 'node:net'; import * as v8 from 'node:v8'; import * as url from 'node:url'; @@ -194,10 +195,10 @@ export async function itremote (name: string, fn: Function, args?: any[]) { }); } -export async function listen (server: http.Server | https.Server) { +export async function listen (server: http.Server | https.Server | http2.Http2SecureServer) { const hostname = '127.0.0.1'; await new Promise(resolve => server.listen(0, hostname, () => resolve())); const { port } = server.address() as net.AddressInfo; - const protocol = (server instanceof https.Server) ? 'https' : 'http'; + const protocol = (server instanceof http.Server) ? 'http' : 'https'; return { port, url: url.format({ protocol, hostname, port }) }; }