Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign up| ;(function(){ | |
| // CommonJS require() | |
| function require(p){ | |
| var path = require.resolve(p) | |
| , mod = require.modules[path]; | |
| if (!mod) throw new Error('failed to require "' + p + '"'); | |
| if (!mod.exports) { | |
| mod.exports = {}; | |
| mod.call(mod.exports, mod, mod.exports, require.relative(path)); | |
| } | |
| return mod.exports; | |
| } | |
| require.modules = {}; | |
| require.resolve = function (path){ | |
| var orig = path | |
| , reg = path + '.js' | |
| , index = path + '/index.js'; | |
| return require.modules[reg] && reg | |
| || require.modules[index] && index | |
| || orig; | |
| }; | |
| require.register = function (path, fn){ | |
| require.modules[path] = fn; | |
| }; | |
| require.relative = function (parent) { | |
| return function(p){ | |
| if ('.' != p.charAt(0)) return require(p); | |
| var path = parent.split('/') | |
| , segs = p.split('/'); | |
| path.pop(); | |
| for (var i = 0; i < segs.length; i++) { | |
| var seg = segs[i]; | |
| if ('..' == seg) path.pop(); | |
| else if ('.' != seg) path.push(seg); | |
| } | |
| return require(path.join('/')); | |
| }; | |
| }; | |
| require.register("browser/debug.js", function(module, exports, require){ | |
| module.exports = function(type){ | |
| return function(){ | |
| } | |
| }; | |
| }); // module: browser/debug.js | |
| require.register("browser/diff.js", function(module, exports, require){ | |
| }); // module: browser/diff.js | |
| require.register("browser/events.js", function(module, exports, require){ | |
| /** | |
| * Module exports. | |
| */ | |
| exports.EventEmitter = EventEmitter; | |
| /** | |
| * Check if `obj` is an array. | |
| */ | |
| function isArray(obj) { | |
| return '[object Array]' == {}.toString.call(obj); | |
| } | |
| /** | |
| * Event emitter constructor. | |
| * | |
| * @api public | |
| */ | |
| function EventEmitter(){}; | |
| /** | |
| * Adds a listener. | |
| * | |
| * @api public | |
| */ | |
| EventEmitter.prototype.on = function (name, fn) { | |
| if (!this.$events) { | |
| this.$events = {}; | |
| } | |
| if (!this.$events[name]) { | |
| this.$events[name] = fn; | |
| } else if (isArray(this.$events[name])) { | |
| this.$events[name].push(fn); | |
| } else { | |
| this.$events[name] = [this.$events[name], fn]; | |
| } | |
| return this; | |
| }; | |
| EventEmitter.prototype.addListener = EventEmitter.prototype.on; | |
| /** | |
| * Adds a volatile listener. | |
| * | |
| * @api public | |
| */ | |
| EventEmitter.prototype.once = function (name, fn) { | |
| var self = this; | |
| function on () { | |
| self.removeListener(name, on); | |
| fn.apply(this, arguments); | |
| }; | |
| on.listener = fn; | |
| this.on(name, on); | |
| return this; | |
| }; | |
| /** | |
| * Removes a listener. | |
| * | |
| * @api public | |
| */ | |
| EventEmitter.prototype.removeListener = function (name, fn) { | |
| if (this.$events && this.$events[name]) { | |
| var list = this.$events[name]; | |
| if (isArray(list)) { | |
| var pos = -1; | |
| for (var i = 0, l = list.length; i < l; i++) { | |
| if (list[i] === fn || (list[i].listener && list[i].listener === fn)) { | |
| pos = i; | |
| break; | |
| } | |
| } | |
| if (pos < 0) { | |
| return this; | |
| } | |
| list.splice(pos, 1); | |
| if (!list.length) { | |
| delete this.$events[name]; | |
| } | |
| } else if (list === fn || (list.listener && list.listener === fn)) { | |
| delete this.$events[name]; | |
| } | |
| } | |
| return this; | |
| }; | |
| /** | |
| * Removes all listeners for an event. | |
| * | |
| * @api public | |
| */ | |
| EventEmitter.prototype.removeAllListeners = function (name) { | |
| if (name === undefined) { | |
| this.$events = {}; | |
| return this; | |
| } | |
| if (this.$events && this.$events[name]) { | |
| this.$events[name] = null; | |
| } | |
| return this; | |
| }; | |
| /** | |
| * Gets all listeners for a certain event. | |
| * | |
| * @api public | |
| */ | |
| EventEmitter.prototype.listeners = function (name) { | |
| if (!this.$events) { | |
| this.$events = {}; | |
| } | |
| if (!this.$events[name]) { | |
| this.$events[name] = []; | |
| } | |
| if (!isArray(this.$events[name])) { | |
| this.$events[name] = [this.$events[name]]; | |
| } | |
| return this.$events[name]; | |
| }; | |
| /** | |
| * Emits an event. | |
| * | |
| * @api public | |
| */ | |
| EventEmitter.prototype.emit = function (name) { | |
| if (!this.$events) { | |
| return false; | |
| } | |
| var handler = this.$events[name]; | |
| if (!handler) { | |
| return false; | |
| } | |
| var args = [].slice.call(arguments, 1); | |
| if ('function' == typeof handler) { | |
| handler.apply(this, args); | |
| } else if (isArray(handler)) { | |
| var listeners = handler.slice(); | |
| for (var i = 0, l = listeners.length; i < l; i++) { | |
| listeners[i].apply(this, args); | |
| } | |
| } else { | |
| return false; | |
| } | |
| return true; | |
| }; | |
| }); // module: browser/events.js | |
| require.register("browser/fs.js", function(module, exports, require){ | |
| }); // module: browser/fs.js | |
| require.register("browser/path.js", function(module, exports, require){ | |
| }); // module: browser/path.js | |
| require.register("browser/progress.js", function(module, exports, require){ | |
| /** | |
| * Expose `Progress`. | |
| */ | |
| module.exports = Progress; | |
| /** | |
| * Initialize a new `Progress` indicator. | |
| */ | |
| function Progress() { | |
| this.percent = 0; | |
| this.size(0); | |
| this.fontSize(11); | |
| this.font('helvetica, arial, sans-serif'); | |
| } | |
| /** | |
| * Set progress size to `n`. | |
| * | |
| * @param {Number} n | |
| * @return {Progress} for chaining | |
| * @api public | |
| */ | |
| Progress.prototype.size = function(n){ | |
| this._size = n; | |
| return this; | |
| }; | |
| /** | |
| * Set text to `str`. | |
| * | |
| * @param {String} str | |
| * @return {Progress} for chaining | |
| * @api public | |
| */ | |
| Progress.prototype.text = function(str){ | |
| this._text = str; | |
| return this; | |
| }; | |
| /** | |
| * Set font size to `n`. | |
| * | |
| * @param {Number} n | |
| * @return {Progress} for chaining | |
| * @api public | |
| */ | |
| Progress.prototype.fontSize = function(n){ | |
| this._fontSize = n; | |
| return this; | |
| }; | |
| /** | |
| * Set font `family`. | |
| * | |
| * @param {String} family | |
| * @return {Progress} for chaining | |
| */ | |
| Progress.prototype.font = function(family){ | |
| this._font = family; | |
| return this; | |
| }; | |
| /** | |
| * Update percentage to `n`. | |
| * | |
| * @param {Number} n | |
| * @return {Progress} for chaining | |
| */ | |
| Progress.prototype.update = function(n){ | |
| this.percent = n; | |
| return this; | |
| }; | |
| /** | |
| * Draw on `ctx`. | |
| * | |
| * @param {CanvasRenderingContext2d} ctx | |
| * @return {Progress} for chaining | |
| */ | |
| Progress.prototype.draw = function(ctx){ | |
| var percent = Math.min(this.percent, 100) | |
| , size = this._size | |
| , half = size / 2 | |
| , x = half | |
| , y = half | |
| , rad = half - 1 | |
| , fontSize = this._fontSize; | |
| ctx.font = fontSize + 'px ' + this._font; | |
| var angle = Math.PI * 2 * (percent / 100); | |
| ctx.clearRect(0, 0, size, size); | |
| // outer circle | |
| ctx.strokeStyle = '#9f9f9f'; | |
| ctx.beginPath(); | |
| ctx.arc(x, y, rad, 0, angle, false); | |
| ctx.stroke(); | |
| // inner circle | |
| ctx.strokeStyle = '#eee'; | |
| ctx.beginPath(); | |
| ctx.arc(x, y, rad - 1, 0, angle, true); | |
| ctx.stroke(); | |
| // text | |
| var text = this._text || (percent | 0) + '%' | |
| , w = ctx.measureText(text).width; | |
| ctx.fillText( | |
| text | |
| , x - w / 2 + 1 | |
| , y + fontSize / 2 - 1); | |
| return this; | |
| }; | |
| }); // module: browser/progress.js | |
| require.register("browser/tty.js", function(module, exports, require){ | |
| exports.isatty = function(){ | |
| return true; | |
| }; | |
| exports.getWindowSize = function(){ | |
| return [window.innerHeight, window.innerWidth]; | |
| }; | |
| }); // module: browser/tty.js | |
| require.register("context.js", function(module, exports, require){ | |
| /** | |
| * Expose `Context`. | |
| */ | |
| module.exports = Context; | |
| /** | |
| * Initialize a new `Context`. | |
| * | |
| * @api private | |
| */ | |
| function Context(){} | |
| /** | |
| * Set or get the context `Runnable` to `runnable`. | |
| * | |
| * @param {Runnable} runnable | |
| * @return {Context} | |
| * @api private | |
| */ | |
| Context.prototype.runnable = function(runnable){ | |
| if (0 == arguments.length) return this._runnable; | |
| this.test = this._runnable = runnable; | |
| return this; | |
| }; | |
| /** | |
| * Set test timeout `ms`. | |
| * | |
| * @param {Number} ms | |
| * @return {Context} self | |
| * @api private | |
| */ | |
| Context.prototype.timeout = function(ms){ | |
| this.runnable().timeout(ms); | |
| return this; | |
| }; | |
| /** | |
| * Inspect the context void of `._runnable`. | |
| * | |
| * @return {String} | |
| * @api private | |
| */ | |
| Context.prototype.inspect = function(){ | |
| return JSON.stringify(this, function(key, val){ | |
| if ('_runnable' == key) return; | |
| if ('test' == key) return; | |
| return val; | |
| }, 2); | |
| }; | |
| }); // module: context.js | |
| require.register("hook.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var Runnable = require('./runnable'); | |
| /** | |
| * Expose `Hook`. | |
| */ | |
| module.exports = Hook; | |
| /** | |
| * Initialize a new `Hook` with the given `title` and callback `fn`. | |
| * | |
| * @param {String} title | |
| * @param {Function} fn | |
| * @api private | |
| */ | |
| function Hook(title, fn) { | |
| Runnable.call(this, title, fn); | |
| this.type = 'hook'; | |
| } | |
| /** | |
| * Inherit from `Runnable.prototype`. | |
| */ | |
| Hook.prototype = new Runnable; | |
| Hook.prototype.constructor = Hook; | |
| /** | |
| * Get or set the test `err`. | |
| * | |
| * @param {Error} err | |
| * @return {Error} | |
| * @api public | |
| */ | |
| Hook.prototype.error = function(err){ | |
| if (0 == arguments.length) { | |
| var err = this._error; | |
| this._error = null; | |
| return err; | |
| } | |
| this._error = err; | |
| }; | |
| }); // module: hook.js | |
| require.register("interfaces/bdd.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var Suite = require('../suite') | |
| , Test = require('../test'); | |
| /** | |
| * BDD-style interface: | |
| * | |
| * describe('Array', function(){ | |
| * describe('#indexOf()', function(){ | |
| * it('should return -1 when not present', function(){ | |
| * | |
| * }); | |
| * | |
| * it('should return the index when present', function(){ | |
| * | |
| * }); | |
| * }); | |
| * }); | |
| * | |
| */ | |
| module.exports = function(suite){ | |
| var suites = [suite]; | |
| suite.on('pre-require', function(context){ | |
| // noop variants | |
| context.xdescribe = function(){}; | |
| context.xit = function(){}; | |
| /** | |
| * Execute before running tests. | |
| */ | |
| context.before = function(fn){ | |
| suites[0].beforeAll(fn); | |
| }; | |
| /** | |
| * Execute after running tests. | |
| */ | |
| context.after = function(fn){ | |
| suites[0].afterAll(fn); | |
| }; | |
| /** | |
| * Execute before each test case. | |
| */ | |
| context.beforeEach = function(fn){ | |
| suites[0].beforeEach(fn); | |
| }; | |
| /** | |
| * Execute after each test case. | |
| */ | |
| context.afterEach = function(fn){ | |
| suites[0].afterEach(fn); | |
| }; | |
| /** | |
| * Describe a "suite" with the given `title` | |
| * and callback `fn` containing nested suites | |
| * and/or tests. | |
| */ | |
| context.describe = context.context = function(title, fn){ | |
| var suite = Suite.create(suites[0], title); | |
| suites.unshift(suite); | |
| fn(); | |
| suites.shift(); | |
| }; | |
| /** | |
| * Describe a specification or test-case | |
| * with the given `title` and callback `fn` | |
| * acting as a thunk. | |
| */ | |
| context.it = context.specify = function(title, fn){ | |
| suites[0].addTest(new Test(title, fn)); | |
| }; | |
| }); | |
| }; | |
| }); // module: interfaces/bdd.js | |
| require.register("interfaces/exports.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var Suite = require('../suite') | |
| , Test = require('../test'); | |
| /** | |
| * TDD-style interface: | |
| * | |
| * exports.Array = { | |
| * '#indexOf()': { | |
| * 'should return -1 when the value is not present': function(){ | |
| * | |
| * }, | |
| * | |
| * 'should return the correct index when the value is present': function(){ | |
| * | |
| * } | |
| * } | |
| * }; | |
| * | |
| */ | |
| module.exports = function(suite){ | |
| var suites = [suite]; | |
| suite.on('require', visit); | |
| function visit(obj) { | |
| var suite; | |
| for (var key in obj) { | |
| if ('function' == typeof obj[key]) { | |
| var fn = obj[key]; | |
| switch (key) { | |
| case 'before': | |
| suites[0].beforeAll(fn); | |
| break; | |
| case 'after': | |
| suites[0].afterAll(fn); | |
| break; | |
| case 'beforeEach': | |
| suites[0].beforeEach(fn); | |
| break; | |
| case 'afterEach': | |
| suites[0].afterEach(fn); | |
| break; | |
| default: | |
| suites[0].addTest(new Test(key, fn)); | |
| } | |
| } else { | |
| var suite = Suite.create(suites[0], key); | |
| suites.unshift(suite); | |
| visit(obj[key]); | |
| suites.shift(); | |
| } | |
| } | |
| } | |
| }; | |
| }); // module: interfaces/exports.js | |
| require.register("interfaces/index.js", function(module, exports, require){ | |
| exports.bdd = require('./bdd'); | |
| exports.tdd = require('./tdd'); | |
| exports.qunit = require('./qunit'); | |
| exports.exports = require('./exports'); | |
| }); // module: interfaces/index.js | |
| require.register("interfaces/qunit.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var Suite = require('../suite') | |
| , Test = require('../test'); | |
| /** | |
| * QUnit-style interface: | |
| * | |
| * suite('Array'); | |
| * | |
| * test('#length', function(){ | |
| * var arr = [1,2,3]; | |
| * ok(arr.length == 3); | |
| * }); | |
| * | |
| * test('#indexOf()', function(){ | |
| * var arr = [1,2,3]; | |
| * ok(arr.indexOf(1) == 0); | |
| * ok(arr.indexOf(2) == 1); | |
| * ok(arr.indexOf(3) == 2); | |
| * }); | |
| * | |
| * suite('String'); | |
| * | |
| * test('#length', function(){ | |
| * ok('foo'.length == 3); | |
| * }); | |
| * | |
| */ | |
| module.exports = function(suite){ | |
| var suites = [suite]; | |
| suite.on('pre-require', function(context){ | |
| /** | |
| * Execute before running tests. | |
| */ | |
| context.before = function(fn){ | |
| suites[0].beforeAll(fn); | |
| }; | |
| /** | |
| * Execute after running tests. | |
| */ | |
| context.after = function(fn){ | |
| suites[0].afterAll(fn); | |
| }; | |
| /** | |
| * Execute before each test case. | |
| */ | |
| context.beforeEach = function(fn){ | |
| suites[0].beforeEach(fn); | |
| }; | |
| /** | |
| * Execute after each test case. | |
| */ | |
| context.afterEach = function(fn){ | |
| suites[0].afterEach(fn); | |
| }; | |
| /** | |
| * Describe a "suite" with the given `title`. | |
| */ | |
| context.suite = function(title){ | |
| if (suites.length > 1) suites.shift(); | |
| var suite = Suite.create(suites[0], title); | |
| suites.unshift(suite); | |
| }; | |
| /** | |
| * Describe a specification or test-case | |
| * with the given `title` and callback `fn` | |
| * acting as a thunk. | |
| */ | |
| context.test = function(title, fn){ | |
| suites[0].addTest(new Test(title, fn)); | |
| }; | |
| }); | |
| }; | |
| }); // module: interfaces/qunit.js | |
| require.register("interfaces/tdd.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var Suite = require('../suite') | |
| , Test = require('../test'); | |
| /** | |
| * TDD-style interface: | |
| * | |
| * suite('Array', function(){ | |
| * suite('#indexOf()', function(){ | |
| * suiteSetup(function(){ | |
| * | |
| * }); | |
| * | |
| * test('should return -1 when not present', function(){ | |
| * | |
| * }); | |
| * | |
| * test('should return the index when present', function(){ | |
| * | |
| * }); | |
| * | |
| * suiteTeardown(function(){ | |
| * | |
| * }); | |
| * }); | |
| * }); | |
| * | |
| */ | |
| module.exports = function(suite){ | |
| var suites = [suite]; | |
| suite.on('pre-require', function(context){ | |
| /** | |
| * Execute before each test case. | |
| */ | |
| context.setup = function(fn){ | |
| suites[0].beforeEach(fn); | |
| }; | |
| /** | |
| * Execute after each test case. | |
| */ | |
| context.teardown = function(fn){ | |
| suites[0].afterEach(fn); | |
| }; | |
| /** | |
| * Execute before the suite. | |
| */ | |
| context.suiteSetup = function(fn){ | |
| suites[0].beforeAll(fn); | |
| }; | |
| /** | |
| * Execute after the suite. | |
| */ | |
| context.suiteTeardown = function(fn){ | |
| suites[0].afterAll(fn); | |
| }; | |
| /** | |
| * Describe a "suite" with the given `title` | |
| * and callback `fn` containing nested suites | |
| * and/or tests. | |
| */ | |
| context.suite = function(title, fn){ | |
| var suite = Suite.create(suites[0], title); | |
| suites.unshift(suite); | |
| fn(); | |
| suites.shift(); | |
| }; | |
| /** | |
| * Describe a specification or test-case | |
| * with the given `title` and callback `fn` | |
| * acting as a thunk. | |
| */ | |
| context.test = function(title, fn){ | |
| suites[0].addTest(new Test(title, fn)); | |
| }; | |
| }); | |
| }; | |
| }); // module: interfaces/tdd.js | |
| require.register("mocha.js", function(module, exports, require){ | |
| /*! | |
| * mocha | |
| * Copyright(c) 2011 TJ Holowaychuk <tj@vision-media.ca> | |
| * MIT Licensed | |
| */ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var path = require('browser/path'); | |
| /** | |
| * Expose `Mocha`. | |
| */ | |
| exports = module.exports = Mocha; | |
| /** | |
| * Expose internals. | |
| */ | |
| exports.utils = require('./utils'); | |
| exports.interfaces = require('./interfaces'); | |
| exports.reporters = require('./reporters'); | |
| exports.Runnable = require('./runnable'); | |
| exports.Context = require('./context'); | |
| exports.Runner = require('./runner'); | |
| exports.Suite = require('./suite'); | |
| exports.Hook = require('./hook'); | |
| exports.Test = require('./test'); | |
| /** | |
| * Return image `name` path. | |
| * | |
| * @param {String} name | |
| * @return {String} | |
| * @api private | |
| */ | |
| function image(name) { | |
| return __dirname + '/../images/' + name + '.png'; | |
| } | |
| /** | |
| * Setup mocha with `options`. | |
| * | |
| * Options: | |
| * | |
| * - `ui` name "bdd", "tdd", "exports" etc | |
| * - `reporter` reporter instance, defaults to `mocha.reporters.Dot` | |
| * - `globals` array of accepted globals | |
| * - `timeout` timeout in milliseconds | |
| * - `ignoreLeaks` ignore global leaks | |
| * - `grep` string or regexp to filter tests with | |
| * | |
| * @param {Object} options | |
| * @api public | |
| */ | |
| function Mocha(options) { | |
| options = options || {}; | |
| this.files = []; | |
| this.options = options; | |
| this.grep(options.grep); | |
| this.suite = new exports.Suite('', new exports.Context); | |
| this.ui(options.ui); | |
| this.reporter(options.reporter); | |
| if (options.timeout) this.suite.timeout(options.timeout); | |
| } | |
| /** | |
| * Add test `file`. | |
| * | |
| * @param {String} file | |
| * @api public | |
| */ | |
| Mocha.prototype.addFile = function(file){ | |
| this.files.push(file); | |
| return this; | |
| }; | |
| /** | |
| * Set reporter to `name`, defaults to "dot". | |
| * | |
| * @param {String} name | |
| * @api public | |
| */ | |
| Mocha.prototype.reporter = function(name){ | |
| name = name || 'dot'; | |
| this._reporter = require('./reporters/' + name); | |
| if (!this._reporter) throw new Error('invalid reporter "' + name + '"'); | |
| return this; | |
| }; | |
| /** | |
| * Set test UI `name`, defaults to "bdd". | |
| * | |
| * @param {String} bdd | |
| * @api public | |
| */ | |
| Mocha.prototype.ui = function(name){ | |
| name = name || 'bdd'; | |
| this._ui = exports.interfaces[name]; | |
| if (!this._ui) throw new Error('invalid interface "' + name + '"'); | |
| this._ui = this._ui(this.suite); | |
| return this; | |
| }; | |
| /** | |
| * Load registered files. | |
| * | |
| * @api private | |
| */ | |
| Mocha.prototype.loadFiles = function(){ | |
| var suite = this.suite; | |
| this.files.forEach(function(file){ | |
| file = path.resolve(file); | |
| suite.emit('pre-require', global, file); | |
| suite.emit('require', require(file), file); | |
| suite.emit('post-require', global, file); | |
| }); | |
| }; | |
| /** | |
| * Enable growl support. | |
| * | |
| * @api private | |
| */ | |
| Mocha.prototype.growl = function(runner, reporter) { | |
| var notify = require('growl'); | |
| runner.on('end', function(){ | |
| var stats = reporter.stats; | |
| if (stats.failures) { | |
| var msg = stats.failures + ' of ' + runner.total + ' tests failed'; | |
| notify(msg, { name: 'mocha', title: 'Failed', image: image('error') }); | |
| } else { | |
| notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', { | |
| name: 'mocha' | |
| , title: 'Passed' | |
| , image: image('ok') | |
| }); | |
| } | |
| }); | |
| }; | |
| /** | |
| * Add regexp to grep for to the options object | |
| * | |
| * @param {RegExp} or {String} re | |
| * @return {Mocha} | |
| * @api public | |
| */ | |
| Mocha.prototype.grep = function(re){ | |
| this.options.grep = 'string' == typeof re | |
| ? new RegExp(re) | |
| : re; | |
| return this; | |
| }; | |
| /** | |
| * Run tests and invoke `fn()` when complete. | |
| * | |
| * @param {Function} fn | |
| * @return {Runner} | |
| * @api public | |
| */ | |
| Mocha.prototype.run = function(fn){ | |
| this.loadFiles(); | |
| var suite = this.suite; | |
| var options = this.options; | |
| var runner = new exports.Runner(suite); | |
| var reporter = new this._reporter(runner); | |
| runner.ignoreLeaks = options.ignoreLeaks; | |
| if (options.grep) runner.grep(options.grep); | |
| if (options.globals) runner.globals(options.globals); | |
| if (options.growl) this.growl(runner, reporter); | |
| return runner.run(fn); | |
| }; | |
| }); // module: mocha.js | |
| require.register("reporters/base.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var tty = require('browser/tty') | |
| , diff = require('browser/diff'); | |
| /** | |
| * Save timer references to avoid Sinon interfering (see GH-237). | |
| */ | |
| var Date = global.Date | |
| , setTimeout = global.setTimeout | |
| , setInterval = global.setInterval | |
| , clearTimeout = global.clearTimeout | |
| , clearInterval = global.clearInterval; | |
| /** | |
| * Check if both stdio streams are associated with a tty. | |
| */ | |
| var isatty = tty.isatty(1) && tty.isatty(2); | |
| /** | |
| * Expose `Base`. | |
| */ | |
| exports = module.exports = Base; | |
| /** | |
| * Enable coloring by default. | |
| */ | |
| exports.useColors = isatty; | |
| /** | |
| * Default color map. | |
| */ | |
| exports.colors = { | |
| 'pass': 90 | |
| , 'fail': 31 | |
| , 'bright pass': 92 | |
| , 'bright fail': 91 | |
| , 'bright yellow': 93 | |
| , 'pending': 36 | |
| , 'suite': 0 | |
| , 'error title': 0 | |
| , 'error message': 31 | |
| , 'error stack': 90 | |
| , 'checkmark': 32 | |
| , 'fast': 90 | |
| , 'medium': 33 | |
| , 'slow': 31 | |
| , 'green': 32 | |
| , 'light': 90 | |
| , 'diff gutter': 90 | |
| , 'diff added': 42 | |
| , 'diff removed': 41 | |
| }; | |
| /** | |
| * Color `str` with the given `type`, | |
| * allowing colors to be disabled, | |
| * as well as user-defined color | |
| * schemes. | |
| * | |
| * @param {String} type | |
| * @param {String} str | |
| * @return {String} | |
| * @api private | |
| */ | |
| var color = exports.color = function(type, str) { | |
| if (!exports.useColors) return str; | |
| return '\033[' + exports.colors[type] + 'm' + str + '\033[0m'; | |
| }; | |
| /** | |
| * Expose term window size, with some | |
| * defaults for when stderr is not a tty. | |
| */ | |
| exports.window = { | |
| width: isatty | |
| ? process.stdout.getWindowSize | |
| ? process.stdout.getWindowSize(1)[0] | |
| : tty.getWindowSize()[1] | |
| : 75 | |
| }; | |
| /** | |
| * Expose some basic cursor interactions | |
| * that are common among reporters. | |
| */ | |
| exports.cursor = { | |
| hide: function(){ | |
| process.stdout.write('\033[?25l'); | |
| }, | |
| show: function(){ | |
| process.stdout.write('\033[?25h'); | |
| }, | |
| deleteLine: function(){ | |
| process.stdout.write('\033[2K'); | |
| }, | |
| beginningOfLine: function(){ | |
| process.stdout.write('\033[0G'); | |
| }, | |
| CR: function(){ | |
| exports.cursor.deleteLine(); | |
| exports.cursor.beginningOfLine(); | |
| } | |
| }; | |
| /** | |
| * A test is considered slow if it | |
| * exceeds the following value in milliseconds. | |
| */ | |
| exports.slow = 75; | |
| /** | |
| * Outut the given `failures` as a list. | |
| * | |
| * @param {Array} failures | |
| * @api public | |
| */ | |
| exports.list = function(failures){ | |
| console.error(); | |
| failures.forEach(function(test, i){ | |
| // format | |
| var fmt = color('error title', ' %s) %s:\n') | |
| + color('error message', ' %s') | |
| + color('error stack', '\n%s\n'); | |
| // msg | |
| var err = test.err | |
| , message = err.message || '' | |
| , stack = err.stack || message | |
| , index = stack.indexOf(message) + message.length | |
| , msg = stack.slice(0, index) | |
| , actual = err.actual | |
| , expected = err.expected; | |
| // actual / expected diff | |
| if ('string' == typeof actual && 'string' == typeof expected) { | |
| var len = Math.max(actual.length, expected.length); | |
| if (len < 20) msg = errorDiff(err, 'Chars'); | |
| else msg = errorDiff(err, 'Words'); | |
| // linenos | |
| var lines = msg.split('\n'); | |
| if (lines.length > 4) { | |
| var width = String(lines.length).length; | |
| msg = lines.map(function(str, i){ | |
| return pad(++i, width) + ' |' + ' ' + str; | |
| }).join('\n'); | |
| } | |
| // legend | |
| msg = '\n' | |
| + color('diff removed', 'actual') | |
| + ' ' | |
| + color('diff added', 'expected') | |
| + '\n\n' | |
| + msg | |
| + '\n'; | |
| // indent | |
| msg = msg.replace(/^/gm, ' '); | |
| fmt = color('error title', ' %s) %s:\n%s') | |
| + color('error stack', '\n%s\n'); | |
| } | |
| // indent stack trace without msg | |
| stack = stack.slice(index ? index + 1 : index) | |
| .replace(/^/gm, ' '); | |
| console.error(fmt, (i + 1), test.fullTitle(), msg, stack); | |
| }); | |
| }; | |
| /** | |
| * Initialize a new `Base` reporter. | |
| * | |
| * All other reporters generally | |
| * inherit from this reporter, providing | |
| * stats such as test duration, number | |
| * of tests passed / failed etc. | |
| * | |
| * @param {Runner} runner | |
| * @api public | |
| */ | |
| function Base(runner) { | |
| var self = this | |
| , stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 } | |
| , failures = this.failures = []; | |
| if (!runner) return; | |
| this.runner = runner; | |
| runner.on('start', function(){ | |
| stats.start = new Date; | |
| }); | |
| runner.on('suite', function(suite){ | |
| stats.suites = stats.suites || 0; | |
| suite.root || stats.suites++; | |
| }); | |
| runner.on('test end', function(test){ | |
| stats.tests = stats.tests || 0; | |
| stats.tests++; | |
| }); | |
| runner.on('pass', function(test){ | |
| stats.passes = stats.passes || 0; | |
| var medium = exports.slow / 2; | |
| test.speed = test.duration > exports.slow | |
| ? 'slow' | |
| : test.duration > medium | |
| ? 'medium' | |
| : 'fast'; | |
| stats.passes++; | |
| }); | |
| runner.on('fail', function(test, err){ | |
| stats.failures = stats.failures || 0; | |
| stats.failures++; | |
| test.err = err; | |
| failures.push(test); | |
| }); | |
| runner.on('end', function(){ | |
| stats.end = new Date; | |
| stats.duration = new Date - stats.start; | |
| }); | |
| runner.on('pending', function(){ | |
| stats.pending++; | |
| }); | |
| } | |
| /** | |
| * Output common epilogue used by many of | |
| * the bundled reporters. | |
| * | |
| * @api public | |
| */ | |
| Base.prototype.epilogue = function(){ | |
| var stats = this.stats | |
| , fmt | |
| , tests; | |
| console.log(); | |
| function pluralize(n) { | |
| return 1 == n ? 'test' : 'tests'; | |
| } | |
| // failure | |
| if (stats.failures) { | |
| fmt = color('bright fail', ' ✖') | |
| + color('fail', ' %d of %d %s failed') | |
| + color('light', ':') | |
| console.error(fmt, | |
| stats.failures, | |
| this.runner.total, | |
| pluralize(this.runner.total)); | |
| Base.list(this.failures); | |
| console.error(); | |
| return; | |
| } | |
| // pass | |
| fmt = color('bright pass', ' ✔') | |
| + color('green', ' %d %s complete') | |
| + color('light', ' (%dms)'); | |
| console.log(fmt, | |
| stats.tests || 0, | |
| pluralize(stats.tests), | |
| stats.duration); | |
| // pending | |
| if (stats.pending) { | |
| fmt = color('pending', ' •') | |
| + color('pending', ' %d %s pending'); | |
| console.log(fmt, stats.pending, pluralize(stats.pending)); | |
| } | |
| console.log(); | |
| }; | |
| /** | |
| * Pad the given `str` to `len`. | |
| * | |
| * @param {String} str | |
| * @param {String} len | |
| * @return {String} | |
| * @api private | |
| */ | |
| function pad(str, len) { | |
| str = String(str); | |
| return Array(len - str.length + 1).join(' ') + str; | |
| } | |
| /** | |
| * Return a character diff for `err`. | |
| * | |
| * @param {Error} err | |
| * @return {String} | |
| * @api private | |
| */ | |
| function errorDiff(err, type) { | |
| return diff['diff' + type](err.actual, err.expected).map(function(str){ | |
| if (/^(\n+)$/.test(str.value)) str.value = Array(++RegExp.$1.length).join('<newline>'); | |
| if (str.added) return colorLines('diff added', str.value); | |
| if (str.removed) return colorLines('diff removed', str.value); | |
| return str.value; | |
| }).join(''); | |
| } | |
| /** | |
| * Color lines for `str`, using the color `name`. | |
| * | |
| * @param {String} name | |
| * @param {String} str | |
| * @return {String} | |
| * @api private | |
| */ | |
| function colorLines(name, str) { | |
| return str.split('\n').map(function(str){ | |
| return color(name, str); | |
| }).join('\n'); | |
| } | |
| }); // module: reporters/base.js | |
| require.register("reporters/doc.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var Base = require('./base') | |
| , utils = require('../utils'); | |
| /** | |
| * Expose `Doc`. | |
| */ | |
| exports = module.exports = Doc; | |
| /** | |
| * Initialize a new `Doc` reporter. | |
| * | |
| * @param {Runner} runner | |
| * @api public | |
| */ | |
| function Doc(runner) { | |
| Base.call(this, runner); | |
| var self = this | |
| , stats = this.stats | |
| , total = runner.total | |
| , indents = 2; | |
| function indent() { | |
| return Array(indents).join(' '); | |
| } | |
| runner.on('suite', function(suite){ | |
| if (suite.root) return; | |
| ++indents; | |
| console.log('%s<section class="suite">', indent()); | |
| ++indents; | |
| console.log('%s<h1>%s</h1>', indent(), suite.title); | |
| console.log('%s<dl>', indent()); | |
| }); | |
| runner.on('suite end', function(suite){ | |
| if (suite.root) return; | |
| console.log('%s</dl>', indent()); | |
| --indents; | |
| console.log('%s</section>', indent()); | |
| --indents; | |
| }); | |
| runner.on('pass', function(test){ | |
| console.log('%s <dt>%s</dt>', indent(), test.title); | |
| var code = utils.escape(utils.clean(test.fn.toString())); | |
| console.log('%s <dd><pre><code>%s</code></pre></dd>', indent(), code); | |
| }); | |
| } | |
| }); // module: reporters/doc.js | |
| require.register("reporters/dot.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var Base = require('./base') | |
| , color = Base.color; | |
| /** | |
| * Expose `Dot`. | |
| */ | |
| exports = module.exports = Dot; | |
| /** | |
| * Initialize a new `Dot` matrix test reporter. | |
| * | |
| * @param {Runner} runner | |
| * @api public | |
| */ | |
| function Dot(runner) { | |
| Base.call(this, runner); | |
| var self = this | |
| , stats = this.stats | |
| , width = Base.window.width * .75 | 0 | |
| , n = 0; | |
| runner.on('start', function(){ | |
| process.stdout.write('\n '); | |
| }); | |
| runner.on('pending', function(test){ | |
| process.stdout.write(color('pending', '.')); | |
| }); | |
| runner.on('pass', function(test){ | |
| if (++n % width == 0) process.stdout.write('\n '); | |
| if ('slow' == test.speed) { | |
| process.stdout.write(color('bright yellow', '.')); | |
| } else { | |
| process.stdout.write(color(test.speed, '.')); | |
| } | |
| }); | |
| runner.on('fail', function(test, err){ | |
| if (++n % width == 0) process.stdout.write('\n '); | |
| process.stdout.write(color('fail', '.')); | |
| }); | |
| runner.on('end', function(){ | |
| console.log(); | |
| self.epilogue(); | |
| }); | |
| } | |
| /** | |
| * Inherit from `Base.prototype`. | |
| */ | |
| Dot.prototype = new Base; | |
| Dot.prototype.constructor = Dot; | |
| }); // module: reporters/dot.js | |
| require.register("reporters/html-cov.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var JSONCov = require('./json-cov') | |
| , fs = require('browser/fs'); | |
| /** | |
| * Expose `HTMLCov`. | |
| */ | |
| exports = module.exports = HTMLCov; | |
| /** | |
| * Initialize a new `JsCoverage` reporter. | |
| * | |
| * @param {Runner} runner | |
| * @api public | |
| */ | |
| function HTMLCov(runner) { | |
| var jade = require('jade') | |
| , file = __dirname + '/templates/coverage.jade' | |
| , str = fs.readFileSync(file, 'utf8') | |
| , fn = jade.compile(str, { filename: file }) | |
| , self = this; | |
| JSONCov.call(this, runner, false); | |
| runner.on('end', function(){ | |
| process.stdout.write(fn({ | |
| cov: self.cov | |
| , coverageClass: coverageClass | |
| })); | |
| }); | |
| } | |
| /** | |
| * Return coverage class for `n`. | |
| * | |
| * @return {String} | |
| * @api private | |
| */ | |
| function coverageClass(n) { | |
| if (n >= 75) return 'high'; | |
| if (n >= 50) return 'medium'; | |
| if (n >= 25) return 'low'; | |
| return 'terrible'; | |
| } | |
| }); // module: reporters/html-cov.js | |
| require.register("reporters/html.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var Base = require('./base') | |
| , utils = require('../utils') | |
| , Progress = require('../browser/progress') | |
| , escape = utils.escape; | |
| /** | |
| * Save timer references to avoid Sinon interfering (see GH-237). | |
| */ | |
| var Date = global.Date | |
| , setTimeout = global.setTimeout | |
| , setInterval = global.setInterval | |
| , clearTimeout = global.clearTimeout | |
| , clearInterval = global.clearInterval; | |
| /** | |
| * Expose `Doc`. | |
| */ | |
| exports = module.exports = HTML; | |
| /** | |
| * Stats template. | |
| */ | |
| var statsTemplate = '<ul id="stats">' | |
| + '<li class="progress"><canvas width="40" height="40"></canvas></li>' | |
| + '<li class="passes">passes: <em>0</em></li>' | |
| + '<li class="failures">failures: <em>0</em></li>' | |
| + '<li class="duration">duration: <em>0</em>s</li>' | |
| + '</ul>'; | |
| /** | |
| * Initialize a new `Doc` reporter. | |
| * | |
| * @param {Runner} runner | |
| * @api public | |
| */ | |
| function HTML(runner) { | |
| Base.call(this, runner); | |
| var self = this | |
| , stats = this.stats | |
| , total = runner.total | |
| , root = document.getElementById('mocha') | |
| , stat = fragment(statsTemplate) | |
| , items = stat.getElementsByTagName('li') | |
| , passes = items[1].getElementsByTagName('em')[0] | |
| , failures = items[2].getElementsByTagName('em')[0] | |
| , duration = items[3].getElementsByTagName('em')[0] | |
| , canvas = stat.getElementsByTagName('canvas')[0] | |
| , report = fragment('<ul id="report"></ul>') | |
| , stack = [report] | |
| , progress | |
| , ctx | |
| if (canvas.getContext) { | |
| ctx = canvas.getContext('2d'); | |
| progress = new Progress; | |
| } | |
| if (!root) return error('#mocha div missing, add it to your document'); | |
| root.appendChild(stat); | |
| root.appendChild(report); | |
| if (progress) progress.size(40); | |
| runner.on('suite', function(suite){ | |
| if (suite.root) return; | |
| // suite | |
| var url = location.protocol + '//' + location.host + location.pathname + '?grep=^' + utils.escapeRegexp(suite.fullTitle()); | |
| var el = fragment('<li class="suite"><h1><a href="%s">%s</a></h1></li>', url, escape(suite.title)); | |
| // container | |
| stack[0].appendChild(el); | |
| stack.unshift(document.createElement('ul')); | |
| el.appendChild(stack[0]); | |
| }); | |
| runner.on('suite end', function(suite){ | |
| if (suite.root) return; | |
| stack.shift(); | |
| }); | |
| runner.on('fail', function(test, err){ | |
| if ('hook' == test.type || err.uncaught) runner.emit('test end', test); | |
| }); | |
| runner.on('test end', function(test){ | |
| window.scrollTo(0, document.body.scrollHeight); | |
| // TODO: add to stats | |
| var percent = stats.tests / total * 100 | 0; | |
| if (progress) progress.update(percent).draw(ctx); | |
| // update stats | |
| var ms = new Date - stats.start; | |
| text(passes, stats.passes); | |
| text(failures, stats.failures); | |
| text(duration, (ms / 1000).toFixed(2)); | |
| // test | |
| if ('passed' == test.state) { | |
| var el = fragment('<li class="test pass %e"><h2>%e<span class="duration">%ems</span></h2></li>', test.speed, test.title, test.duration); | |
| } else if (test.pending) { | |
| var el = fragment('<li class="test pass pending"><h2>%e</h2></li>', test.title); | |
| } else { | |
| var el = fragment('<li class="test fail"><h2>%e</h2></li>', test.title); | |
| var str = test.err.stack || test.err.toString(); | |
| // FF / Opera do not add the message | |
| if (!~str.indexOf(test.err.message)) { | |
| str = test.err.message + '\n' + str; | |
| } | |
| // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we | |
| // check for the result of the stringifying. | |
| if ('[object Error]' == str) str = test.err.message; | |
| // Safari doesn't give you a stack. Let's at least provide a source line. | |
| if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) { | |
| str += "\n(" + test.err.sourceURL + ":" + test.err.line + ")"; | |
| } | |
| el.appendChild(fragment('<pre class="error">%e</pre>', str)); | |
| } | |
| // toggle code | |
| var h2 = el.getElementsByTagName('h2')[0]; | |
| on(h2, 'click', function(){ | |
| pre.style.display = 'none' == pre.style.display | |
| ? 'block' | |
| : 'none'; | |
| }); | |
| // code | |
| // TODO: defer | |
| if (!test.pending) { | |
| var pre = fragment('<pre><code>%e</code></pre>', utils.clean(test.fn.toString())); | |
| el.appendChild(pre); | |
| pre.style.display = 'none'; | |
| } | |
| stack[0].appendChild(el); | |
| }); | |
| } | |
| /** | |
| * Display error `msg`. | |
| */ | |
| function error(msg) { | |
| document.body.appendChild(fragment('<div id="error">%s</div>', msg)); | |
| } | |
| /** | |
| * Return a DOM fragment from `html`. | |
| */ | |
| function fragment(html) { | |
| var args = arguments | |
| , div = document.createElement('div') | |
| , i = 1; | |
| div.innerHTML = html.replace(/%([se])/g, function(_, type){ | |
| switch (type) { | |
| case 's': return String(args[i++]); | |
| case 'e': return escape(args[i++]); | |
| } | |
| }); | |
| return div.firstChild; | |
| } | |
| /** | |
| * Set `el` text to `str`. | |
| */ | |
| function text(el, str) { | |
| if (el.textContent) { | |
| el.textContent = str; | |
| } else { | |
| el.innerText = str; | |
| } | |
| } | |
| /** | |
| * Listen on `event` with callback `fn`. | |
| */ | |
| function on(el, event, fn) { | |
| if (el.addEventListener) { | |
| el.addEventListener(event, fn, false); | |
| } else { | |
| el.attachEvent('on' + event, fn); | |
| } | |
| } | |
| }); // module: reporters/html.js | |
| require.register("reporters/index.js", function(module, exports, require){ | |
| exports.Base = require('./base'); | |
| exports.Dot = require('./dot'); | |
| exports.Doc = require('./doc'); | |
| exports.TAP = require('./tap'); | |
| exports.JSON = require('./json'); | |
| exports.HTML = require('./html'); | |
| exports.List = require('./list'); | |
| exports.Min = require('./min'); | |
| exports.Spec = require('./spec'); | |
| exports.Nyan = require('./nyan'); | |
| exports.XUnit = require('./xunit'); | |
| exports.Progress = require('./progress'); | |
| exports.Landing = require('./landing'); | |
| exports.JSONCov = require('./json-cov'); | |
| exports.HTMLCov = require('./html-cov'); | |
| exports.JSONStream = require('./json-stream'); | |
| exports.Teamcity = require('./teamcity'); | |
| }); // module: reporters/index.js | |
| require.register("reporters/json-cov.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var Base = require('./base'); | |
| /** | |
| * Expose `JSONCov`. | |
| */ | |
| exports = module.exports = JSONCov; | |
| /** | |
| * Initialize a new `JsCoverage` reporter. | |
| * | |
| * @param {Runner} runner | |
| * @param {Boolean} output | |
| * @api public | |
| */ | |
| function JSONCov(runner, output) { | |
| var self = this | |
| , output = 1 == arguments.length ? true : output; | |
| Base.call(this, runner); | |
| var tests = [] | |
| , failures = [] | |
| , passes = []; | |
| runner.on('test end', function(test){ | |
| tests.push(test); | |
| }); | |
| runner.on('pass', function(test){ | |
| passes.push(test); | |
| }); | |
| runner.on('fail', function(test){ | |
| failures.push(test); | |
| }); | |
| runner.on('end', function(){ | |
| var cov = global._$jscoverage || {}; | |
| var result = self.cov = map(cov); | |
| result.stats = self.stats; | |
| result.tests = tests.map(clean); | |
| result.failures = failures.map(clean); | |
| result.passes = passes.map(clean); | |
| if (!output) return; | |
| process.stdout.write(JSON.stringify(result, null, 2 )); | |
| }); | |
| } | |
| /** | |
| * Map jscoverage data to a JSON structure | |
| * suitable for reporting. | |
| * | |
| * @param {Object} cov | |
| * @return {Object} | |
| * @api private | |
| */ | |
| function map(cov) { | |
| var ret = { | |
| instrumentation: 'node-jscoverage' | |
| , sloc: 0 | |
| , hits: 0 | |
| , misses: 0 | |
| , coverage: 0 | |
| , files: [] | |
| }; | |
| for (var filename in cov) { | |
| var data = coverage(filename, cov[filename]); | |
| ret.files.push(data); | |
| ret.hits += data.hits; | |
| ret.misses += data.misses; | |
| ret.sloc += data.sloc; | |
| } | |
| if (ret.sloc > 0) { | |
| ret.coverage = (ret.hits / ret.sloc) * 100; | |
| } | |
| return ret; | |
| }; | |
| /** | |
| * Map jscoverage data for a single source file | |
| * to a JSON structure suitable for reporting. | |
| * | |
| * @param {String} filename name of the source file | |
| * @param {Object} data jscoverage coverage data | |
| * @return {Object} | |
| * @api private | |
| */ | |
| function coverage(filename, data) { | |
| var ret = { | |
| filename: filename, | |
| coverage: 0, | |
| hits: 0, | |
| misses: 0, | |
| sloc: 0, | |
| source: {} | |
| }; | |
| data.source.forEach(function(line, num){ | |
| num++; | |
| if (data[num] === 0) { | |
| ret.misses++; | |
| ret.sloc++; | |
| } else if (data[num] !== undefined) { | |
| ret.hits++; | |
| ret.sloc++; | |
| } | |
| ret.source[num] = { | |
| source: line | |
| , coverage: data[num] === undefined | |
| ? '' | |
| : data[num] | |
| }; | |
| }); | |
| ret.coverage = ret.hits / ret.sloc * 100; | |
| return ret; | |
| } | |
| /** | |
| * Return a plain-object representation of `test` | |
| * free of cyclic properties etc. | |
| * | |
| * @param {Object} test | |
| * @return {Object} | |
| * @api private | |
| */ | |
| function clean(test) { | |
| return { | |
| title: test.title | |
| , fullTitle: test.fullTitle() | |
| , duration: test.duration | |
| } | |
| } | |
| }); // module: reporters/json-cov.js | |
| require.register("reporters/json-stream.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var Base = require('./base') | |
| , color = Base.color; | |
| /** | |
| * Expose `List`. | |
| */ | |
| exports = module.exports = List; | |
| /** | |
| * Initialize a new `List` test reporter. | |
| * | |
| * @param {Runner} runner | |
| * @api public | |
| */ | |
| function List(runner) { | |
| Base.call(this, runner); | |
| var self = this | |
| , stats = this.stats | |
| , total = runner.total; | |
| runner.on('start', function(){ | |
| console.log(JSON.stringify(['start', { total: total }])); | |
| }); | |
| runner.on('pass', function(test){ | |
| console.log(JSON.stringify(['pass', clean(test)])); | |
| }); | |
| runner.on('fail', function(test, err){ | |
| console.log(JSON.stringify(['fail', clean(test)])); | |
| }); | |
| runner.on('end', function(){ | |
| process.stdout.write(JSON.stringify(['end', self.stats])); | |
| }); | |
| } | |
| /** | |
| * Return a plain-object representation of `test` | |
| * free of cyclic properties etc. | |
| * | |
| * @param {Object} test | |
| * @return {Object} | |
| * @api private | |
| */ | |
| function clean(test) { | |
| return { | |
| title: test.title | |
| , fullTitle: test.fullTitle() | |
| , duration: test.duration | |
| } | |
| } | |
| }); // module: reporters/json-stream.js | |
| require.register("reporters/json.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var Base = require('./base') | |
| , cursor = Base.cursor | |
| , color = Base.color; | |
| /** | |
| * Expose `JSON`. | |
| */ | |
| exports = module.exports = JSONReporter; | |
| /** | |
| * Initialize a new `JSON` reporter. | |
| * | |
| * @param {Runner} runner | |
| * @api public | |
| */ | |
| function JSONReporter(runner) { | |
| var self = this; | |
| Base.call(this, runner); | |
| var tests = [] | |
| , failures = [] | |
| , passes = []; | |
| runner.on('test end', function(test){ | |
| tests.push(test); | |
| }); | |
| runner.on('pass', function(test){ | |
| passes.push(test); | |
| }); | |
| runner.on('fail', function(test){ | |
| failures.push(test); | |
| }); | |
| runner.on('end', function(){ | |
| var obj = { | |
| stats: self.stats | |
| , tests: tests.map(clean) | |
| , failures: failures.map(clean) | |
| , passes: passes.map(clean) | |
| }; | |
| process.stdout.write(JSON.stringify(obj, null, 2)); | |
| }); | |
| } | |
| /** | |
| * Return a plain-object representation of `test` | |
| * free of cyclic properties etc. | |
| * | |
| * @param {Object} test | |
| * @return {Object} | |
| * @api private | |
| */ | |
| function clean(test) { | |
| return { | |
| title: test.title | |
| , fullTitle: test.fullTitle() | |
| , duration: test.duration | |
| } | |
| } | |
| }); // module: reporters/json.js | |
| require.register("reporters/landing.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var Base = require('./base') | |
| , cursor = Base.cursor | |
| , color = Base.color; | |
| /** | |
| * Expose `Landing`. | |
| */ | |
| exports = module.exports = Landing; | |
| /** | |
| * Airplane color. | |
| */ | |
| Base.colors.plane = 0; | |
| /** | |
| * Airplane crash color. | |
| */ | |
| Base.colors['plane crash'] = 31; | |
| /** | |
| * Runway color. | |
| */ | |
| Base.colors.runway = 90; | |
| /** | |
| * Initialize a new `Landing` reporter. | |
| * | |
| * @param {Runner} runner | |
| * @api public | |
| */ | |
| function Landing(runner) { | |
| Base.call(this, runner); | |
| var self = this | |
| , stats = this.stats | |
| , width = Base.window.width * .75 | 0 | |
| , total = runner.total | |
| , stream = process.stdout | |
| , plane = color('plane', '✈') | |
| , crashed = -1 | |
| , n = 0; | |
| function runway() { | |
| var buf = Array(width).join('-'); | |
| return ' ' + color('runway', buf); | |
| } | |
| runner.on('start', function(){ | |
| stream.write('\n '); | |
| cursor.hide(); | |
| }); | |
| runner.on('test end', function(test){ | |
| // check if the plane crashed | |
| var col = -1 == crashed | |
| ? width * ++n / total | 0 | |
| : crashed; | |
| // show the crash | |
| if ('failed' == test.state) { | |
| plane = color('plane crash', '✈'); | |
| crashed = col; | |
| } | |
| // render landing strip | |
| stream.write('\033[4F\n\n'); | |
| stream.write(runway()); | |
| stream.write('\n '); | |
| stream.write(color('runway', Array(col).join('⋅'))); | |
| stream.write(plane) | |
| stream.write(color('runway', Array(width - col).join('⋅') + '\n')); | |
| stream.write(runway()); | |
| stream.write('\033[0m'); | |
| }); | |
| runner.on('end', function(){ | |
| cursor.show(); | |
| console.log(); | |
| self.epilogue(); | |
| }); | |
| } | |
| /** | |
| * Inherit from `Base.prototype`. | |
| */ | |
| Landing.prototype = new Base; | |
| Landing.prototype.constructor = Landing; | |
| }); // module: reporters/landing.js | |
| require.register("reporters/list.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var Base = require('./base') | |
| , cursor = Base.cursor | |
| , color = Base.color; | |
| /** | |
| * Expose `List`. | |
| */ | |
| exports = module.exports = List; | |
| /** | |
| * Initialize a new `List` test reporter. | |
| * | |
| * @param {Runner} runner | |
| * @api public | |
| */ | |
| function List(runner) { | |
| Base.call(this, runner); | |
| var self = this | |
| , stats = this.stats | |
| , n = 0; | |
| runner.on('start', function(){ | |
| console.log(); | |
| }); | |
| runner.on('test', function(test){ | |
| process.stdout.write(color('pass', ' ' + test.fullTitle() + ': ')); | |
| }); | |
| runner.on('pending', function(test){ | |
| var fmt = color('checkmark', ' -') | |
| + color('pending', ' %s'); | |
| console.log(fmt, test.fullTitle()); | |
| }); | |
| runner.on('pass', function(test){ | |
| var fmt = color('checkmark', ' ✓') | |
| + color('pass', ' %s: ') | |
| + color(test.speed, '%dms'); | |
| cursor.CR(); | |
| console.log(fmt, test.fullTitle(), test.duration); | |
| }); | |
| runner.on('fail', function(test, err){ | |
| cursor.CR(); | |
| console.log(color('fail', ' %d) %s'), ++n, test.fullTitle()); | |
| }); | |
| runner.on('end', self.epilogue.bind(self)); | |
| } | |
| /** | |
| * Inherit from `Base.prototype`. | |
| */ | |
| List.prototype = new Base; | |
| List.prototype.constructor = List; | |
| }); // module: reporters/list.js | |
| require.register("reporters/markdown.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var Base = require('./base') | |
| , utils = require('../utils'); | |
| /** | |
| * Expose `Markdown`. | |
| */ | |
| exports = module.exports = Markdown; | |
| /** | |
| * Initialize a new `Markdown` reporter. | |
| * | |
| * @param {Runner} runner | |
| * @api public | |
| */ | |
| function Markdown(runner) { | |
| Base.call(this, runner); | |
| var self = this | |
| , stats = this.stats | |
| , total = runner.total | |
| , level = 0 | |
| , buf = ''; | |
| function title(str) { | |
| return Array(level).join('#') + ' ' + str; | |
| } | |
| function indent() { | |
| return Array(level).join(' '); | |
| } | |
| function mapTOC(suite, obj) { | |
| var ret = obj; | |
| obj = obj[suite.title] = obj[suite.title] || { suite: suite }; | |
| suite.suites.forEach(function(suite){ | |
| mapTOC(suite, obj); | |
| }); | |
| return ret; | |
| } | |
| function stringifyTOC(obj, level) { | |
| ++level; | |
| var buf = ''; | |
| var link; | |
| for (var key in obj) { | |
| if ('suite' == key) continue; | |
| if (key) link = ' - [' + key + '](#' + utils.slug(obj[key].suite.fullTitle()) + ')\n'; | |
| if (key) buf += Array(level).join(' ') + link; | |
| buf += stringifyTOC(obj[key], level); | |
| } | |
| --level; | |
| return buf; | |
| } | |
| function generateTOC(suite) { | |
| var obj = mapTOC(suite, {}); | |
| return stringifyTOC(obj, 0); | |
| } | |
| generateTOC(runner.suite); | |
| runner.on('suite', function(suite){ | |
| ++level; | |
| var slug = utils.slug(suite.fullTitle()); | |
| buf += '<a name="' + slug + '" />' + '\n'; | |
| buf += title(suite.title) + '\n'; | |
| }); | |
| runner.on('suite end', function(suite){ | |
| --level; | |
| }); | |
| runner.on('pass', function(test){ | |
| var code = utils.clean(test.fn.toString()); | |
| buf += test.title + '.\n'; | |
| buf += '\n```js\n'; | |
| buf += code + '\n'; | |
| buf += '```\n\n'; | |
| }); | |
| runner.on('end', function(){ | |
| process.stdout.write('# TOC\n'); | |
| process.stdout.write(generateTOC(runner.suite)); | |
| process.stdout.write(buf); | |
| }); | |
| } | |
| }); // module: reporters/markdown.js | |
| require.register("reporters/min.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var Base = require('./base'); | |
| /** | |
| * Expose `Min`. | |
| */ | |
| exports = module.exports = Min; | |
| /** | |
| * Initialize a new `Min` minimal test reporter (best used with --watch). | |
| * | |
| * @param {Runner} runner | |
| * @api public | |
| */ | |
| function Min(runner) { | |
| Base.call(this, runner); | |
| runner.on('start', function(){ | |
| // clear screen | |
| process.stdout.write('\033[2J'); | |
| // set cursor position | |
| process.stdout.write('\033[1;3H'); | |
| }); | |
| runner.on('end', this.epilogue.bind(this)); | |
| } | |
| /** | |
| * Inherit from `Base.prototype`. | |
| */ | |
| Min.prototype = new Base; | |
| Min.prototype.constructor = Min; | |
| }); // module: reporters/min.js | |
| require.register("reporters/nyan.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var Base = require('./base') | |
| , color = Base.color; | |
| /** | |
| * Expose `Dot`. | |
| */ | |
| exports = module.exports = NyanCat; | |
| /** | |
| * Initialize a new `Dot` matrix test reporter. | |
| * | |
| * @param {Runner} runner | |
| * @api public | |
| */ | |
| function NyanCat(runner) { | |
| Base.call(this, runner); | |
| var self = this | |
| , stats = this.stats | |
| , width = Base.window.width * .75 | 0 | |
| , rainbowColors = this.rainbowColors = self.generateColors() | |
| , colorIndex = this.colorIndex = 0 | |
| , numerOfLines = this.numberOfLines = 4 | |
| , trajectories = this.trajectories = [[], [], [], []] | |
| , nyanCatWidth = this.nyanCatWidth = 11 | |
| , trajectoryWidthMax = this.trajectoryWidthMax = (width - nyanCatWidth) | |
| , scoreboardWidth = this.scoreboardWidth = 5 | |
| , tick = this.tick = 0 | |
| , n = 0; | |
| runner.on('start', function(){ | |
| Base.cursor.hide(); | |
| self.draw('start'); | |
| }); | |
| runner.on('pending', function(test){ | |
| self.draw('pending'); | |
| }); | |
| runner.on('pass', function(test){ | |
| self.draw('pass'); | |
| }); | |
| runner.on('fail', function(test, err){ | |
| self.draw('fail'); | |
| }); | |
| runner.on('end', function(){ | |
| Base.cursor.show(); | |
| for (var i = 0; i < self.numberOfLines; i++) write('\n'); | |
| self.epilogue(); | |
| }); | |
| } | |
| /** | |
| * Draw the nyan cat with runner `status`. | |
| * | |
| * @param {String} status | |
| * @api private | |
| */ | |
| NyanCat.prototype.draw = function(status){ | |
| this.appendRainbow(); | |
| this.drawScoreboard(); | |
| this.drawRainbow(); | |
| this.drawNyanCat(status); | |
| this.tick = !this.tick; | |
| }; | |
| /** | |
| * Draw the "scoreboard" showing the number | |
| * of passes, failures and pending tests. | |
| * | |
| * @api private | |
| */ | |
| NyanCat.prototype.drawScoreboard = function(){ | |
| var stats = this.stats; | |
| var colors = Base.colors; | |
| function draw(color, n) { | |
| write(' '); | |
| write('\033[' + color + 'm' + n + '\033[0m'); | |
| write('\n'); | |
| } | |
| draw(colors.green, stats.passes); | |
| draw(colors.fail, stats.failures); | |
| draw(colors.pending, stats.pending); | |
| write('\n'); | |
| this.cursorUp(this.numberOfLines); | |
| }; | |
| /** | |
| * Append the rainbow. | |
| * | |
| * @api private | |
| */ | |
| NyanCat.prototype.appendRainbow = function(){ | |
| var segment = this.tick ? '_' : '-'; | |
| var rainbowified = this.rainbowify(segment); | |
| for (var index = 0; index < this.numberOfLines; index++) { | |
| var trajectory = this.trajectories[index]; | |
| if (trajectory.length >= this.trajectoryWidthMax) trajectory.shift(); | |
| trajectory.push(rainbowified); | |
| } | |
| }; | |
| /** | |
| * Draw the rainbow. | |
| * | |
| * @api private | |
| */ | |
| NyanCat.prototype.drawRainbow = function(){ | |
| var self = this; | |
| this.trajectories.forEach(function(line, index) { | |
| write('\033[' + self.scoreboardWidth + 'C'); | |
| write(line.join('')); | |
| write('\n'); | |
| }); | |
| this.cursorUp(this.numberOfLines); | |
| }; | |
| /** | |
| * Draw the nyan cat with `status`. | |
| * | |
| * @param {String} status | |
| * @api private | |
| */ | |
| NyanCat.prototype.drawNyanCat = function(status) { | |
| var self = this; | |
| var startWidth = this.scoreboardWidth + this.trajectories[0].length; | |
| [0, 1, 2, 3].forEach(function(index) { | |
| write('\033[' + startWidth + 'C'); | |
| switch (index) { | |
| case 0: | |
| write('_,------,'); | |
| write('\n'); | |
| break; | |
| case 1: | |
| var padding = self.tick ? ' ' : ' '; | |
| write('_|' + padding + '/\\_/\\ '); | |
| write('\n'); | |
| break; | |
| case 2: | |
| var padding = self.tick ? '_' : '__'; | |
| var tail = self.tick ? '~' : '^'; | |
| var face; | |
| switch (status) { | |
| case 'pass': | |
| face = '( ^ .^)'; | |
| break; | |
| case 'fail': | |
| face = '( o .o)'; | |
| break; | |
| default: | |
| face = '( - .-)'; | |
| } | |
| write(tail + '|' + padding + face + ' '); | |
| write('\n'); | |
| break; | |
| case 3: | |
| var padding = self.tick ? ' ' : ' '; | |
| write(padding + '"" "" '); | |
| write('\n'); | |
| break; | |
| } | |
| }); | |
| this.cursorUp(this.numberOfLines); | |
| }; | |
| /** | |
| * Move cursor up `n`. | |
| * | |
| * @param {Number} n | |
| * @api private | |
| */ | |
| NyanCat.prototype.cursorUp = function(n) { | |
| write('\033[' + n + 'A'); | |
| }; | |
| /** | |
| * Move cursor down `n`. | |
| * | |
| * @param {Number} n | |
| * @api private | |
| */ | |
| NyanCat.prototype.cursorDown = function(n) { | |
| write('\033[' + n + 'B'); | |
| }; | |
| /** | |
| * Generate rainbow colors. | |
| * | |
| * @return {Array} | |
| * @api private | |
| */ | |
| NyanCat.prototype.generateColors = function(){ | |
| var colors = []; | |
| for (var i = 0; i < (6 * 7); i++) { | |
| var pi3 = Math.floor(Math.PI / 3); | |
| var n = (i * (1.0 / 6)); | |
| var r = Math.floor(3 * Math.sin(n) + 3); | |
| var g = Math.floor(3 * Math.sin(n + 2 * pi3) + 3); | |
| var b = Math.floor(3 * Math.sin(n + 4 * pi3) + 3); | |
| colors.push(36 * r + 6 * g + b + 16); | |
| } | |
| return colors; | |
| }; | |
| /** | |
| * Apply rainbow to the given `str`. | |
| * | |
| * @param {String} str | |
| * @return {String} | |
| * @api private | |
| */ | |
| NyanCat.prototype.rainbowify = function(str){ | |
| var color = this.rainbowColors[this.colorIndex % this.rainbowColors.length]; | |
| this.colorIndex += 1; | |
| return '\033[38;5;' + color + 'm' + str + '\033[0m'; | |
| }; | |
| /** | |
| * Stdout helper. | |
| */ | |
| function write(string) { | |
| process.stdout.write(string); | |
| } | |
| /** | |
| * Inherit from `Base.prototype`. | |
| */ | |
| NyanCat.prototype = new Base; | |
| NyanCat.prototype.constructor = NyanCat; | |
| }); // module: reporters/nyan.js | |
| require.register("reporters/progress.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var Base = require('./base') | |
| , cursor = Base.cursor | |
| , color = Base.color; | |
| /** | |
| * Expose `Progress`. | |
| */ | |
| exports = module.exports = Progress; | |
| /** | |
| * General progress bar color. | |
| */ | |
| Base.colors.progress = 90; | |
| /** | |
| * Initialize a new `Progress` bar test reporter. | |
| * | |
| * @param {Runner} runner | |
| * @param {Object} options | |
| * @api public | |
| */ | |
| function Progress(runner, options) { | |
| Base.call(this, runner); | |
| var self = this | |
| , options = options || {} | |
| , stats = this.stats | |
| , width = Base.window.width * .50 | 0 | |
| , total = runner.total | |
| , complete = 0 | |
| , max = Math.max; | |
| // default chars | |
| options.open = options.open || '['; | |
| options.complete = options.complete || '▬'; | |
| options.incomplete = options.incomplete || '⋅'; | |
| options.close = options.close || ']'; | |
| options.verbose = false; | |
| // tests started | |
| runner.on('start', function(){ | |
| console.log(); | |
| cursor.hide(); | |
| }); | |
| // tests complete | |
| runner.on('test end', function(){ | |
| complete++; | |
| var incomplete = total - complete | |
| , percent = complete / total | |
| , n = width * percent | 0 | |
| , i = width - n; | |
| cursor.CR(); | |
| process.stdout.write('\033[J'); | |
| process.stdout.write(color('progress', ' ' + options.open)); | |
| process.stdout.write(Array(n).join(options.complete)); | |
| process.stdout.write(Array(i).join(options.incomplete)); | |
| process.stdout.write(color('progress', options.close)); | |
| if (options.verbose) { | |
| process.stdout.write(color('progress', ' ' + complete + ' of ' + total)); | |
| } | |
| }); | |
| // tests are complete, output some stats | |
| // and the failures if any | |
| runner.on('end', function(){ | |
| cursor.show(); | |
| console.log(); | |
| self.epilogue(); | |
| }); | |
| } | |
| /** | |
| * Inherit from `Base.prototype`. | |
| */ | |
| Progress.prototype = new Base; | |
| Progress.prototype.constructor = Progress; | |
| }); // module: reporters/progress.js | |
| require.register("reporters/spec.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var Base = require('./base') | |
| , cursor = Base.cursor | |
| , color = Base.color; | |
| /** | |
| * Expose `Spec`. | |
| */ | |
| exports = module.exports = Spec; | |
| /** | |
| * Initialize a new `Spec` test reporter. | |
| * | |
| * @param {Runner} runner | |
| * @api public | |
| */ | |
| function Spec(runner) { | |
| Base.call(this, runner); | |
| var self = this | |
| , stats = this.stats | |
| , indents = 0 | |
| , n = 0; | |
| function indent() { | |
| return Array(indents).join(' ') | |
| } | |
| runner.on('start', function(){ | |
| console.log(); | |
| }); | |
| runner.on('suite', function(suite){ | |
| ++indents; | |
| console.log(color('suite', '%s%s'), indent(), suite.title); | |
| }); | |
| runner.on('suite end', function(suite){ | |
| --indents; | |
| if (1 == indents) console.log(); | |
| }); | |
| runner.on('test', function(test){ | |
| process.stdout.write(indent() + color('pass', ' ◦ ' + test.title + ': ')); | |
| }); | |
| runner.on('pending', function(test){ | |
| var fmt = indent() + color('pending', ' - %s'); | |
| console.log(fmt, test.title); | |
| }); | |
| runner.on('pass', function(test){ | |
| if ('fast' == test.speed) { | |
| var fmt = indent() | |
| + color('checkmark', ' ✓') | |
| + color('pass', ' %s '); | |
| cursor.CR(); | |
| console.log(fmt, test.title); | |
| } else { | |
| var fmt = indent() | |
| + color('checkmark', ' ✓') | |
| + color('pass', ' %s ') | |
| + color(test.speed, '(%dms)'); | |
| cursor.CR(); | |
| console.log(fmt, test.title, test.duration); | |
| } | |
| }); | |
| runner.on('fail', function(test, err){ | |
| cursor.CR(); | |
| console.log(indent() + color('fail', ' %d) %s'), ++n, test.title); | |
| }); | |
| runner.on('end', self.epilogue.bind(self)); | |
| } | |
| /** | |
| * Inherit from `Base.prototype`. | |
| */ | |
| Spec.prototype = new Base; | |
| Spec.prototype.constructor = Spec; | |
| }); // module: reporters/spec.js | |
| require.register("reporters/tap.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var Base = require('./base') | |
| , cursor = Base.cursor | |
| , color = Base.color; | |
| /** | |
| * Expose `TAP`. | |
| */ | |
| exports = module.exports = TAP; | |
| /** | |
| * Initialize a new `TAP` reporter. | |
| * | |
| * @param {Runner} runner | |
| * @api public | |
| */ | |
| function TAP(runner) { | |
| Base.call(this, runner); | |
| var self = this | |
| , stats = this.stats | |
| , total = runner.total | |
| , n = 1; | |
| runner.on('start', function(){ | |
| console.log('%d..%d', 1, total); | |
| }); | |
| runner.on('test end', function(){ | |
| ++n; | |
| }); | |
| runner.on('pending', function(test){ | |
| console.log('ok %d %s # SKIP -', n, title(test)); | |
| }); | |
| runner.on('pass', function(test){ | |
| console.log('ok %d %s', n, title(test)); | |
| }); | |
| runner.on('fail', function(test, err){ | |
| console.log('not ok %d %s', n, title(test)); | |
| console.log(err.stack.replace(/^/gm, ' ')); | |
| }); | |
| } | |
| /** | |
| * Return a TAP-safe title of `test` | |
| * | |
| * @param {Object} test | |
| * @return {String} | |
| * @api private | |
| */ | |
| function title(test) { | |
| return test.fullTitle().replace(/#/g, ''); | |
| } | |
| }); // module: reporters/tap.js | |
| require.register("reporters/teamcity.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var Base = require('./base'); | |
| /** | |
| * Expose `Teamcity`. | |
| */ | |
| exports = module.exports = Teamcity; | |
| /** | |
| * Initialize a new `Teamcity` reporter. | |
| * | |
| * @param {Runner} runner | |
| * @api public | |
| */ | |
| function Teamcity(runner) { | |
| Base.call(this, runner); | |
| var stats = this.stats; | |
| runner.on('start', function() { | |
| console.log("##teamcity[testSuiteStarted name='mocha.suite']"); | |
| }); | |
| runner.on('test', function(test) { | |
| console.log("##teamcity[testStarted name='" + escape(test.fullTitle()) + "']"); | |
| }); | |
| runner.on('fail', function(test, err) { | |
| console.log("##teamcity[testFailed name='" + escape(test.fullTitle()) + "' message='" + escape(err.message) + "']"); | |
| }); | |
| runner.on('pending', function(test) { | |
| console.log("##teamcity[testIgnored name='" + escape(test.fullTitle()) + "' message='pending']"); | |
| }); | |
| runner.on('test end', function(test) { | |
| console.log("##teamcity[testFinished name='" + escape(test.fullTitle()) + "' duration='" + test.duration + "']"); | |
| }); | |
| runner.on('end', function() { | |
| console.log("##teamcity[testSuiteFinished name='mocha.suite' duration='" + stats.duration + "']"); | |
| }); | |
| } | |
| /** | |
| * Escape the given `str`. | |
| */ | |
| function escape(str) { | |
| return str | |
| .replace(/\|/g, "||") | |
| .replace(/\n/g, "|n") | |
| .replace(/\r/g, "|r") | |
| .replace(/\[/g, "|[") | |
| .replace(/\]/g, "|]") | |
| .replace(/\u0085/g, "|x") | |
| .replace(/\u2028/g, "|l") | |
| .replace(/\u2029/g, "|p") | |
| .replace(/'/g, "|'"); | |
| } | |
| }); // module: reporters/teamcity.js | |
| require.register("reporters/xunit.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var Base = require('./base') | |
| , utils = require('../utils') | |
| , escape = utils.escape; | |
| /** | |
| * Save timer references to avoid Sinon interfering (see GH-237). | |
| */ | |
| var Date = global.Date | |
| , setTimeout = global.setTimeout | |
| , setInterval = global.setInterval | |
| , clearTimeout = global.clearTimeout | |
| , clearInterval = global.clearInterval; | |
| /** | |
| * Expose `XUnit`. | |
| */ | |
| exports = module.exports = XUnit; | |
| /** | |
| * Initialize a new `XUnit` reporter. | |
| * | |
| * @param {Runner} runner | |
| * @api public | |
| */ | |
| function XUnit(runner) { | |
| Base.call(this, runner); | |
| var stats = this.stats | |
| , tests = [] | |
| , self = this; | |
| runner.on('test end', function(test){ | |
| tests.push(test); | |
| }); | |
| runner.on('end', function(){ | |
| console.log(tag('testsuite', { | |
| name: 'Mocha Tests' | |
| , tests: stats.tests | |
| , failures: stats.failures | |
| , errors: stats.failures | |
| , skip: stats.tests - stats.failures - stats.passes | |
| , timestamp: (new Date).toUTCString() | |
| , time: stats.duration / 1000 | |
| }, false)); | |
| tests.forEach(test); | |
| console.log('</testsuite>'); | |
| }); | |
| } | |
| /** | |
| * Inherit from `Base.prototype`. | |
| */ | |
| XUnit.prototype = new Base; | |
| XUnit.prototype.constructor = XUnit; | |
| /** | |
| * Output tag for the given `test.` | |
| */ | |
| function test(test) { | |
| var attrs = { | |
| classname: test.parent.fullTitle() | |
| , name: test.title | |
| , time: test.duration / 1000 | |
| }; | |
| if ('failed' == test.state) { | |
| var err = test.err; | |
| attrs.message = escape(err.message); | |
| console.log(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(err.stack)))); | |
| } else if (test.pending) { | |
| console.log(tag('testcase', attrs, false, tag('skipped', {}, true))); | |
| } else { | |
| console.log(tag('testcase', attrs, true) ); | |
| } | |
| } | |
| /** | |
| * HTML tag helper. | |
| */ | |
| function tag(name, attrs, close, content) { | |
| var end = close ? '/>' : '>' | |
| , pairs = [] | |
| , tag; | |
| for (var key in attrs) { | |
| pairs.push(key + '="' + escape(attrs[key]) + '"'); | |
| } | |
| tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end; | |
| if (content) tag += content + '</' + name + end; | |
| return tag; | |
| } | |
| /** | |
| * Return cdata escaped CDATA `str`. | |
| */ | |
| function cdata(str) { | |
| return '<![CDATA[' + escape(str) + ']]>'; | |
| } | |
| }); // module: reporters/xunit.js | |
| require.register("runnable.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var EventEmitter = require('browser/events').EventEmitter | |
| , debug = require('browser/debug')('runnable'); | |
| /** | |
| * Save timer references to avoid Sinon interfering (see GH-237). | |
| */ | |
| var Date = global.Date | |
| , setTimeout = global.setTimeout | |
| , setInterval = global.setInterval | |
| , clearTimeout = global.clearTimeout | |
| , clearInterval = global.clearInterval; | |
| /** | |
| * Expose `Runnable`. | |
| */ | |
| module.exports = Runnable; | |
| /** | |
| * Initialize a new `Runnable` with the given `title` and callback `fn`. | |
| * | |
| * @param {String} title | |
| * @param {Function} fn | |
| * @api private | |
| */ | |
| function Runnable(title, fn) { | |
| this.title = title; | |
| this.fn = fn; | |
| this.async = fn && fn.length; | |
| this.sync = ! this.async; | |
| this._timeout = 2000; | |
| this.timedOut = false; | |
| } | |
| /** | |
| * Inherit from `EventEmitter.prototype`. | |
| */ | |
| Runnable.prototype = new EventEmitter; | |
| Runnable.prototype.constructor = Runnable; | |
| /** | |
| * Set & get timeout `ms`. | |
| * | |
| * @param {Number} ms | |
| * @return {Runnable|Number} ms or self | |
| * @api private | |
| */ | |
| Runnable.prototype.timeout = function(ms){ | |
| if (0 == arguments.length) return this._timeout; | |
| debug('timeout %d', ms); | |
| this._timeout = ms; | |
| if (this.timer) this.resetTimeout(); | |
| return this; | |
| }; | |
| /** | |
| * Return the full title generated by recursively | |
| * concatenating the parent's full title. | |
| * | |
| * @return {String} | |
| * @api public | |
| */ | |
| Runnable.prototype.fullTitle = function(){ | |
| return this.parent.fullTitle() + ' ' + this.title; | |
| }; | |
| /** | |
| * Clear the timeout. | |
| * | |
| * @api private | |
| */ | |
| Runnable.prototype.clearTimeout = function(){ | |
| clearTimeout(this.timer); | |
| }; | |
| /** | |
| * Inspect the runnable void of private properties. | |
| * | |
| * @return {String} | |
| * @api private | |
| */ | |
| Runnable.prototype.inspect = function(){ | |
| return JSON.stringify(this, function(key, val){ | |
| if ('_' == key[0]) return; | |
| if ('parent' == key) return '#<Suite>'; | |
| if ('ctx' == key) return '#<Context>'; | |
| return val; | |
| }, 2); | |
| }; | |
| /** | |
| * Reset the timeout. | |
| * | |
| * @api private | |
| */ | |
| Runnable.prototype.resetTimeout = function(){ | |
| var self = this | |
| , ms = this.timeout(); | |
| this.clearTimeout(); | |
| if (ms) { | |
| this.timer = setTimeout(function(){ | |
| self.callback(new Error('timeout of ' + ms + 'ms exceeded')); | |
| self.timedOut = true; | |
| }, ms); | |
| } | |
| }; | |
| /** | |
| * Run the test and invoke `fn(err)`. | |
| * | |
| * @param {Function} fn | |
| * @api private | |
| */ | |
| Runnable.prototype.run = function(fn){ | |
| var self = this | |
| , ms = this.timeout() | |
| , start = new Date | |
| , ctx = this.ctx | |
| , finished | |
| , emitted; | |
| if (ctx) ctx.runnable(this); | |
| // timeout | |
| if (this.async) { | |
| if (ms) { | |
| this.timer = setTimeout(function(){ | |
| done(new Error('timeout of ' + ms + 'ms exceeded')); | |
| self.timedOut = true; | |
| }, ms); | |
| } | |
| } | |
| // called multiple times | |
| function multiple(err) { | |
| if (emitted) return; | |
| emitted = true; | |
| self.emit('error', err || new Error('done() called multiple times')); | |
| } | |
| // finished | |
| function done(err) { | |
| if (self.timedOut) return; | |
| if (finished) return multiple(err); | |
| self.clearTimeout(); | |
| self.duration = new Date - start; | |
| finished = true; | |
| fn(err); | |
| } | |
| // for .resetTimeout() | |
| this.callback = done; | |
| // async | |
| if (this.async) { | |
| try { | |
| this.fn.call(ctx, function(err){ | |
| if (err instanceof Error) return done(err); | |
| if (null != err) return done(new Error('done() invoked with non-Error: ' + err)); | |
| done(); | |
| }); | |
| } catch (err) { | |
| done(err); | |
| } | |
| return; | |
| } | |
| // sync | |
| try { | |
| if (!this.pending) this.fn.call(ctx); | |
| this.duration = new Date - start; | |
| fn(); | |
| } catch (err) { | |
| fn(err); | |
| } | |
| }; | |
| }); // module: runnable.js | |
| require.register("runner.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var EventEmitter = require('browser/events').EventEmitter | |
| , debug = require('browser/debug')('runner') | |
| , Test = require('./test') | |
| , utils = require('./utils') | |
| , filter = utils.filter | |
| , keys = utils.keys | |
| , noop = function(){}; | |
| /** | |
| * Expose `Runner`. | |
| */ | |
| module.exports = Runner; | |
| /** | |
| * Initialize a `Runner` for the given `suite`. | |
| * | |
| * Events: | |
| * | |
| * - `start` execution started | |
| * - `end` execution complete | |
| * - `suite` (suite) test suite execution started | |
| * - `suite end` (suite) all tests (and sub-suites) have finished | |
| * - `test` (test) test execution started | |
| * - `test end` (test) test completed | |
| * - `hook` (hook) hook execution started | |
| * - `hook end` (hook) hook complete | |
| * - `pass` (test) test passed | |
| * - `fail` (test, err) test failed | |
| * | |
| * @api public | |
| */ | |
| function Runner(suite) { | |
| var self = this; | |
| this._globals = []; | |
| this.suite = suite; | |
| this.total = suite.total(); | |
| this.failures = 0; | |
| this.on('test end', function(test){ self.checkGlobals(test); }); | |
| this.on('hook end', function(hook){ self.checkGlobals(hook); }); | |
| this.grep(/.*/); | |
| this.globals(utils.keys(global).concat(['errno'])); | |
| } | |
| /** | |
| * Inherit from `EventEmitter.prototype`. | |
| */ | |
| Runner.prototype = new EventEmitter; | |
| Runner.prototype.constructor = Runner; | |
| /** | |
| * Run tests with full titles matching `re`. Updates runner.total | |
| * with number of tests matched. | |
| * | |
| * @param {RegExp} re | |
| * @param {Boolean} invert | |
| * @return {Runner} for chaining | |
| * @api public | |
| */ | |
| Runner.prototype.grep = function(re, invert){ | |
| debug('grep %s', re); | |
| this._grep = re; | |
| this._invert = invert; | |
| this.total = this.grepTotal(this.suite); | |
| return this; | |
| }; | |
| /** | |
| * Returns the number of tests matching the grep search for the | |
| * given suite. | |
| * | |
| * @param {Suite} suite | |
| * @return {Number} | |
| * @api public | |
| */ | |
| Runner.prototype.grepTotal = function(suite) { | |
| var self = this; | |
| var total = 0; | |
| suite.eachTest(function(test){ | |
| var match = self._grep.test(test.fullTitle()); | |
| if (self._invert) match = !match; | |
| if (match) total++; | |
| }); | |
| return total; | |
| }; | |
| /** | |
| * Allow the given `arr` of globals. | |
| * | |
| * @param {Array} arr | |
| * @return {Runner} for chaining | |
| * @api public | |
| */ | |
| Runner.prototype.globals = function(arr){ | |
| if (0 == arguments.length) return this._globals; | |
| debug('globals %j', arr); | |
| utils.forEach(arr, function(arr){ | |
| this._globals.push(arr); | |
| }, this); | |
| return this; | |
| }; | |
| /** | |
| * Check for global variable leaks. | |
| * | |
| * @api private | |
| */ | |
| Runner.prototype.checkGlobals = function(test){ | |
| if (this.ignoreLeaks) return; | |
| var leaks = filterLeaks(this._globals); | |
| this._globals = this._globals.concat(leaks); | |
| if (leaks.length > 1) { | |
| this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + '')); | |
| } else if (leaks.length) { | |
| this.fail(test, new Error('global leak detected: ' + leaks[0])); | |
| } | |
| }; | |
| /** | |
| * Fail the given `test`. | |
| * | |
| * @param {Test} test | |
| * @param {Error} err | |
| * @api private | |
| */ | |
| Runner.prototype.fail = function(test, err){ | |
| ++this.failures; | |
| test.state = 'failed'; | |
| if ('string' == typeof err) { | |
| err = new Error('the string "' + err + '" was thrown, throw an Error :)'); | |
| } | |
| this.emit('fail', test, err); | |
| }; | |
| /** | |
| * Fail the given `hook` with `err`. | |
| * | |
| * Hook failures (currently) hard-end due | |
| * to that fact that a failing hook will | |
| * surely cause subsequent tests to fail, | |
| * causing jumbled reporting. | |
| * | |
| * @param {Hook} hook | |
| * @param {Error} err | |
| * @api private | |
| */ | |
| Runner.prototype.failHook = function(hook, err){ | |
| this.fail(hook, err); | |
| this.emit('end'); | |
| }; | |
| /** | |
| * Run hook `name` callbacks and then invoke `fn()`. | |
| * | |
| * @param {String} name | |
| * @param {Function} function | |
| * @api private | |
| */ | |
| Runner.prototype.hook = function(name, fn){ | |
| var suite = this.suite | |
| , hooks = suite['_' + name] | |
| , ms = suite._timeout | |
| , self = this | |
| , timer; | |
| function next(i) { | |
| var hook = hooks[i]; | |
| if (!hook) return fn(); | |
| self.currentRunnable = hook; | |
| self.emit('hook', hook); | |
| hook.on('error', function(err){ | |
| self.failHook(hook, err); | |
| }); | |
| hook.run(function(err){ | |
| hook.removeAllListeners('error'); | |
| var testError = hook.error(); | |
| if (testError) self.fail(self.test, testError); | |
| if (err) return self.failHook(hook, err); | |
| self.emit('hook end', hook); | |
| next(++i); | |
| }); | |
| } | |
| process.nextTick(function(){ | |
| next(0); | |
| }); | |
| }; | |
| /** | |
| * Run hook `name` for the given array of `suites` | |
| * in order, and callback `fn(err)`. | |
| * | |
| * @param {String} name | |
| * @param {Array} suites | |
| * @param {Function} fn | |
| * @api private | |
| */ | |
| Runner.prototype.hooks = function(name, suites, fn){ | |
| var self = this | |
| , orig = this.suite; | |
| function next(suite) { | |
| self.suite = suite; | |
| if (!suite) { | |
| self.suite = orig; | |
| return fn(); | |
| } | |
| self.hook(name, function(err){ | |
| if (err) { | |
| self.suite = orig; | |
| return fn(err); | |
| } | |
| next(suites.pop()); | |
| }); | |
| } | |
| next(suites.pop()); | |
| }; | |
| /** | |
| * Run hooks from the top level down. | |
| * | |
| * @param {String} name | |
| * @param {Function} fn | |
| * @api private | |
| */ | |
| Runner.prototype.hookUp = function(name, fn){ | |
| var suites = [this.suite].concat(this.parents()).reverse(); | |
| this.hooks(name, suites, fn); | |
| }; | |
| /** | |
| * Run hooks from the bottom up. | |
| * | |
| * @param {String} name | |
| * @param {Function} fn | |
| * @api private | |
| */ | |
| Runner.prototype.hookDown = function(name, fn){ | |
| var suites = [this.suite].concat(this.parents()); | |
| this.hooks(name, suites, fn); | |
| }; | |
| /** | |
| * Return an array of parent Suites from | |
| * closest to furthest. | |
| * | |
| * @return {Array} | |
| * @api private | |
| */ | |
| Runner.prototype.parents = function(){ | |
| var suite = this.suite | |
| , suites = []; | |
| while (suite = suite.parent) suites.push(suite); | |
| return suites; | |
| }; | |
| /** | |
| * Run the current test and callback `fn(err)`. | |
| * | |
| * @param {Function} fn | |
| * @api private | |
| */ | |
| Runner.prototype.runTest = function(fn){ | |
| var test = this.test | |
| , self = this; | |
| try { | |
| test.on('error', function(err){ | |
| self.fail(test, err); | |
| }); | |
| test.run(fn); | |
| } catch (err) { | |
| fn(err); | |
| } | |
| }; | |
| /** | |
| * Run tests in the given `suite` and invoke | |
| * the callback `fn()` when complete. | |
| * | |
| * @param {Suite} suite | |
| * @param {Function} fn | |
| * @api private | |
| */ | |
| Runner.prototype.runTests = function(suite, fn){ | |
| var self = this | |
| , tests = suite.tests | |
| , test; | |
| function next(err) { | |
| // if we bail after first err | |
| if (self.failures && suite._bail) return fn(); | |
| // next test | |
| test = tests.shift(); | |
| // all done | |
| if (!test) return fn(); | |
| // grep | |
| var match = self._grep.test(test.fullTitle()); | |
| if (self._invert) match = !match; | |
| if (!match) return next(); | |
| // pending | |
| if (test.pending) { | |
| self.emit('pending', test); | |
| self.emit('test end', test); | |
| return next(); | |
| } | |
| // execute test and hook(s) | |
| self.emit('test', self.test = test); | |
| self.hookDown('beforeEach', function(){ | |
| self.currentRunnable = self.test; | |
| self.runTest(function(err){ | |
| test = self.test; | |
| if (err) { | |
| self.fail(test, err); | |
| self.emit('test end', test); | |
| return self.hookUp('afterEach', next); | |
| } | |
| test.state = 'passed'; | |
| self.emit('pass', test); | |
| self.emit('test end', test); | |
| self.hookUp('afterEach', next); | |
| }); | |
| }); | |
| } | |
| this.next = next; | |
| next(); | |
| }; | |
| /** | |
| * Run the given `suite` and invoke the | |
| * callback `fn()` when complete. | |
| * | |
| * @param {Suite} suite | |
| * @param {Function} fn | |
| * @api private | |
| */ | |
| Runner.prototype.runSuite = function(suite, fn){ | |
| var total = this.grepTotal(suite) | |
| , self = this | |
| , i = 0; | |
| debug('run suite %s', suite.fullTitle()); | |
| if (!total) return fn(); | |
| this.emit('suite', this.suite = suite); | |
| function next() { | |
| var curr = suite.suites[i++]; | |
| if (!curr) return done(); | |
| self.runSuite(curr, next); | |
| } | |
| function done() { | |
| self.suite = suite; | |
| self.hook('afterAll', function(){ | |
| self.emit('suite end', suite); | |
| fn(); | |
| }); | |
| } | |
| this.hook('beforeAll', function(){ | |
| self.runTests(suite, next); | |
| }); | |
| }; | |
| /** | |
| * Handle uncaught exceptions. | |
| * | |
| * @param {Error} err | |
| * @api private | |
| */ | |
| Runner.prototype.uncaught = function(err){ | |
| debug('uncaught exception'); | |
| var runnable = this.currentRunnable; | |
| if ('failed' == runnable.state) return; | |
| runnable.clearTimeout(); | |
| err.uncaught = true; | |
| this.fail(runnable, err); | |
| // recover from test | |
| if ('test' == runnable.type) { | |
| this.emit('test end', runnable); | |
| this.hookUp('afterEach', this.next); | |
| return; | |
| } | |
| // bail on hooks | |
| this.emit('end'); | |
| }; | |
| /** | |
| * Run the root suite and invoke `fn(failures)` | |
| * on completion. | |
| * | |
| * @param {Function} fn | |
| * @return {Runner} for chaining | |
| * @api public | |
| */ | |
| Runner.prototype.run = function(fn){ | |
| var self = this | |
| , fn = fn || function(){}; | |
| debug('start'); | |
| // uncaught callback | |
| function uncaught(err) { | |
| self.uncaught(err); | |
| } | |
| // callback | |
| this.on('end', function(){ | |
| debug('end'); | |
| process.removeListener('uncaughtException', uncaught); | |
| fn(self.failures); | |
| }); | |
| // run suites | |
| this.emit('start'); | |
| this.runSuite(this.suite, function(){ | |
| debug('finished running'); | |
| self.emit('end'); | |
| }); | |
| // uncaught exception | |
| process.on('uncaughtException', uncaught); | |
| return this; | |
| }; | |
| /** | |
| * Filter leaks with the given globals flagged as `ok`. | |
| * | |
| * @param {Array} ok | |
| * @return {Array} | |
| * @api private | |
| */ | |
| function filterLeaks(ok) { | |
| return filter(keys(global), function(key){ | |
| var matched = filter(ok, function(ok){ | |
| if (~ok.indexOf('*')) return 0 == key.indexOf(ok.split('*')[0]); | |
| return key == ok; | |
| }); | |
| return matched.length == 0 && (!global.navigator || 'onerror' !== key); | |
| }); | |
| } | |
| }); // module: runner.js | |
| require.register("suite.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var EventEmitter = require('browser/events').EventEmitter | |
| , debug = require('browser/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, parent.ctx); | |
| suite.parent = parent; | |
| title = suite.fullTitle(); | |
| parent.addSuite(suite); | |
| return suite; | |
| }; | |
| /** | |
| * Initialize a new `Suite` with the given | |
| * `title` and `ctx`. | |
| * | |
| * @param {String} title | |
| * @param {Context} ctx | |
| * @api private | |
| */ | |
| function Suite(title, ctx) { | |
| this.title = title; | |
| this.ctx = ctx; | |
| 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 = new EventEmitter; | |
| Suite.prototype.constructor = Suite; | |
| /** | |
| * Return a clone of this `Suite`. | |
| * | |
| * @return {Suite} | |
| * @api private | |
| */ | |
| Suite.prototype.clone = function(){ | |
| var suite = new Suite(this.title); | |
| debug('clone'); | |
| suite.ctx = this.ctx; | |
| 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()); | |
| hook.ctx = this.ctx; | |
| 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()); | |
| hook.ctx = this.ctx; | |
| 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()); | |
| hook.ctx = this.ctx; | |
| 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()); | |
| hook.ctx = this.ctx; | |
| 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()); | |
| test.ctx = this.ctx; | |
| 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; | |
| }; | |
| /** | |
| * Iterates through each suite recursively to find | |
| * all tests. Applies a function in the format | |
| * `fn(test)`. | |
| * | |
| * @param {Function} fn | |
| * @return {Suite} | |
| * @api private | |
| */ | |
| Suite.prototype.eachTest = function(fn){ | |
| utils.forEach(this.tests, fn); | |
| utils.forEach(this.suites, function(suite){ | |
| suite.eachTest(fn); | |
| }); | |
| return this; | |
| }; | |
| }); // module: suite.js | |
| require.register("test.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var Runnable = require('./runnable'); | |
| /** | |
| * Expose `Test`. | |
| */ | |
| module.exports = Test; | |
| /** | |
| * Initialize a new `Test` with the given `title` and callback `fn`. | |
| * | |
| * @param {String} title | |
| * @param {Function} fn | |
| * @api private | |
| */ | |
| function Test(title, fn) { | |
| Runnable.call(this, title, fn); | |
| this.pending = !fn; | |
| this.type = 'test'; | |
| } | |
| /** | |
| * Inherit from `Runnable.prototype`. | |
| */ | |
| Test.prototype = new Runnable; | |
| Test.prototype.constructor = Test; | |
| }); // module: test.js | |
| require.register("utils.js", function(module, exports, require){ | |
| /** | |
| * Module dependencies. | |
| */ | |
| var fs = require('browser/fs') | |
| , path = require('browser/path') | |
| , join = path.join | |
| , debug = require('browser/debug')('watch'); | |
| /** | |
| * Ignored directories. | |
| */ | |
| var ignore = ['node_modules', '.git']; | |
| /** | |
| * Escape special characters in the given string of html. | |
| * | |
| * @param {String} html | |
| * @return {String} | |
| * @api private | |
| */ | |
| exports.escape = function(html) { | |
| return String(html) | |
| .replace(/&/g, '&') | |
| .replace(/"/g, '"') | |
| .replace(/</g, '<') | |
| .replace(/>/g, '>'); | |
| }; | |
| /** | |
| * Array#forEach (<=IE8) | |
| * | |
| * @param {Array} array | |
| * @param {Function} fn | |
| * @param {Object} scope | |
| * @api private | |
| */ | |
| exports.forEach = function(arr, fn, scope) { | |
| for (var i = 0, l = arr.length; i < l; i++) | |
| fn.call(scope, arr[i], i); | |
| }; | |
| /** | |
| * Array#indexOf (<=IE8) | |
| * | |
| * @parma {Array} arr | |
| * @param {Object} obj to find index of | |
| * @param {Number} start | |
| * @api private | |
| */ | |
| exports.indexOf = function (arr, obj, start) { | |
| for (var i = start || 0, l = arr.length; i < l; i++) { | |
| if (arr[i] === obj) | |
| return i; | |
| } | |
| return -1; | |
| }; | |
| /** | |
| * Array#reduce (<=IE8) | |
| * | |
| * @param {Array} array | |
| * @param {Function} fn | |
| * @param {Object} initial value | |
| * @param {Object} scope | |
| * @api private | |
| */ | |
| exports.reduce = function(arr, fn, val, scope) { | |
| var rval = val; | |
| for (var i = 0, l = arr.length; i < l; i++) { | |
| rval = fn.call(scope, rval, arr[i], i, arr); | |
| } | |
| return rval; | |
| }; | |
| /** | |
| * Array#filter (<=IE8) | |
| * | |
| * @param {Array} array | |
| * @param {Function} fn | |
| * @param {Object} scope | |
| * @api private | |
| */ | |
| exports.filter = function(arr, fn, scope) { | |
| var ret = []; | |
| for (var i = 0, l = arr.length; i < l; i++) { | |
| var val = arr[i]; | |
| if (fn.call(scope, val, i, arr)) | |
| ret.push(val); | |
| } | |
| return ret; | |
| }; | |
| /** | |
| * Object.keys (<=IE8) | |
| * | |
| * @param {Object} obj | |
| * @return {Array} keys | |
| * @api private | |
| */ | |
| exports.keys = Object.keys || function(obj) { | |
| var keys = [] | |
| , has = Object.prototype.hasOwnProperty // for `window` on <=IE8 | |
| for (var key in obj) { | |
| if (has.call(obj, key)) { | |
| keys.push(key); | |
| } | |
| } | |
| return keys; | |
| }; | |
| /** | |
| * Watch the given `files` for changes | |
| * and invoke `fn(file)` on modification. | |
| * | |
| * @param {Array} files | |
| * @param {Function} fn | |
| * @api private | |
| */ | |
| exports.watch = function(files, fn){ | |
| var options = { interval: 100 }; | |
| files.forEach(function(file){ | |
| debug('file %s', file); | |
| fs.watchFile(file, options, function(curr, prev){ | |
| if (prev.mtime < curr.mtime) fn(file); | |
| }); | |
| }); | |
| }; | |
| /** | |
| * Ignored files. | |
| */ | |
| function ignored(path){ | |
| return !~ignore.indexOf(path); | |
| } | |
| /** | |
| * Lookup files in the given `dir`. | |
| * | |
| * @return {Array} | |
| * @api private | |
| */ | |
| exports.files = function(dir, ret){ | |
| ret = ret || []; | |
| fs.readdirSync(dir) | |
| .filter(ignored) | |
| .forEach(function(path){ | |
| path = join(dir, path); | |
| if (fs.statSync(path).isDirectory()) { | |
| exports.files(path, ret); | |
| } else if (path.match(/\.(js|coffee)$/)) { | |
| ret.push(path); | |
| } | |
| }); | |
| return ret; | |
| }; | |
| /** | |
| * Compute a slug from the given `str`. | |
| * | |
| * @param {String} str | |
| * @return {String} | |
| * @api private | |
| */ | |
| exports.slug = function(str){ | |
| return str | |
| .toLowerCase() | |
| .replace(/ +/g, '-') | |
| .replace(/[^-\w]/g, ''); | |
| }; | |
| /** | |
| * Strip the function definition from `str`, | |
| * and re-indent for pre whitespace. | |
| */ | |
| exports.clean = function(str) { | |
| str = str | |
| .replace(/^function *\(.*\) *{/, '') | |
| .replace(/\s+\}$/, ''); | |
| var spaces = str.match(/^\n?( *)/)[1].length | |
| , re = new RegExp('^ {' + spaces + '}', 'gm'); | |
| str = str.replace(re, ''); | |
| return str.trim(); | |
| }; | |
| /** | |
| * Escape regular expression characters in `str`. | |
| * | |
| * @param {String} str | |
| * @return {String} | |
| * @api private | |
| */ | |
| exports.escapeRegexp = function(str){ | |
| return str.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&"); | |
| }; | |
| }); // module: utils.js | |
| /** | |
| * Node shims. | |
| * | |
| * These are meant only to allow | |
| * mocha.js to run untouched, not | |
| * to allow running node code in | |
| * the browser. | |
| */ | |
| process = {}; | |
| process.exit = function(status){}; | |
| process.stdout = {}; | |
| global = window; | |
| /** | |
| * next tick implementation. | |
| */ | |
| process.nextTick = (function(){ | |
| // postMessage behaves badly on IE8 | |
| if (window.ActiveXObject || !window.postMessage) { | |
| return function(fn){ fn() }; | |
| } | |
| // based on setZeroTimeout by David Baron | |
| // - http://dbaron.org/log/20100309-faster-timeouts | |
| var timeouts = [] | |
| , name = 'mocha-zero-timeout' | |
| window.addEventListener('message', function(e){ | |
| if (e.source == window && e.data == name) { | |
| if (e.stopPropagation) e.stopPropagation(); | |
| if (timeouts.length) timeouts.shift()(); | |
| } | |
| }, true); | |
| return function(fn){ | |
| timeouts.push(fn); | |
| window.postMessage(name, '*'); | |
| } | |
| })(); | |
| /** | |
| * Remove uncaughtException listener. | |
| */ | |
| process.removeListener = function(e){ | |
| if ('uncaughtException' == e) { | |
| window.onerror = null; | |
| } | |
| }; | |
| /** | |
| * Implements uncaughtException listener. | |
| */ | |
| process.on = function(e, fn){ | |
| if ('uncaughtException' == e) { | |
| window.onerror = fn; | |
| } | |
| }; | |
| /** | |
| * Expose mocha. | |
| */ | |
| window.mocha = require('mocha'); | |
| // boot | |
| ;(function(){ | |
| var utils = mocha.utils | |
| , options = {} | |
| mocha.suite = new mocha.Suite('', new mocha.Context()); | |
| /** | |
| * Highlight the given string of `js`. | |
| */ | |
| function highlight(js) { | |
| return js | |
| .replace(/</g, '<') | |
| .replace(/>/g, '>') | |
| .replace(/\/\/(.*)/gm, '<span class="comment">//$1</span>') | |
| .replace(/('.*?')/gm, '<span class="string">$1</span>') | |
| .replace(/(\d+\.\d+)/gm, '<span class="number">$1</span>') | |
| .replace(/(\d+)/gm, '<span class="number">$1</span>') | |
| .replace(/\bnew *(\w+)/gm, '<span class="keyword">new</span> <span class="init">$1</span>') | |
| .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '<span class="keyword">$1</span>') | |
| } | |
| /** | |
| * Highlight code contents. | |
| */ | |
| function highlightCode() { | |
| var code = document.getElementsByTagName('code'); | |
| for (var i = 0, len = code.length; i < len; ++i) { | |
| code[i].innerHTML = highlight(code[i].innerHTML); | |
| } | |
| } | |
| /** | |
| * Parse the given `qs`. | |
| */ | |
| function parse(qs) { | |
| return utils.reduce(qs.replace('?', '').split('&'), function(obj, pair){ | |
| var i = pair.indexOf('=') | |
| , key = pair.slice(0, i) | |
| , val = pair.slice(++i); | |
| obj[key] = decodeURIComponent(val); | |
| return obj; | |
| }, {}); | |
| } | |
| /** | |
| * Setup mocha with the given setting options. | |
| */ | |
| mocha.setup = function(opts){ | |
| if ('string' === typeof opts) options.ui = opts; | |
| else options = opts; | |
| ui = mocha.interfaces[options.ui]; | |
| if (!ui) throw new Error('invalid mocha interface "' + ui + '"'); | |
| if (options.timeout) mocha.suite.timeout(options.timeout); | |
| ui(mocha.suite); | |
| mocha.suite.emit('pre-require', window); | |
| }; | |
| /** | |
| * Run mocha, returning the Runner. | |
| */ | |
| mocha.run = function(fn){ | |
| mocha.suite.emit('run'); | |
| var runner = new mocha.Runner(mocha.suite); | |
| var Reporter = options.reporter || mocha.reporters.HTML; | |
| var reporter = new Reporter(runner); | |
| var query = parse(window.location.search || ""); | |
| if (query.grep) runner.grep(new RegExp(query.grep)); | |
| if (options.ignoreLeaks) runner.ignoreLeaks = true; | |
| if (options.globals) runner.globals(options.globals); | |
| runner.globals(['location']); | |
| runner.on('end', highlightCode); | |
| return runner.run(fn); | |
| }; | |
| })(); | |
| })(); |