👷 proper IPCRunner, IPCReporter for electron mocha test runner
This commit is contained in:
parent
6546fe5e87
commit
0ff4498392
2 changed files with 128 additions and 37 deletions
|
@ -6,6 +6,9 @@
|
|||
const { app, BrowserWindow, ipcMain } = require('electron');
|
||||
const { tmpdir } = require('os');
|
||||
const { join } = require('path');
|
||||
const path = require('path');
|
||||
const mocha = require('mocha');
|
||||
const events = require('events');
|
||||
|
||||
const optimist = require('optimist')
|
||||
.describe('grep', 'only run tests matching <pattern>').alias('grep', 'g').alias('grep', 'f').string('grep')
|
||||
|
@ -14,6 +17,7 @@ const optimist = require('optimist')
|
|||
.describe('build', 'run with build output (out-build)').boolean('build')
|
||||
.describe('coverage', 'generate coverage report').boolean('coverage')
|
||||
.describe('debug', 'open dev tools, keep window open, reuse app data').string('debug')
|
||||
.describe('reporter', 'the mocha reporter').string('reporter').default('reporter', 'spec')
|
||||
.describe('help', 'show the help').alias('help', 'h');
|
||||
|
||||
const argv = optimist.argv;
|
||||
|
@ -27,6 +31,59 @@ if (!argv.debug) {
|
|||
app.setPath('userData', join(tmpdir(), `vscode-tests-${Date.now()}`));
|
||||
}
|
||||
|
||||
function deserializeSuite(suite) {
|
||||
return {
|
||||
title: suite.title,
|
||||
fullTitle: () => suite.fullTitle,
|
||||
timeout: () => suite.timeout,
|
||||
retries: () => suite.retries,
|
||||
enableTimeouts: () => suite.enableTimeouts,
|
||||
slow: () => suite.slow,
|
||||
bail: () => suite.bail,
|
||||
};
|
||||
}
|
||||
|
||||
function deserializeRunnable(runnable) {
|
||||
return {
|
||||
title: runnable.title,
|
||||
fullTitle: () => runnable.fullTitle,
|
||||
async: runnable.async,
|
||||
slow: () => runnable.slow,
|
||||
speed: runnable.speed,
|
||||
duration: runnable.duration
|
||||
};
|
||||
}
|
||||
|
||||
function deserializeError(err) {
|
||||
const inspect = err.inspect;
|
||||
err.inspect = () => inspect;
|
||||
return err;
|
||||
}
|
||||
|
||||
class IPCRunner extends events.EventEmitter {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.didFail = false;
|
||||
|
||||
ipcMain.on('start', () => this.emit('start'));
|
||||
ipcMain.on('end', () => this.emit('end'));
|
||||
ipcMain.on('suite', (e, suite) => this.emit('suite', deserializeSuite(suite)));
|
||||
ipcMain.on('suite end', (e, suite) => this.emit('suite end', deserializeSuite(suite)));
|
||||
ipcMain.on('test', (e, test) => this.emit('test', deserializeRunnable(test)));
|
||||
ipcMain.on('test end', (e, test) => this.emit('test end', deserializeRunnable(test)));
|
||||
ipcMain.on('hook', (e, hook) => this.emit('hook', deserializeRunnable(hook)));
|
||||
ipcMain.on('hook end', (e, hook) => this.emit('hook end', deserializeRunnable(hook)));
|
||||
ipcMain.on('pass', (e, test) => this.emit('pass', deserializeRunnable(test)));
|
||||
ipcMain.on('fail', (e, test, err) => {
|
||||
this.didFail = true;
|
||||
this.emit('fail', deserializeRunnable(test), deserializeError(err));
|
||||
});
|
||||
ipcMain.on('pending', (e, test) => this.emit('pending', deserializeRunnable(test)));
|
||||
}
|
||||
}
|
||||
|
||||
app.on('ready', () => {
|
||||
|
||||
const win = new BrowserWindow({
|
||||
|
@ -49,28 +106,20 @@ app.on('ready', () => {
|
|||
|
||||
win.loadURL(`file://${__dirname}/renderer.html`);
|
||||
|
||||
const reporterPath = path.join(path.dirname(require.resolve('mocha')), 'lib', 'reporters', argv.reporter);
|
||||
let Reporter;
|
||||
|
||||
const _failures = [];
|
||||
ipcMain.on('fail', (e, test) => {
|
||||
_failures.push(test);
|
||||
process.stdout.write('X');
|
||||
});
|
||||
ipcMain.on('pass', () => {
|
||||
process.stdout.write('.');
|
||||
});
|
||||
try {
|
||||
Reporter = require(reporterPath);
|
||||
} catch (err) {
|
||||
console.warn(`could not load reporter: ${argv.reporter}`);
|
||||
Reporter = mocha.reporters.Spec;
|
||||
}
|
||||
|
||||
ipcMain.on('done', () => {
|
||||
const runner = new IPCRunner();
|
||||
new Reporter(runner);
|
||||
|
||||
console.log(`\nDone with ${_failures.length} failures.\n`);
|
||||
|
||||
for (const fail of _failures) {
|
||||
console.error(fail.title);
|
||||
console.error(fail.stack);
|
||||
console.error('\n');
|
||||
}
|
||||
|
||||
if (!argv.debug) {
|
||||
app.exit(_failures.length > 0 ? 1 : 0);
|
||||
}
|
||||
});
|
||||
if (!argv.debug) {
|
||||
ipcMain.on('all done', () => app.exit(runner.didFail ? 1 : 0));
|
||||
}
|
||||
});
|
||||
|
|
|
@ -13,7 +13,6 @@ const minimatch = require('minimatch');
|
|||
const istanbul = require('istanbul');
|
||||
const i_remap = require('remap-istanbul/lib/remap');
|
||||
|
||||
|
||||
let _tests_glob = '**/test/**/*.test.js';
|
||||
let loader;
|
||||
let _out;
|
||||
|
@ -180,6 +179,58 @@ function loadTests(opts) {
|
|||
});
|
||||
}
|
||||
|
||||
function serializeSuite(suite) {
|
||||
return {
|
||||
title: suite.title,
|
||||
fullTitle: suite.fullTitle(),
|
||||
timeout: suite.timeout(),
|
||||
retries: suite.retries(),
|
||||
enableTimeouts: suite.enableTimeouts(),
|
||||
slow: suite.slow(),
|
||||
bail: suite.bail()
|
||||
};
|
||||
}
|
||||
|
||||
function serializeRunnable(runnable) {
|
||||
return {
|
||||
title: runnable.title,
|
||||
fullTitle: runnable.fullTitle(),
|
||||
async: runnable.async,
|
||||
slow: runnable.slow(),
|
||||
speed: runnable.speed,
|
||||
duration: runnable.duration
|
||||
};
|
||||
}
|
||||
|
||||
function serializeError(err) {
|
||||
return {
|
||||
message: err.message,
|
||||
stack: err.stack,
|
||||
actual: err.actual,
|
||||
expected: err.expected,
|
||||
uncaught: err.uncaught,
|
||||
showDiff: err.showDiff,
|
||||
inspect: typeof err.inspect === 'function' ? err.inspect() : ''
|
||||
};
|
||||
}
|
||||
|
||||
class IPCReporter {
|
||||
|
||||
constructor(runner) {
|
||||
runner.on('start', () => ipcRenderer.send('start'));
|
||||
runner.on('end', () => ipcRenderer.send('end'));
|
||||
runner.on('suite', suite => ipcRenderer.send('suite', serializeSuite(suite)));
|
||||
runner.on('suite end', suite => ipcRenderer.send('suite end', serializeSuite(suite)));
|
||||
runner.on('test', test => ipcRenderer.send('test', serializeRunnable(test)));
|
||||
runner.on('test end', test => ipcRenderer.send('test end', serializeRunnable(test)));
|
||||
runner.on('hook', hook => ipcRenderer.send('hook', serializeRunnable(hook)));
|
||||
runner.on('hook end', hook => ipcRenderer.send('hook end', serializeRunnable(hook)));
|
||||
runner.on('pass', test => ipcRenderer.send('pass', serializeRunnable(test)));
|
||||
runner.on('fail', (test, err) => ipcRenderer.send('fail', serializeRunnable(test), serializeError(err)));
|
||||
runner.on('pending', test => ipcRenderer.send('pending', serializeRunnable(test)));
|
||||
}
|
||||
}
|
||||
|
||||
function runTests(opts) {
|
||||
|
||||
return loadTests(opts).then(() => {
|
||||
|
@ -188,24 +239,15 @@ function runTests(opts) {
|
|||
mocha.grep(opts.grep);
|
||||
}
|
||||
|
||||
const runner = mocha.run(() => {
|
||||
if (!opts.debug) {
|
||||
mocha.reporter(IPCReporter);
|
||||
}
|
||||
|
||||
mocha.run(() => {
|
||||
createCoverageReport(opts).then(() => {
|
||||
ipcRenderer.send('done');
|
||||
ipcRenderer.send('all done');
|
||||
});
|
||||
});
|
||||
|
||||
runner.on('fail', function (test) {
|
||||
ipcRenderer.send('fail', {
|
||||
title: test.fullTitle(),
|
||||
stack: test.err.stack
|
||||
});
|
||||
console.error(test.fullTitle());
|
||||
console.error(test.err.stack);
|
||||
});
|
||||
|
||||
runner.on('pass', function () {
|
||||
ipcRenderer.send('pass');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue