index.js 5.6 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');
12
// const MochaJUnitReporter = require('mocha-junit-reporter');
13
const url = require('url');
J
Johannes Rieken 已提交
14

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

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

J
Johannes Rieken 已提交
29
const argv = optimist.argv;
J
Johannes Rieken 已提交
30

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

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

40 41
function deserializeSuite(suite) {
	return {
J
Joao Moreno 已提交
42 43 44
		root: suite.root,
		suites: suite.suites,
		tests: suite.tests,
45 46 47 48 49 50
		title: suite.title,
		fullTitle: () => suite.fullTitle,
		timeout: () => suite.timeout,
		retries: () => suite.retries,
		enableTimeouts: () => suite.enableTimeouts,
		slow: () => suite.slow,
T
thomas 已提交
51
		bail: () => suite.bail
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 94 95
	};
}

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 已提交
96 97 98 99 100
function parseReporterOption(value) {
	let r = /^([^=]+)=(.*)$/.exec(value);
	return r ? { [r[1]]: r[2] } : {};
}

J
Johannes Rieken 已提交
101 102
app.on('ready', () => {

103 104 105 106 107 108 109
	ipcMain.on('error', (_, err) => {
		if (!argv.debug) {
			console.error(err);
			app.exit(1);
		}
	});

J
Johannes Rieken 已提交
110 111 112
	const win = new BrowserWindow({
		height: 600,
		width: 800,
113
		show: false,
114 115
		webPreferences: {
			backgroundThrottling: false,
116 117
			nodeIntegration: true,
			webSecurity: false,
R
Robo 已提交
118 119
			webviewTag: true,
			enableWebSQL: false
120
		}
J
Johannes Rieken 已提交
121 122 123
	});

	win.webContents.on('did-finish-load', () => {
J
Johannes Rieken 已提交
124
		if (argv.debug) {
125
			win.show();
A
Alex Dima 已提交
126
			win.webContents.openDevTools();
J
Johannes Rieken 已提交
127
		}
J
Johannes Rieken 已提交
128
		win.webContents.send('run', argv);
J
Johannes Rieken 已提交
129 130
	});

131
	win.loadURL(url.format({ pathname: path.join(__dirname, 'renderer.html'), protocol: 'file:', slashes: true }));
J
Johannes Rieken 已提交
132

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

J
Joao Moreno 已提交
135
	if (argv.tfs) {
J
Joao Moreno 已提交
136
		new mocha.reporters.Spec(runner);
137 138 139 140 141 142 143
		// TODO@deepak the mocha Junit reporter seems to cause a hang when running with Electron 6 inside docker container
		// new MochaJUnitReporter(runner, {
		// 	reporterOptions: {
		// 		testsuitesTitle: `${argv.tfs} ${process.platform}`,
		// 		mochaFile: process.env.BUILD_ARTIFACTSTAGINGDIRECTORY ? path.join(process.env.BUILD_ARTIFACTSTAGINGDIRECTORY, `test-results/${process.platform}-${argv.tfs.toLowerCase().replace(/[^\w]/g, '-')}-results.xml`) : undefined
		// 	}
		// });
J
Joao Moreno 已提交
144 145 146 147 148 149 150 151 152 153 154 155 156 157
	} 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 已提交
158

J
Joao Moreno 已提交
159 160 161 162 163 164
		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 已提交
165

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