UNPKG

5.45 kBJavaScriptView Raw
1'use strict';
2
3var assert = require('assert');
4var EventEmitter = require('events').EventEmitter;
5var Promise = require('promise');
6var chalk = require('chalk');
7var ms = require('ms');
8var result = require('test-result');
9var timeout = require('./timeout');
10
11module.exports = TestSuite;
12function TestSuite(name) {
13 this.name = name;
14 this.colors = true;
15 this._queue = [];
16 this._stack = [];
17 EventEmitter.call(this);
18}
19TestSuite.prototype = Object.create(EventEmitter.prototype);
20TestSuite.constructor = TestSuite;
21TestSuite.now = function () {
22 return (new Date()).getTime();
23};
24
25TestSuite.prototype.addTest = function (name, fn, options) {
26 assert(typeof name === 'string', 'The description must be a string')
27 assert(typeof fn === 'function', 'The test must be a function')
28 if (fn.length === 1) {
29 fn = Promise.denodeify(fn);
30 }
31 this._queue.push(new TestCase(false, name, fn, options || {}));
32};
33TestSuite.prototype.addCode = function (fn, options) {
34 this._queue.push(new TestCase(true, '', fn, options || {}));
35};
36TestSuite.prototype.run = function () {
37 var index = 0;
38 var self = this;
39 return new Promise(function (resolve, reject) {
40 function next() {
41 while (index >= self._queue.length && self._stack.length) {
42 var frame = self._stack.pop();
43 index = frame.index;
44 self._queue = frame.queue;
45 self.emit('end-section', frame.name);
46 }
47 if (index >= self._queue.length) {
48 self.emit('suite-pass');
49 return resolve();
50 }
51 var test = self._queue[index];
52 if (test.justRun) {
53 self.emit('run-start');
54 Promise.resolve(null).then(function () {
55 return timeout(test.fn(), test.timeout);
56 }).done(function () {
57 self.emit('run-pass');
58 self.emit('run-end');
59 index++;
60 next();
61 }, function (err) {
62 self.emit('run-fail', err);
63 self.emit('run-end');
64 self.emit('suite-fail');
65 reject(err);
66 });
67 return;
68 }
69 self._stack.push(new StackFrame(index + 1, self._queue, test.name));
70 index = 0;
71 self._queue = [];
72 self.emit('start', test.name);
73 Promise.resolve(null).then(function () {
74 return timeout(test.fn(), test.timeout)
75 }).done(function () {
76 if (self._queue.length) {
77 self.emit('end', test.name);
78 self.emit('start-section', test.name);
79 } else {
80 self.emit('pass', test.name);
81 self.emit('end', test.name);
82 var frame = self._stack.pop();
83 index = frame.index;
84 self._queue = frame.queue;
85 }
86 next();
87 }, function (err) {
88 self.emit('fail', test.name, err);
89 self.emit('end', test.name);
90 self.emit('suite-fail');
91 reject(err);
92 });
93 }
94 self.emit('suite-start');
95 next();
96 });
97};
98
99TestSuite.prototype.disableColors = function () {
100 this.colors = false;
101};
102TestSuite.prototype.addLogging = function () {
103 var self = this;
104 function color(color, str) {
105 return self.colors ? chalk[color](str) : str;
106 }
107 var indent = [];
108 var start = Date.now();
109 this.on('start-section', function (name) {
110 console.log(indent.join('') + color('magenta', ' \u2022 ') + name);
111 indent.push(' ');
112 });
113 this.on('end-section', function (name) {
114 indent.pop();
115 });
116 this.on('start', function () {
117 start = TestSuite.now();
118 });
119 this.on('run-start', function () {
120 start = TestSuite.now();
121 });
122 this.on('pass', function (name) {
123 var end = TestSuite.now();
124 var duration = end - start;
125 console.log(indent.join('') +
126 color('green', ' \u2713 ') +
127 name +
128 color('cyan', ' (' + ms(duration) + ')'));
129 });
130 this.on('fail', function (name, err) {
131 var end = TestSuite.now();
132 var duration = end - start;
133 console.log(indent.join('') +
134 color('red', ' \u2717 ') +
135 name +
136 color('cyan', ' (' + ms(duration) + ')'));
137 console.log('');
138 var errString = errorToString(err);
139 console.log(errString.replace(/^/gm, indent.join('') + ' '));
140 });
141 this.on('run-fail', function (err) {
142 var end = TestSuite.now();
143 var duration = end - start;
144 console.log(indent.join('') +
145 color('red', ' \u2717 ') +
146 'run' +
147 color('cyan', ' (' + ms(duration) + ')'));
148 console.log('');
149 var errString = errorToString(err);
150 console.log(errString.replace(/^/gm, indent.join('') + ' '));
151 });
152};
153TestSuite.prototype.addExit = function () {
154 var name = this.name || 'tests';
155 var start = TestSuite.now();
156 this.on('suite-start', function () {
157 start = TestSuite.now();
158 });
159 this.on('suite-pass', function () {
160 console.log('');
161 console.log('Total duration ' + ms(TestSuite.now() - start));
162 result.pass(name);
163 });
164 this.on('suite-fail', function () {
165 console.log('');
166 console.log('Total duration ' + ms(TestSuite.now() - start));
167 result.fail(name);
168 });
169};
170
171function TestCase(justRun, name, fn, options) {
172 this.justRun = justRun;
173 this.name = name;
174 this.fn = fn;
175 this.timeout = options.timeout || '20 seconds';
176}
177function StackFrame(index, queue, name) {
178 this.index = index;
179 this.queue = queue;
180 this.name = name;
181}
182
183function errorToString(e) {
184 return '' + (e.stack || /* istanbul ignore next */ (e.message || e));
185}