index.js 5.2 KB
Newer Older
J
Johannes Rieken 已提交
1 2 3 4 5 6 7 8
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

const { app, BrowserWindow, ipcMain } = require('electron');
const { tmpdir } = require('os');
const { join } = require('path');
9 10 11
const path = require('path');
const mocha = require('mocha');
const events = require('events');
J
Johannes Rieken 已提交
12

J
Joao Moreno 已提交
13 14
const defaultReporterName = process.platform === 'win32' ? 'list' : 'spec';

J
Johannes Rieken 已提交
15
const optimist = require('optimist')
J
Joao Moreno 已提交
16
	.describe('grep', 'only run tests matching <pattern>').alias('grep', 'g').alias('grep', 'f').string('grep')
J
Johannes Rieken 已提交
17
	.describe('run', 'only run tests from <file>').string('run')
J
Johannes Rieken 已提交
18
	.describe('runGlob', 'only run tests matching <file_pattern>').alias('runGlob', 'runGrep').string('runGlob')
19
	.describe('build', 'run with build output (out-build)').boolean('build')
J
Johannes Rieken 已提交
20
	.describe('coverage', 'generate coverage report').boolean('coverage')
J
Joao Moreno 已提交
21
	.describe('debug', 'open dev tools, keep window open, reuse app data').string('debug')
J
Joao Moreno 已提交
22 23 24
	.describe('reporter', 'the mocha reporter').string('reporter').default('reporter', defaultReporterName)
	.describe('reporter-options', 'the mocha reporter options').string('reporter-options').default('reporter-options', '')
	.describe('tfs').boolean('tfs')
J
Joao Moreno 已提交
25
	.describe('help', 'show the help').alias('help', 'h');
J
Johannes Rieken 已提交
26

J
Johannes Rieken 已提交
27
const argv = optimist.argv;
J
Johannes Rieken 已提交
28

J
Joao Moreno 已提交
29 30 31 32 33
if (argv.help) {
	optimist.showHelp();
	process.exit(0);
}

J
Johannes Rieken 已提交
34
if (!argv.debug) {
35 36
	app.setPath('userData', join(tmpdir(), `vscode-tests-${Date.now()}`));
}
J
Johannes Rieken 已提交
37

38 39
function deserializeSuite(suite) {
	return {
J
Joao Moreno 已提交
40 41 42
		root: suite.root,
		suites: suite.suites,
		tests: suite.tests,
43 44 45 46 47 48
		title: suite.title,
		fullTitle: () => suite.fullTitle,
		timeout: () => suite.timeout,
		retries: () => suite.retries,
		enableTimeouts: () => suite.enableTimeouts,
		slow: () => suite.slow,
T
thomas 已提交
49
		bail: () => suite.bail
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
	};
}

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)));
	}
}

J
Joao Moreno 已提交
94 95 96 97 98
function parseReporterOption(value) {
	let r = /^([^=]+)=(.*)$/.exec(value);
	return r ? { [r[1]]: r[2] } : {};
}

J
Joao Moreno 已提交
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
class TFSReporter extends mocha.reporters.Base {

	constructor(runner) {
		super(runner);

		runner.on('pending', test => {
			console.log('PEND', test.fullTitle());
		});
		runner.on('pass', test => {
			console.log('OK  ', test.fullTitle(), `(${test.duration}ms)`);
		});
		runner.on('fail', test => {
			console.log('FAIL', test.fullTitle(), `(${test.duration}ms)`);
		});
		runner.once('end', () => {
			this.epilogue();
		});
	}
}

J
Johannes Rieken 已提交
119 120 121 122 123
app.on('ready', () => {

	const win = new BrowserWindow({
		height: 600,
		width: 800,
124
		show: false,
125 126 127 128
		webPreferences: {
			backgroundThrottling: false,
			webSecurity: false
		}
J
Johannes Rieken 已提交
129 130 131
	});

	win.webContents.on('did-finish-load', () => {
J
Johannes Rieken 已提交
132
		if (argv.debug) {
133
			win.show();
134
			win.webContents.openDevTools({ mode: 'right' });
J
Johannes Rieken 已提交
135
		}
J
Johannes Rieken 已提交
136
		win.webContents.send('run', argv);
J
Johannes Rieken 已提交
137 138
	});

J
Johannes Rieken 已提交
139
	win.loadURL(`file://${__dirname}/renderer.html`);
J
Johannes Rieken 已提交
140

J
Joao Moreno 已提交
141
	const runner = new IPCRunner();
J
Johannes Rieken 已提交
142

J
Joao Moreno 已提交
143
	if (argv.tfs) {
J
Joao Moreno 已提交
144
		new TFSReporter(runner);
J
Joao Moreno 已提交
145 146 147 148 149 150 151 152 153 154 155 156 157 158
	} else {
		const reporterPath = path.join(path.dirname(require.resolve('mocha')), 'lib', 'reporters', argv.reporter);
		let Reporter;

		try {
			Reporter = require(reporterPath);
		} catch (err) {
			try {
				Reporter = require(argv.reporter);
			} catch (err) {
				Reporter = process.platform === 'win32' ? mocha.reporters.List : mocha.reporters.Spec;
				console.warn(`could not load reporter: ${argv.reporter}, using ${Reporter.name}`);
			}
		}
J
Johannes Rieken 已提交
159

J
Joao Moreno 已提交
160 161 162 163 164 165
		let reporterOptions = argv['reporter-options'];
		reporterOptions = typeof reporterOptions === 'string' ? [reporterOptions] : reporterOptions;
		reporterOptions = reporterOptions.reduce((r, o) => Object.assign(r, parseReporterOption(o)), {});

		new Reporter(runner, { reporterOptions });
	}
J
Johannes Rieken 已提交
166

167 168 169
	if (!argv.debug) {
		ipcMain.on('all done', () => app.exit(runner.didFail ? 1 : 0));
	}
J
Johannes Rieken 已提交
170
});