UNPKG

4.38 kBJavaScriptView Raw
1var async = require('async');
2var fs = require('fs');
3var spawn = require('child_process').spawn;
4var EventEmitter = require('events').EventEmitter;
5var util = require('util');
6var helper = require('./helper.js');
7
8util.inherits(Antr, EventEmitter);
9
10function Antr (options, cb) {
11 var self = this;
12 this._cb = cb || null;
13
14 options = options || {};
15 this._options = {
16 dirname: options.dirname || '.',
17 filter: options.filter || /^(?!\.)(.+)\.js$/,
18 batchSize: options.batchSize || 8,
19 timeout: (isNaN(parseInt(options.timeout)) )? 30000 : parseInt(options.timeout) * 1000,
20 listFiles: options.listFiles || false,
21 progressBar: (options.progressBar == false) ? false : true,
22 succinct: (options.succinct == true) ? true : false
23 }
24 this._stats = {
25 failed: 0,
26 passed: 0,
27 total: 0,
28 failRate: 0,
29 failedTests: [],
30 passedTests: [],
31 timeTaken: null
32 }
33}
34
35Antr.prototype.run = function() {
36 var self = this;
37
38 self.getFiles(function (err, files) {
39 if(files && files.length == 0 || !files) {
40 self.emit('complete', {code: 1, message: 'No files found.'});
41 if (self._cb !== null) self._cb('ERROR: No files found.', self._stats);
42 } else {
43 self.emit('start', files);
44
45 var stack = [];
46 var complete = [];
47 var totalTests = files.length;
48
49 async.eachLimit(files, self._options.batchSize, function (item, cb) {
50 self.runSingleTest(item, self, cb);
51 }, function (err) {
52 self.emit('complete', {code: 0, message: ''});
53 if (self._cb !== null) {
54 if(self._stats.failed == 0) {
55 self._cb(null, self._stats);
56 } else {
57 self._cb('ERROR: ' + self._stats.failed + ' tests failed.', self._stats);
58 }
59 }
60 })
61 }
62 });
63}
64
65Antr.prototype.runSingleTest = function(item, self, callback){
66 var runTest = spawn(process.execPath, [ item ]);
67 var storedData = [];
68
69 var timeout = setTimeout(function () {
70 storedData.push({type: 'timeout', data: 'ERROR: No response received from test after ' + (self._options.timeout / 1000) + ' seconds.'});
71 var data = {item: item, code: 1, data: storedData};
72 self.updateStats(data);
73 self.emit('fileComplete', 1, item, storedData);
74 runTest.removeListener('exit', onExit);
75 runTest.stdout.removeListener('data', outOnData);
76 runTest.stderr.removeListener('data', errOnData);
77 return callback(null, data);
78 }, this._options.timeout);
79
80 var outOnData = function (data) {
81 storedData.push({type: 'stdout', data: data});
82 };
83 var errOnData = function (data) {
84 storedData.push({type: 'stderr', data: data});
85 };
86
87 runTest.stdout.setEncoding('utf8');
88 runTest.stdout.on('data', outOnData);
89
90 runTest.stderr.setEncoding('utf8');
91 runTest.stderr.on('data', errOnData);
92
93 var onExit = function(code, signal){
94 var data = { item: item, code: code, data: storedData };
95 self.updateStats(data);
96 self.emit('fileComplete', code, item, storedData);
97 clearTimeout(timeout);
98 return callback(null, data);
99 }
100
101 runTest.on('exit', onExit);
102}
103
104Antr.prototype.updateStats = function(data) {
105 if(!data) return;
106 if(data.code == 0) {
107 this._stats.passed++;
108 this._stats.passedTests.push(data.item);
109 } else {
110 this._stats.failed++;
111 this._stats.failedTests.push(data.item);
112 }
113 this._stats.total++;
114 this._stats.failRate = (this._stats.failed / this._stats.total).toFixed(1) * 100;
115}
116
117Antr.prototype.setTime = function(value) {
118 this._stats.timeTaken = value;
119}
120
121Antr.prototype.getFiles = function (cb) {
122 var self = this;
123
124 var dirs = ( this._options.dirname instanceof Array ) ? this._options.dirname : [this._options.dirname];
125
126 async.map(dirs, this.findFiles.bind(this), function(err, results){
127 results = results.filter(function(n){return n;});
128 var files = helper.concatArray(results);
129 if( self._options.listFiles ) console.log('Files going to be run: ', files);
130 cb(null, files);
131 });
132}
133
134Antr.prototype.findFiles = function(dir, cb){
135 var self = this;
136 helper.walk(dir, function (err, files) {
137 if( err ) return cb(err, null);
138 async.filter(files, function (item, callback) {
139 var split = item.split('/');
140 callback(self._options.filter.test(split[split.length - 1]));
141 }, function (filteredFiles) {
142 cb(null, filteredFiles);
143 });
144 });
145}
146
147module.exports = Antr;