direct-dev
Version:
Yandex Direct dev tools
2,304 lines (2,008 loc) • 423 kB
JavaScript
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
(function (process,global){
'use strict';
/* eslint no-unused-vars: off */
/* eslint-env commonjs */
/**
* Shim process.stdout.
*/
process.stdout = require('browser-stdout')();
var Mocha = require('./lib/mocha');
/**
* Create a Mocha instance.
*
* @return {undefined}
*/
var mocha = new Mocha({ reporter: 'html' });
/**
* Save timer references to avoid Sinon interfering (see GH-237).
*/
var Date = global.Date;
var setTimeout = global.setTimeout;
var setInterval = global.setInterval;
var clearTimeout = global.clearTimeout;
var clearInterval = global.clearInterval;
var uncaughtExceptionHandlers = [];
var originalOnerrorHandler = global.onerror;
/**
* Remove uncaughtException listener.
* Revert to original onerror handler if previously defined.
*/
process.removeListener = function (e, fn) {
if (e === 'uncaughtException') {
if (originalOnerrorHandler) {
global.onerror = originalOnerrorHandler;
} else {
global.onerror = function () {};
}
var i = Mocha.utils.indexOf(uncaughtExceptionHandlers, fn);
if (i !== -1) {
uncaughtExceptionHandlers.splice(i, 1);
}
}
};
/**
* Implements uncaughtException listener.
*/
process.on = function (e, fn) {
if (e === 'uncaughtException') {
global.onerror = function (err, url, line) {
fn(new Error(err + ' (' + url + ':' + line + ')'));
return !mocha.allowUncaught;
};
uncaughtExceptionHandlers.push(fn);
}
};
// The BDD UI is registered by default, but no UI will be functional in the
// browser without an explicit call to the overridden `mocha.ui` (see below).
// Ensure that this default UI does not expose its methods to the global scope.
mocha.suite.removeAllListeners('pre-require');
var immediateQueue = [];
var immediateTimeout;
function timeslice () {
var immediateStart = new Date().getTime();
while (immediateQueue.length && (new Date().getTime() - immediateStart) < 100) {
immediateQueue.shift()();
}
if (immediateQueue.length) {
immediateTimeout = setTimeout(timeslice, 0);
} else {
immediateTimeout = null;
}
}
/**
* High-performance override of Runner.immediately.
*/
Mocha.Runner.immediately = function (callback) {
immediateQueue.push(callback);
if (!immediateTimeout) {
immediateTimeout = setTimeout(timeslice, 0);
}
};
/**
* Function to allow assertion libraries to throw errors directly into mocha.
* This is useful when running tests in a browser because window.onerror will
* only receive the 'message' attribute of the Error.
*/
mocha.throwError = function (err) {
Mocha.utils.forEach(uncaughtExceptionHandlers, function (fn) {
fn(err);
});
throw err;
};
/**
* Override ui to ensure that the ui functions are initialized.
* Normally this would happen in Mocha.prototype.loadFiles.
*/
mocha.ui = function (ui) {
Mocha.prototype.ui.call(this, ui);
this.suite.emit('pre-require', global, null, this);
return this;
};
/**
* Setup mocha with the given setting options.
*/
mocha.setup = function (opts) {
if (typeof opts === 'string') {
opts = { ui: opts };
}
for (var opt in opts) {
if (opts.hasOwnProperty(opt)) {
this[opt](opts[opt]);
}
}
return this;
};
/**
* Run mocha, returning the Runner.
*/
mocha.run = function (fn) {
var options = mocha.options;
mocha.globals('location');
var query = Mocha.utils.parseQuery(global.location.search || '');
if (query.grep) {
mocha.grep(query.grep);
}
if (query.fgrep) {
mocha.fgrep(query.fgrep);
}
if (query.invert) {
mocha.invert();
}
return Mocha.prototype.run.call(mocha, function (err) {
// The DOM Document is not available in Web Workers.
var document = global.document;
if (document && document.getElementById('mocha') && options.noHighlighting !== true) {
Mocha.utils.highlightTags('code');
}
if (fn) {
fn(err);
}
});
};
/**
* Expose the process shim.
* https://github.com/mochajs/mocha/pull/916
*/
Mocha.process = process;
/**
* Expose mocha.
*/
global.Mocha = Mocha;
global.mocha = mocha;
// this allows test/acceptance/required-tokens.js to pass; thus,
// you can now do `const describe = require('mocha').describe` in a
// browser context (assuming browserification). should fix #880
module.exports = global;
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./lib/mocha":14,"_process":67,"browser-stdout":41}],2:[function(require,module,exports){
'use strict';
function noop () {}
module.exports = function () {
return noop;
};
},{}],3:[function(require,module,exports){
'use strict';
/**
* Module exports.
*/
exports.EventEmitter = EventEmitter;
/**
* Object#toString reference.
*/
var objToString = Object.prototype.toString;
/**
* Check if a value is an array.
*
* @api private
* @param {*} val The value to test.
* @return {boolean} true if the value is an array, otherwise false.
*/
function isArray (val) {
return objToString.call(val) === '[object Array]';
}
/**
* Event emitter constructor.
*
* @api public
*/
function EventEmitter () {}
/**
* Add a listener.
*
* @api public
* @param {string} name Event name.
* @param {Function} fn Event handler.
* @return {EventEmitter} Emitter instance.
*/
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
* @param {string} name Event name.
* @param {Function} fn Event handler.
* @return {EventEmitter} Emitter instance.
*/
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;
};
/**
* Remove a listener.
*
* @api public
* @param {string} name Event name.
* @param {Function} fn Event handler.
* @return {EventEmitter} Emitter instance.
*/
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;
};
/**
* Remove all listeners for an event.
*
* @api public
* @param {string} name Event name.
* @return {EventEmitter} Emitter instance.
*/
EventEmitter.prototype.removeAllListeners = function (name) {
if (name === undefined) {
this.$events = {};
return this;
}
if (this.$events && this.$events[name]) {
this.$events[name] = null;
}
return this;
};
/**
* Get all listeners for a given event.
*
* @api public
* @param {string} name Event name.
* @return {EventEmitter} Emitter instance.
*/
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];
};
/**
* Emit an event.
*
* @api public
* @param {string} name Event name.
* @return {boolean} true if at least one handler was invoked, else false.
*/
EventEmitter.prototype.emit = function (name) {
if (!this.$events) {
return false;
}
var handler = this.$events[name];
if (!handler) {
return false;
}
var args = Array.prototype.slice.call(arguments, 1);
if (typeof handler === 'function') {
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;
};
},{}],4:[function(require,module,exports){
'use strict';
/**
* 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 `size`.
*
* @api public
* @param {number} size
* @return {Progress} Progress instance.
*/
Progress.prototype.size = function (size) {
this._size = size;
return this;
};
/**
* Set text to `text`.
*
* @api public
* @param {string} text
* @return {Progress} Progress instance.
*/
Progress.prototype.text = function (text) {
this._text = text;
return this;
};
/**
* Set font size to `size`.
*
* @api public
* @param {number} size
* @return {Progress} Progress instance.
*/
Progress.prototype.fontSize = function (size) {
this._fontSize = size;
return this;
};
/**
* Set font to `family`.
*
* @param {string} family
* @return {Progress} Progress instance.
*/
Progress.prototype.font = function (family) {
this._font = family;
return this;
};
/**
* Update percentage to `n`.
*
* @param {number} n
* @return {Progress} Progress instance.
*/
Progress.prototype.update = function (n) {
this.percent = n;
return this;
};
/**
* Draw on `ctx`.
*
* @param {CanvasRenderingContext2d} ctx
* @return {Progress} Progress instance.
*/
Progress.prototype.draw = function (ctx) {
try {
var percent = Math.min(this.percent, 100);
var size = this._size;
var half = size / 2;
var x = half;
var y = half;
var rad = half - 1;
var 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) + '%';
var w = ctx.measureText(text).width;
ctx.fillText(text, x - w / 2 + 1, y + fontSize / 2 - 1);
} catch (err) {
// don't fail if we can't render progress
}
return this;
};
},{}],5:[function(require,module,exports){
(function (global){
'use strict';
exports.isatty = function isatty () {
return true;
};
exports.getWindowSize = function getWindowSize () {
if ('innerHeight' in global) {
return [global.innerHeight, global.innerWidth];
}
// In a Web Worker, the DOM Window is not available.
return [640, 480];
};
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],6:[function(require,module,exports){
'use strict';
/**
* Module dependencies.
*/
var JSON = require('json3');
/**
* Expose `Context`.
*/
module.exports = Context;
/**
* Initialize a new `Context`.
*
* @api private
*/
function Context () {}
/**
* Set or get the context `Runnable` to `runnable`.
*
* @api private
* @param {Runnable} runnable
* @return {Context}
*/
Context.prototype.runnable = function (runnable) {
if (!arguments.length) {
return this._runnable;
}
this.test = this._runnable = runnable;
return this;
};
/**
* Set test timeout `ms`.
*
* @api private
* @param {number} ms
* @return {Context} self
*/
Context.prototype.timeout = function (ms) {
if (!arguments.length) {
return this.runnable().timeout();
}
this.runnable().timeout(ms);
return this;
};
/**
* Set test timeout `enabled`.
*
* @api private
* @param {boolean} enabled
* @return {Context} self
*/
Context.prototype.enableTimeouts = function (enabled) {
this.runnable().enableTimeouts(enabled);
return this;
};
/**
* Set test slowness threshold `ms`.
*
* @api private
* @param {number} ms
* @return {Context} self
*/
Context.prototype.slow = function (ms) {
this.runnable().slow(ms);
return this;
};
/**
* Mark a test as skipped.
*
* @api private
* @return {Context} self
*/
Context.prototype.skip = function () {
this.runnable().skip();
return this;
};
/**
* Allow a number of retries on failed tests
*
* @api private
* @param {number} n
* @return {Context} self
*/
Context.prototype.retries = function (n) {
if (!arguments.length) {
return this.runnable().retries();
}
this.runnable().retries(n);
return this;
};
/**
* Inspect the context void of `._runnable`.
*
* @api private
* @return {string}
*/
Context.prototype.inspect = function () {
return JSON.stringify(this, function (key, val) {
return key === 'runnable' || key === 'test' ? undefined : val;
}, 2);
};
},{"json3":54}],7:[function(require,module,exports){
'use strict';
/**
* Module dependencies.
*/
var Runnable = require('./runnable');
var inherits = require('./utils').inherits;
/**
* 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`.
*/
inherits(Hook, Runnable);
/**
* Get or set the test `err`.
*
* @param {Error} err
* @return {Error}
* @api public
*/
Hook.prototype.error = function (err) {
if (!arguments.length) {
err = this._error;
this._error = null;
return err;
}
this._error = err;
};
},{"./runnable":33,"./utils":38}],8:[function(require,module,exports){
'use strict';
/**
* Module dependencies.
*/
var 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() {
* // ...
* });
* });
* });
*
* @param {Suite} suite Root suite.
*/
module.exports = function (suite) {
var suites = [suite];
suite.on('pre-require', function (context, file, mocha) {
var common = require('./common')(suites, context, mocha);
context.before = common.before;
context.after = common.after;
context.beforeEach = common.beforeEach;
context.afterEach = common.afterEach;
context.run = mocha.options.delay && common.runWithSuite(suite);
/**
* Describe a "suite" with the given `title`
* and callback `fn` containing nested suites
* and/or tests.
*/
context.describe = context.context = function (title, fn) {
return common.suite.create({
title: title,
file: file,
fn: fn
});
};
/**
* Pending describe.
*/
context.xdescribe = context.xcontext = context.describe.skip = function (title, fn) {
return common.suite.skip({
title: title,
file: file,
fn: fn
});
};
/**
* Exclusive suite.
*/
context.describe.only = function (title, fn) {
return common.suite.only({
title: title,
file: file,
fn: fn
});
};
/**
* Describe a specification or test-case
* with the given `title` and callback `fn`
* acting as a thunk.
*/
context.it = context.specify = function (title, fn) {
var suite = suites[0];
if (suite.isPending()) {
fn = null;
}
var test = new Test(title, fn);
test.file = file;
suite.addTest(test);
return test;
};
/**
* Exclusive test-case.
*/
context.it.only = function (title, fn) {
return common.test.only(mocha, context.it(title, fn));
};
/**
* Pending test case.
*/
context.xit = context.xspecify = context.it.skip = function (title) {
context.it(title);
};
/**
* Number of attempts to retry.
*/
context.it.retries = function (n) {
context.retries(n);
};
});
};
},{"../test":36,"./common":9}],9:[function(require,module,exports){
'use strict';
var Suite = require('../suite');
/**
* Functions common to more than one interface.
*
* @param {Suite[]} suites
* @param {Context} context
* @param {Mocha} mocha
* @return {Object} An object containing common functions.
*/
module.exports = function (suites, context, mocha) {
return {
/**
* This is only present if flag --delay is passed into Mocha. It triggers
* root suite execution.
*
* @param {Suite} suite The root suite.
* @return {Function} A function which runs the root suite
*/
runWithSuite: function runWithSuite (suite) {
return function run () {
suite.run();
};
},
/**
* Execute before running tests.
*
* @param {string} name
* @param {Function} fn
*/
before: function (name, fn) {
suites[0].beforeAll(name, fn);
},
/**
* Execute after running tests.
*
* @param {string} name
* @param {Function} fn
*/
after: function (name, fn) {
suites[0].afterAll(name, fn);
},
/**
* Execute before each test case.
*
* @param {string} name
* @param {Function} fn
*/
beforeEach: function (name, fn) {
suites[0].beforeEach(name, fn);
},
/**
* Execute after each test case.
*
* @param {string} name
* @param {Function} fn
*/
afterEach: function (name, fn) {
suites[0].afterEach(name, fn);
},
suite: {
/**
* Create an exclusive Suite; convenience function
* See docstring for create() below.
*
* @param {Object} opts
* @returns {Suite}
*/
only: function only (opts) {
mocha.options.hasOnly = true;
opts.isOnly = true;
return this.create(opts);
},
/**
* Create a Suite, but skip it; convenience function
* See docstring for create() below.
*
* @param {Object} opts
* @returns {Suite}
*/
skip: function skip (opts) {
opts.pending = true;
return this.create(opts);
},
/**
* Creates a suite.
* @param {Object} opts Options
* @param {string} opts.title Title of Suite
* @param {Function} [opts.fn] Suite Function (not always applicable)
* @param {boolean} [opts.pending] Is Suite pending?
* @param {string} [opts.file] Filepath where this Suite resides
* @param {boolean} [opts.isOnly] Is Suite exclusive?
* @returns {Suite}
*/
create: function create (opts) {
var suite = Suite.create(suites[0], opts.title);
suite.pending = Boolean(opts.pending);
suite.file = opts.file;
suites.unshift(suite);
if (opts.isOnly) {
suite.parent._onlySuites = suite.parent._onlySuites.concat(suite);
mocha.options.hasOnly = true;
}
if (typeof opts.fn === 'function') {
opts.fn.call(suite);
suites.shift();
} else if (typeof opts.fn === 'undefined' && !suite.pending) {
throw new Error('Suite "' + suite.fullTitle() + '" was defined but no callback was supplied. Supply a callback or explicitly skip the suite.');
}
return suite;
}
},
test: {
/**
* Exclusive test-case.
*
* @param {Object} mocha
* @param {Function} test
* @returns {*}
*/
only: function (mocha, test) {
test.parent._onlyTests = test.parent._onlyTests.concat(test);
mocha.options.hasOnly = true;
return test;
},
/**
* Pending test case.
*
* @param {string} title
*/
skip: function (title) {
context.test(title);
},
/**
* Number of retry attempts
*
* @param {number} n
*/
retries: function (n) {
context.retries(n);
}
}
};
};
},{"../suite":35}],10:[function(require,module,exports){
'use strict';
/**
* Module dependencies.
*/
var Suite = require('../suite');
var Test = require('../test');
/**
* Exports-style (as Node.js module) 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() {
*
* }
* }
* };
*
* @param {Suite} suite Root suite.
*/
module.exports = function (suite) {
var suites = [suite];
suite.on('require', visit);
function visit (obj, file) {
var suite;
for (var key in obj) {
if (typeof obj[key] === 'function') {
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:
var test = new Test(key, fn);
test.file = file;
suites[0].addTest(test);
}
} else {
suite = Suite.create(suites[0], key);
suites.unshift(suite);
visit(obj[key], file);
suites.shift();
}
}
}
};
},{"../suite":35,"../test":36}],11:[function(require,module,exports){
'use strict';
exports.bdd = require('./bdd');
exports.tdd = require('./tdd');
exports.qunit = require('./qunit');
exports.exports = require('./exports');
},{"./bdd":8,"./exports":10,"./qunit":12,"./tdd":13}],12:[function(require,module,exports){
'use strict';
/**
* Module dependencies.
*/
var 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);
* });
*
* @param {Suite} suite Root suite.
*/
module.exports = function (suite) {
var suites = [suite];
suite.on('pre-require', function (context, file, mocha) {
var common = require('./common')(suites, context, mocha);
context.before = common.before;
context.after = common.after;
context.beforeEach = common.beforeEach;
context.afterEach = common.afterEach;
context.run = mocha.options.delay && common.runWithSuite(suite);
/**
* Describe a "suite" with the given `title`.
*/
context.suite = function (title) {
if (suites.length > 1) {
suites.shift();
}
return common.suite.create({
title: title,
file: file,
fn: false
});
};
/**
* Exclusive Suite.
*/
context.suite.only = function (title) {
if (suites.length > 1) {
suites.shift();
}
return common.suite.only({
title: title,
file: file,
fn: false
});
};
/**
* Describe a specification or test-case
* with the given `title` and callback `fn`
* acting as a thunk.
*/
context.test = function (title, fn) {
var test = new Test(title, fn);
test.file = file;
suites[0].addTest(test);
return test;
};
/**
* Exclusive test-case.
*/
context.test.only = function (title, fn) {
return common.test.only(mocha, context.test(title, fn));
};
context.test.skip = common.test.skip;
context.test.retries = common.test.retries;
});
};
},{"../test":36,"./common":9}],13:[function(require,module,exports){
'use strict';
/**
* Module dependencies.
*/
var 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() {
*
* });
* });
* });
*
* @param {Suite} suite Root suite.
*/
module.exports = function (suite) {
var suites = [suite];
suite.on('pre-require', function (context, file, mocha) {
var common = require('./common')(suites, context, mocha);
context.setup = common.beforeEach;
context.teardown = common.afterEach;
context.suiteSetup = common.before;
context.suiteTeardown = common.after;
context.run = mocha.options.delay && common.runWithSuite(suite);
/**
* Describe a "suite" with the given `title` and callback `fn` containing
* nested suites and/or tests.
*/
context.suite = function (title, fn) {
return common.suite.create({
title: title,
file: file,
fn: fn
});
};
/**
* Pending suite.
*/
context.suite.skip = function (title, fn) {
return common.suite.skip({
title: title,
file: file,
fn: fn
});
};
/**
* Exclusive test-case.
*/
context.suite.only = function (title, fn) {
return common.suite.only({
title: title,
file: file,
fn: fn
});
};
/**
* Describe a specification or test-case with the given `title` and
* callback `fn` acting as a thunk.
*/
context.test = function (title, fn) {
var suite = suites[0];
if (suite.isPending()) {
fn = null;
}
var test = new Test(title, fn);
test.file = file;
suite.addTest(test);
return test;
};
/**
* Exclusive test-case.
*/
context.test.only = function (title, fn) {
return common.test.only(mocha, context.test(title, fn));
};
context.test.skip = common.test.skip;
context.test.retries = common.test.retries;
});
};
},{"../test":36,"./common":9}],14:[function(require,module,exports){
(function (process,global,__dirname){
'use strict';
/*!
* mocha
* Copyright(c) 2011 TJ Holowaychuk <tj@vision-media.ca>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var escapeRe = require('escape-string-regexp');
var path = require('path');
var reporters = require('./reporters');
var utils = require('./utils');
/**
* Expose `Mocha`.
*/
exports = module.exports = Mocha;
/**
* To require local UIs and reporters when running in node.
*/
if (!process.browser) {
var cwd = process.cwd();
module.paths.push(cwd, path.join(cwd, 'node_modules'));
}
/**
* Expose internals.
*/
exports.utils = utils;
exports.interfaces = require('./interfaces');
exports.reporters = 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.
*
* @api private
* @param {string} name
* @return {string}
*/
function image (name) {
return path.join(__dirname, '../images', name + '.png');
}
/**
* Set up mocha with `options`.
*
* Options:
*
* - `ui` name "bdd", "tdd", "exports" etc
* - `reporter` reporter instance, defaults to `mocha.reporters.spec`
* - `globals` array of accepted globals
* - `timeout` timeout in milliseconds
* - `retries` number of times to retry failed tests
* - `bail` bail on the first test failure
* - `slow` milliseconds to wait before considering a test slow
* - `ignoreLeaks` ignore global leaks
* - `fullTrace` display the full stack-trace on failing
* - `grep` string or regexp to filter tests with
*
* @param {Object} options
* @api public
*/
function Mocha (options) {
options = options || {};
this.files = [];
this.options = options;
if (options.grep) {
this.grep(new RegExp(options.grep));
}
if (options.fgrep) {
this.fgrep(options.fgrep);
}
this.suite = new exports.Suite('', new exports.Context());
this.ui(options.ui);
this.bail(options.bail);
this.reporter(options.reporter, options.reporterOptions);
if (typeof options.timeout !== 'undefined' && options.timeout !== null) {
this.timeout(options.timeout);
}
if (typeof options.retries !== 'undefined' && options.retries !== null) {
this.retries(options.retries);
}
this.useColors(options.useColors);
if (options.enableTimeouts !== null) {
this.enableTimeouts(options.enableTimeouts);
}
if (options.slow) {
this.slow(options.slow);
}
}
/**
* Enable or disable bailing on the first failure.
*
* @api public
* @param {boolean} [bail]
*/
Mocha.prototype.bail = function (bail) {
if (!arguments.length) {
bail = true;
}
this.suite.bail(bail);
return this;
};
/**
* Add test `file`.
*
* @api public
* @param {string} file
*/
Mocha.prototype.addFile = function (file) {
this.files.push(file);
return this;
};
/**
* Set reporter to `reporter`, defaults to "spec".
*
* @param {String|Function} reporter name or constructor
* @param {Object} reporterOptions optional options
* @api public
* @param {string|Function} reporter name or constructor
* @param {Object} reporterOptions optional options
*/
Mocha.prototype.reporter = function (reporter, reporterOptions) {
if (typeof reporter === 'function') {
this._reporter = reporter;
} else {
reporter = reporter || 'spec';
var _reporter;
// Try to load a built-in reporter.
if (reporters[reporter]) {
_reporter = reporters[reporter];
}
// Try to load reporters from process.cwd() and node_modules
if (!_reporter) {
try {
_reporter = require(reporter);
} catch (err) {
err.message.indexOf('Cannot find module') !== -1
? console.warn('"' + reporter + '" reporter not found')
: console.warn('"' + reporter + '" reporter blew up with error:\n' + err.stack);
}
}
if (!_reporter && reporter === 'teamcity') {
console.warn('The Teamcity reporter was moved to a package named ' +
'mocha-teamcity-reporter ' +
'(https://npmjs.org/package/mocha-teamcity-reporter).');
}
if (!_reporter) {
throw new Error('invalid reporter "' + reporter + '"');
}
this._reporter = _reporter;
}
this.options.reporterOptions = reporterOptions;
return this;
};
/**
* Set test UI `name`, defaults to "bdd".
*
* @api public
* @param {string} bdd
*/
Mocha.prototype.ui = function (name) {
name = name || 'bdd';
this._ui = exports.interfaces[name];
if (!this._ui) {
try {
this._ui = require(name);
} catch (err) {
throw new Error('invalid interface "' + name + '"');
}
}
this._ui = this._ui(this.suite);
this.suite.on('pre-require', function (context) {
exports.afterEach = context.afterEach || context.teardown;
exports.after = context.after || context.suiteTeardown;
exports.beforeEach = context.beforeEach || context.setup;
exports.before = context.before || context.suiteSetup;
exports.describe = context.describe || context.suite;
exports.it = context.it || context.test;
exports.setup = context.setup || context.beforeEach;
exports.suiteSetup = context.suiteSetup || context.before;
exports.suiteTeardown = context.suiteTeardown || context.after;
exports.suite = context.suite || context.describe;
exports.teardown = context.teardown || context.afterEach;
exports.test = context.test || context.it;
exports.run = context.run;
});
return this;
};
/**
* Load registered files.
*
* @api private
*/
Mocha.prototype.loadFiles = function (fn) {
var self = this;
var suite = this.suite;
this.files.forEach(function (file) {
file = path.resolve(file);
suite.emit('pre-require', global, file, self);
suite.emit('require', require(file), file, self);
suite.emit('post-require', global, file, self);
});
fn && fn();
};
/**
* 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')
});
}
});
};
/**
* Escape string and add it to grep as a regexp.
*
* @api public
* @param str
* @returns {Mocha}
*/
Mocha.prototype.fgrep = function (str) {
return this.grep(new RegExp(escapeRe(str)));
};
/**
* Add regexp to grep, if `re` is a string it is escaped.
*
* @param {RegExp|String} re
* @return {Mocha}
* @api public
* @param {RegExp|string} re
* @return {Mocha}
*/
Mocha.prototype.grep = function (re) {
if (utils.isString(re)) {
// extract args if it's regex-like, i.e: [string, pattern, flag]
var arg = re.match(/^\/(.*)\/(g|i|)$|.*/);
this.options.grep = new RegExp(arg[1] || arg[0], arg[2]);
} else {
this.options.grep = re;
}
return this;
};
/**
* Invert `.grep()` matches.
*
* @return {Mocha}
* @api public
*/
Mocha.prototype.invert = function () {
this.options.invert = true;
return this;
};
/**
* Ignore global leaks.
*
* @param {Boolean} ignore
* @return {Mocha}
* @api public
* @param {boolean} ignore
* @return {Mocha}
*/
Mocha.prototype.ignoreLeaks = function (ignore) {
this.options.ignoreLeaks = Boolean(ignore);
return this;
};
/**
* Enable global leak checking.
*
* @return {Mocha}
* @api public
*/
Mocha.prototype.checkLeaks = function () {
this.options.ignoreLeaks = false;
return this;
};
/**
* Display long stack-trace on failing
*
* @return {Mocha}
* @api public
*/
Mocha.prototype.fullTrace = function () {
this.options.fullStackTrace = true;
return this;
};
/**
* Enable growl support.
*
* @return {Mocha}
* @api public
*/
Mocha.prototype.growl = function () {
this.options.growl = true;
return this;
};
/**
* Ignore `globals` array or string.
*
* @param {Array|String} globals
* @return {Mocha}
* @api public
* @param {Array|string} globals
* @return {Mocha}
*/
Mocha.prototype.globals = function (globals) {
this.options.globals = (this.options.globals || []).concat(globals);
return this;
};
/**
* Emit color output.
*
* @param {Boolean} colors
* @return {Mocha}
* @api public
* @param {boolean} colors
* @return {Mocha}
*/
Mocha.prototype.useColors = function (colors) {
if (colors !== undefined) {
this.options.useColors = colors;
}
return this;
};
/**
* Use inline diffs rather than +/-.
*
* @param {Boolean} inlineDiffs
* @return {Mocha}
* @api public
* @param {boolean} inlineDiffs
* @return {Mocha}
*/
Mocha.prototype.useInlineDiffs = function (inlineDiffs) {
this.options.useInlineDiffs = inlineDiffs !== undefined && inlineDiffs;
return this;
};
/**
* Set the timeout in milliseconds.
*
* @param {Number} timeout
* @return {Mocha}
* @api public
* @param {number} timeout
* @return {Mocha}
*/
Mocha.prototype.timeout = function (timeout) {
this.suite.timeout(timeout);
return this;
};
/**
* Set the number of times to retry failed tests.
*
* @param {Number} retry times
* @return {Mocha}
* @api public
*/
Mocha.prototype.retries = function (n) {
this.suite.retries(n);
return this;
};
/**
* Set slowness threshold in milliseconds.
*
* @param {Number} slow
* @return {Mocha}
* @api public
* @param {number} slow
* @return {Mocha}
*/
Mocha.prototype.slow = function (slow) {
this.suite.slow(slow);
return this;
};
/**
* Enable timeouts.
*
* @param {Boolean} enabled
* @return {Mocha}
* @api public
* @param {boolean} enabled
* @return {Mocha}
*/
Mocha.prototype.enableTimeouts = function (enabled) {
this.suite.enableTimeouts(arguments.length && enabled !== undefined ? enabled : true);
return this;
};
/**
* Makes all tests async (accepting a callback)
*
* @return {Mocha}
* @api public
*/
Mocha.prototype.asyncOnly = function () {
this.options.asyncOnly = true;
return this;
};
/**
* Disable syntax highlighting (in browser).
*
* @api public
*/
Mocha.prototype.noHighlighting = function () {
this.options.noHighlighting = true;
return this;
};
/**
* Enable uncaught errors to propagate (in browser).
*
* @return {Mocha}
* @api public
*/
Mocha.prototype.allowUncaught = function () {
this.options.allowUncaught = true;
return this;
};
/**
* Delay root suite execution.
* @returns {Mocha}
*/
Mocha.prototype.delay = function delay () {
this.options.delay = true;
return this;
};
/**
* Run tests and invoke `fn()` when complete.
*
* @api public
* @param {Function} fn
* @return {Runner}
*/
Mocha.prototype.run = function (fn) {
if (this.files.length) {
this.loadFiles();
}
var suite = this.suite;
var options = this.options;
options.files = this.files;
var runner = new exports.Runner(suite, options.delay);
var reporter = new this._reporter(runner, options);
runner.ignoreLeaks = options.ignoreLeaks !== false;
runner.fullStackTrace = options.fullStackTrace;
runner.hasOnly = options.hasOnly;
runner.asyncOnly = options.asyncOnly;
runner.allowUncaught = options.allowUncaught;
if (options.grep) {
runner.grep(options.grep, options.invert);
}
if (options.globals) {
runner.globals(options.globals);
}
if (options.growl) {
this._growl(runner, reporter);
}
if (options.useColors !== undefined) {
exports.reporters.Base.useColors = options.useColors;
}
exports.reporters.Base.inlineDiffs = options.useInlineDiffs;
function done (failures) {
if (reporter.done) {
reporter.done(failures, fn);
} else {
fn && fn(failures);
}
}
return runner.run(done);
};
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},"/lib")
},{"./context":6,"./hook":7,"./interfaces":11,"./reporters":21,"./runnable":33,"./runner":34,"./suite":35,"./test":36,"./utils":38,"_process":67,"escape-string-regexp":47,"growl":49,"path":42}],15:[function(require,module,exports){
'use strict';
/**
* Helpers.
*/
var s = 1000;
var m = s * 60;
var h = m * 60;
var d = h * 24;
var y = d * 365.25;
/**
* Parse or format the given `val`.
*
* Options:
*
* - `long` verbose formatting [false]
*
* @api public
* @param {string|number} val
* @param {Object} options
* @return {string|number}
*/
module.exports = function (val, options) {
options = options || {};
if (typeof val === 'string') {
return parse(val);
}
// https://github.com/mochajs/mocha/pull/1035
return options['long'] ? longFormat(val) : shortFormat(val);
};
/**
* Parse the given `str` and return milliseconds.
*
* @api private
* @param {string} str
* @return {number}
*/
function parse (str) {
var match = (/^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i).exec(str);
if (!match) {
return;
}
var n = parseFloat(match[1]);
var type = (match[2] || 'ms').toLowerCase();
switch (type) {
case 'years':
case 'year':
case 'y':
return n * y;
case 'days':
case 'day':
case 'd':
return n * d;
case 'hours':
case 'hour':
case 'h':
return n * h;
case 'minutes':
case 'minute':
case 'm':
return n * m;
case 'seconds':
case 'second':
case 's':
return n * s;
case 'ms':
return n;
default:
// No default case
}
}
/**
* Short format for `ms`.
*
* @api private
* @param {number} ms
* @return {string}
*/
function shortFormat (ms) {
if (ms >= d) {
return Math.round(ms / d) + 'd';
}
if (ms >= h) {
return Math.round(ms / h) + 'h';
}
if (ms >= m) {
return Math.round(ms / m) + 'm';
}
if (ms >= s) {
return Math.round(ms / s) + 's';
}
return ms + 'ms';
}
/**
* Long format for `ms`.
*
* @api private
* @param {number} ms
* @return {string}
*/
function longFormat (ms) {
return plural(ms, d, 'day') ||
plural(ms, h, 'hour') ||
plural(ms, m, 'minute') ||
plural(ms, s, 'second') ||
ms + ' ms';
}
/**
* Pluralization helper.
*
* @api private
* @param {number} ms
* @param {number} n
* @param {string} name
*/
function plural (ms, n, name) {
if (ms < n) {
return;
}
if (ms < n * 1.5) {
return Math.floor(ms / n) + ' ' + name;
}
return Math.ceil(ms / n) + ' ' + name + 's';
}
},{}],16:[function(require,module,exports){
'use strict';
/**
* Expose `Pending`.
*/
module.exports = Pending;
/**
* Initialize a new `Pending` error with the given message.
*
* @param {string} message
*/
function Pending (message) {
this.message = message;
}
},{}],17:[function(require,module,exports){
(function (process,global){
'use strict';
/**
* Module dependencies.
*/
var tty = require('tty');
var diff = require('diff');
var ms = require('../ms');
var utils = require('../utils');
var supportsColor = process.browser ? null : require('supports-color');
/**
* Expose `Base`.
*/
exports = module.exports = Base;
/**
* Save timer references to avoid Sinon interfering.
* See: https://github.com/mochajs/mocha/issues/237
*/
/* eslint-disable no-unused-vars, no-native-reassign */
var Date = global.Date;
var setTimeout = global.setTimeout;
var setInterval = global.setInterval;
var clearTimeout = global.clearTimeout;
var clearInterval = global.clearInterval;
/* eslint-enable no-unused-vars, no-native-reassign */
/**
* Check if both stdio streams are associated with a tty.
*/
var isatty = tty.isatty(1) && tty.isatty(2);
/**
* Enable coloring by default, except in the browser interface.
*/
exports.useColors = !process.browser && (supportsColor || (process.env.MOCHA_COLORS !== undefined));
/**
* Inline diffs instead of +/-
*/
exports.inlineDiffs = false;
/**
* 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': 32,
'diff removed': 31
};
/**
* Default symbol map.
*/
exports.symbols = {
ok: '✓',
err: '✖',
dot: '․',
comma: ',',
bang: '!'
};
// With node.js on Windows: use symbols available in terminal default fonts
if (process.platform === 'win32') {
exports.symbols.ok = '\u221A';
exports.symbols.err = '\u00D7';
exports.symbols.dot = '.';
}
/**
* 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 String(str);
}
return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m';
};
/**
* Expose term window size, with some defaults for when stderr is not a tty.
*/
exports.window = {
width: 75
};
if (isatty) {
exports.window.width = process.stdout.getWindowSize
? process.stdout.getWindowSize(1)[0]
: tty.getWindowSize()[1];
}
/**
* Expose some basic cursor interactions that are common among reporters.
*/
exports.cursor = {
hide: function () {
isatty && process.stdout.write('\u001b[?25l');
},
show: function () {
isatty && process.stdout.write('\u001b[?25h');
},
deleteLine: function () {
isatty && process.stdout.write('\u001b[2K');
},
beginningOfLine: function () {
isatty && process.stdout.write('\u001b[0G');
},
CR: function () {
if (isatty) {
exports.cursor.deleteLine();
exports.cursor.beginningOfLine();
} else {
process.stdout.write('\r');
}
}
};
/**
* Outut the given `failures` as a list.
*
* @param {Array} failures
* @api public
*/
exports.list = function (failures) {
console.log();
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 msg;
var err = test.err;
var message;
if (err.message && typeof err.message.toString === 'function') {
message = err.message + '';
} else if (typeof err.inspect === 'function') {
message = err.inspect() + '';
} else {
message = '';
}
var stack = err.stack || message;
var index = message ? stack.indexOf(message) : -1;
var actual = err.actual;
var expected = err.expected;
var escape = true;
if (index === -1) {
msg = message;
} else {
index += message.length;
msg = stack.slice(0, index);
// remove msg from stack
stack = stack.slice(index + 1);
}
// uncaught
if (err.uncaught) {
msg = 'Uncaught ' + msg;
}
// explicitly show diff
if (err.showDiff !== false && sameType(actual, expected) && expected !== undefined) {
escape = false;
if (!(utils.isString(actual) && utils.isString(expected))) {
err.actual = actual = utils.stringify(actual);
err.expected = expected = utils.stringify(expected);
}
fmt = color('error title', ' %s) %s:\n%s') + color('error stack', '\n%s\n');
var match = message.match(/^([^:]+): expected/);
msg = '\n ' + color('error message', match ? match[1] : msg);
if (exports.inlineDiffs) {
msg += inlineDiff(err, escape);
} else {
msg += unifiedDiff(err, escape);
}
}
// indent stack trace
stack = stack.replace(/^/gm, ' ');
console.log(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 stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 };
var failures = this.failures = [];
if (!runner) {
return;
}
this.runner = runner;
runner.stats = stats;
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 () {
stats.tests = stats.tests || 0;
stats.tests++;
});
runner.on('pass', function (test) {
stats.passes = stats.passes || 0;
if (test.duration > test.slow()) {
test.speed = 'slow';
} else if (test.duration > test.slow() / 2) {
test.speed = 'medium';
} else {
test.speed = '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;
var fmt;
console.log();
// passes
fmt = color('bright pass', ' ') +
color('green', ' %d passing') +
color('light', ' (%s)');
console.log(fmt,
stats.passes || 0,
ms(stats.duration));
// pending
if (stats.pending) {
fmt = color('pending', ' ') +
color('pending', ' %d pending');
console.log(fmt, stats.pending);
}
// failures
if (stats.failures) {
fmt = color('fail', ' %d failing');
console.log(fmt, stats.failures);
Base.list(this.failures);
console.log();
}
console.log();
};
/**
* Pad the given `str` to `len`.
*
* @api private
* @param {string} str
* @param {string} len
* @return {string}
*/
function pad (str, len) {
str = String(str);
return Array(len - str.length + 1).join(' ') + str;
}
/**
* Returns an inline diff between 2 strings with coloured ANSI output
*
* @api private
* @param {Error} err with actual/expected
* @param {boolean} escape
* @return {string} Diff
*/
function inlineDiff (err, escape) {
var msg = errorDiff(err, 'WordsWithSpace', escape);
// linenos
var lines = msg.split('\n');
if (lines.length > 4) {
var width = String(lines.length).length;
msg = lines.map(function (str, i) {
return pad(+