1 | 'use strict';
|
2 | require('./lib/worker/load-chalk');
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 | const path = require('path');
|
9 | const meow = require('meow');
|
10 | const Promise = require('bluebird');
|
11 | const uniqueTempDir = require('unique-temp-dir');
|
12 | const arrify = require('arrify');
|
13 | const resolveCwd = require('resolve-cwd');
|
14 | const escapeStringRegexp = require('escape-string-regexp');
|
15 | const babelPipeline = require('./lib/babel-pipeline');
|
16 | const RunStatus = require('./lib/run-status');
|
17 | const VerboseReporter = require('./lib/reporters/verbose');
|
18 | const loadConfig = require('./lib/load-config');
|
19 | const normalizeExtensions = require('./lib/extensions');
|
20 |
|
21 | function 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 |
|
33 | Promise.longStackTraces();
|
34 |
|
35 | const conf = loadConfig({
|
36 | defaults: {
|
37 | babel: {
|
38 | testOptions: {}
|
39 | },
|
40 | compileEnhancements: true
|
41 | }
|
42 | });
|
43 |
|
44 | const {projectDir} = conf;
|
45 |
|
46 | const 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 |
|
70 | if (cli.input.length === 0) {
|
71 | throw new Error('Specify a test file');
|
72 | }
|
73 |
|
74 | const file = path.resolve(cli.input[0]);
|
75 | const cacheDir = conf.cacheEnabled === false ? uniqueTempDir() : path.join(projectDir, 'node_modules', '.cache', 'ava');
|
76 |
|
77 | const babelConfig = babelPipeline.validate(conf.babel);
|
78 | conf.extensions = normalizeExtensions(conf.extensions || [], babelConfig);
|
79 |
|
80 | const _regexpFullExtensions = new RegExp(`\\.(${conf.extensions.full.map(ext => escapeStringRegexp(ext)).join('|')})$`);
|
81 |
|
82 | const precompileFull = babelPipeline.build(process.cwd(), cacheDir, babelConfig, conf.compileEnhancements === true);
|
83 |
|
84 | let precompileEnhancementsOnly = () => null;
|
85 | if (conf.compileEnhancements) {
|
86 | precompileEnhancementsOnly = babelPipeline.build(projectDir, cacheDir, null, conf.compileEnhancements);
|
87 | }
|
88 |
|
89 | const precompiled = {};
|
90 | precompiled[file] = _regexpFullExtensions.test(file) ? precompileFull(file) : precompileEnhancementsOnly(file);
|
91 |
|
92 | const 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 |
|
104 | process.connected = true;
|
105 | process.channel = {ref() {}, unref() {}};
|
106 |
|
107 | const reporter = new VerboseReporter({
|
108 | reportStream: process.stdout,
|
109 | stdStream: process.stderr,
|
110 | watching: false
|
111 | });
|
112 |
|
113 | const runStatus = new RunStatus(1, null);
|
114 | runStatus.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 |
|
147 | reporter.startRun({
|
148 | failFastEnabled: false,
|
149 | files: [file],
|
150 | matching: false,
|
151 | previousFailures: 0,
|
152 | status: runStatus
|
153 | });
|
154 |
|
155 | process.on('beforeExit', () => {
|
156 | process.exitCode = process.exitCode || runStatus.suggestExitCode({matching: false});
|
157 | });
|
158 |
|
159 | if (console.profile) {
|
160 | console.profile('AVA test-worker process');
|
161 | }
|
162 |
|
163 | setImmediate(() => {
|
164 | require('./lib/worker/subprocess');
|
165 | });
|