source: Dev/trunk/node_modules/mocha/lib/suite.js @ 484

Last change on this file since 484 was 484, checked in by hendrikvanantwerpen, 11 years ago

Commit node_modules, to make checkouts and builds more deterministic.

File size: 5.9 KB
Line 
1
2/**
3 * Module dependencies.
4 */
5
6var EventEmitter = require('events').EventEmitter
7  , debug = require('debug')('mocha:suite')
8  , milliseconds = require('./ms')
9  , utils = require('./utils')
10  , Hook = require('./hook');
11
12/**
13 * Expose `Suite`.
14 */
15
16exports = module.exports = Suite;
17
18/**
19 * Create a new `Suite` with the given `title`
20 * and parent `Suite`. When a suite with the
21 * same title is already present, that suite
22 * is returned to provide nicer reporter
23 * and more flexible meta-testing.
24 *
25 * @param {Suite} parent
26 * @param {String} title
27 * @return {Suite}
28 * @api public
29 */
30
31exports.create = function(parent, title){
32  var suite = new Suite(title, parent.ctx);
33  suite.parent = parent;
34  if (parent.pending) suite.pending = true;
35  title = suite.fullTitle();
36  parent.addSuite(suite);
37  return suite;
38};
39
40/**
41 * Initialize a new `Suite` with the given
42 * `title` and `ctx`.
43 *
44 * @param {String} title
45 * @param {Context} ctx
46 * @api private
47 */
48
49function Suite(title, ctx) {
50  this.title = title;
51  this.ctx = ctx;
52  this.suites = [];
53  this.tests = [];
54  this.pending = false;
55  this._beforeEach = [];
56  this._beforeAll = [];
57  this._afterEach = [];
58  this._afterAll = [];
59  this.root = !title;
60  this._timeout = 2000;
61  this._slow = 75;
62  this._bail = false;
63}
64
65/**
66 * Inherit from `EventEmitter.prototype`.
67 */
68
69Suite.prototype.__proto__ = EventEmitter.prototype;
70
71/**
72 * Return a clone of this `Suite`.
73 *
74 * @return {Suite}
75 * @api private
76 */
77
78Suite.prototype.clone = function(){
79  var suite = new Suite(this.title);
80  debug('clone');
81  suite.ctx = this.ctx;
82  suite.timeout(this.timeout());
83  suite.slow(this.slow());
84  suite.bail(this.bail());
85  return suite;
86};
87
88/**
89 * Set timeout `ms` or short-hand such as "2s".
90 *
91 * @param {Number|String} ms
92 * @return {Suite|Number} for chaining
93 * @api private
94 */
95
96Suite.prototype.timeout = function(ms){
97  if (0 == arguments.length) return this._timeout;
98  if ('string' == typeof ms) ms = milliseconds(ms);
99  debug('timeout %d', ms);
100  this._timeout = parseInt(ms, 10);
101  return this;
102};
103
104/**
105 * Set slow `ms` or short-hand such as "2s".
106 *
107 * @param {Number|String} ms
108 * @return {Suite|Number} for chaining
109 * @api private
110 */
111
112Suite.prototype.slow = function(ms){
113  if (0 === arguments.length) return this._slow;
114  if ('string' == typeof ms) ms = milliseconds(ms);
115  debug('slow %d', ms);
116  this._slow = ms;
117  return this;
118};
119
120/**
121 * Sets whether to bail after first error.
122 *
123 * @parma {Boolean} bail
124 * @return {Suite|Number} for chaining
125 * @api private
126 */
127
128Suite.prototype.bail = function(bail){
129  if (0 == arguments.length) return this._bail;
130  debug('bail %s', bail);
131  this._bail = bail;
132  return this;
133};
134
135/**
136 * Run `fn(test[, done])` before running tests.
137 *
138 * @param {Function} fn
139 * @return {Suite} for chaining
140 * @api private
141 */
142
143Suite.prototype.beforeAll = function(fn){
144  if (this.pending) return this;
145  var hook = new Hook('"before all" hook', fn);
146  hook.parent = this;
147  hook.timeout(this.timeout());
148  hook.slow(this.slow());
149  hook.ctx = this.ctx;
150  this._beforeAll.push(hook);
151  this.emit('beforeAll', hook);
152  return this;
153};
154
155/**
156 * Run `fn(test[, done])` after running tests.
157 *
158 * @param {Function} fn
159 * @return {Suite} for chaining
160 * @api private
161 */
162
163Suite.prototype.afterAll = function(fn){
164  if (this.pending) return this;
165  var hook = new Hook('"after all" hook', fn);
166  hook.parent = this;
167  hook.timeout(this.timeout());
168  hook.slow(this.slow());
169  hook.ctx = this.ctx;
170  this._afterAll.push(hook);
171  this.emit('afterAll', hook);
172  return this;
173};
174
175/**
176 * Run `fn(test[, done])` before each test case.
177 *
178 * @param {Function} fn
179 * @return {Suite} for chaining
180 * @api private
181 */
182
183Suite.prototype.beforeEach = function(fn){
184  if (this.pending) return this;
185  var hook = new Hook('"before each" hook', fn);
186  hook.parent = this;
187  hook.timeout(this.timeout());
188  hook.slow(this.slow());
189  hook.ctx = this.ctx;
190  this._beforeEach.push(hook);
191  this.emit('beforeEach', hook);
192  return this;
193};
194
195/**
196 * Run `fn(test[, done])` after each test case.
197 *
198 * @param {Function} fn
199 * @return {Suite} for chaining
200 * @api private
201 */
202
203Suite.prototype.afterEach = function(fn){
204  if (this.pending) return this;
205  var hook = new Hook('"after each" hook', fn);
206  hook.parent = this;
207  hook.timeout(this.timeout());
208  hook.slow(this.slow());
209  hook.ctx = this.ctx;
210  this._afterEach.push(hook);
211  this.emit('afterEach', hook);
212  return this;
213};
214
215/**
216 * Add a test `suite`.
217 *
218 * @param {Suite} suite
219 * @return {Suite} for chaining
220 * @api private
221 */
222
223Suite.prototype.addSuite = function(suite){
224  suite.parent = this;
225  suite.timeout(this.timeout());
226  suite.slow(this.slow());
227  suite.bail(this.bail());
228  this.suites.push(suite);
229  this.emit('suite', suite);
230  return this;
231};
232
233/**
234 * Add a `test` to this suite.
235 *
236 * @param {Test} test
237 * @return {Suite} for chaining
238 * @api private
239 */
240
241Suite.prototype.addTest = function(test){
242  test.parent = this;
243  test.timeout(this.timeout());
244  test.slow(this.slow());
245  test.ctx = this.ctx;
246  this.tests.push(test);
247  this.emit('test', test);
248  return this;
249};
250
251/**
252 * Return the full title generated by recursively
253 * concatenating the parent's full title.
254 *
255 * @return {String}
256 * @api public
257 */
258
259Suite.prototype.fullTitle = function(){
260  if (this.parent) {
261    var full = this.parent.fullTitle();
262    if (full) return full + ' ' + this.title;
263  }
264  return this.title;
265};
266
267/**
268 * Return the total number of tests.
269 *
270 * @return {Number}
271 * @api public
272 */
273
274Suite.prototype.total = function(){
275  return utils.reduce(this.suites, function(sum, suite){
276    return sum + suite.total();
277  }, 0) + this.tests.length;
278};
279
280/**
281 * Iterates through each suite recursively to find
282 * all tests. Applies a function in the format
283 * `fn(test)`.
284 *
285 * @param {Function} fn
286 * @return {Suite}
287 * @api private
288 */
289
290Suite.prototype.eachTest = function(fn){
291  utils.forEach(this.tests, fn);
292  utils.forEach(this.suites, function(suite){
293    suite.eachTest(fn);
294  });
295  return this;
296};
Note: See TracBrowser for help on using the repository browser.