mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
185 lines
6.3 KiB
TypeScript
185 lines
6.3 KiB
TypeScript
import { expect } from 'chai';
|
|
import { BrowserWindow, ipcMain, IpcMainInvokeEvent } from 'electron';
|
|
|
|
describe('ipc module', () => {
|
|
describe('invoke', () => {
|
|
let w = (null as unknown as BrowserWindow);
|
|
|
|
before(async () => {
|
|
w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true } });
|
|
await w.loadURL('about:blank');
|
|
});
|
|
after(async () => {
|
|
w.destroy();
|
|
});
|
|
|
|
async function rendererInvoke (...args: any[]) {
|
|
const { ipcRenderer } = require('electron');
|
|
try {
|
|
const result = await ipcRenderer.invoke('test', ...args);
|
|
ipcRenderer.send('result', { result });
|
|
} catch (e) {
|
|
ipcRenderer.send('result', { error: e.message });
|
|
}
|
|
}
|
|
|
|
it('receives a response from a synchronous handler', async () => {
|
|
ipcMain.handleOnce('test', (e: IpcMainInvokeEvent, arg: number) => {
|
|
expect(arg).to.equal(123);
|
|
return 3;
|
|
});
|
|
const done = new Promise(resolve => ipcMain.once('result', (e, arg) => {
|
|
expect(arg).to.deep.equal({ result: 3 });
|
|
resolve();
|
|
}));
|
|
await w.webContents.executeJavaScript(`(${rendererInvoke})(123)`);
|
|
await done;
|
|
});
|
|
|
|
it('receives a response from an asynchronous handler', async () => {
|
|
ipcMain.handleOnce('test', async (e: IpcMainInvokeEvent, arg: number) => {
|
|
expect(arg).to.equal(123);
|
|
await new Promise(resolve => setImmediate(resolve));
|
|
return 3;
|
|
});
|
|
const done = new Promise(resolve => ipcMain.once('result', (e, arg) => {
|
|
expect(arg).to.deep.equal({ result: 3 });
|
|
resolve();
|
|
}));
|
|
await w.webContents.executeJavaScript(`(${rendererInvoke})(123)`);
|
|
await done;
|
|
});
|
|
|
|
it('receives an error from a synchronous handler', async () => {
|
|
ipcMain.handleOnce('test', () => {
|
|
throw new Error('some error');
|
|
});
|
|
const done = new Promise(resolve => ipcMain.once('result', (e, arg) => {
|
|
expect(arg.error).to.match(/some error/);
|
|
resolve();
|
|
}));
|
|
await w.webContents.executeJavaScript(`(${rendererInvoke})()`);
|
|
await done;
|
|
});
|
|
|
|
it('receives an error from an asynchronous handler', async () => {
|
|
ipcMain.handleOnce('test', async () => {
|
|
await new Promise(resolve => setImmediate(resolve));
|
|
throw new Error('some error');
|
|
});
|
|
const done = new Promise(resolve => ipcMain.once('result', (e, arg) => {
|
|
expect(arg.error).to.match(/some error/);
|
|
resolve();
|
|
}));
|
|
await w.webContents.executeJavaScript(`(${rendererInvoke})()`);
|
|
await done;
|
|
});
|
|
|
|
it('throws an error if no handler is registered', async () => {
|
|
const done = new Promise(resolve => ipcMain.once('result', (e, arg) => {
|
|
expect(arg.error).to.match(/No handler registered/);
|
|
resolve();
|
|
}));
|
|
await w.webContents.executeJavaScript(`(${rendererInvoke})()`);
|
|
await done;
|
|
});
|
|
|
|
it('throws an error when invoking a handler that was removed', async () => {
|
|
ipcMain.handle('test', () => {});
|
|
ipcMain.removeHandler('test');
|
|
const done = new Promise(resolve => ipcMain.once('result', (e, arg) => {
|
|
expect(arg.error).to.match(/No handler registered/);
|
|
resolve();
|
|
}));
|
|
await w.webContents.executeJavaScript(`(${rendererInvoke})()`);
|
|
await done;
|
|
});
|
|
|
|
it('forbids multiple handlers', async () => {
|
|
ipcMain.handle('test', () => {});
|
|
try {
|
|
expect(() => { ipcMain.handle('test', () => {}); }).to.throw(/second handler/);
|
|
} finally {
|
|
ipcMain.removeHandler('test');
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('ordering', () => {
|
|
let w = (null as unknown as BrowserWindow);
|
|
|
|
before(async () => {
|
|
w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true } });
|
|
await w.loadURL('about:blank');
|
|
});
|
|
after(async () => {
|
|
w.destroy();
|
|
});
|
|
|
|
it('between send and sendSync is consistent', async () => {
|
|
const received: number[] = [];
|
|
ipcMain.on('test-async', (e, i) => { received.push(i); });
|
|
ipcMain.on('test-sync', (e, i) => { received.push(i); e.returnValue = null; });
|
|
const done = new Promise(resolve => ipcMain.once('done', () => { resolve(); }));
|
|
function rendererStressTest () {
|
|
const { ipcRenderer } = require('electron');
|
|
for (let i = 0; i < 1000; i++) {
|
|
switch ((Math.random() * 2) | 0) {
|
|
case 0:
|
|
ipcRenderer.send('test-async', i);
|
|
break;
|
|
case 1:
|
|
ipcRenderer.sendSync('test-sync', i);
|
|
break;
|
|
}
|
|
}
|
|
ipcRenderer.send('done');
|
|
}
|
|
try {
|
|
w.webContents.executeJavaScript(`(${rendererStressTest})()`);
|
|
await done;
|
|
} finally {
|
|
ipcMain.removeAllListeners('test-async');
|
|
ipcMain.removeAllListeners('test-sync');
|
|
}
|
|
expect(received).to.have.lengthOf(1000);
|
|
expect(received).to.deep.equal([...received].sort((a, b) => a - b));
|
|
});
|
|
|
|
it('between send, sendSync, and invoke is consistent', async () => {
|
|
const received: number[] = [];
|
|
ipcMain.handle('test-invoke', (e, i) => { received.push(i); });
|
|
ipcMain.on('test-async', (e, i) => { received.push(i); });
|
|
ipcMain.on('test-sync', (e, i) => { received.push(i); e.returnValue = null; });
|
|
const done = new Promise(resolve => ipcMain.once('done', () => { resolve(); }));
|
|
function rendererStressTest () {
|
|
const { ipcRenderer } = require('electron');
|
|
for (let i = 0; i < 1000; i++) {
|
|
switch ((Math.random() * 3) | 0) {
|
|
case 0:
|
|
ipcRenderer.send('test-async', i);
|
|
break;
|
|
case 1:
|
|
ipcRenderer.sendSync('test-sync', i);
|
|
break;
|
|
case 2:
|
|
ipcRenderer.invoke('test-invoke', i);
|
|
break;
|
|
}
|
|
}
|
|
ipcRenderer.send('done');
|
|
}
|
|
try {
|
|
w.webContents.executeJavaScript(`(${rendererStressTest})()`);
|
|
await done;
|
|
} finally {
|
|
ipcMain.removeHandler('test-invoke');
|
|
ipcMain.removeAllListeners('test-async');
|
|
ipcMain.removeAllListeners('test-sync');
|
|
}
|
|
expect(received).to.have.lengthOf(1000);
|
|
expect(received).to.deep.equal([...received].sort((a, b) => a - b));
|
|
});
|
|
});
|
|
});
|