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');
J
Johannes Rieken 已提交
13

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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