UNPKG

4.29 kBJavaScriptView Raw
1'use strict';
2require('./lib/worker/load-chalk'); // eslint-disable-line import/no-unassigned-import
3
4// Iron-node does not work with forked processes
5// This cli command will run a single file in the current process.
6// Intended to be used with iron-node for profiling purposes.
7
8const path = require('path');
9const meow = require('meow');
10const Promise = require('bluebird');
11const uniqueTempDir = require('unique-temp-dir');
12const arrify = require('arrify');
13const resolveCwd = require('resolve-cwd');
14const escapeStringRegexp = require('escape-string-regexp');
15const babelPipeline = require('./lib/babel-pipeline');
16const RunStatus = require('./lib/run-status');
17const VerboseReporter = require('./lib/reporters/verbose');
18const loadConfig = require('./lib/load-config');
19const normalizeExtensions = require('./lib/extensions');
20
21function resolveModules(modules) {
22 return arrify(modules).map(name => {
23 const modulePath = resolveCwd.silent(name);
24
25 if (modulePath === undefined) {
26 throw new Error(`Could not resolve required module '${name}'`);
27 }
28
29 return modulePath;
30 });
31}
32
33Promise.longStackTraces();
34
35const conf = loadConfig({
36 defaults: {
37 babel: {
38 testOptions: {}
39 },
40 compileEnhancements: true
41 }
42});
43
44const {projectDir} = conf;
45// Define a minimal set of options from the main CLI
46const cli = meow(`
47 Usage
48 $ iron-node node_modules/ava/profile.js <test-file>
49
50 Options
51 --fail-fast Stop after first test failure
52 --serial, -s Run tests serially
53
54`, {
55 string: [
56 '_'
57 ],
58 boolean: [
59 'fail-fast',
60 'verbose',
61 'serial',
62 'tap'
63 ],
64 default: conf,
65 alias: {
66 s: 'serial'
67 }
68});
69
70if (cli.input.length === 0) {
71 throw new Error('Specify a test file');
72}
73
74const file = path.resolve(cli.input[0]);
75const cacheDir = conf.cacheEnabled === false ? uniqueTempDir() : path.join(projectDir, 'node_modules', '.cache', 'ava');
76
77const babelConfig = babelPipeline.validate(conf.babel);
78conf.extensions = normalizeExtensions(conf.extensions || [], babelConfig);
79
80const _regexpFullExtensions = new RegExp(`\\.(${conf.extensions.full.map(ext => escapeStringRegexp(ext)).join('|')})$`);
81
82const precompileFull = babelPipeline.build(process.cwd(), cacheDir, babelConfig, conf.compileEnhancements === true);
83
84let precompileEnhancementsOnly = () => null;
85if (conf.compileEnhancements) {
86 precompileEnhancementsOnly = babelPipeline.build(projectDir, cacheDir, null, conf.compileEnhancements);
87}
88
89const precompiled = {};
90precompiled[file] = _regexpFullExtensions.test(file) ? precompileFull(file) : precompileEnhancementsOnly(file);
91
92const opts = {
93 file,
94 projectDir,
95 failFast: cli.flags.failFast,
96 serial: cli.flags.serial,
97 tty: false,
98 cacheDir,
99 precompiled,
100 require: resolveModules(conf.require)
101};
102
103// Mock the behavior of a parent process
104process.connected = true;
105process.channel = {ref() {}, unref() {}};
106
107const reporter = new VerboseReporter({
108 reportStream: process.stdout,
109 stdStream: process.stderr,
110 watching: false
111});
112
113const runStatus = new RunStatus(1, null);
114runStatus.observeWorker({
115 file,
116 onStateChange(listener) {
117 const emit = evt => listener(Object.assign(evt, {testFile: file}));
118 process.send = data => {
119 if (data && data.ava) {
120 const evt = data.ava;
121 if (evt.type === 'ready-for-options') {
122 process.emit('message', {ava: {type: 'options', options: opts}});
123 } else if (evt.type === 'ping') {
124 if (console.profileEnd) {
125 console.profileEnd();
126 }
127
128 if (process.exitCode) {
129 emit({type: 'worker-failed', nonZeroExitCode: process.exitCode});
130 } else {
131 emit({type: 'worker-finished', forcedExit: false});
132 process.exitCode = runStatus.suggestExitCode({matching: false});
133 }
134
135 setImmediate(() => {
136 reporter.endRun();
137 process.emit('message', {ava: {type: 'pong'}});
138 });
139 } else {
140 emit(data.ava);
141 }
142 }
143 };
144 }
145}, file);
146
147reporter.startRun({
148 failFastEnabled: false,
149 files: [file],
150 matching: false,
151 previousFailures: 0,
152 status: runStatus
153});
154
155process.on('beforeExit', () => {
156 process.exitCode = process.exitCode || runStatus.suggestExitCode({matching: false});
157});
158
159if (console.profile) {
160 console.profile('AVA test-worker process');
161}
162
163setImmediate(() => {
164 require('./lib/worker/subprocess'); // eslint-disable-line import/no-unassigned-import
165});