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');
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')
J
Johannes Rieken 已提交
20
	.describe('runGlob', 'only run tests matching <file_pattern>').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 103 104 105
app.on('ready', () => {

	const win = new BrowserWindow({
		height: 600,
		width: 800,
106
		show: false,
107 108 109 110
		webPreferences: {
			backgroundThrottling: false,
			webSecurity: false
		}
J
Johannes Rieken 已提交
111 112 113
	});

	win.webContents.on('did-finish-load', () => {
J
Johannes Rieken 已提交
114
		if (argv.debug) {
115
			win.show();
116
			win.webContents.openDevTools({ mode: 'right' });
J
Johannes Rieken 已提交
117
		}
J
Johannes Rieken 已提交
118
		win.webContents.send('run', argv);
J
Johannes Rieken 已提交
119 120
	});

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

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

J
Joao Moreno 已提交
125
	if (argv.tfs) {
J
Joao Moreno 已提交
126
		new mocha.reporters.Spec(runner);
J
Joao Moreno 已提交
127 128
		new MochaJUnitReporter(runner, {
			reporterOptions: {
J
Joao Moreno 已提交
129 130
				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 已提交
131 132
			}
		});
J
Joao Moreno 已提交
133 134 135 136 137 138 139 140 141 142 143 144 145 146
	} 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 已提交
147

J
Joao Moreno 已提交
148 149 150 151 152 153
		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 已提交
154

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