UNPKG

ds-algo-study

Version:

Just experimenting with publishing a package

1,508 lines (1,306 loc) 620 kB
( 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 wuite. * @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' ) } );