You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
238 lines
4.6 KiB
238 lines
4.6 KiB
|
|
/** |
|
* Module dependencies. |
|
*/ |
|
|
|
var EventEmitter = require('events').EventEmitter |
|
, debug = require('debug')('suite') |
|
, utils = require('./utils') |
|
, Hook = require('./hook'); |
|
|
|
/** |
|
* Expose `Suite`. |
|
*/ |
|
|
|
exports = module.exports = Suite; |
|
|
|
/** |
|
* Create a new `Suite` with the given `title` |
|
* and parent `Suite`. When a suite with the |
|
* same title is already present, that suite |
|
* is returned to provide nicer reporter |
|
* and more flexible meta-testing. |
|
* |
|
* @param {Suite} parent |
|
* @param {String} title |
|
* @return {Suite} |
|
* @api public |
|
*/ |
|
|
|
exports.create = function(parent, title){ |
|
var suite = new Suite(title); |
|
suite.parent = parent; |
|
title = suite.fullTitle(); |
|
parent.addSuite(suite); |
|
return suite; |
|
}; |
|
|
|
/** |
|
* Initialize a new `Suite` with the given `title`. |
|
* |
|
* @param {String} title |
|
* @api private |
|
*/ |
|
|
|
function Suite(title) { |
|
this.title = title; |
|
this.suites = []; |
|
this.tests = []; |
|
this._beforeEach = []; |
|
this._beforeAll = []; |
|
this._afterEach = []; |
|
this._afterAll = []; |
|
this.root = !title; |
|
this._timeout = 2000; |
|
this._bail = false; |
|
} |
|
|
|
/** |
|
* Inherit from `EventEmitter.prototype`. |
|
*/ |
|
|
|
Suite.prototype.__proto__ = EventEmitter.prototype; |
|
|
|
/** |
|
* Return a clone of this `Suite`. |
|
* |
|
* @return {Suite} |
|
* @api private |
|
*/ |
|
|
|
Suite.prototype.clone = function(){ |
|
var suite = new Suite(this.title); |
|
debug('clone'); |
|
suite.timeout(this.timeout()); |
|
suite.bail(this.bail()); |
|
return suite; |
|
}; |
|
|
|
/** |
|
* Set timeout `ms` or short-hand such as "2s". |
|
* |
|
* @param {Number|String} ms |
|
* @return {Suite|Number} for chaining |
|
* @api private |
|
*/ |
|
|
|
Suite.prototype.timeout = function(ms){ |
|
if (0 == arguments.length) return this._timeout; |
|
if (String(ms).match(/s$/)) ms = parseFloat(ms) * 1000; |
|
debug('timeout %d', ms); |
|
this._timeout = parseInt(ms, 10); |
|
return this; |
|
}; |
|
|
|
/** |
|
* Sets whether to bail after first error. |
|
* |
|
* @parma {Boolean} bail |
|
* @return {Suite|Number} for chaining |
|
* @api private |
|
*/ |
|
|
|
Suite.prototype.bail = function(bail){ |
|
if (0 == arguments.length) return this._bail; |
|
debug('bail %s', bail); |
|
this._bail = bail; |
|
return this; |
|
}; |
|
|
|
/** |
|
* Run `fn(test[, done])` before running tests. |
|
* |
|
* @param {Function} fn |
|
* @return {Suite} for chaining |
|
* @api private |
|
*/ |
|
|
|
Suite.prototype.beforeAll = function(fn){ |
|
var hook = new Hook('"before all" hook', fn); |
|
hook.parent = this; |
|
hook.timeout(this.timeout()); |
|
this._beforeAll.push(hook); |
|
this.emit('beforeAll', hook); |
|
return this; |
|
}; |
|
|
|
/** |
|
* Run `fn(test[, done])` after running tests. |
|
* |
|
* @param {Function} fn |
|
* @return {Suite} for chaining |
|
* @api private |
|
*/ |
|
|
|
Suite.prototype.afterAll = function(fn){ |
|
var hook = new Hook('"after all" hook', fn); |
|
hook.parent = this; |
|
hook.timeout(this.timeout()); |
|
this._afterAll.push(hook); |
|
this.emit('afterAll', hook); |
|
return this; |
|
}; |
|
|
|
/** |
|
* Run `fn(test[, done])` before each test case. |
|
* |
|
* @param {Function} fn |
|
* @return {Suite} for chaining |
|
* @api private |
|
*/ |
|
|
|
Suite.prototype.beforeEach = function(fn){ |
|
var hook = new Hook('"before each" hook', fn); |
|
hook.parent = this; |
|
hook.timeout(this.timeout()); |
|
this._beforeEach.push(hook); |
|
this.emit('beforeEach', hook); |
|
return this; |
|
}; |
|
|
|
/** |
|
* Run `fn(test[, done])` after each test case. |
|
* |
|
* @param {Function} fn |
|
* @return {Suite} for chaining |
|
* @api private |
|
*/ |
|
|
|
Suite.prototype.afterEach = function(fn){ |
|
var hook = new Hook('"after each" hook', fn); |
|
hook.parent = this; |
|
hook.timeout(this.timeout()); |
|
this._afterEach.push(hook); |
|
this.emit('afterEach', hook); |
|
return this; |
|
}; |
|
|
|
/** |
|
* Add a test `suite`. |
|
* |
|
* @param {Suite} suite |
|
* @return {Suite} for chaining |
|
* @api private |
|
*/ |
|
|
|
Suite.prototype.addSuite = function(suite){ |
|
suite.parent = this; |
|
suite.timeout(this.timeout()); |
|
suite.bail(this.bail()); |
|
this.suites.push(suite); |
|
this.emit('suite', suite); |
|
return this; |
|
}; |
|
|
|
/** |
|
* Add a `test` to this suite. |
|
* |
|
* @param {Test} test |
|
* @return {Suite} for chaining |
|
* @api private |
|
*/ |
|
|
|
Suite.prototype.addTest = function(test){ |
|
test.parent = this; |
|
test.timeout(this.timeout()); |
|
this.tests.push(test); |
|
this.emit('test', test); |
|
return this; |
|
}; |
|
|
|
/** |
|
* Return the full title generated by recursively |
|
* concatenating the parent's full title. |
|
* |
|
* @return {String} |
|
* @api public |
|
*/ |
|
|
|
Suite.prototype.fullTitle = function(){ |
|
if (this.parent) { |
|
var full = this.parent.fullTitle(); |
|
if (full) return full + ' ' + this.title; |
|
} |
|
return this.title; |
|
}; |
|
|
|
/** |
|
* Return the total number of tests. |
|
* |
|
* @return {Number} |
|
* @api public |
|
*/ |
|
|
|
Suite.prototype.total = function(){ |
|
return utils.reduce(this.suites, function(sum, suite){ |
|
return sum + suite.total(); |
|
}, 0) + this.tests.length; |
|
};
|
|
|