/*! * should - test framework agnostic BDD-style assertions * @version v7.1.1 * @author TJ Holowaychuk and contributors * @link https://github.com/shouldjs/should.js * @license MIT */ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Should = f()}})(function(){var define,module,exports;return (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= 0) { // once we have located the function frame // we need to strip out everything before it (and its line) var next_line = out.indexOf('\n', idx + 1); out = out.substring(next_line + 1); } } this.stack = out; } } }; var indent = ' '; function prependIndent(line) { return indent + line; } function indentLines(text) { return text.split('\n').map(prependIndent).join('\n'); } // assert.AssertionError instanceof Error AssertionError.prototype = Object.create(Error.prototype, { name: { value: 'AssertionError' }, generateMessage: { value: function() { if(!this.operator && this.previous) { return this.previous.message; } var actual = util.format(this.actual); var expected = 'expected' in this ? ' ' + util.format(this.expected) : ''; var details = 'details' in this && this.details ? ' (' + this.details + ')' : ''; var previous = this.previous ? '\n' + indentLines(this.previous.message) : ''; return 'expected ' + actual + (this.negate ? ' not ' : ' ') + this.operator + expected + details + previous; } } }); module.exports = AssertionError; },{"./util":18}],3:[function(require,module,exports){ var AssertionError = require('./assertion-error'); var util = require('./util'); /** * should Assertion * @param {*} obj Given object for assertion * @constructor * @memberOf should * @static */ function Assertion(obj) { this.obj = obj; this.anyOne = false; this.negate = false; this.params = {actual: obj}; } /** * Way to extend Assertion function. It uses some logic * to define only positive assertions and itself rule with negative assertion. * * All actions happen in subcontext and this method take care about negation. * Potentially we can add some more modifiers that does not depends from state of assertion. * @memberOf Assertion * @category assertion * @static * @param {String} name Name of assertion. It will be used for defining method or getter on Assertion.prototype * @param {Function} func Function that will be called on executing assertion * @example * * Assertion.add('asset', function() { * this.params = { operator: 'to be asset' }; * * this.obj.should.have.property('id').which.is.a.Number(); * this.obj.should.have.property('path'); * }); */ Assertion.add = function(name, func) { var prop = {enumerable: true, configurable: true}; prop.value = function() { var context = new Assertion(this.obj, this, name); context.anyOne = this.anyOne; try { func.apply(context, arguments); } catch(e) { //check for fail if(e instanceof AssertionError) { //negative fail if(this.negate) { this.obj = context.obj; this.negate = false; return this; } if(context !== e.assertion) { context.params.previous = e; } //positive fail context.negate = false; context.fail(); } // throw if it is another exception throw e; } //negative pass if(this.negate) { context.negate = true;//because .fail will set negate context.params.details = 'false negative fail'; context.fail(); } //positive pass if(!this.params.operator) this.params = context.params;//shortcut this.obj = context.obj; this.negate = false; return this; }; Object.defineProperty(Assertion.prototype, name, prop); }; Assertion.addChain = function(name, onCall) { onCall = onCall || function() { }; Object.defineProperty(Assertion.prototype, name, { get: function() { onCall(); return this; }, enumerable: true }); }; /** * Create alias for some `Assertion` property * * @memberOf Assertion * @category assertion * @static * @param {String} from Name of to map * @param {String} to Name of alias * @example * * Assertion.alias('true', 'True'); */ Assertion.alias = function(from, to) { var desc = Object.getOwnPropertyDescriptor(Assertion.prototype, from); if(!desc) throw new Error('Alias ' + from + ' -> ' + to + ' could not be created as ' + from + ' not defined'); Object.defineProperty(Assertion.prototype, to, desc); }; Assertion.prototype = { constructor: Assertion, /** * Base method for assertions. Before calling this method need to fill Assertion#params object. This method usually called from other assertion methods. * `Assertion#params` can contain such properties: * * `operator` - required string containing description of this assertion * * `obj` - optional replacement for this.obj, it usefull if you prepare more clear object then given * * `message` - if this property filled with string any others will be ignored and this one used as assertion message * * `expected` - any object used when you need to assert relation between given object and expected. Like given == expected (== is a relation) * * `details` - additional string with details to generated message * * @memberOf Assertion * @category assertion * @param {*} expr Any expression that will be used as a condition for asserting. * @example * * var a = new should.Assertion(42); * * a.params = { * operator: 'to be magic number', * } * * a.assert(false); * //throws AssertionError: expected 42 to be magic number */ assert: function(expr) { if(expr) return this; var params = this.params; if('obj' in params && !('actual' in params)) { params.actual = params.obj; } else if(!('obj' in params) && !('actual' in params)) { params.actual = this.obj; } params.stackStartFunction = params.stackStartFunction || this.assert; params.negate = this.negate; params.assertion = this; throw new AssertionError(params); }, /** * Shortcut for `Assertion#assert(false)`. * * @memberOf Assertion * @category assertion * @example * * var a = new should.Assertion(42); * * a.params = { * operator: 'to be magic number', * } * * a.fail(); * //throws AssertionError: expected 42 to be magic number */ fail: function() { return this.assert(false); }, /** * Negation modifier. Current assertion chain become negated. Each call invert negation on current assertion. * * @memberOf Assertion * @category assertion */ get not() { this.negate = !this.negate; return this; }, /** * Any modifier - it affect on execution of sequenced assertion to do not `check all`, but `check any of`. * * @memberOf Assertion * @category assertion */ get any() { this.anyOne = true; return this; } }; module.exports = Assertion; },{"./assertion-error":2,"./util":18}],4:[function(require,module,exports){ var Formatter = require('should-format').Formatter; var config = { checkProtoEql: false, getFormatter: function(opts) { return new Formatter(opts || config); } }; module.exports = config; },{"should-format":21}],5:[function(require,module,exports){ // implement assert interface using already written peaces of should.js // http://wiki.commonjs.org/wiki/Unit_Testing/1.0 // // THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! // // Originally from narwhal.js (http://narwhaljs.org) // Copyright (c) 2009 Thomas Robinson <280north.com> // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the 'Software'), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // when used in node, this will actually load the util module we depend on // versus loading the builtin util module as happens otherwise // this is a bug in node module loading as far as I am concerned var Assertion = require('./../assertion'); var _deepEqual = require('should-equal'); var pSlice = Array.prototype.slice; // 1. The assert module provides functions that throw // AssertionError's when particular conditions are not met. The // assert module must conform to the following interface. var assert = module.exports = ok; // 3. All of the following functions must throw an AssertionError // when a corresponding condition is not met, with a message that // may be undefined if not provided. All assertion methods provide // both the actual and expected values to the assertion error for // display purposes. /** * Node.js standard [`assert.fail`](http://nodejs.org/api/assert.html#assert_assert_fail_actual_expected_message_operator). * @static * @memberOf should * @category assertion assert * @param {*} actual Actual object * @param {*} expected Expected object * @param {string} message Message for assertion * @param {string} operator Operator text */ function fail(actual, expected, message, operator, stackStartFunction) { var a = new Assertion(actual); a.params = { operator: operator, expected: expected, message: message, stackStartFunction: stackStartFunction || fail }; a.fail(); } // EXTENSION! allows for well behaved errors defined elsewhere. assert.fail = fail; // 4. Pure assertion tests whether a value is truthy, as determined // by !!guard. // assert.ok(guard, message_opt); // This statement is equivalent to assert.equal(true, !!guard, // message_opt);. To test strictly for the value true, use // assert.strictEqual(true, guard, message_opt);. /** * Node.js standard [`assert.ok`](http://nodejs.org/api/assert.html#assert_assert_value_message_assert_ok_value_message). * @static * @memberOf should * @category assertion assert * @param {*} value * @param {string} [message] */ function ok(value, message) { if(!value) fail(value, true, message, '==', assert.ok); } assert.ok = ok; // 5. The equality assertion tests shallow, coercive equality with // ==. // assert.equal(actual, expected, message_opt); /** * Node.js standard [`assert.equal`](http://nodejs.org/api/assert.html#assert_assert_equal_actual_expected_message). * @static * @memberOf should * @category assertion assert * @param {*} actual * @param {*} expected * @param {string} [message] */ assert.equal = function equal(actual, expected, message) { if(actual != expected) fail(actual, expected, message, '==', assert.equal); }; // 6. The non-equality assertion tests for whether two objects are not equal // with != assert.notEqual(actual, expected, message_opt); /** * Node.js standard [`assert.notEqual`](http://nodejs.org/api/assert.html#assert_assert_notequal_actual_expected_message). * @static * @memberOf should * @category assertion assert * @param {*} actual * @param {*} expected * @param {string} [message] */ assert.notEqual = function notEqual(actual, expected, message) { if(actual == expected) { fail(actual, expected, message, '!=', assert.notEqual); } }; // 7. The equivalence assertion tests a deep equality relation. // assert.deepEqual(actual, expected, message_opt); /** * Node.js standard [`assert.deepEqual`](http://nodejs.org/api/assert.html#assert_assert_deepequal_actual_expected_message). * @static * @memberOf should * @category assertion assert * @param {*} actual * @param {*} expected * @param {string} [message] */ assert.deepEqual = function deepEqual(actual, expected, message) { if(!_deepEqual(actual, expected).result) { fail(actual, expected, message, 'deepEqual', assert.deepEqual); } }; // 8. The non-equivalence assertion tests for any deep inequality. // assert.notDeepEqual(actual, expected, message_opt); /** * Node.js standard [`assert.notDeepEqual`](http://nodejs.org/api/assert.html#assert_assert_notdeepequal_actual_expected_message). * @static * @memberOf should * @category assertion assert * @param {*} actual * @param {*} expected * @param {string} [message] */ assert.notDeepEqual = function notDeepEqual(actual, expected, message) { if(_deepEqual(actual, expected).result) { fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual); } }; // 9. The strict equality assertion tests strict equality, as determined by ===. // assert.strictEqual(actual, expected, message_opt); /** * Node.js standard [`assert.strictEqual`](http://nodejs.org/api/assert.html#assert_assert_strictequal_actual_expected_message). * @static * @memberOf should * @category assertion assert * @param {*} actual * @param {*} expected * @param {string} [message] */ assert.strictEqual = function strictEqual(actual, expected, message) { if(actual !== expected) { fail(actual, expected, message, '===', assert.strictEqual); } }; // 10. The strict non-equality assertion tests for strict inequality, as // determined by !==. assert.notStrictEqual(actual, expected, message_opt); /** * Node.js standard [`assert.notStrictEqual`](http://nodejs.org/api/assert.html#assert_assert_notstrictequal_actual_expected_message). * @static * @memberOf should * @category assertion assert * @param {*} actual * @param {*} expected * @param {string} [message] */ assert.notStrictEqual = function notStrictEqual(actual, expected, message) { if(actual === expected) { fail(actual, expected, message, '!==', assert.notStrictEqual); } }; function expectedException(actual, expected) { if(!actual || !expected) { return false; } if(Object.prototype.toString.call(expected) == '[object RegExp]') { return expected.test(actual); } else if(actual instanceof expected) { return true; } else if(expected.call({}, actual) === true) { return true; } return false; } function _throws(shouldThrow, block, expected, message) { var actual; if(typeof expected == 'string') { message = expected; expected = null; } try { block(); } catch(e) { actual = e; } message = (expected && expected.name ? ' (' + expected.name + ')' : '.') + (message ? ' ' + message : '.'); if(shouldThrow && !actual) { fail(actual, expected, 'Missing expected exception' + message); } if(!shouldThrow && expectedException(actual, expected)) { fail(actual, expected, 'Got unwanted exception' + message); } if((shouldThrow && actual && expected && !expectedException(actual, expected)) || (!shouldThrow && actual)) { throw actual; } } // 11. Expected to throw an error: // assert.throws(block, Error_opt, message_opt); /** * Node.js standard [`assert.throws`](http://nodejs.org/api/assert.html#assert_assert_throws_block_error_message). * @static * @memberOf should * @category assertion assert * @param {Function} block * @param {Function} [error] * @param {String} [message] */ assert.throws = function(block, /*optional*/error, /*optional*/message) { _throws.apply(this, [true].concat(pSlice.call(arguments))); }; // EXTENSION! This is annoying to write outside this module. /** * Node.js standard [`assert.doesNotThrow`](http://nodejs.org/api/assert.html#assert_assert_doesnotthrow_block_message). * @static * @memberOf should * @category assertion assert * @param {Function} block * @param {String} [message] */ assert.doesNotThrow = function(block, /*optional*/message) { _throws.apply(this, [false].concat(pSlice.call(arguments))); }; /** * Node.js standard [`assert.ifError`](http://nodejs.org/api/assert.html#assert_assert_iferror_value). * @static * @memberOf should * @category assertion assert * @param {Error} err */ assert.ifError = function(err) { if(err) { throw err; } }; },{"./../assertion":3,"should-equal":20}],6:[function(require,module,exports){ /* * Should * Copyright(c) 2010-2014 TJ Holowaychuk * MIT Licensed */ var util = require('../util') , assert = require('./_assert') , AssertionError = require('../assertion-error'); module.exports = function(should) { var i = should.format; /* * Expose assert to should * * This allows you to do things like below * without require()ing the assert module. * * should.equal(foo.bar, undefined); * */ util.merge(should, assert); /** * Assert _obj_ exists, with optional message. * * @static * @memberOf should * @category assertion assert * @alias should.exists * @param {*} obj * @param {String} [msg] * @example * * should.exist(1); * should.exist(new Date()); */ should.exist = should.exists = function(obj, msg) { if(null == obj) { throw new AssertionError({ message: msg || ('expected ' + i(obj) + ' to exist'), stackStartFunction: should.exist }); } }; should.not = {}; /** * Asserts _obj_ does not exist, with optional message. * * @name not.exist * @static * @memberOf should * @category assertion assert * @alias should.not.exists * @param {*} obj * @param {String} [msg] * @example * * should.not.exist(null); * should.not.exist(void 0); */ should.not.exist = should.not.exists = function(obj, msg) { if(null != obj) { throw new AssertionError({ message: msg || ('expected ' + i(obj) + ' to not exist'), stackStartFunction: should.not.exist }); } }; }; },{"../assertion-error":2,"../util":18,"./_assert":5}],7:[function(require,module,exports){ /* * Should * Copyright(c) 2010-2014 TJ Holowaychuk * MIT Licensed */ module.exports = function(should, Assertion) { /** * Assert given object is exactly `true`. * * @name true * @memberOf Assertion * @category assertion bool * @alias Assertion#True * @example * * (true).should.be.true(); * false.should.not.be.true(); * * ({ a: 10}).should.not.be.true(); */ Assertion.add('true', function() { this.is.exactly(true); }); Assertion.alias('true', 'True'); /** * Assert given object is exactly `false`. * * @name false * @memberOf Assertion * @category assertion bool * @alias Assertion#False * @example * * (true).should.not.be.false(); * false.should.be.false(); */ Assertion.add('false', function() { this.is.exactly(false); }); Assertion.alias('false', 'False'); /** * Assert given object is thuthy according javascript type conversions. * * @name ok * @memberOf Assertion * @category assertion bool * @example * * (true).should.be.ok(); * ''.should.not.be.ok(); * should(null).not.be.ok(); * should(void 0).not.be.ok(); * * (10).should.be.ok(); * (0).should.not.be.ok(); */ Assertion.add('ok', function() { this.params = { operator: 'to be truthy' }; this.assert(this.obj); }); }; },{}],8:[function(require,module,exports){ module.exports = function(should, Assertion) { /** * Simple chaining. It actually do nothing. * * @memberOf Assertion * @name be * @property {should.Assertion} be * @alias Assertion#an * @alias Assertion#of * @alias Assertion#a * @alias Assertion#and * @alias Assertion#have * @alias Assertion#has * @alias Assertion#with * @alias Assertion#is * @alias Assertion#which * @alias Assertion#the * @alias Assertion#it * @category assertion chaining */ ['an', 'of', 'a', 'and', 'be', 'has', 'have', 'with', 'is', 'which', 'the', 'it'].forEach(function(name) { Assertion.addChain(name); }); }; },{}],9:[function(require,module,exports){ /* * Should * Copyright(c) 2010-2014 TJ Holowaychuk * MIT Licensed */ var util = require('../util'); var eql = require('should-equal'); module.exports = function(should, Assertion) { var i = should.format; /** * Assert that given object contain something that equal to `other`. It uses `should-equal` for equality checks. * If given object is array it search that one of elements was equal to `other`. * If given object is string it checks if `other` is a substring - expected that `other` is a string. * If given object is Object it checks that `other` is a subobject - expected that `other` is a object. * * @name containEql * @memberOf Assertion * @category assertion contain * @param {*} other Nested object * @example * * [1, 2, 3].should.containEql(1); * [{ a: 1 }, 'a', 10].should.containEql({ a: 1 }); * * 'abc'.should.containEql('b'); * 'ab1c'.should.containEql(1); * * ({ a: 10, c: { d: 10 }}).should.containEql({ a: 10 }); * ({ a: 10, c: { d: 10 }}).should.containEql({ c: { d: 10 }}); * ({ a: 10, c: { d: 10 }}).should.containEql({ b: 10 }); * // throws AssertionError: expected { a: 10, c: { d: 10 } } to contain { b: 10 } * // expected { a: 10, c: { d: 10 } } to have property b */ Assertion.add('containEql', function(other) { this.params = {operator: 'to contain ' + i(other)}; this.is.not.null().and.not.undefined(); var obj = this.obj; if(typeof obj == 'string') { this.assert(obj.indexOf(String(other)) >= 0); } else if(util.isIndexable(obj)) { this.assert(util.some(obj, function(v) { return eql(v, other).result; })); } else { this.have.properties(other); } }); /** * Assert that given object is contain equally structured object on the same depth level. * If given object is an array and `other` is an array it checks that the eql elements is going in the same sequence in given array (recursive) * If given object is an object it checks that the same keys contain deep equal values (recursive) * On other cases it try to check with `.eql` * * @name containDeepOrdered * @memberOf Assertion * @category assertion contain * @param {*} other Nested object * @example * * [ 1, 2, 3].should.containDeepOrdered([1, 2]); * [ 1, 2, [ 1, 2, 3 ]].should.containDeepOrdered([ 1, [ 2, 3 ]]); * * ({ a: 10, b: { c: 10, d: [1, 2, 3] }}).should.containDeepOrdered({a: 10}); * ({ a: 10, b: { c: 10, d: [1, 2, 3] }}).should.containDeepOrdered({b: {c: 10}}); * ({ a: 10, b: { c: 10, d: [1, 2, 3] }}).should.containDeepOrdered({b: {d: [1, 3]}}); */ Assertion.add('containDeepOrdered', function(other) { this.params = {operator: 'to contain ' + i(other)}; var obj = this.obj; if(typeof obj == 'string') {// expect other to be string this.is.equal(String(other)); } else if(util.isIndexable(obj) && util.isIndexable(other)) { for(var objIdx = 0, otherIdx = 0, objLength = util.length(obj), otherLength = util.length(other); objIdx < objLength && otherIdx < otherLength; objIdx++) { try { should(obj[objIdx]).containDeepOrdered(other[otherIdx]); otherIdx++; } catch(e) { if(e instanceof should.AssertionError) { continue; } throw e; } } this.assert(otherIdx === otherLength); } else if(obj != null && other != null && typeof obj == 'object' && typeof other == 'object') {// object contains object case util.forEach(other, function(value, key) { should(obj[key]).containDeepOrdered(value); }); // if both objects is empty means we finish traversing - and we need to compare for hidden values if(util.isEmptyObject(other)) { this.eql(other); } } else { this.eql(other); } }); /** * The same like `Assertion#containDeepOrdered` but all checks on arrays without order. * * @name containDeep * @memberOf Assertion * @category assertion contain * @param {*} other Nested object * @example * * [ 1, 2, 3].should.containDeep([2, 1]); * [ 1, 2, [ 1, 2, 3 ]].should.containDeep([ 1, [ 3, 1 ]]); */ Assertion.add('containDeep', function(other) { this.params = {operator: 'to contain ' + i(other)}; var obj = this.obj; if(typeof obj == 'string') {// expect other to be string this.is.equal(String(other)); } else if(util.isIndexable(obj) && util.isIndexable(other)) { var usedKeys = {}; util.forEach(other, function(otherItem) { this.assert(util.some(obj, function(item, index) { if(index in usedKeys) return false; try { should(item).containDeep(otherItem); usedKeys[index] = true; return true; } catch(e) { if(e instanceof should.AssertionError) { return false; } throw e; } })); }, this); } else if(obj != null && other != null && typeof obj == 'object' && typeof other == 'object') {// object contains object case util.forEach(other, function(value, key) { should(obj[key]).containDeep(value); }); // if both objects is empty means we finish traversing - and we need to compare for hidden values if(util.isEmptyObject(other)) { this.eql(other); } } else { this.eql(other); } }); }; },{"../util":18,"should-equal":20}],10:[function(require,module,exports){ /* * Should * Copyright(c) 2010-2014 TJ Holowaychuk * MIT Licensed */ var eql = require('should-equal'); var type = require('should-type'); var util = require('../util'); function formatEqlResult(r, a, b) { return ((r.path.length > 0 ? 'at ' + r.path.map(util.formatProp).join(' -> ') : '') + (r.a === a ? '' : ', A has ' + util.format(r.a)) + (r.b === b ? '' : ' and B has ' + util.format(r.b)) + (r.showReason ? ' because ' + r.reason : '')).trim(); } module.exports = function(should, Assertion) { /** * Deep object equality comparison. For full spec see [`should-equal tests`](https://github.com/shouldjs/equal/blob/master/test.js). * * @name eql * @memberOf Assertion * @category assertion equality * @alias Assertion#deepEqual * @param {*} val Expected value * @param {string} [description] Optional message * @example * * (10).should.be.eql(10); * ('10').should.not.be.eql(10); * (-0).should.not.be.eql(+0); * * NaN.should.be.eql(NaN); * * ({ a: 10}).should.be.eql({ a: 10 }); * [ 'a' ].should.not.be.eql({ '0': 'a' }); */ Assertion.add('eql', function(val, description) { this.params = {operator: 'to equal', expected: val, message: description}; var result = eql(this.obj, val, should.config); this.params.details = result.result ? '' : formatEqlResult(result, this.obj, val); this.params.showDiff = eql(type(this.obj), type(val)).result; this.assert(result.result); }); /** * Exact comparison using ===. * * @name equal * @memberOf Assertion * @category assertion equality * @alias Assertion#exactly * @param {*} val Expected value * @param {string} [description] Optional message * @example * * 10.should.be.equal(10); * 'a'.should.be.exactly('a'); * * should(null).be.exactly(null); */ Assertion.add('equal', function(val, description) { this.params = {operator: 'to be', expected: val, message: description}; this.params.showDiff = eql(type(this.obj), type(val)).result; this.assert(val === this.obj); }); Assertion.alias('equal', 'exactly'); Assertion.alias('eql', 'deepEqual'); function addOneOf(name, message, method) { Assertion.add(name, function(vals) { if(arguments.length !== 1) { vals = Array.prototype.slice.call(arguments); } else { should(vals).be.Array(); } this.params = {operator: message, expected: vals}; var obj = this.obj; var found = false; util.forEach(vals, function(val) { try { should(val)[method](obj); found = true; return false; } catch(e) { if(e instanceof should.AssertionError) { return;//do nothing } throw e; } }); this.assert(found); }); } /** * Exact comparison using === to be one of supplied objects. * * @name equalOneOf * @memberOf Assertion * @category assertion equality * @param {Array|*} vals Expected values * @example * * 'ab'.should.be.equalOneOf('a', 10, 'ab'); * 'ab'.should.be.equalOneOf(['a', 10, 'ab']); */ addOneOf('equalOneOf', 'to be equals one of', 'equal'); /** * Exact comparison using .eql to be one of supplied objects. * * @name oneOf * @memberOf Assertion * @category assertion equality * @param {Array|*} vals Expected values * @example * * ({a: 10}).should.be.oneOf('a', 10, 'ab', {a: 10}); * ({a: 10}).should.be.oneOf(['a', 10, 'ab', {a: 10}]); */ addOneOf('oneOf', 'to be one of', 'eql'); }; },{"../util":18,"should-equal":20,"should-type":23}],11:[function(require,module,exports){ /* * Should * Copyright(c) 2010-2014 TJ Holowaychuk * MIT Licensed */ var util = require('../util'); module.exports = function(should, Assertion) { var i = should.format; /** * Assert given function throws error with such message. * * @name throw * @memberOf Assertion * @category assertion errors * @alias Assertion#throwError * @param {string|RegExp|Function|Object|GeneratorFunction|GeneratorObject} [message] Message to match or properties * @param {Object} [properties] Optional properties that will be matched to thrown error * @example * * (function(){ throw new Error('fail') }).should.throw(); * (function(){ throw new Error('fail') }).should.throw('fail'); * (function(){ throw new Error('fail') }).should.throw(/fail/); * * (function(){ throw new Error('fail') }).should.throw(Error); * var error = new Error(); * error.a = 10; * (function(){ throw error; }).should.throw(Error, { a: 10 }); * (function(){ throw error; }).should.throw({ a: 10 }); * (function*() { * yield throwError(); * }).should.throw(); */ Assertion.add('throw', function(message, properties) { var fn = this.obj , err = {} , errorInfo = '' , thrown = false; if(util.isGeneratorFunction(fn)) { return should(fn()).throw(message, properties); } else if(util.isGeneratorObject(fn)) { return should(fn.next.bind(fn)).throw(message, properties); } this.is.a.Function(); var errorMatched = true; try { fn(); } catch(e) { thrown = true; err = e; } if(thrown) { if(message) { if('string' == typeof message) { errorMatched = message == err.message; } else if(message instanceof RegExp) { errorMatched = message.test(err.message); } else if('function' == typeof message) { errorMatched = err instanceof message; } else if(null != message) { try { should(err).match(message); } catch(e) { if(e instanceof should.AssertionError) { errorInfo = ": " + e.message; errorMatched = false; } else { throw e; } } } if(!errorMatched) { if('string' == typeof message || message instanceof RegExp) { errorInfo = " with a message matching " + i(message) + ", but got '" + err.message + "'"; } else if('function' == typeof message) { errorInfo = " of type " + util.functionName(message) + ", but got " + util.functionName(err.constructor); } } else if('function' == typeof message && properties) { try { should(err).match(properties); } catch(e) { if(e instanceof should.AssertionError) { errorInfo = ": " + e.message; errorMatched = false; } else { throw e; } } } } else { errorInfo = " (got " + i(err) + ")"; } } this.params = { operator: 'to throw exception' + errorInfo }; this.assert(thrown); this.assert(errorMatched); }); Assertion.alias('throw', 'throwError'); }; },{"../util":18}],12:[function(require,module,exports){ /* * Should * Copyright(c) 2010-2014 TJ Holowaychuk * MIT Licensed */ var util = require('../util'); var eql = require('should-equal'); module.exports = function(should, Assertion) { var i = should.format; /** * Asserts if given object match `other` object, using some assumptions: * First object matched if they are equal, * If `other` is a regexp and given object is a string check on matching with regexp * If `other` is a regexp and given object is an array check if all elements matched regexp * If `other` is a regexp and given object is an object check values on matching regexp * If `other` is a function check if this function throws AssertionError on given object or return false - it will be assumed as not matched * If `other` is an object check if the same keys matched with above rules * All other cases failed * * @name match * @memberOf Assertion * @category assertion matching * @param {*} other Object to match * @param {string} [description] Optional message * @example * 'foobar'.should.match(/^foo/); * 'foobar'.should.not.match(/^bar/); * * ({ a: 'foo', c: 'barfoo' }).should.match(/foo$/); * * ['a', 'b', 'c'].should.match(/[a-z]/); * * (5).should.not.match(function(n) { * return n < 0; * }); * (5).should.not.match(function(it) { * it.should.be.an.Array(); * }); * ({ a: 10, b: 'abc', c: { d: 10 }, d: 0 }).should * .match({ a: 10, b: /c$/, c: function(it) { * return it.should.have.property('d', 10); * }}); * * [10, 'abc', { d: 10 }, 0].should * .match({ '0': 10, '1': /c$/, '2': function(it) { * return it.should.have.property('d', 10); * }}); */ Assertion.add('match', function(other, description) { this.params = {operator: 'to match ' + i(other), message: description}; if(!eql(this.obj, other).result) { if(other instanceof RegExp) { // something - regex if(typeof this.obj == 'string') { this.assert(other.exec(this.obj)); } else if(util.isIndexable(this.obj)) { util.forEach(this.obj, function(item) { this.assert(other.exec(item));// should we try to convert to String and exec? }, this); } else if(null != this.obj && typeof this.obj == 'object') { var notMatchedProps = [], matchedProps = []; util.forEach(this.obj, function(value, name) { if(other.exec(value)) matchedProps.push(util.formatProp(name)); else notMatchedProps.push(util.formatProp(name) + ' (' + i(value) + ')'); }, this); if(notMatchedProps.length) this.params.operator += '\n not matched properties: ' + notMatchedProps.join(', '); if(matchedProps.length) this.params.operator += '\n matched properties: ' + matchedProps.join(', '); this.assert(notMatchedProps.length === 0); } // should we try to convert to String and exec? } else if(typeof other == 'function') { var res; res = other(this.obj); //if(res instanceof Assertion) { // this.params.operator += '\n ' + res.getMessage(); //} //if we throw exception ok - it is used .should inside if(typeof res == 'boolean') { this.assert(res); // if it is just boolean function assert on it } } else if(other != null && typeof other == 'object') { // try to match properties (for Object and Array) notMatchedProps = []; matchedProps = []; util.forEach(other, function(value, key) { try { should(this.obj).have.property(key).which.match(value); matchedProps.push(util.formatProp(key)); } catch(e) { if(e instanceof should.AssertionError) { notMatchedProps.push(util.formatProp(key) + ' (' + i(this.obj[key]) + ')'); } else { throw e; } } }, this); if(notMatchedProps.length) this.params.operator += '\n not matched properties: ' + notMatchedProps.join(', '); if(matchedProps.length) this.params.operator += '\n matched properties: ' + matchedProps.join(', '); this.assert(notMatchedProps.length === 0); } else { this.assert(false); } } }); /** * Asserts if given object values or array elements all match `other` object, using some assumptions: * First object matched if they are equal, * If `other` is a regexp - matching with regexp * If `other` is a function check if this function throws AssertionError on given object or return false - it will be assumed as not matched * All other cases check if this `other` equal to each element * * @name matchEach * @memberOf Assertion * @category assertion matching * @alias Assertion#matchSome * @param {*} other Object to match * @param {string} [description] Optional message * @example * [ 'a', 'b', 'c'].should.matchEach(/\w+/); * [ 'a', 'a', 'a'].should.matchEach('a'); * * [ 'a', 'a', 'a'].should.matchEach(function(value) { value.should.be.eql('a') }); * * { a: 'a', b: 'a', c: 'a' }.should.matchEach(function(value) { value.should.be.eql('a') }); */ Assertion.add('matchEach', function(other, description) { this.params = {operator: 'to match each ' + i(other), message: description}; util.forEach(this.obj, function(value) { should(value).match(other); }, this); }); /** * Asserts if any of given object values or array elements match `other` object, using some assumptions: * First object matched if they are equal, * If `other` is a regexp - matching with regexp * If `other` is a function check if this function throws AssertionError on given object or return false - it will be assumed as not matched * All other cases check if this `other` equal to each element * * @name matchAny * @memberOf Assertion * @category assertion matching * @param {*} other Object to match * @alias Assertion#matchEvery * @param {string} [description] Optional message * @example * [ 'a', 'b', 'c'].should.matchAny(/\w+/); * [ 'a', 'b', 'c'].should.matchAny('a'); * * [ 'a', 'b', 'c'].should.matchAny(function(value) { value.should.be.eql('a') }); * * { a: 'a', b: 'b', c: 'c' }.should.matchAny(function(value) { value.should.be.eql('a') }); */ Assertion.add('matchAny', function(other, description) { this.params = {operator: 'to match any ' + i(other), message: description}; this.assert(util.some(this.obj, function(value) { try { should(value).match(other); return true; } catch(e) { if(e instanceof should.AssertionError) { // Caught an AssertionError, return false to the iterator return false; } throw e; } })); }); Assertion.alias('matchAny', 'matchSome'); Assertion.alias('matchEach', 'matchEvery'); }; },{"../util":18,"should-equal":20}],13:[function(require,module,exports){ /* * Should * Copyright(c) 2010-2014 TJ Holowaychuk * MIT Licensed */ module.exports = function(should, Assertion) { /** * Assert given object is NaN * @name NaN * @memberOf Assertion * @category assertion numbers * @example * * (10).should.not.be.NaN(); * NaN.should.be.NaN(); */ Assertion.add('NaN', function() { this.params = { operator: 'to be NaN' }; this.assert(this.obj !== this.obj); }); /** * Assert given object is not finite (positive or negative) * * @name Infinity * @memberOf Assertion * @category assertion numbers * @example * * (10).should.not.be.Infinity(); * NaN.should.not.be.Infinity(); */ Assertion.add('Infinity', function() { this.params = { operator: 'to be Infinity' }; this.is.a.Number() .and.not.a.NaN() .and.assert(!isFinite(this.obj)); }); /** * Assert given number between `start` and `finish` or equal one of them. * * @name within * @memberOf Assertion * @category assertion numbers * @param {number} start Start number * @param {number} finish Finish number * @param {string} [description] Optional message * @example * * (10).should.be.within(0, 20); */ Assertion.add('within', function(start, finish, description) { this.params = { operator: 'to be within ' + start + '..' + finish, message: description }; this.assert(this.obj >= start && this.obj <= finish); }); /** * Assert given number near some other `value` within `delta` * * @name approximately * @memberOf Assertion * @category assertion numbers * @param {number} value Center number * @param {number} delta Radius * @param {string} [description] Optional message * @example * * (9.99).should.be.approximately(10, 0.1); */ Assertion.add('approximately', function(value, delta, description) { this.params = { operator: 'to be approximately ' + value + ' ±' + delta, message: description }; this.assert(Math.abs(this.obj - value) <= delta); }); /** * Assert given number above `n`. * * @name above * @alias Assertion#greaterThan * @memberOf Assertion * @category assertion numbers * @param {number} n Margin number * @param {string} [description] Optional message * @example * * (10).should.be.above(0); */ Assertion.add('above', function(n, description) { this.params = { operator: 'to be above ' + n, message: description }; this.assert(this.obj > n); }); /** * Assert given number below `n`. * * @name below * @alias Assertion#lessThan * @memberOf Assertion * @category assertion numbers * @param {number} n Margin number * @param {string} [description] Optional message * @example * * (0).should.be.below(10); */ Assertion.add('below', function(n, description) { this.params = { operator: 'to be below ' + n, message: description }; this.assert(this.obj < n); }); Assertion.alias('above', 'greaterThan'); Assertion.alias('below', 'lessThan'); /** * Assert given number above `n`. * * @name aboveOrEqual * @alias Assertion#greaterThanOrEqual * @memberOf Assertion * @category assertion numbers * @param {number} n Margin number * @param {string} [description] Optional message * @example * * (10).should.be.aboveOrEqual(0); * (10).should.be.aboveOrEqual(10); */ Assertion.add('aboveOrEqual', function(n, description) { this.params = { operator: 'to be above or equal' + n, message: description }; this.assert(this.obj >= n); }); /** * Assert given number below `n`. * * @name belowOrEqual * @alias Assertion#lessThanOrEqual * @memberOf Assertion * @category assertion numbers * @param {number} n Margin number * @param {string} [description] Optional message * @example * * (0).should.be.belowOrEqual(10); * (0).should.be.belowOrEqual(0); */ Assertion.add('belowOrEqual', function(n, description) { this.params = { operator: 'to be below or equal' + n, message: description }; this.assert(this.obj <= n); }); Assertion.alias('aboveOrEqual', 'greaterThanOrEqual'); Assertion.alias('belowOrEqual', 'lessThanOrEqual'); }; },{}],14:[function(require,module,exports){ /* * Should * Copyright(c) 2010-2014 TJ Holowaychuk * MIT Licensed */ var util = require('../util'); var eql = require('should-equal'); var aSlice = Array.prototype.slice; module.exports = function(should, Assertion) { var i = should.format; /** * Asserts given object has some descriptor. **On success it change given object to be value of property**. * * @name propertyWithDescriptor * @memberOf Assertion * @category assertion property * @param {string} name Name of property * @param {Object} desc Descriptor like used in Object.defineProperty (not required to add all properties) * @example * * ({ a: 10 }).should.have.propertyWithDescriptor('a', { enumerable: true }); */ Assertion.add('propertyWithDescriptor', function(name, desc) { this.params = {actual: this.obj, operator: 'to have own property with descriptor ' + i(desc)}; var obj = this.obj; this.have.ownProperty(name); should(Object.getOwnPropertyDescriptor(Object(obj), name)).have.properties(desc); }); function processPropsArgs() { var args = {}; if(arguments.length > 1) { args.names = aSlice.call(arguments); } else { var arg = arguments[0]; if(typeof arg === 'string') { args.names = [arg]; } else if(util.isIndexable(arg)) { args.names = arg; } else { args.names = Object.keys(arg); args.values = arg; } } return args; } /** * Asserts given object has enumerable property with optionally value. **On success it change given object to be value of property**. * * @name enumerable * @memberOf Assertion * @category assertion property * @param {string} name Name of property * @param {*} [val] Optional property value to check * @example * * ({ a: 10 }).should.have.enumerable('a'); */ Assertion.add('enumerable', function(name, val) { name = util.convertPropertyName(name); this.params = { operator: "to have enumerable property " + util.formatProp(name) + (arguments.length > 1 ? " equal to " + i(val): "") }; var desc = { enumerable: true }; if(arguments.length > 1) desc.value = val; this.have.propertyWithDescriptor(name, desc); }); /** * Asserts given object has enumerable properties * * @name enumerables * @memberOf Assertion * @category assertion property * @param {Array|...string|Object} names Names of property * @example * * ({ a: 10, b: 10 }).should.have.enumerables('a'); */ Assertion.add('enumerables', function(names) { var args = processPropsArgs.apply(null, arguments); this.params = { operator: "to have enumerables " + args.names.map(util.formatProp) }; var obj = this.obj; args.names.forEach(function(name) { should(obj).have.enumerable(name); }); }); /** * Asserts given object has property with optionally value. **On success it change given object to be value of property**. * * @name property * @memberOf Assertion * @category assertion property * @param {string} name Name of property * @param {*} [val] Optional property value to check * @example * * ({ a: 10 }).should.have.property('a'); */ Assertion.add('property', function(name, val) { name = util.convertPropertyName(name); if(arguments.length > 1) { var p = {}; p[name] = val; this.have.properties(p); } else { this.have.properties(name); } this.obj = this.obj[name]; }); /** * Asserts given object has properties. On this method affect .any modifier, which allow to check not all properties. * * @name properties * @memberOf Assertion * @category assertion property * @param {Array|...string|Object} names Names of property * @example * * ({ a: 10 }).should.have.properties('a'); * ({ a: 10, b: 20 }).should.have.properties([ 'a' ]); * ({ a: 10, b: 20 }).should.have.properties({ b: 20 }); */ Assertion.add('properties', function(names) { var values = {}; if(arguments.length > 1) { names = aSlice.call(arguments); } else if(!Array.isArray(names)) { if(typeof names == 'string' || typeof names == 'symbol') { names = [names]; } else { values = names; names = Object.keys(names); } } var obj = Object(this.obj), missingProperties = []; //just enumerate properties and check if they all present names.forEach(function(name) { if(!(name in obj)) missingProperties.push(util.formatProp(name)); }); var props = missingProperties; if(props.length === 0) { props = names.map(util.formatProp); } else if(this.anyOne) { props = names.filter(function(name) { return missingProperties.indexOf(util.formatProp(name)) < 0; }).map(util.formatProp); } var operator = (props.length === 1 ? 'to have property ' : 'to have ' + (this.anyOne ? 'any of ' : '') + 'properties ') + props.join(', '); this.params = {obj: this.obj, operator: operator}; //check that all properties presented //or if we request one of them that at least one them presented this.assert(missingProperties.length === 0 || (this.anyOne && missingProperties.length != names.length)); // check if values in object matched expected var valueCheckNames = Object.keys(values); if(valueCheckNames.length) { var wrongValues = []; props = []; // now check values, as there we have all properties valueCheckNames.forEach(function(name) { var value = values[name]; if(!eql(obj[name], value).result) { wrongValues.push(util.formatProp(name) + ' of ' + i(value) + ' (got ' + i(obj[name]) + ')'); } else { props.push(util.formatProp(name) + ' of ' + i(value)); } }); if((wrongValues.length !== 0 && !this.anyOne) || (this.anyOne && props.length === 0)) { props = wrongValues; } operator = (props.length === 1 ? 'to have property ' : 'to have ' + (this.anyOne ? 'any of ' : '') + 'properties ') + props.join(', '); this.params = {obj: this.obj, operator: operator}; //if there is no not matched values //or there is at least one matched this.assert(wrongValues.length === 0 || (this.anyOne && wrongValues.length != valueCheckNames.length)); } }); /** * Asserts given object has property `length` with given value `n` * * @name length * @alias Assertion#lengthOf * @memberOf Assertion * @category assertion property * @param {number} n Expected length * @param {string} [description] Optional message * @example * * [1, 2].should.have.length(2); */ Assertion.add('length', function(n, description) { this.have.property('length', n, description); }); Assertion.alias('length', 'lengthOf'); var hasOwnProperty = Object.prototype.hasOwnProperty; /** * Asserts given object has own property. **On success it change given object to be value of property**. * * @name ownProperty * @alias Assertion#hasOwnProperty * @memberOf Assertion * @category assertion property * @param {string} name Name of property * @param {string} [description] Optional message * @example * * ({ a: 10 }).should.have.ownProperty('a'); */ Assertion.add('ownProperty', function(name, description) { name = util.convertPropertyName(name); this.params = { actual: this.obj, operator: 'to have own property ' + util.formatProp(name), message: description }; this.assert(hasOwnProperty.call(this.obj, name)); this.obj = this.obj[name]; }); Assertion.alias('ownProperty', 'hasOwnProperty'); /** * Asserts given object is empty. For strings, arrays and arguments it checks .length property, for objects it checks keys. * * @name empty * @memberOf Assertion * @category assertion property * @example * * ''.should.be.empty(); * [].should.be.empty(); * ({}).should.be.empty(); */ Assertion.add('empty', function() { this.params = {operator: 'to be empty'}; if(util.length(this.obj) !== void 0) { should(this.obj).have.property('length', 0); } else { var obj = Object(this.obj); // wrap to reference for booleans and numbers for(var prop in obj) { should(this.obj).not.have.ownProperty(prop); } } }, true); /** * Asserts given object has exact keys. Compared to `properties`, `keys` does not accept Object as a argument. * * @name keys * @alias Assertion#key * @memberOf Assertion * @category assertion property * @param {Array|...string} [keys] Keys to check * @example * * ({ a: 10 }).should.have.keys('a'); * ({ a: 10, b: 20 }).should.have.keys('a', 'b'); * ({ a: 10, b: 20 }).should.have.keys([ 'a', 'b' ]); * ({}).should.have.keys(); */ Assertion.add('keys', function(keys) { if(arguments.length > 1) keys = aSlice.call(arguments); else if(arguments.length === 1 && typeof keys === 'string') keys = [keys]; else if(arguments.length === 0) keys = []; keys = keys.map(String); var obj = Object(this.obj); // first check if some keys are missing var missingKeys = []; keys.forEach(function(key) { if(!hasOwnProperty.call(this.obj, key)) missingKeys.push(util.formatProp(key)); }, this); // second check for extra keys var extraKeys = []; Object.keys(obj).forEach(function(key) { if(keys.indexOf(key) < 0) { extraKeys.push(util.formatProp(key)); } }); var verb = keys.length === 0 ? 'to be empty' : 'to have ' + (keys.length === 1 ? 'key ' : 'keys '); this.params = {operator: verb + keys.map(util.formatProp).join(', ')}; if(missingKeys.length > 0) this.params.operator += '\n\tmissing keys: ' + missingKeys.join(', '); if(extraKeys.length > 0) this.params.operator += '\n\textra keys: ' + extraKeys.join(', '); this.assert(missingKeys.length === 0 && extraKeys.length === 0); }); Assertion.alias("keys", "key"); /** * Asserts given object has nested property in depth by path. **On success it change given object to be value of final property**. * * @name propertyByPath * @memberOf Assertion * @category assertion property * @param {Array|...string} properties Properties path to search * @example * * ({ a: {b: 10}}).should.have.propertyByPath('a', 'b').eql(10); */ Assertion.add('propertyByPath', function(properties) { if(arguments.length > 1) properties = aSlice.call(arguments); else if(arguments.length === 1 && typeof properties == 'string') properties = [properties]; else if(arguments.length === 0) properties = []; var allProps = properties.map(util.formatProp); properties = properties.map(String); var obj = should(Object(this.obj)); var foundProperties = []; var currentProperty; while(currentProperty = properties.shift()) { this.params = {operator: 'to have property by path ' + allProps.join(', ') + ' - failed on ' + util.formatProp(currentProperty)}; obj = obj.have.property(currentProperty); foundProperties.push(currentProperty); } this.params = {obj: this.obj, operator: 'to have property by path ' + allProps.join(', ')}; this.obj = obj.obj; }); }; },{"../util":18,"should-equal":20}],15:[function(require,module,exports){ /* * Should * Copyright(c) 2010-2014 TJ Holowaychuk * MIT Licensed */ module.exports = function(should, Assertion) { /** * Assert given string starts with prefix * @name startWith * @memberOf Assertion * @category assertion strings * @param {string} str Prefix * @param {string} [description] Optional message * @example * * 'abc'.should.startWith('a'); */ Assertion.add('startWith', function(str, description) { this.params = { operator: 'to start with ' + should.format(str), message: description }; this.assert(0 === this.obj.indexOf(str)); }); /** * Assert given string starts with prefix * @name endWith * @memberOf Assertion * @category assertion strings * @param {string} str Prefix * @param {string} [description] Optional message * @example * * 'abca'.should.endWith('a'); */ Assertion.add('endWith', function(str, description) { this.params = { operator: 'to end with ' + should.format(str), message: description }; this.assert(this.obj.indexOf(str, this.obj.length - str.length) >= 0); }); }; },{}],16:[function(require,module,exports){ /* * Should * Copyright(c) 2010-2014 TJ Holowaychuk * MIT Licensed */ var util = require('../util'); module.exports = function(should, Assertion) { /** * Assert given object is number * @name Number * @memberOf Assertion * @category assertion types */ Assertion.add('Number', function() { this.params = {operator: 'to be a number'}; this.have.type('number'); }); /** * Assert given object is arguments * @name arguments * @alias Assertion#Arguments * @memberOf Assertion * @category assertion types */ Assertion.add('arguments', function() { this.params = {operator: 'to be arguments'}; this.have.class('Arguments'); }); Assertion.alias('arguments', 'Arguments'); /** * Assert given object has some type using `typeof` * @name type * @memberOf Assertion * @param {string} type Type name * @param {string} [description] Optional message * @category assertion types */ Assertion.add('type', function(type, description) { this.params = {operator: 'to have type ' + type, message: description}; should(typeof this.obj).be.exactly(type); }); /** * Assert given object is instance of `constructor` * @name instanceof * @alias Assertion#instanceOf * @memberOf Assertion * @param {Function} constructor Constructor function * @param {string} [description] Optional message * @category assertion types */ Assertion.add('instanceof', function(constructor, description) { this.params = {operator: 'to be an instance of ' + util.functionName(constructor), message: description}; this.assert(Object(this.obj) instanceof constructor); }); Assertion.alias('instanceof', 'instanceOf'); /** * Assert given object is function * @name Function * @memberOf Assertion * @category assertion types */ Assertion.add('Function', function() { this.params = {operator: 'to be a function'}; this.have.type('function'); }); /** * Assert given object is object * @name Object * @memberOf Assertion * @category assertion types */ Assertion.add('Object', function() { this.params = {operator: 'to be an object'}; this.is.not.null().and.have.type('object'); }); /** * Assert given object is string * @name String * @memberOf Assertion * @category assertion types */ Assertion.add('String', function() { this.params = {operator: 'to be a string'}; this.have.type('string'); }); /** * Assert given object is array * @name Array * @memberOf Assertion * @category assertion types */ Assertion.add('Array', function() { this.params = {operator: 'to be an array'}; this.have.class('Array'); }); /** * Assert given object is boolean * @name Boolean * @memberOf Assertion * @category assertion types */ Assertion.add('Boolean', function() { this.params = {operator: 'to be a boolean'}; this.have.type('boolean'); }); /** * Assert given object is error * @name Error * @memberOf Assertion * @category assertion types */ Assertion.add('Error', function() { this.params = {operator: 'to be an error'}; this.have.instanceOf(Error); }); /** * Assert given object is null * @name null * @alias Assertion#Null * @memberOf Assertion * @category assertion types */ Assertion.add('null', function() { this.params = {operator: 'to be null'}; this.assert(this.obj === null); }); Assertion.alias('null', 'Null'); /** * Assert given object has some internal [[Class]], via Object.prototype.toString call * @name class * @alias Assertion#Class * @memberOf Assertion * @category assertion types */ Assertion.add('class', function(cls) { this.params = {operator: 'to have [[Class]] ' + cls}; this.assert(Object.prototype.toString.call(this.obj) === '[object ' + cls + ']'); }); Assertion.alias('class', 'Class'); /** * Assert given object is undefined * @name undefined * @alias Assertion#Undefined * @memberOf Assertion * @category assertion types */ Assertion.add('undefined', function() { this.params = {operator: 'to be undefined'}; this.assert(this.obj === void 0); }); Assertion.alias('undefined', 'Undefined'); /** * Assert given object supports es6 iterable protocol (just check * that object has property Symbol.iterator, which is a function) * @name iterable * @memberOf Assertion * @category assertion es6 */ Assertion.add('iterable', function() { this.params = {operator: 'to be iterable'}; should(this.obj).have.property(Symbol.iterator).which.is.a.Function(); }); /** * Assert given object supports es6 iterator protocol (just check * that object has property next, which is a function) * @name iterator * @memberOf Assertion * @category assertion es6 */ Assertion.add('iterator', function() { this.params = {operator: 'to be iterator'}; should(this.obj).have.property('next').which.is.a.Function(); }); /** * Assert given object is a generator object * @name generator * @memberOf Assertion * @category assertion es6 */ Assertion.add('generator', function() { this.params = {operator: 'to be generator'}; should(this.obj).be.iterable .and.iterator .and.it.is.equal(this.obj[Symbol.iterator]()); }); }; },{"../util":18}],17:[function(require,module,exports){ /* * Should * Copyright(c) 2010-2014 TJ Holowaychuk * MIT Licensed */ var util = require('./util'); /** * Our function should * * @param {*} obj Object to assert * @returns {should.Assertion} Returns new Assertion for beginning assertion chain * @example * * var should = require('should'); * should('abc').be.a.String(); */ var should = function should(obj) { return (new should.Assertion(obj)); }; should.AssertionError = require('./assertion-error'); should.Assertion = require('./assertion'); should.format = util.format; should.type = require('should-type'); should.util = util; /** * Object with configuration. * It contains such properties: * * `checkProtoEql` boolean - Affect if `.eql` will check objects prototypes * Also it can contain options for should-format. * * @type {Object} * @memberOf should * @static * @example * * var a = { a: 10 }, b = Object.create(null); * b.a = 10; * * a.should.be.eql(b); * //not throws * * should.config.checkProtoEql = true; * a.should.be.eql(b); * //throws AssertionError: expected { a: 10 } to equal { a: 10 } (because A and B have different prototypes) */ should.config = require('./config'); //Expose should to external world. exports = module.exports = should; /** * Allow to extend given prototype with should property using given name. This getter will **unwrap** all standard wrappers like `Number`, `Boolean`, `String`. * Using `should(obj)` is the equivalent of using `obj.should` with known issues (like nulls and method calls etc). * * @param {string} [propertyName] Name of property to add. Default is `'should'`. * @param {Object} [proto] Prototype to extend with. Default is `Object.prototype`. * @memberOf should * @returns {{ name: string, descriptor: Object, proto: Object }} Descriptor enough to return all back * @static * @example * * var prev = should.extend('must', Object.prototype); * * 'abc'.must.startWith('a'); * * var should = should.noConflict(prev); * should.not.exist(Object.prototype.must); */ should.extend = function(propertyName, proto) { propertyName = propertyName || 'should'; proto = proto || Object.prototype; var prevDescriptor = Object.getOwnPropertyDescriptor(proto, propertyName); Object.defineProperty(proto, propertyName, { set: function() { }, get: function() { return should(util.isWrapperType(this) ? this.valueOf() : this); }, configurable: true }); return { name: propertyName, descriptor: prevDescriptor, proto: proto }; }; /** * Delete previous extension. If `desc` missing it will remove default extension. * * @param {{ name: string, descriptor: Object, proto: Object }} [desc] Returned from `should.extend` object * @memberOf should * @returns {Function} Returns should function * @static * @example * * var should = require('should').noConflict(); * * should(Object.prototype).not.have.property('should'); * * var prev = should.extend('must', Object.prototype); * 'abc'.must.startWith('a'); * should.noConflict(prev); * * should(Object.prototype).not.have.property('must'); */ should.noConflict = function(desc) { desc = desc || should._prevShould; if(desc) { delete desc.proto[desc.name]; if(desc.descriptor) { Object.defineProperty(desc.proto, desc.name, desc.descriptor); } } return should; }; /** * Simple utility function for a bit more easier should assertion extension * @param {Function} f So called plugin function. It should accept 2 arguments: `should` function and `Assertion` constructor * @memberOf should * @returns {Function} Returns `should` function * @static * @example * * should.use(function(should, Assertion) { * Assertion.add('asset', function() { * this.params = { operator: 'to be asset' }; * * this.obj.should.have.property('id').which.is.a.Number(); * this.obj.should.have.property('path'); * }) * }) */ should.use = function(f) { f(should, should.Assertion); return this; }; should .use(require('./ext/assert')) .use(require('./ext/chain')) .use(require('./ext/bool')) .use(require('./ext/number')) .use(require('./ext/eql')) .use(require('./ext/type')) .use(require('./ext/string')) .use(require('./ext/property')) .use(require('./ext/error')) .use(require('./ext/match')) .use(require('./ext/contain')); },{"./assertion":3,"./assertion-error":2,"./config":4,"./ext/assert":6,"./ext/bool":7,"./ext/chain":8,"./ext/contain":9,"./ext/eql":10,"./ext/error":11,"./ext/match":12,"./ext/number":13,"./ext/property":14,"./ext/string":15,"./ext/type":16,"./util":18,"should-type":23}],18:[function(require,module,exports){ /* * Should * Copyright(c) 2010-2014 TJ Holowaychuk * MIT Licensed */ var type = require('should-type'); var config = require('./config'); /** * Check if given obj just a primitive type wrapper * @param {Object} obj * @returns {boolean} * @private */ exports.isWrapperType = function(obj) { return obj instanceof Number || obj instanceof String || obj instanceof Boolean; }; exports.merge = function(a, b) { if(a && b) { for(var key in b) { a[key] = b[key]; } } return a; }; var hasOwnProperty = Object.prototype.hasOwnProperty; exports.forEach = function forEach(obj, f, context) { if(exports.isGeneratorFunction(obj)) { return forEach(obj(), f, context); } else if (exports.isGeneratorObject(obj)) { var value = obj.next(); while(!value.done) { if(f.call(context, value.value, 'value', obj) === false) return; value = obj.next(); } } else { for(var prop in obj) { if(hasOwnProperty.call(obj, prop)) { if(f.call(context, obj[prop], prop, obj) === false) return; } } } }; exports.some = function(obj, f, context) { var res = false; exports.forEach(obj, function(value, key) { if(f.call(context, value, key, obj)) { res = true; return false; } }, context); return res; }; exports.isEmptyObject = function(obj) { for(var prop in obj) { if(hasOwnProperty.call(obj, prop)) { return false; } } return true; }; exports.isIndexable = function(obj) { var t = type(obj); return (t.type === type.OBJECT && t.cls === type.ARRAY) || (t.type === type.OBJECT && t.cls === type.BUFFER) || (t.type === type.OBJECT && t.cls === type.ARGUMENTS) || (t.type === type.OBJECT && t.cls === type.ARRAY_BUFFER) || (t.type === type.OBJECT && t.cls === type.TYPED_ARRAY) || (t.type === type.OBJECT && t.cls === type.DATA_VIEW) || (t.type === type.OBJECT && t.cls === type.STRING) || (t.type === type.STRING); }; exports.length = function(obj) { var t = type(obj); switch(t.type) { case type.STRING: return obj.length; case type.OBJECT: switch(t.cls) { case type.ARRAY_BUFFER: case type.TYPED_ARRAY: case type.DATA_VIEW: return obj.byteLength; case type.ARRAY: case type.BUFFER: case type.ARGUMENTS: case type.FUNCTION: return obj.length; } } }; exports.convertPropertyName = function(name) { if(typeof name == 'symbol') { return name; } else { return String(name); } }; exports.isGeneratorObject = function(obj) { if(!obj) return false; return typeof obj.next == 'function' && typeof obj[Symbol.iterator] == 'function' && obj[Symbol.iterator]() === obj; }; //TODO find better way exports.isGeneratorFunction = function(f) { if(typeof f != 'function') return false; return /^function\s*\*\s*/.test(f.toString()); }; exports.format = function(value, opts) { return config.getFormatter(opts).format(value); }; exports.functionName = require('should-format').Formatter.functionName; exports.formatProp = function(value) { return config.getFormatter().formatPropertyName(String(value)); }; },{"./config":4,"should-format":21,"should-type":23}],19:[function(require,module,exports){ module.exports = function format(msg) { var args = arguments; for(var i = 1, l = args.length; i < l; i++) { msg = msg.replace(/%s/, args[i]); } return msg; } },{}],20:[function(require,module,exports){ var getType = require('should-type'); var format = require('./format'); var hasOwnProperty = Object.prototype.hasOwnProperty; function makeResult(r, path, reason, a, b) { var o = {result: r}; if(!r) { o.path = path; o.reason = reason; o.a = a; o.b = b; } return o; } var EQUALS = makeResult(true); function typeToString(t) { return t.type + (t.cls ? '(' + t.cls + (t.sub ? ' ' + t.sub : '') + ')' : ''); } var REASON = { PLUS_0_AND_MINUS_0: '+0 is not equal to -0', DIFFERENT_TYPES: 'A has type %s and B has type %s', NAN_NUMBER: 'NaN is not equal to any number', EQUALITY: 'A is not equal to B', EQUALITY_PROTOTYPE: 'A and B have different prototypes', WRAPPED_VALUE: 'A wrapped value is not equal to B wrapped value', FUNCTION_SOURCES: 'function A is not equal to B by source code value (via .toString call)', MISSING_KEY: '%s has no key %s', CIRCULAR_VALUES: 'A has circular reference that was visited not in the same time as B', SET_MAP_MISSING_KEY: 'Set/Map missing key', MAP_VALUE_EQUALITY: 'Values of the same key in A and B is not equal' }; function eqInternal(a, b, opts, stackA, stackB, path) { var r = EQUALS; function result(comparison, reason) { return makeResult(comparison, path, reason, a, b); } function checkPropertyEquality(property) { return eqInternal(a[property], b[property], opts, stackA, stackB, path.concat([property])); } // equal a and b exit early if(a === b) { // check for +0 !== -0; return result(a !== 0 || (1 / a == 1 / b), REASON.PLUS_0_AND_MINUS_0); } var l, p; var typeA = getType(a), typeB = getType(b); // if objects has different types they are not equals var typeDifferents = typeA.type !== typeB.type || typeA.cls !== typeB.cls; if(typeDifferents || ((opts.checkSubType && typeA.sub !== typeB.sub) || !opts.checkSubType)) { return result(false, format(REASON.DIFFERENT_TYPES, typeToString(typeA), typeToString(typeB))); } //early checks for types switch(typeA.type) { case 'number': // NaN !== NaN return (a !== a) ? result(b !== b, REASON.NAN_NUMBER) // but treat `+0` vs. `-0` as not equal : (a === 0 ? result(1 / a === 1 / b, REASON.PLUS_0_AND_MINUS_0) : result(a === b, REASON.EQUALITY)); case 'boolean': case 'string': return result(a === b, REASON.EQUALITY); case 'function': var fA = a.toString(), fB = b.toString(); r = eqInternal(fA, fB, opts, stackA, stackB, path); if(!r.result) { r.reason = REASON.FUNCTION_SOURCES; return r; } break;//check user properties case 'object': // additional checks for object instances switch(typeA.cls) { // check regexp flags // TODO add es6 flags case 'regexp': p = ['source', 'global', 'multiline', 'lastIndex', 'ignoreCase']; while(p.length) { r = checkPropertyEquality(p.shift()); if(!r.result) return r; } break;//check user properties //check by timestamp only case 'date': if(+a !== +b) { return result(false, REASON.EQUALITY); } break;//check user properties //primitive type wrappers case 'number': case 'boolean': case 'string': r = eqInternal(a.valueOf(), b.valueOf(), opts, stackA, stackB, path); if(!r.result) { r.reason = REASON.WRAPPED_VALUE; return r; } break;//check user properties //node buffer case 'buffer': //if length different it is obviously different r = checkPropertyEquality('length'); if(!r.result) return r; l = a.length; while(l--) { r = checkPropertyEquality(l); if(!r.result) return r; } //we do not check for user properties because //node Buffer have some strange hidden properties return EQUALS; case 'error': //check defined properties p = ['name', 'message']; while(p.length) { r = checkPropertyEquality(p.shift()); if(!r.result) return r; } break;//check user properties case 'array': case 'arguments': case 'typed-array': r = checkPropertyEquality('length'); if(!r.result) return r; break;//check user properties case 'array-buffer': r = checkPropertyEquality('byteLength'); if(!r.result) return r; break;//check user properties case 'map': case 'set': r = checkPropertyEquality('size'); if(!r.result) return r; stackA.push(a); stackB.push(b); var itA = a.entries(); var nextA = itA.next(); while(!nextA.done) { var key = nextA.value[0]; //first check for primitive key if we can do light check //using .has and .get if(getType(key).type != 'object') { if(b.has(key)) { if(typeA.cls == 'map') { //for map we also check its value to be equal var value = b.get(key); r = eqInternal(nextA.value[1], value, opts, stackA, stackB, path); if(!r.result) { r.a = nextA.value; r.b = value; r.reason = REASON.MAP_VALUE_EQUALITY; break; } } } else { r = result(false, REASON.SET_MAP_MISSING_KEY); r.a = key; r.b = key; break; } } else { //heavy check //we search by iterator for key equality using equal var itB = b.entries(); var nextB = itB.next(); while(!nextB.done) { //first check for keys r = eqInternal(nextA.value[0], nextB.value[0], opts, stackA, stackB, path); if(!r.result) { r.reason = REASON.SET_MAP_MISSING_KEY; r.a = key; r.b = key; } else { if(typeA.cls == 'map') { r = eqInternal(nextA.value[1], nextB.value[1], opts, stackA, stackB, path); if(!r.result) { r.a = nextA.value; r.b = nextB.value; r.reason = REASON.MAP_VALUE_EQUALITY; } } break; } nextB = itB.next(); } } if(!r.result) { break; } nextA = itA.next(); } stackA.pop(); stackB.pop(); if(!r.result) { r.reason = REASON.SET_MAP_MISSING_ENTRY; return r; } break; //check user properties } } // compare deep objects and arrays // stacks contain references only // l = stackA.length; while(l--) { if(stackA[l] == a) { return result(stackB[l] == b, REASON.CIRCULAR_VALUES); } } // add `a` and `b` to the stack of traversed objects stackA.push(a); stackB.push(b); var key; for(key in b) { if(hasOwnProperty.call(b, key)) { r = result(hasOwnProperty.call(a, key), format(REASON.MISSING_KEY, 'A', key)); if(!r.result) { break; } if(r.result) { r = checkPropertyEquality(key); if(!r.result) { break; } } } } if(r.result) { // ensure both objects have the same number of properties for(key in a) { if(hasOwnProperty.call(a, key)) { r = result(hasOwnProperty.call(b, key), format(REASON.MISSING_KEY, 'B', key)); if(!r.result) { return r; } } } } stackA.pop(); stackB.pop(); if(!r.result) return r; var prototypesEquals = false, canComparePrototypes = false; if(opts.checkProtoEql) { if(Object.getPrototypeOf) {//TODO should i check prototypes for === or use eq? prototypesEquals = Object.getPrototypeOf(a) === Object.getPrototypeOf(b); canComparePrototypes = true; } else if(a.__proto__ && b.__proto__) { prototypesEquals = a.__proto__ === b.__proto__; canComparePrototypes = true; } if(canComparePrototypes && !prototypesEquals) { r = result(prototypesEquals, REASON.EQUALITY_PROTOTYPE); r.showReason = true; if(!r.result) { return r; } } } return EQUALS; } var defaultOptions = { checkProtoEql: true, checkSubType: true }; function eq(a, b, opts) { opts = opts || {}; if(typeof opts.checkProtoEql !== 'boolean') opts.checkProtoEql = defaultOptions.checkProtoEql; if(typeof opts.checkSubType !== 'boolean') opts.checkSubType = defaultOptions.checkSubType; var r = eqInternal(a, b, opts, [], [], []); return r; } module.exports = eq; eq.r = REASON; },{"./format":19,"should-type":23}],21:[function(require,module,exports){ var getType = require('should-type'); var util = require('./util'); function genKeysFunc(f) { return function(value) { var k = f(value); k.sort(); return k; }; } function Formatter(opts) { opts = opts || {}; this.seen = []; this.keys = genKeysFunc(opts.keys === false ? Object.getOwnPropertyNames : Object.keys); this.maxLineLength = typeof opts.maxLineLength === 'number' ? opts.maxLineLength : 60; this.propSep = opts.propSep || ','; this.isUTCdate = !!opts.isUTCdate; } Formatter.prototype = { constructor: Formatter, format: function(value) { var t = getType(value); var name1 = t.type, name2 = t.type; if(t.cls) { name1 += '_' + t.cls; name2 += '_' + t.cls; } if(t.sub) { name2 += '_' + t.sub; } var f = this['_format_' + name2] || this['_format_' + name1] || this['_format_' + t.type] || this.defaultFormat; return f.call(this, value).trim(); }, _formatObject: function(value, opts) { opts = opts || {}; var mainKeys = opts.keys || this.keys(value); var len = 0; var formatPropertyValue = opts.formatPropertyValue || this.formatPropertyValue; var formatPropertyName = opts.formatPropertyName || this.formatPropertyName; var keyValueSep = opts.keyValueSep || ': '; var keyFilter = opts.keyFilter || function() { return true; }; this.seen.push(value); var keys = []; mainKeys.forEach(function(key) { if(!keyFilter(key)) return; var fName = formatPropertyName.call(this, key); var f = (fName ? fName + keyValueSep : '') + formatPropertyValue.call(this, value, key); len += f.length; keys.push(f); }, this); this.seen.pop(); (opts.additionalProperties || []).forEach(function(keyValue) { var f = keyValue[0] + keyValueSep + this.format(keyValue[1]); len += f.length; keys.push(f); }, this); var prefix = opts.prefix || Formatter.constructorName(value) || ''; if(prefix.length > 0) prefix += ' '; var lbracket, rbracket; if(Array.isArray(opts.brackets)) { lbracket = opts.brackets && opts.brackets[0]; rbracket = opts.brackets && opts.brackets[1]; } else { lbracket = '{'; rbracket = '}'; } var rootValue = opts.value || ''; if(keys.length === 0) return rootValue || (prefix + lbracket + rbracket); if(len <= this.maxLineLength) { return prefix + lbracket + ' ' + (rootValue ? rootValue + ' ' : '') + keys.join(this.propSep + ' ') + ' ' + rbracket; } else { return prefix + lbracket + '\n' + (rootValue ? ' ' + rootValue + '\n' : '') + keys.map(util.addSpaces).join(this.propSep + '\n') + '\n' + rbracket; } }, formatObject: function(value, prefix, props) { props = props || this.keys(value); var len = 0; this.seen.push(value); props = props.map(function(prop) { var f = this.formatProperty(value, prop); len += f.length; return f; }, this); this.seen.pop(); if(props.length === 0) return '{}'; if(len <= this.maxLineLength) { return '{ ' + (prefix ? prefix + ' ' : '') + props.join(this.propSep + ' ') + ' }'; } else { return '{' + '\n' + (prefix ? ' ' + prefix + '\n' : '') + props.map(util.addSpaces).join(this.propSep + '\n') + '\n' + '}'; } }, formatPropertyName: function(name) { return name.match(/^[a-zA-Z_$][a-zA-Z_$0-9]*$/) ? name : this.format(name); }, formatProperty: function(value, prop) { var desc = Formatter.getPropertyDescriptor(value, prop); var propName = this.formatPropertyName(prop); var propValue = desc.get && desc.set ? '[Getter/Setter]' : desc.get ? '[Getter]' : desc.set ? '[Setter]' : this.seen.indexOf(desc.value) >= 0 ? '[Circular]' : this.format(desc.value); return propName + ': ' + propValue; }, formatPropertyValue: function(value, prop) { var desc = Formatter.getPropertyDescriptor(value, prop); var propValue = desc.get && desc.set ? '[Getter/Setter]' : desc.get ? '[Getter]' : desc.set ? '[Setter]' : this.seen.indexOf(desc.value) >= 0 ? '[Circular]' : this.format(desc.value); return propValue; } }; Formatter.add = function add(type, cls, sub, f) { var args = Array.prototype.slice.call(arguments); f = args.pop(); Formatter.prototype['_format_' + args.join('_')] = f; }; Formatter.formatObjectWithPrefix = function formatObjectWithPrefix(f) { return function(value) { var prefix = f.call(this, value); var props = this.keys(value); if(props.length == 0) return prefix; else return this.formatObject(value, prefix, props); }; }; var functionNameRE = /^\s*function\s*(\S*)\s*\(/; Formatter.functionName = function functionName(f) { if(f.name) { return f.name; } var name = f.toString().match(functionNameRE)[1]; return name; }; Formatter.constructorName = function(obj) { while (obj) { var descriptor = Object.getOwnPropertyDescriptor(obj, 'constructor'); if (descriptor !== undefined && typeof descriptor.value === 'function') { var name = Formatter.functionName(descriptor.value); if(name !== '') { return name; } } obj = Object.getPrototypeOf(obj); } }; Formatter.getPropertyDescriptor = function(obj, value) { var desc; try { desc = Object.getOwnPropertyDescriptor(obj, value) || {value: obj[value]}; } catch(e) { desc = {value: e}; } return desc; }; Formatter.generateFunctionForIndexedArray = function generateFunctionForIndexedArray(lengthProp, name, padding) { return function(value) { var max = this.byteArrayMaxLength || 50; var length = value[lengthProp]; var formattedValues = []; var len = 0; for(var i = 0; i < max && i < length; i++) { var b = value[i] || 0; var v = util.pad0(b.toString(16), padding); len += v.length; formattedValues.push(v); } var prefix = value.constructor.name || name || ''; if(prefix) prefix += ' '; if(formattedValues.length === 0) return prefix + '[]'; if(len <= this.maxLineLength) { return prefix + '[ ' + formattedValues.join(this.propSep + ' ') + ' ' + ']'; } else { return prefix + '[\n' + formattedValues.map(util.addSpaces).join(this.propSep + '\n') + '\n' + ']'; } }; }; Formatter.add('undefined', function() { return 'undefined' }); Formatter.add('null', function() { return 'null' }); Formatter.add('boolean', function(value) { return value ? 'true': 'false' }); Formatter.add('symbol', function(value) { return value.toString() }); ['number', 'boolean'].forEach(function(name) { Formatter.add('object', name, function(value) { return this._formatObject(value, { additionalProperties: [['[[PrimitiveValue]]', value.valueOf()]] }); }); }); Formatter.add('object', 'string', function(value) { var realValue = value.valueOf(); return this._formatObject(value, { keyFilter: function(key) { //skip useless indexed properties return !(key.match(/\d+/) && parseInt(key, 10) < realValue.length); }, additionalProperties: [['[[PrimitiveValue]]', realValue]] }); }); Formatter.add('object', 'regexp', function(value) { return this._formatObject(value, { value: String(value) }); }); Formatter.add('number', function(value) { if(value === 0 && 1 / value < 0) return '-0'; return String(value); }); Formatter.add('string', function(value) { return '\'' + JSON.stringify(value).replace(/^"|"$/g, '') .replace(/'/g, "\\'") .replace(/\\"/g, '"') + '\''; }); Formatter.add('object', function(value) { return this._formatObject(value); }); Formatter.add('object', 'arguments', function(value) { return this._formatObject(value, { prefix: 'Arguments', formatPropertyName: function(key) { if(!key.match(/\d+/)) { return this.formatPropertyName(key); } }, brackets: ['[', ']'] }); }); Formatter.add('object', 'array', function(value) { return this._formatObject(value, { formatPropertyName: function(key) { if(!key.match(/\d+/)) { return this.formatPropertyName(key); } }, brackets: ['[', ']'] }); }); function formatDate(value, isUTC) { var prefix = isUTC ? 'UTC' : ''; var date = value['get' + prefix + 'FullYear']() + '-' + util.pad0(value['get' + prefix + 'Month']() + 1, 2) + '-' + util.pad0(value['get' + prefix + 'Date'](), 2); var time = util.pad0(value['get' + prefix + 'Hours'](), 2) + ':' + util.pad0(value['get' + prefix + 'Minutes'](), 2) + ':' + util.pad0(value['get' + prefix + 'Seconds'](), 2) + '.' + util.pad0(value['get' + prefix + 'Milliseconds'](), 3); var to = value.getTimezoneOffset(); var absTo = Math.abs(to); var hours = Math.floor(absTo / 60); var minutes = absTo - hours * 60; var tzFormat = (to < 0 ? '+' : '-') + util.pad0(hours, 2) + util.pad0(minutes, 2); return date + ' ' + time + (isUTC ? '' : ' ' + tzFormat); } Formatter.add('object', 'date', function(value) { return this._formatObject(value, { value: formatDate(value, this.isUTCdate) }); }); Formatter.add('function', function(value) { return this._formatObject(value, { additionalProperties: [['name', Formatter.functionName(value)]] }); }); Formatter.add('object', 'error', function(value) { return this._formatObject(value, { prefix: value.name, additionalProperties: [['message', value.message]] }); }); Formatter.add('object', 'buffer', Formatter.generateFunctionForIndexedArray('length', 'Buffer', 2)); Formatter.add('object', 'array-buffer', Formatter.generateFunctionForIndexedArray('byteLength', 'ArrayBuffer', 2)); Formatter.add('object', 'typed-array', 'int8', Formatter.generateFunctionForIndexedArray('length', 'Int8Array', 2)); Formatter.add('object', 'typed-array', 'uint8', Formatter.generateFunctionForIndexedArray('length', 'Uint8Array', 2)); Formatter.add('object', 'typed-array', 'uint8clamped', Formatter.generateFunctionForIndexedArray('length', 'Uint8ClampedArray', 2)); Formatter.add('object', 'typed-array', 'int16', Formatter.generateFunctionForIndexedArray('length', 'Int16Array', 4)); Formatter.add('object', 'typed-array', 'uint16', Formatter.generateFunctionForIndexedArray('length', 'Uint16Array', 4)); Formatter.add('object', 'typed-array', 'int32', Formatter.generateFunctionForIndexedArray('length', 'Int32Array', 8)); Formatter.add('object', 'typed-array', 'uint32', Formatter.generateFunctionForIndexedArray('length', 'Uint32Array', 8)); //TODO add float32 and float64 Formatter.add('object', 'promise', function() { return '[Promise]';//TODO it could be nice to inspect its state and value }); Formatter.add('object', 'xhr', function() { return '[XMLHttpRequest]';//TODO it could be nice to inspect its state }); Formatter.add('object', 'html-element', function(value) { return value.outerHTML; }); Formatter.add('object', 'html-element', '#text', function(value) { return value.nodeValue; }); Formatter.add('object', 'html-element', '#document', function(value) { return value.documentElement.outerHTML; }); Formatter.add('object', 'host', function() { return '[Host]'; }); Formatter.add('object', 'set', function(value) { var iter = value.values(); var len = 0; this.seen.push(value); var props = []; var next = iter.next(); while(!next.done) { var val = next.value; var f = this.format(val); len += f.length; props.push(f); next = iter.next(); } this.seen.pop(); if(props.length === 0) return 'Set {}'; if(len <= this.maxLineLength) { return 'Set { ' + props.join(this.propSep + ' ') + ' }'; } else { return 'Set {\n' + props.map(util.addSpaces).join(this.propSep + '\n') + '\n' + '}'; } }); Formatter.add('object', 'map', function(value) { var iter = value.entries(); var len = 0; this.seen.push(value); var props = []; var next = iter.next(); while(!next.done) { var val = next.value; var fK = this.format(val[0]); var fV = this.format(val[1]); var f; if((fK.length + fV.length + 4) <= this.maxLineLength) { f = fK + ' => ' + fV; } else { f = fK + ' =>\n' + fV; } len += fK.length + fV.length + 4; props.push(f); next = iter.next(); } this.seen.pop(); if(props.length === 0) return 'Map {}'; if(len <= this.maxLineLength) { return 'Map { ' + props.join(this.propSep + ' ') + ' }'; } else { return 'Map {\n' + props.map(util.addSpaces).join(this.propSep + '\n') + '\n' + '}'; } }); Formatter.prototype.defaultFormat = Formatter.prototype._format_object; function defaultFormat(value, opts) { return new Formatter(opts).format(value); } defaultFormat.Formatter = Formatter; module.exports = defaultFormat; },{"./util":22,"should-type":23}],22:[function(require,module,exports){ function addSpaces(v) { return v.split('\n').map(function(vv) { return ' ' + vv; }).join('\n'); } function pad(str, value, filler) { str = String(str) var isRight = false; if(value < 0) { isRight = true; value = -value; } if(str.length < value) { var padding = new Array(value - str.length + 1).join(filler); return isRight ? str + padding : padding + str; } else{ return str; } } module.exports = { addSpaces: addSpaces, pad: pad, pad0: function(str, value) { return pad(str, value, '0'); } }; },{}],23:[function(require,module,exports){ var toString = Object.prototype.toString; var types = require('./types'); /** * Simple data function to store type information * @param {string} type Usually what is returned from typeof * @param {string} cls Sanitized @Class via Object.prototype.toString * @param {string} sub If type and cls the same, and need to specify somehow * @private * @example * * //for null * new Type('null'); * * //for Date * new Type('object', 'date'); * * //for Uint8Array * * new Type('object', 'typed-array', 'uint8'); */ function Type(type, cls, sub) { this.type = type; this.cls = cls; this.sub = sub; } /** * Function to store type checks * @private */ function TypeChecker() { this.checks = []; } TypeChecker.prototype = { add: function(func) { this.checks.push(func); return this; }, addTypeOf: function(type, res) { return this.add(function(obj, tpeOf) { if(tpeOf === type) { return new Type(res); } }); }, addClass: function(cls, res, sub) { return this.add(function(obj, tpeOf, objCls) { if(objCls === cls) { return new Type(types.OBJECT, res, sub); } }); }, getType: function(obj) { var typeOf = typeof obj; var cls = toString.call(obj); for(var i = 0, l = this.checks.length; i < l; i++) { var res = this.checks[i].call(this, obj, typeOf, cls); if(typeof res !== 'undefined') return res; } } }; var main = new TypeChecker(); //TODO add iterators main .addTypeOf(types.NUMBER, types.NUMBER) .addTypeOf(types.UNDEFINED, types.UNDEFINED) .addTypeOf(types.STRING, types.STRING) .addTypeOf(types.BOOLEAN, types.BOOLEAN) .addTypeOf(types.FUNCTION, types.FUNCTION) .addTypeOf(types.SYMBOL, types.SYMBOL) .add(function(obj, tpeOf) { if(obj === null) return new Type(types.NULL); }) .addClass('[object String]', types.STRING) .addClass('[object Boolean]', types.BOOLEAN) .addClass('[object Number]', types.NUMBER) .addClass('[object Array]', types.ARRAY) .addClass('[object RegExp]', types.REGEXP) .addClass('[object Error]', types.ERROR) .addClass('[object Date]', types.DATE) .addClass('[object Arguments]', types.ARGUMENTS) .addClass('[object Math]') .addClass('[object JSON]') .addClass('[object ArrayBuffer]', types.ARRAY_BUFFER) .addClass('[object Int8Array]', types.TYPED_ARRAY, 'int8') .addClass('[object Uint8Array]', types.TYPED_ARRAY, 'uint8') .addClass('[object Uint8ClampedArray]', types.TYPED_ARRAY, 'uint8clamped') .addClass('[object Int16Array]', types.TYPED_ARRAY, 'int16') .addClass('[object Uint16Array]', types.TYPED_ARRAY, 'uint16') .addClass('[object Int32Array]', types.TYPED_ARRAY, 'int32') .addClass('[object Uint32Array]', types.TYPED_ARRAY, 'uint32') .addClass('[object Float32Array]', types.TYPED_ARRAY, 'float32') .addClass('[object Float64Array]', types.TYPED_ARRAY, 'float64') .addClass('[object DataView]', types.DATA_VIEW) .addClass('[object Map]', types.MAP) .addClass('[object WeakMap]', types.WEAK_MAP) .addClass('[object Set]', types.SET) .addClass('[object WeakSet]', types.WEAK_SET) .addClass('[object Promise]', types.PROMISE) .addClass('[object Blob]', types.BLOB) .addClass('[object File]', types.FILE) .addClass('[object FileList]', types.FILE_LIST) .addClass('[object XMLHttpRequest]', types.XHR) .add(function(obj) { if((typeof Promise === types.FUNCTION && obj instanceof Promise) || (typeof obj.then === types.FUNCTION)) { return new Type(types.OBJECT, types.PROMISE); } }) .add(function(obj) { if(typeof Buffer !== 'undefined' && obj instanceof Buffer) { return new Type(types.OBJECT, types.BUFFER); } }) .add(function(obj) { if(typeof Node !== 'undefined' && obj instanceof Node) { return new Type(types.OBJECT, types.HTML_ELEMENT, obj.nodeName); } }) .add(function(obj) { // probably at the begginging should be enough these checks if(obj.Boolean === Boolean && obj.Number === Number && obj.String === String && obj.Date === Date) { return new Type(types.OBJECT, types.HOST); } }) .add(function() { return new Type(types.OBJECT); }); /** * Get type information of anything * * @param {any} obj Anything that could require type information * @return {Type} type info */ function getGlobalType(obj) { return main.getType(obj); } getGlobalType.checker = main; getGlobalType.TypeChecker = TypeChecker; getGlobalType.Type = Type; Object.keys(types).forEach(function(typeName) { getGlobalType[typeName] = types[typeName]; }); module.exports = getGlobalType; },{"./types":24}],24:[function(require,module,exports){ var types = { NUMBER: 'number', UNDEFINED: 'undefined', STRING: 'string', BOOLEAN: 'boolean', OBJECT: 'object', FUNCTION: 'function', NULL: 'null', ARRAY: 'array', REGEXP: 'regexp', DATE: 'date', ERROR: 'error', ARGUMENTS: 'arguments', SYMBOL: 'symbol', ARRAY_BUFFER: 'array-buffer', TYPED_ARRAY: 'typed-array', DATA_VIEW: 'data-view', MAP: 'map', SET: 'set', WEAK_SET: 'weak-set', WEAK_MAP: 'weak-map', PROMISE: 'promise', // node buffer BUFFER: 'buffer', // dom html element HTML_ELEMENT: 'html-element', HTML_ELEMENT_TEXT: 'html-element-text', DOCUMENT: 'document', WINDOW: 'window', FILE: 'file', FILE_LIST: 'file-list', BLOB: 'blob', HOST: 'host', XHR: 'xhr' }; module.exports = types; },{}]},{},[1])(1) });