2020-03-20 20:28:31 +00:00
|
|
|
import { expect } from 'chai';
|
|
|
|
import * as childProcess from 'child_process';
|
|
|
|
import * as http from 'http';
|
2020-04-22 22:53:12 +00:00
|
|
|
import * as Busboy from 'busboy';
|
2020-03-20 20:28:31 +00:00
|
|
|
import * as path from 'path';
|
2020-04-23 20:08:50 +00:00
|
|
|
import { ifdescribe, ifit } from './spec-helpers';
|
2020-03-20 20:28:31 +00:00
|
|
|
import * as temp from 'temp';
|
2020-04-22 22:53:12 +00:00
|
|
|
import { app } from 'electron/main';
|
2020-04-07 00:04:09 +00:00
|
|
|
import { crashReporter } from 'electron/common';
|
2020-03-20 20:28:31 +00:00
|
|
|
import { AddressInfo } from 'net';
|
|
|
|
import { EventEmitter } from 'events';
|
2020-04-22 22:53:12 +00:00
|
|
|
import * as fs from 'fs';
|
|
|
|
import * as v8 from 'v8';
|
2020-03-20 20:28:31 +00:00
|
|
|
|
|
|
|
temp.track();
|
|
|
|
|
2020-04-23 20:08:50 +00:00
|
|
|
const isWindowsOnArm = process.platform === 'win32' && process.arch === 'arm64';
|
|
|
|
|
2020-03-20 20:28:31 +00:00
|
|
|
const afterTest: ((() => void) | (() => Promise<void>))[] = [];
|
2019-11-01 20:37:02 +00:00
|
|
|
async function cleanup () {
|
2019-10-14 21:38:54 +00:00
|
|
|
for (const cleanup of afterTest) {
|
2020-03-20 20:28:31 +00:00
|
|
|
const r = cleanup();
|
|
|
|
if (r instanceof Promise) { await r; }
|
2019-10-14 21:38:54 +00:00
|
|
|
}
|
2020-03-20 20:28:31 +00:00
|
|
|
afterTest.length = 0;
|
2019-10-14 21:38:54 +00:00
|
|
|
}
|
|
|
|
|
2020-04-22 22:53:12 +00:00
|
|
|
type CrashInfo = {
|
|
|
|
prod: string
|
|
|
|
ver: string
|
|
|
|
process_type: string // eslint-disable-line camelcase
|
|
|
|
platform: string
|
|
|
|
extra1: string
|
|
|
|
extra2: string
|
|
|
|
extra3: undefined
|
|
|
|
_productName: string
|
|
|
|
_companyName: string
|
|
|
|
_version: string
|
|
|
|
upload_file_minidump: Buffer // eslint-disable-line camelcase
|
|
|
|
}
|
|
|
|
|
|
|
|
function checkCrash (expectedProcessType: string, fields: CrashInfo) {
|
|
|
|
expect(String(fields.prod)).to.equal('Electron');
|
|
|
|
expect(String(fields.ver)).to.equal(process.versions.electron);
|
|
|
|
expect(String(fields.process_type)).to.equal(expectedProcessType);
|
|
|
|
expect(String(fields.platform)).to.equal(process.platform);
|
|
|
|
expect(String(fields._productName)).to.equal('Zombies');
|
|
|
|
expect(String(fields._companyName)).to.equal('Umbrella Corporation');
|
|
|
|
expect(String(fields._version)).to.equal(app.getVersion());
|
|
|
|
expect(fields.upload_file_minidump).to.be.an.instanceOf(Buffer);
|
|
|
|
expect(fields.upload_file_minidump.length).to.be.greaterThan(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
function checkCrashExtra (fields: CrashInfo) {
|
|
|
|
expect(String(fields.extra1)).to.equal('extra1');
|
|
|
|
expect(String(fields.extra2)).to.equal('extra2');
|
|
|
|
expect(fields.extra3).to.be.undefined();
|
|
|
|
}
|
2019-10-14 21:38:54 +00:00
|
|
|
|
2020-04-22 22:53:12 +00:00
|
|
|
const startRemoteControlApp = async () => {
|
|
|
|
const appPath = path.join(__dirname, 'fixtures', 'apps', 'remote-control');
|
|
|
|
const appProcess = childProcess.spawn(process.execPath, [appPath]);
|
|
|
|
const port = await new Promise<number>(resolve => {
|
|
|
|
appProcess.stdout.on('data', d => {
|
|
|
|
const m = /Listening: (\d+)/.exec(d.toString());
|
|
|
|
if (m && m[1] != null) {
|
|
|
|
resolve(Number(m[1]));
|
|
|
|
}
|
|
|
|
});
|
2020-03-20 20:28:31 +00:00
|
|
|
});
|
2020-04-22 22:53:12 +00:00
|
|
|
function remoteEval (js: string): any {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
const req = http.request({
|
|
|
|
host: '127.0.0.1',
|
|
|
|
port,
|
|
|
|
method: 'POST'
|
|
|
|
}, res => {
|
|
|
|
const chunks = [] as Buffer[];
|
|
|
|
res.on('data', chunk => { chunks.push(chunk); });
|
|
|
|
res.on('end', () => {
|
|
|
|
const ret = v8.deserialize(Buffer.concat(chunks));
|
|
|
|
if (Object.prototype.hasOwnProperty.call(ret, 'error')) {
|
|
|
|
reject(new Error(`remote error: ${ret.error}\n\nTriggered at:`));
|
|
|
|
} else {
|
|
|
|
resolve(ret.result);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
req.write(js);
|
|
|
|
req.end();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
afterTest.push(() => { appProcess.kill('SIGINT'); });
|
|
|
|
return { remoteEval };
|
|
|
|
};
|
2019-10-14 21:38:54 +00:00
|
|
|
|
2020-04-22 22:53:12 +00:00
|
|
|
const startServer = async () => {
|
|
|
|
const crashes: CrashInfo[] = [];
|
|
|
|
function getCrashes () { return crashes; }
|
|
|
|
const emitter = new EventEmitter();
|
|
|
|
function waitForCrash (): Promise<CrashInfo> {
|
|
|
|
return new Promise(resolve => {
|
|
|
|
emitter.once('crash', (crash) => {
|
|
|
|
resolve(crash);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
2019-10-14 21:38:54 +00:00
|
|
|
|
2020-04-22 22:53:12 +00:00
|
|
|
const server = http.createServer((req, res) => {
|
|
|
|
const busboy = new Busboy({ headers: req.headers });
|
|
|
|
const fields = {} as Record<string, any>;
|
|
|
|
const files = {} as Record<string, Buffer>;
|
|
|
|
busboy.on('file', (fieldname, file) => {
|
|
|
|
const chunks = [] as Array<Buffer>;
|
|
|
|
file.on('data', (chunk) => {
|
|
|
|
chunks.push(chunk);
|
|
|
|
});
|
|
|
|
file.on('end', () => {
|
|
|
|
files[fieldname] = Buffer.concat(chunks);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
busboy.on('field', (fieldname, val) => {
|
|
|
|
fields[fieldname] = val;
|
|
|
|
});
|
|
|
|
busboy.on('finish', () => {
|
|
|
|
const reportId = 'abc-123-def-456-abc-789-abc-123-abcd';
|
|
|
|
res.end(reportId, async () => {
|
|
|
|
req.socket.destroy();
|
|
|
|
emitter.emit('crash', { ...fields, ...files });
|
|
|
|
});
|
|
|
|
});
|
|
|
|
req.pipe(busboy);
|
|
|
|
});
|
2019-10-14 21:38:54 +00:00
|
|
|
|
2020-04-22 22:53:12 +00:00
|
|
|
await new Promise(resolve => {
|
|
|
|
server.listen(0, '127.0.0.1', () => { resolve(); });
|
2020-03-20 20:28:31 +00:00
|
|
|
});
|
2019-10-14 21:38:54 +00:00
|
|
|
|
2020-04-22 22:53:12 +00:00
|
|
|
const port = (server.address() as AddressInfo).port;
|
2019-10-14 21:38:54 +00:00
|
|
|
|
2020-04-22 22:53:12 +00:00
|
|
|
afterTest.push(() => { server.close(); });
|
2019-10-14 21:38:54 +00:00
|
|
|
|
2020-04-22 22:53:12 +00:00
|
|
|
return { getCrashes, port, waitForCrash };
|
|
|
|
};
|
2019-10-14 21:38:54 +00:00
|
|
|
|
2020-04-22 22:53:12 +00:00
|
|
|
function runApp (appPath: string, args: Array<string> = []) {
|
|
|
|
const appProcess = childProcess.spawn(process.execPath, [appPath, ...args]);
|
|
|
|
return new Promise(resolve => {
|
|
|
|
appProcess.once('exit', resolve);
|
|
|
|
});
|
|
|
|
}
|
2019-10-14 21:38:54 +00:00
|
|
|
|
2020-04-22 22:53:12 +00:00
|
|
|
function runCrashApp (crashType: string, port: number, extraArgs: Array<string> = []) {
|
|
|
|
const appPath = path.join(__dirname, 'fixtures', 'apps', 'crash');
|
|
|
|
return runApp(appPath, [
|
|
|
|
`--crash-type=${crashType}`,
|
|
|
|
`--crash-reporter-url=http://127.0.0.1:${port}`,
|
|
|
|
...extraArgs
|
|
|
|
]);
|
|
|
|
}
|
2019-10-14 21:38:54 +00:00
|
|
|
|
2020-04-22 22:53:12 +00:00
|
|
|
function waitForNewFileInDir (dir: string): Promise<string[]> {
|
2020-04-23 20:08:50 +00:00
|
|
|
function readdirIfPresent (dir: string): string[] {
|
|
|
|
try {
|
|
|
|
return fs.readdirSync(dir);
|
|
|
|
} catch (e) {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const initialFiles = readdirIfPresent(dir);
|
2020-04-22 22:53:12 +00:00
|
|
|
return new Promise(resolve => {
|
|
|
|
const ivl = setInterval(() => {
|
2020-04-23 20:08:50 +00:00
|
|
|
const newCrashFiles = readdirIfPresent(dir).filter(f => !initialFiles.includes(f));
|
2020-04-22 22:53:12 +00:00
|
|
|
if (newCrashFiles.length) {
|
|
|
|
clearInterval(ivl);
|
|
|
|
resolve(newCrashFiles);
|
|
|
|
}
|
|
|
|
}, 1000);
|
|
|
|
});
|
|
|
|
}
|
2019-10-14 21:38:54 +00:00
|
|
|
|
2020-04-22 22:53:12 +00:00
|
|
|
// TODO(alexeykuzmin): [Ch66] This test fails on Linux. Fix it and enable back.
|
|
|
|
ifdescribe(!process.mas && !process.env.DISABLE_CRASH_REPORTER_TESTS && process.platform !== 'linux')('crashReporter module', function () {
|
|
|
|
afterEach(cleanup);
|
2019-10-14 21:38:54 +00:00
|
|
|
|
2020-04-22 22:53:12 +00:00
|
|
|
it('should send minidump when renderer crashes', async () => {
|
|
|
|
const { port, waitForCrash } = await startServer();
|
|
|
|
runCrashApp('renderer', port);
|
|
|
|
const crash = await waitForCrash();
|
|
|
|
checkCrash('renderer', crash);
|
|
|
|
});
|
2019-10-14 21:38:54 +00:00
|
|
|
|
2020-04-22 22:53:12 +00:00
|
|
|
it('should send minidump when sandboxed renderer crashes', async () => {
|
|
|
|
const { port, waitForCrash } = await startServer();
|
|
|
|
runCrashApp('sandboxed-renderer', port);
|
|
|
|
const crash = await waitForCrash();
|
|
|
|
checkCrash('renderer', crash);
|
|
|
|
checkCrashExtra(crash);
|
|
|
|
});
|
2019-10-14 21:38:54 +00:00
|
|
|
|
2020-04-22 22:53:12 +00:00
|
|
|
it('should send minidump with updated parameters when renderer crashes', async () => {
|
|
|
|
const { port, waitForCrash } = await startServer();
|
|
|
|
runCrashApp('renderer', port, ['--set-extra-parameters-in-renderer']);
|
|
|
|
const crash = await waitForCrash();
|
|
|
|
checkCrash('renderer', crash);
|
|
|
|
expect(crash.extra1).to.be.undefined();
|
|
|
|
expect(crash.extra2).to.equal('extra2');
|
|
|
|
expect(crash.extra3).to.equal('added');
|
|
|
|
});
|
2019-10-14 21:38:54 +00:00
|
|
|
|
2020-04-22 22:53:12 +00:00
|
|
|
it('should send minidump with updated parameters when sandboxed renderer crashes', async () => {
|
|
|
|
const { port, waitForCrash } = await startServer();
|
|
|
|
runCrashApp('sandboxed-renderer', port, ['--set-extra-parameters-in-renderer']);
|
|
|
|
const crash = await waitForCrash();
|
|
|
|
checkCrash('renderer', crash);
|
|
|
|
expect(crash.extra1).to.be.undefined();
|
|
|
|
expect(crash.extra2).to.equal('extra2');
|
|
|
|
expect(crash.extra3).to.equal('added');
|
|
|
|
});
|
2019-10-14 21:38:54 +00:00
|
|
|
|
2020-04-22 22:53:12 +00:00
|
|
|
it('should send minidump when main process crashes', async () => {
|
|
|
|
const { port, waitForCrash } = await startServer();
|
|
|
|
runCrashApp('main', port);
|
|
|
|
const crash = await waitForCrash();
|
|
|
|
checkCrash('browser', crash);
|
|
|
|
checkCrashExtra(crash);
|
2020-03-20 20:28:31 +00:00
|
|
|
});
|
2020-04-22 22:53:12 +00:00
|
|
|
|
|
|
|
it('should send minidump when a node process crashes', async () => {
|
|
|
|
const { port, waitForCrash } = await startServer();
|
|
|
|
runCrashApp('node', port);
|
|
|
|
const crash = await waitForCrash();
|
|
|
|
checkCrash('node', crash);
|
|
|
|
checkCrashExtra(crash);
|
|
|
|
});
|
|
|
|
|
2020-04-23 20:08:50 +00:00
|
|
|
// TODO(jeremy): re-enable on woa
|
|
|
|
ifit(!isWindowsOnArm)('should not send a minidump when uploadToServer is false', async () => {
|
2020-04-22 22:53:12 +00:00
|
|
|
const { port, getCrashes } = await startServer();
|
|
|
|
const crashesDir = path.join(app.getPath('temp'), 'Zombies Crashes');
|
|
|
|
const completedCrashesDir = path.join(crashesDir, 'completed');
|
|
|
|
const crashAppeared = waitForNewFileInDir(completedCrashesDir);
|
|
|
|
await runCrashApp('renderer', port, ['--no-upload']);
|
|
|
|
await crashAppeared;
|
|
|
|
// wait a sec in case crashpad is about to upload a crash
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
|
|
expect(getCrashes()).to.have.length(0);
|
2020-03-20 20:28:31 +00:00
|
|
|
});
|
2019-10-14 21:38:54 +00:00
|
|
|
|
2020-04-22 22:53:12 +00:00
|
|
|
describe('start() option validation', () => {
|
|
|
|
it('requires that the companyName option be specified', () => {
|
2019-10-14 21:38:54 +00:00
|
|
|
expect(() => {
|
2020-04-22 22:53:12 +00:00
|
|
|
crashReporter.start({ companyName: 'dummy' } as any);
|
2020-03-20 20:28:31 +00:00
|
|
|
}).to.throw('submitURL is a required option to crashReporter.start');
|
2020-04-22 22:53:12 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it('requires that the submitURL option be specified', () => {
|
2019-10-14 21:38:54 +00:00
|
|
|
expect(() => {
|
2020-04-22 22:53:12 +00:00
|
|
|
crashReporter.start({ submitURL: 'dummy' } as any);
|
2020-03-20 20:28:31 +00:00
|
|
|
}).to.throw('companyName is a required option to crashReporter.start');
|
|
|
|
});
|
2019-10-14 21:38:54 +00:00
|
|
|
|
2020-04-22 22:53:12 +00:00
|
|
|
it('can be called twice', async () => {
|
|
|
|
const { remoteEval } = await startRemoteControlApp();
|
|
|
|
|
|
|
|
await remoteEval(`require('electron').crashReporter.start({companyName: "Umbrella Corporation", submitURL: "http://127.0.0.1"})`);
|
|
|
|
await remoteEval(`require('electron').crashReporter.start({companyName: "Umbrella Corporation", submitURL: "http://127.0.0.1"})`);
|
2020-03-20 20:28:31 +00:00
|
|
|
});
|
|
|
|
});
|
2019-10-14 21:38:54 +00:00
|
|
|
|
|
|
|
describe('getCrashesDirectory', () => {
|
2020-04-22 22:53:12 +00:00
|
|
|
it('correctly returns the directory', async () => {
|
|
|
|
const { remoteEval } = await startRemoteControlApp();
|
|
|
|
await remoteEval(`require('electron').crashReporter.start({companyName: "Umbrella Corporation", submitURL: "http://127.0.0.1"})`);
|
|
|
|
const crashesDir = await remoteEval(`require('electron').crashReporter.getCrashesDirectory()`);
|
|
|
|
const dir = path.join(app.getPath('temp'), 'remote-control Crashes');
|
2020-03-20 20:28:31 +00:00
|
|
|
expect(crashesDir).to.equal(dir);
|
|
|
|
});
|
|
|
|
});
|
2019-10-14 21:38:54 +00:00
|
|
|
|
|
|
|
describe('getUploadedReports', () => {
|
2020-04-22 22:53:12 +00:00
|
|
|
it('returns an array of reports', async () => {
|
|
|
|
const { remoteEval } = await startRemoteControlApp();
|
|
|
|
await remoteEval(`require('electron').crashReporter.start({companyName: "Umbrella Corporation", submitURL: "http://127.0.0.1"})`);
|
|
|
|
const reports = await remoteEval(`require('electron').crashReporter.getUploadedReports()`);
|
2020-03-20 20:28:31 +00:00
|
|
|
expect(reports).to.be.an('array');
|
|
|
|
});
|
|
|
|
});
|
2019-10-14 21:38:54 +00:00
|
|
|
|
2020-04-23 20:08:50 +00:00
|
|
|
// TODO(jeremy): re-enable on woa
|
|
|
|
ifdescribe(!isWindowsOnArm)('getLastCrashReport', () => {
|
2020-04-22 22:53:12 +00:00
|
|
|
it('returns the last uploaded report', async () => {
|
|
|
|
const { remoteEval } = await startRemoteControlApp();
|
|
|
|
const { port, waitForCrash } = await startServer();
|
|
|
|
|
|
|
|
// 0. clear the crash reports directory.
|
|
|
|
const dir = path.join(app.getPath('temp'), 'remote-control Crashes');
|
|
|
|
try {
|
|
|
|
fs.rmdirSync(dir, { recursive: true });
|
|
|
|
} catch (e) { /* ignore */ }
|
|
|
|
|
|
|
|
// 1. start the crash reporter.
|
|
|
|
await remoteEval(`require('electron').crashReporter.start({companyName: "Umbrella Corporation", submitURL: "http://127.0.0.1:${port}", ignoreSystemCrashHandler: true})`);
|
|
|
|
// 2. generate a crash.
|
|
|
|
remoteEval(`(function() { const {BrowserWindow} = require('electron'); const bw = new BrowserWindow({show: false, webPreferences: {nodeIntegration: true}}); bw.loadURL('about:blank'); bw.webContents.executeJavaScript('process.crash()') })()`);
|
|
|
|
await waitForCrash();
|
|
|
|
// 3. get the crash from getLastCrashReport.
|
|
|
|
const firstReport = await remoteEval(`require('electron').crashReporter.getLastCrashReport()`);
|
|
|
|
expect(firstReport).to.not.be.null();
|
|
|
|
expect(firstReport.date).to.be.an.instanceOf(Date);
|
2020-03-20 20:28:31 +00:00
|
|
|
});
|
|
|
|
});
|
2019-10-14 21:38:54 +00:00
|
|
|
|
|
|
|
describe('getUploadToServer()', () => {
|
2020-04-22 22:53:12 +00:00
|
|
|
it('returns true when uploadToServer is set to true (by default)', async () => {
|
|
|
|
const { remoteEval } = await startRemoteControlApp();
|
2019-10-14 21:38:54 +00:00
|
|
|
|
2020-04-22 22:53:12 +00:00
|
|
|
await remoteEval(`require('electron').crashReporter.start({companyName: "Umbrella Corporation", submitURL: "http://127.0.0.1"})`);
|
|
|
|
const uploadToServer = await remoteEval(`require('electron').crashReporter.getUploadToServer()`);
|
|
|
|
expect(uploadToServer).to.be.true();
|
2020-03-20 20:28:31 +00:00
|
|
|
});
|
2020-04-22 22:53:12 +00:00
|
|
|
|
|
|
|
it('returns false when uploadToServer is set to false in init', async () => {
|
|
|
|
const { remoteEval } = await startRemoteControlApp();
|
|
|
|
await remoteEval(`require('electron').crashReporter.start({companyName: "Umbrella Corporation", submitURL: "http://127.0.0.1", uploadToServer: false})`);
|
|
|
|
const uploadToServer = await remoteEval(`require('electron').crashReporter.getUploadToServer()`);
|
|
|
|
expect(uploadToServer).to.be.false();
|
2020-03-20 20:28:31 +00:00
|
|
|
});
|
2020-04-22 22:53:12 +00:00
|
|
|
|
|
|
|
it('is updated by setUploadToServer', async () => {
|
|
|
|
const { remoteEval } = await startRemoteControlApp();
|
|
|
|
await remoteEval(`require('electron').crashReporter.start({companyName: "Umbrella Corporation", submitURL: "http://127.0.0.1"})`);
|
|
|
|
await remoteEval(`require('electron').crashReporter.setUploadToServer(false)`);
|
|
|
|
expect(await remoteEval(`require('electron').crashReporter.getUploadToServer()`)).to.be.false();
|
|
|
|
await remoteEval(`require('electron').crashReporter.setUploadToServer(true)`);
|
|
|
|
expect(await remoteEval(`require('electron').crashReporter.getUploadToServer()`)).to.be.true();
|
2020-03-20 20:28:31 +00:00
|
|
|
});
|
|
|
|
});
|
2019-10-14 21:38:54 +00:00
|
|
|
|
|
|
|
describe('Parameters', () => {
|
2020-04-22 22:53:12 +00:00
|
|
|
it('returns all of the current parameters', async () => {
|
|
|
|
const { remoteEval } = await startRemoteControlApp();
|
|
|
|
await remoteEval(`require('electron').crashReporter.start({companyName: "Umbrella Corporation", submitURL: "http://127.0.0.1", extra: {"extra1": "hi"}})`);
|
|
|
|
const parameters = await remoteEval(`require('electron').crashReporter.getParameters()`);
|
2020-03-20 20:28:31 +00:00
|
|
|
expect(parameters).to.be.an('object');
|
2020-04-22 22:53:12 +00:00
|
|
|
expect(parameters.extra1).to.equal('hi');
|
2020-03-20 20:28:31 +00:00
|
|
|
});
|
2019-10-14 21:38:54 +00:00
|
|
|
|
2020-04-22 22:53:12 +00:00
|
|
|
it('adds and removes parameters', async () => {
|
|
|
|
const { remoteEval } = await startRemoteControlApp();
|
|
|
|
await remoteEval(`require('electron').crashReporter.start({companyName: "Umbrella Corporation", submitURL: "http://127.0.0.1"})`);
|
|
|
|
await remoteEval(`require('electron').crashReporter.addExtraParameter('hello', 'world')`);
|
|
|
|
{
|
|
|
|
const parameters = await remoteEval(`require('electron').crashReporter.getParameters()`);
|
|
|
|
expect(parameters).to.have.property('hello');
|
|
|
|
expect(parameters.hello).to.equal('world');
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
await remoteEval(`require('electron').crashReporter.removeExtraParameter('hello')`);
|
|
|
|
const parameters = await remoteEval(`require('electron').crashReporter.getParameters()`);
|
|
|
|
expect(parameters).not.to.have.property('hello');
|
|
|
|
}
|
2020-03-20 20:28:31 +00:00
|
|
|
});
|
|
|
|
});
|
2019-10-14 21:38:54 +00:00
|
|
|
|
|
|
|
describe('when not started', () => {
|
2020-04-22 22:53:12 +00:00
|
|
|
it('does not prevent process from crashing', async () => {
|
|
|
|
const appPath = path.join(__dirname, '..', 'spec', 'fixtures', 'api', 'cookie-app');
|
|
|
|
await runApp(appPath);
|
2020-03-20 20:28:31 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|