fix: flaky utility and BrowserView tests (#44451)

* fix: flake wait for crash with specific serviceName

* fix: flake when unrelated WebContents exists during BrowserView tests

* fix: wait for crash before forking

* use name
This commit is contained in:
Sam Maddock 2024-10-30 21:29:01 -04:00 committed by GitHub
parent 7cdf1a01b8
commit 31f8e7553b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 31 additions and 11 deletions

View file

@ -1,4 +1,4 @@
import { BrowserView, BrowserWindow, screen, webContents } from 'electron/main'; import { BrowserView, BrowserWindow, screen, session, webContents } from 'electron/main';
import { expect } from 'chai'; import { expect } from 'chai';
@ -11,24 +11,29 @@ import { closeWindow } from './lib/window-helpers';
describe('BrowserView module', () => { describe('BrowserView module', () => {
const fixtures = path.resolve(__dirname, 'fixtures'); const fixtures = path.resolve(__dirname, 'fixtures');
const ses = session.fromPartition(crypto.randomUUID());
let w: BrowserWindow; let w: BrowserWindow;
let view: BrowserView; let view: BrowserView;
const getSessionWebContents = () =>
webContents.getAllWebContents().filter(wc => wc.session === ses);
beforeEach(() => { beforeEach(() => {
expect(webContents.getAllWebContents().length).to.equal(0, 'expected no webContents to exist'); expect(getSessionWebContents().length).to.equal(0, 'expected no webContents to exist');
w = new BrowserWindow({ w = new BrowserWindow({
show: false, show: false,
width: 400, width: 400,
height: 400, height: 400,
webPreferences: { webPreferences: {
backgroundThrottling: false backgroundThrottling: false,
session: ses
} }
}); });
}); });
afterEach(async () => { afterEach(async () => {
if (!w.isDestroyed()) { if (w && !w.isDestroyed()) {
const p = once(w.webContents, 'destroyed'); const p = once(w.webContents, 'destroyed');
await closeWindow(w); await closeWindow(w);
w = null as any; w = null as any;
@ -42,7 +47,7 @@ describe('BrowserView module', () => {
await p; await p;
} }
expect(webContents.getAllWebContents().length).to.equal(0, 'expected no webContents to exist'); expect(getSessionWebContents().length).to.equal(0, 'expected no webContents to exist');
}); });
it('sets the correct class name on the prototype', () => { it('sets the correct class name on the prototype', () => {
@ -50,7 +55,7 @@ describe('BrowserView module', () => {
}); });
it('can be created with an existing webContents', async () => { it('can be created with an existing webContents', async () => {
const wc = (webContents as typeof ElectronInternal.WebContents).create({ sandbox: true }); const wc = (webContents as typeof ElectronInternal.WebContents).create({ session: ses, sandbox: true });
await wc.loadURL('about:blank'); await wc.loadURL('about:blank');
view = new BrowserView({ webContents: wc } as any); view = new BrowserView({ webContents: wc } as any);

View file

@ -144,21 +144,36 @@ describe('utilityProcess module', () => {
}); });
describe('app \'child-process-gone\' event', () => { describe('app \'child-process-gone\' event', () => {
const waitForCrash = (name: string) => {
return new Promise<Electron.Details>((resolve) => {
app.on('child-process-gone', function onCrash (_event, details) {
if (details.name === name) {
app.off('child-process-gone', onCrash);
resolve(details);
}
});
});
};
ifit(!isWindows32Bit)('with default serviceName', async () => { ifit(!isWindows32Bit)('with default serviceName', async () => {
const name = 'Node Utility Process';
const crashPromise = waitForCrash(name);
utilityProcess.fork(path.join(fixturesPath, 'crash.js')); utilityProcess.fork(path.join(fixturesPath, 'crash.js'));
const [, details] = await once(app, 'child-process-gone') as [any, Electron.Details]; const details = await crashPromise;
expect(details.type).to.equal('Utility'); expect(details.type).to.equal('Utility');
expect(details.serviceName).to.equal('node.mojom.NodeService'); expect(details.serviceName).to.equal('node.mojom.NodeService');
expect(details.name).to.equal('Node Utility Process'); expect(details.name).to.equal(name);
expect(details.reason).to.be.oneOf(['crashed', 'abnormal-exit']); expect(details.reason).to.be.oneOf(['crashed', 'abnormal-exit']);
}); });
ifit(!isWindows32Bit)('with custom serviceName', async () => { ifit(!isWindows32Bit)('with custom serviceName', async () => {
utilityProcess.fork(path.join(fixturesPath, 'crash.js'), [], { serviceName: 'Hello World!' }); const name = crypto.randomUUID();
const [, details] = await once(app, 'child-process-gone') as [any, Electron.Details]; const crashPromise = waitForCrash(name);
utilityProcess.fork(path.join(fixturesPath, 'crash.js'), [], { serviceName: name });
const details = await crashPromise;
expect(details.type).to.equal('Utility'); expect(details.type).to.equal('Utility');
expect(details.serviceName).to.equal('node.mojom.NodeService'); expect(details.serviceName).to.equal('node.mojom.NodeService');
expect(details.name).to.equal('Hello World!'); expect(details.name).to.equal(name);
expect(details.reason).to.be.oneOf(['crashed', 'abnormal-exit']); expect(details.reason).to.be.oneOf(['crashed', 'abnormal-exit']);
}); });
}); });