UNPKG

7.58 kBJavaScriptView Raw
1//
2
3'use strict';
4
5function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
6
7var _fs = require('fs');
8
9var _path = require('path');
10
11var _path2 = _interopRequireDefault(_path);
12
13var _module2 = require('module');
14
15var _module3 = _interopRequireDefault(_module2);
16
17//
18
19var _objectAssign = require('object-assign');
20
21var _objectAssign2 = _interopRequireDefault(_objectAssign);
22
23var _which = require('which');
24
25var _which2 = _interopRequireDefault(_which);
26
27var _mkdirp = require('mkdirp');
28
29var _mkdirp2 = _interopRequireDefault(_mkdirp);
30
31var _lodashPartial = require('lodash.partial');
32
33var _lodashPartial2 = _interopRequireDefault(_lodashPartial);
34
35var _nomnomnomnom = require('nomnomnomnom');
36
37var _nomnomnomnom2 = _interopRequireDefault(_nomnomnomnom);
38
39var _istanbul = require('istanbul');
40
41var _instrumenter = require('./instrumenter');
42
43//
44
45//
46
47_nomnomnomnom2['default'].command('cover').help("transparently adds coverage information to a node command. Saves coverage.json and reports at the end of execution").option('cmd', {
48 required: true,
49 position: 1,
50 help: 'ES6 js files to cover (using babel)'
51}).option('config', {
52 metavar: '<path-to-config>',
53 help: 'the configuration file to use, defaults to .istanbul.yml'
54}).option('default-excludes', {
55 'default': true,
56 flag: true,
57 help: 'apply default excludes [ **/node_modules/**, **/test/**, **/tests/** ]'
58}).option('excludes', {
59 abbr: 'x',
60 'default': [],
61 help: 'one or more fileset patterns e.g. "**/vendor/**"',
62 list: true,
63 metavar: '<exclude-pattern>'
64}).option('report', {
65 'default': 'lcv',
66 metavar: '<format>',
67 list: true,
68 help: 'report format'
69}).option('root', {
70 'default': '.',
71 metavar: '<path>',
72 help: 'the root path to look for files to instrument'
73}).option('include', {
74 'default': ['**/*.js'],
75 metavar: '<include-pattern>',
76 list: true,
77 abbr: 'i',
78 help: 'one or more fileset patterns e.g. \'**/*.js\''
79}).option('verbose', {
80 flag: true,
81 abbr: 'v',
82 help: 'verbose mode'
83}).option('include-all-sources', {
84 'default': false,
85 flag: true,
86 help: 'instrument all unused sources after running tests'
87}).callback(function (opts) {
88
89 var args = opts._,
90 files = [],
91 cmdArgs = [];
92
93 args.forEach(function (arg) {
94
95 var file = lookupFiles(arg);
96 if (file) files = files.concat(file);
97 });
98
99 opts.include = opts.include.concat(files);
100
101 coverCmd(opts);
102});
103;
104
105_nomnomnomnom2['default'].nom();
106
107function lookupFiles(path) {
108
109 if ((0, _fs.existsSync)(path)) {
110 var stat = (0, _fs.statSync)(path);
111 if (stat.isFile()) return path;
112 }
113}
114
115function callback(err) {
116 if (err) {
117 console.error(err);
118 process.exit(1);
119 }
120 process.exit(0);
121}
122
123function coverCmd(opts) {
124
125 var config = overrideConfigWith(opts);
126 var istanbulCoveragePath = _path2['default'].resolve(config.reporting.dir());
127 var reporter = new _istanbul.Reporter(config, istanbulCoveragePath);
128
129 var cmd = opts.cmd;
130
131 var cmdArgs = opts['--'] || [];
132
133 if (!(0, _fs.existsSync)(cmd)) {
134 try {
135 cmd = _which2['default'].sync(cmd);
136 } catch (ex) {
137 return callback('Unable to resolve file [' + cmd + ']');
138 }
139 } else {
140 cmd = _path2['default'].resolve(cmd);
141 }
142
143 if (opts.verbose) console.error('Isparta options : \n ', opts);
144
145 var excludes = config.instrumentation.excludes(true);
146 enableHooks();
147
148 ////
149
150 function overrideConfigWith(opts) {
151 var overrides = {
152 verbose: opts.verbose,
153 instrumentation: {
154 root: opts.root,
155 'default-excludes': opts['default-excludes'],
156 excludes: opts.excludes,
157 'include-all-sources': opts['include-all-sources'],
158 // preload-sources is deprecated
159 // TODO(douglasduteil): remove this option
160 'preload-sources': opts['preload-sources']
161 },
162 reporting: {
163 reports: opts.report,
164 print: opts.print,
165 dir: opts.dir
166 },
167 hooks: {
168 'hook-run-in-context': opts['hook-run-in-context'],
169 'post-require-hook': opts['post-require-hook'],
170 'handle-sigint': opts['handle-sigint']
171 }
172 };
173
174 return _istanbul.config.loadFile(opts.config, overrides);
175 }
176
177 function enableHooks() {
178 opts.reportingDir = _path2['default'].resolve(config.reporting.dir());
179 _mkdirp2['default'].sync(opts.reportingDir);
180 reporter.addAll(config.reporting.reports());
181
182 if (config.reporting.print() !== 'none') {
183 switch (config.reporting.print()) {
184 case 'detail':
185 reporter.add('text');
186 break;
187 case 'both':
188 reporter.add('text');
189 reporter.add('text-summary');
190 break;
191 default:
192 reporter.add('text-summary');
193 break;
194 }
195 }
196
197 excludes.push(_path2['default'].relative(process.cwd(), _path2['default'].join(opts.reportingDir, '**', '*')));
198
199 (0, _istanbul.matcherFor)({
200 root: config.instrumentation.root() || process.cwd(),
201 includes: opts.include || config.instrumentation.extensions().map(function (ext) {
202 return '**/*' + ext;
203 }),
204 excludes: excludes
205 }, function (err, matchFn) {
206 if (err) {
207 return callback(err);
208 }
209
210 prepareCoverage(matchFn);
211 runCommandFn();
212 });
213 }
214
215 function prepareCoverage(matchFn) {
216 var coverageVar = '$$cov_' + Date.now() + '$$';
217 var instrumenter = new _instrumenter.Instrumenter({ coverageVariable: coverageVar });
218 var transformer = instrumenter.instrumentSync.bind(instrumenter);
219
220 _istanbul.hook.hookRequire(matchFn, transformer, (0, _objectAssign2['default'])({ verbose: opts.verbose }, config.instrumentation.config));
221
222 global[coverageVar] = {};
223
224 if (config.hooks.handleSigint()) {
225 process.once('SIGINT', process.exit);
226 }
227
228 process.once('exit', function (code) {
229 if (code) {
230 process.exit(code);
231 }
232 var file = _path2['default'].resolve(opts.reportingDir, 'coverage.json');
233 var cov = undefined,
234 collector = undefined;
235
236 if (typeof global[coverageVar] === 'undefined' || Object.keys(global[coverageVar]).length === 0) {
237 console.error('No coverage information was collected, exit without writing coverage information');
238 return;
239 } else {
240 cov = global[coverageVar];
241 }
242
243 _mkdirp2['default'].sync(opts.reportingDir);
244 if (config.reporting.print() !== 'none') {
245 console.error(Array(80 + 1).join('='));
246 console.error('Writing coverage object [' + file + ']');
247 }
248 (0, _fs.writeFileSync)(file, JSON.stringify(cov), 'utf8');
249 collector = new _istanbul.Collector();
250 collector.add(cov);
251 if (config.reporting.print() !== 'none') {
252 console.error('Writing coverage reports at [' + opts.reportingDir + ']');
253 console.error(Array(80 + 1).join('='));
254 }
255 reporter.write(collector, true, callback);
256 });
257
258 if (config.instrumentation.includeAllSources()) {
259 matchFn.files.forEach(function (file) {
260 if (opts.verbose) {
261 console.error('Preload ' + file);
262 }
263 try {
264 require(file);
265 } catch (ex) {
266 if (opts.verbose) {
267 console.error('Unable to preload ' + file);
268 }
269 // swallow
270 }
271 });
272 }
273 }
274
275 function runCommandFn() {
276 process.argv = ["node", cmd].concat(cmdArgs);
277 if (opts.verbose) {
278 console.log('Running: ' + process.argv.join(' '));
279 }
280 process.env.running_under_istanbul = 1;
281 _module3['default'].runMain(cmd, null, true);
282 }
283}
\No newline at end of file