chai@4.1.0

This commit is contained in:
v1adko 2017-06-24 09:30:03 +03:00
parent 2eddd79002
commit 45cb32710a
3 changed files with 205 additions and 89 deletions

290
chai.js
View file

@ -14,7 +14,7 @@ var used = [];
* Chai version
*/
exports.version = '4.0.2';
exports.version = '4.1.0';
/*!
* Assertion Error
@ -691,6 +691,16 @@ module.exports = function (chai, _) {
*
* expect({a: 1, b: 2, c: 3}).to.include({a: 1, b: 2});
*
* When the target is a Set or WeakSet, `.include` asserts that the given `val` is a
* member of the target. SameValueZero equality algorithm is used.
*
* expect(new Set([1, 2])).to.include(2);
*
* When the target is a Map, `.include` asserts that the given `val` is one of
* the values of the target. SameValueZero equality algorithm is used.
*
* expect(new Map([['a', 1], ['b', 2]])).to.include(2);
*
* Because `.include` does different things based on the target's type, it's
* important to check the target's type before using `.include`. See the `.a`
* doc for info on testing a target's type.
@ -699,8 +709,8 @@ module.exports = function (chai, _) {
*
* By default, strict (`===`) equality is used to compare array members and
* object properties. Add `.deep` earlier in the chain to use deep equality
* instead. See the `deep-eql` project page for info on the deep equality
* algorithm: https://github.com/chaijs/deep-eql.
* instead (WeakSet targets are not supported). See the `deep-eql` project
* page for info on the deep equality algorithm: https://github.com/chaijs/deep-eql.
*
* // Target array deeply (but not strictly) includes `{a: 1}`
* expect([{a: 1}]).to.deep.include({a: 1});
@ -810,25 +820,24 @@ module.exports = function (chai, _) {
* @api public
*/
function includeChainingBehavior () {
flag(this, 'contains', true);
function SameValueZero(a, b) {
return (_.isNaN(a) && _.isNaN(b)) || a === b;
}
function isDeepIncluded (arr, val) {
return arr.some(function (arrVal) {
return _.eql(arrVal, val);
});
function includeChainingBehavior () {
flag(this, 'contains', true);
}
function include (val, msg) {
if (msg) flag(this, 'message', msg);
_.expectTypes(this, ['array', 'object', 'string'], flag(this, 'ssfi'));
_.expectTypes(this, [
'array', 'object', 'string',
'map', 'set', 'weakset',
]);
var obj = flag(this, 'object')
, objType = _.type(obj).toLowerCase()
, isDeep = flag(this, 'deep')
, descriptor = isDeep ? 'deep ' : '';
, objType = _.type(obj).toLowerCase();
// This block is for asserting a subset of properties in an object.
if (objType === 'object') {
@ -865,10 +874,62 @@ module.exports = function (chai, _) {
return;
}
// Assert inclusion in an array or substring in a string.
var isDeep = flag(this, 'deep')
, descriptor = isDeep ? 'deep ' : ''
, included = false;
switch (objType) {
case 'string':
included = obj.indexOf(val) !== -1;
break;
case 'weakset':
if (isDeep) {
var flagMsg = flag(this, 'message')
, ssfi = flag(this, 'ssfi');
flagMsg = flagMsg ? flagMsg + ': ' : '';
throw new AssertionError(
flagMsg + 'unable to use .deep.include with WeakSet',
undefined,
ssfi
);
}
included = obj.has(val);
break;
case 'map':
var isEql = isDeep ? _.eql : SameValueZero;
obj.forEach(function (item) {
included = included || isEql(item, val);
});
break;
case 'set':
if (isDeep) {
obj.forEach(function (item) {
included = included || _.eql(item, val);
});
} else {
included = obj.has(val);
}
break;
case 'array':
if (isDeep) {
included = obj.some(function (item) {
return _.eql(item, val);
})
} else {
included = obj.indexOf(val) !== -1;
}
break;
}
// Assert inclusion in collection or substring in a string.
this.assert(
objType === 'string' || !isDeep ? ~obj.indexOf(val)
: isDeepIncluded(obj, val)
included
, 'expected #{this} to ' + descriptor + 'include ' + _.inspect(val)
, 'expected #{this} to not ' + descriptor + 'include ' + _.inspect(val));
}
@ -1385,7 +1446,7 @@ module.exports = function (chai, _) {
/**
* ### .above(n[, msg])
*
* Asserts that the target is a number greater than the given number `n`.
* Asserts that the target is a number or a date greater than the given number or date `n` respectively.
* However, it's often best to assert that the target is equal to its expected
* value.
*
@ -1430,21 +1491,29 @@ module.exports = function (chai, _) {
var obj = flag(this, 'object')
, doLength = flag(this, 'doLength')
, flagMsg = flag(this, 'message')
, ssfi = flag(this, 'ssfi');
, msgPrefix = ((flagMsg) ? flagMsg + ': ' : '')
, ssfi = flag(this, 'ssfi')
, objType = _.type(obj).toLowerCase()
, nType = _.type(n).toLowerCase()
, shouldThrow = true;
if (doLength) {
new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
}
if (!doLength && (objType === 'date' && nType !== 'date')) {
errorMessage = msgPrefix + 'the argument to above must be a date';
} else if (nType !== 'number' && (doLength || objType === 'number')) {
errorMessage = msgPrefix + 'the argument to above must be a number';
} else if (!doLength && (objType !== 'date' && objType !== 'number')) {
var printObj = (objType === 'string') ? "'" + obj + "'" : obj;
errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date';
} else {
new Assertion(obj, flagMsg, ssfi, true).is.a('number');
shouldThrow = false;
}
if (typeof n !== 'number') {
flagMsg = flagMsg ? flagMsg + ': ' : '';
throw new AssertionError(
flagMsg + 'the argument to above must be a number',
undefined,
ssfi
);
if (shouldThrow) {
throw new AssertionError(errorMessage, undefined, ssfi);
}
if (doLength) {
@ -1459,8 +1528,9 @@ module.exports = function (chai, _) {
} else {
this.assert(
obj > n
, 'expected #{this} to be above ' + n
, 'expected #{this} to be at most ' + n
, 'expected #{this} to be above #{exp}'
, 'expected #{this} to be at most #{exp}'
, n
);
}
}
@ -1472,8 +1542,8 @@ module.exports = function (chai, _) {
/**
* ### .least(n[, msg])
*
* Asserts that the target is a number greater than or equal to the given
* number `n`. However, it's often best to assert that the target is equal to
* Asserts that the target is a number or a date greater than or equal to the given
* number or date `n` respectively. However, it's often best to assert that the target is equal to
* its expected value.
*
* expect(2).to.equal(2); // Recommended
@ -1517,21 +1587,29 @@ module.exports = function (chai, _) {
var obj = flag(this, 'object')
, doLength = flag(this, 'doLength')
, flagMsg = flag(this, 'message')
, ssfi = flag(this, 'ssfi');
, msgPrefix = ((flagMsg) ? flagMsg + ': ' : '')
, ssfi = flag(this, 'ssfi')
, objType = _.type(obj).toLowerCase()
, nType = _.type(n).toLowerCase()
, shouldThrow = true;
if (doLength) {
new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
} else {
new Assertion(obj, flagMsg, ssfi, true).is.a('number');
}
if (typeof n !== 'number') {
flagMsg = flagMsg ? flagMsg + ': ' : '';
throw new AssertionError(
flagMsg + 'the argument to least must be a number',
undefined,
ssfi
);
if (!doLength && (objType === 'date' && nType !== 'date')) {
errorMessage = msgPrefix + 'the argument to least must be a date';
} else if (nType !== 'number' && (doLength || objType === 'number')) {
errorMessage = msgPrefix + 'the argument to least must be a number';
} else if (!doLength && (objType !== 'date' && objType !== 'number')) {
var printObj = (objType === 'string') ? "'" + obj + "'" : obj;
errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date';
} else {
shouldThrow = false;
}
if (shouldThrow) {
throw new AssertionError(errorMessage, undefined, ssfi);
}
if (doLength) {
@ -1546,8 +1624,9 @@ module.exports = function (chai, _) {
} else {
this.assert(
obj >= n
, 'expected #{this} to be at least ' + n
, 'expected #{this} to be below ' + n
, 'expected #{this} to be at least #{exp}'
, 'expected #{this} to be below #{exp}'
, n
);
}
}
@ -1558,7 +1637,7 @@ module.exports = function (chai, _) {
/**
* ### .below(n[, msg])
*
* Asserts that the target is a number less than the given number `n`.
* Asserts that the target is a number or a date less than the given number or date `n` respectively.
* However, it's often best to assert that the target is equal to its expected
* value.
*
@ -1603,21 +1682,29 @@ module.exports = function (chai, _) {
var obj = flag(this, 'object')
, doLength = flag(this, 'doLength')
, flagMsg = flag(this, 'message')
, ssfi = flag(this, 'ssfi');
, msgPrefix = ((flagMsg) ? flagMsg + ': ' : '')
, ssfi = flag(this, 'ssfi')
, objType = _.type(obj).toLowerCase()
, nType = _.type(n).toLowerCase()
, shouldThrow = true;
if (doLength) {
new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
} else {
new Assertion(obj, flagMsg, ssfi, true).is.a('number');
}
if (typeof n !== 'number') {
flagMsg = flagMsg ? flagMsg + ': ' : '';
throw new AssertionError(
flagMsg + 'the argument to below must be a number',
undefined,
ssfi
);
if (!doLength && (objType === 'date' && nType !== 'date')) {
errorMessage = msgPrefix + 'the argument to below must be a date';
} else if (nType !== 'number' && (doLength || objType === 'number')) {
errorMessage = msgPrefix + 'the argument to below must be a number';
} else if (!doLength && (objType !== 'date' && objType !== 'number')) {
var printObj = (objType === 'string') ? "'" + obj + "'" : obj;
errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date';
} else {
shouldThrow = false;
}
if (shouldThrow) {
throw new AssertionError(errorMessage, undefined, ssfi);
}
if (doLength) {
@ -1632,8 +1719,9 @@ module.exports = function (chai, _) {
} else {
this.assert(
obj < n
, 'expected #{this} to be below ' + n
, 'expected #{this} to be at least ' + n
, 'expected #{this} to be below #{exp}'
, 'expected #{this} to be at least #{exp}'
, n
);
}
}
@ -1645,8 +1733,8 @@ module.exports = function (chai, _) {
/**
* ### .most(n[, msg])
*
* Asserts that the target is a number less than or equal to the given number
* `n`. However, it's often best to assert that the target is equal to its
* Asserts that the target is a number or a date less than or equal to the given number
* or date `n` respectively. However, it's often best to assert that the target is equal to its
* expected value.
*
* expect(1).to.equal(1); // Recommended
@ -1689,21 +1777,29 @@ module.exports = function (chai, _) {
var obj = flag(this, 'object')
, doLength = flag(this, 'doLength')
, flagMsg = flag(this, 'message')
, ssfi = flag(this, 'ssfi');
, msgPrefix = ((flagMsg) ? flagMsg + ': ' : '')
, ssfi = flag(this, 'ssfi')
, objType = _.type(obj).toLowerCase()
, nType = _.type(n).toLowerCase()
, shouldThrow = true;
if (doLength) {
new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
}
if (!doLength && (objType === 'date' && nType !== 'date')) {
errorMessage = msgPrefix + 'the argument to most must be a date';
} else if (nType !== 'number' && (doLength || objType === 'number')) {
errorMessage = msgPrefix + 'the argument to most must be a number';
} else if (!doLength && (objType !== 'date' && objType !== 'number')) {
var printObj = (objType === 'string') ? "'" + obj + "'" : obj;
errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date';
} else {
new Assertion(obj, flagMsg, ssfi, true).is.a('number');
shouldThrow = false;
}
if (typeof n !== 'number') {
flagMsg = flagMsg ? flagMsg + ': ' : '';
throw new AssertionError(
flagMsg + 'the argument to most must be a number',
undefined,
ssfi
);
if (shouldThrow) {
throw new AssertionError(errorMessage, undefined, ssfi);
}
if (doLength) {
@ -1718,8 +1814,9 @@ module.exports = function (chai, _) {
} else {
this.assert(
obj <= n
, 'expected #{this} to be at most ' + n
, 'expected #{this} to be above ' + n
, 'expected #{this} to be at most #{exp}'
, 'expected #{this} to be above #{exp}'
, n
);
}
}
@ -1730,8 +1827,8 @@ module.exports = function (chai, _) {
/**
* ### .within(start, finish[, msg])
*
* Asserts that the target is a number greater than or equal to the given
* number `start`, and less than or equal to the given number `finish`.
* Asserts that the target is a number or a date greater than or equal to the given
* number or date `start`, and less than or equal to the given number or date `finish` respectively.
* However, it's often best to assert that the target is equal to its expected
* value.
*
@ -1773,24 +1870,35 @@ module.exports = function (chai, _) {
Assertion.addMethod('within', function (start, finish, msg) {
if (msg) flag(this, 'message', msg);
var obj = flag(this, 'object')
, range = start + '..' + finish
, doLength = flag(this, 'doLength')
, flagMsg = flag(this, 'message')
, ssfi = flag(this, 'ssfi');
, msgPrefix = ((flagMsg) ? flagMsg + ': ' : '')
, ssfi = flag(this, 'ssfi')
, objType = _.type(obj).toLowerCase()
, startType = _.type(start).toLowerCase()
, finishType = _.type(finish).toLowerCase()
, shouldThrow = true
, range = (startType === 'date' && finishType === 'date')
? start.toUTCString() + '..' + finish.toUTCString()
: start + '..' + finish;
if (doLength) {
new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
} else {
new Assertion(obj, flagMsg, ssfi, true).is.a('number');
}
if (typeof start !== 'number' || typeof finish !== 'number') {
flagMsg = flagMsg ? flagMsg + ': ' : '';
throw new AssertionError(
flagMsg + 'the arguments to within must be numbers',
undefined,
ssfi
);
if (!doLength && (objType === 'date' && (startType !== 'date' || finishType !== 'date'))) {
errorMessage = msgPrefix + 'the arguments to within must be dates';
} else if ((startType !== 'number' || finishType !== 'number') && (doLength || objType === 'number')) {
errorMessage = msgPrefix + 'the arguments to within must be numbers';
} else if (!doLength && (objType !== 'date' && objType !== 'number')) {
var printObj = (objType === 'string') ? "'" + obj + "'" : obj;
errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date';
} else {
shouldThrow = false;
}
if (shouldThrow) {
throw new AssertionError(errorMessage, undefined, ssfi);
}
if (doLength) {
@ -2005,6 +2113,7 @@ module.exports = function (chai, _) {
var isNested = flag(this, 'nested')
, isOwn = flag(this, 'own')
, flagMsg = flag(this, 'message')
, obj = flag(this, 'object')
, ssfi = flag(this, 'ssfi');
if (isNested && isOwn) {
@ -2016,9 +2125,17 @@ module.exports = function (chai, _) {
);
}
if (obj === null || obj === undefined) {
flagMsg = flagMsg ? flagMsg + ': ' : '';
throw new AssertionError(
flagMsg + 'Target cannot be null or undefined.',
undefined,
ssfi
);
}
var isDeep = flag(this, 'deep')
, negate = flag(this, 'negate')
, obj = flag(this, 'object')
, pathInfo = isNested ? _.getPathInfo(obj, name) : null
, value = isNested ? pathInfo.value : obj[name];
@ -7720,8 +7837,6 @@ module.exports = function compareByInspect(a, b) {
*
* @param {Mixed} obj constructed Assertion
* @param {Array} type A list of allowed types for this assertion
* @param {Function} ssfi starting point for removing implementation frames from
* stack trace of AssertionError
* @namespace Utils
* @name expectTypes
* @api public
@ -7731,8 +7846,9 @@ var AssertionError = require('assertion-error');
var flag = require('./flag');
var type = require('type-detect');
module.exports = function expectTypes(obj, types, ssfi) {
module.exports = function expectTypes(obj, types) {
var flagMsg = flag(obj, 'message');
var ssfi = flag(obj, 'ssfi');
flagMsg = flagMsg ? flagMsg + ': ' : '';
@ -7740,7 +7856,7 @@ module.exports = function expectTypes(obj, types, ssfi) {
types = types.map(function (t) { return t.toLowerCase(); });
types.sort();
// Transforms ['lorem', 'ipsum'] into 'a lirum, or an ipsum'
// Transforms ['lorem', 'ipsum'] into 'a lorem, or an ipsum'
var str = types.map(function (t, index) {
var art = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(t.charAt(0)) ? 'an' : 'a';
var or = types.length > 1 && index === types.length - 1 ? 'or ' : '';
@ -8257,7 +8373,7 @@ function formatValue(ctx, value, recurseTimes) {
var container = document.createElementNS(ns, '_');
container.appendChild(value.cloneNode(false));
html = container.innerHTML
var html = container.innerHTML
.replace('><', '>' + value.innerHTML + '<');
container.innerHTML = '';
return html;

View file

@ -10,7 +10,7 @@ var used = [];
* Chai version
*/
exports.version = '4.0.2';
exports.version = '4.1.0';
/*!
* Assertion Error

View file

@ -17,7 +17,7 @@
"Veselin Todorov <hi@vesln.com>",
"John Firebaugh <john.firebaugh@gmail.com>"
],
"version": "4.0.2",
"version": "4.1.0",
"repository": {
"type": "git",
"url": "https://github.com/chaijs/chai"