Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow dates for isBelow and isAbove assertions #990

Merged
merged 17 commits into from
Jun 23, 2017
171 changes: 109 additions & 62 deletions lib/chai/core/assertions.js
Original file line number Diff line number Diff line change
Expand Up @@ -1024,7 +1024,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.
*
Expand Down Expand Up @@ -1069,21 +1069,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) {
Expand All @@ -1098,8 +1106,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
);
}
}
Expand All @@ -1111,8 +1120,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
Expand Down Expand Up @@ -1156,21 +1165,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 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 {
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 least must be a number',
undefined,
ssfi
);
if (shouldThrow) {
throw new AssertionError(errorMessage, undefined, ssfi);
}

if (doLength) {
Expand All @@ -1185,8 +1202,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
);
}
}
Expand All @@ -1197,7 +1215,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.
*
Expand Down Expand Up @@ -1242,21 +1260,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 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 {
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 below must be a number',
undefined,
ssfi
);
if (shouldThrow) {
throw new AssertionError(errorMessage, undefined, ssfi);
}

if (doLength) {
Expand All @@ -1271,8 +1297,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
);
}
}
Expand All @@ -1284,8 +1311,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
Expand Down Expand Up @@ -1328,21 +1355,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) {
Expand All @@ -1357,8 +1392,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
);
}
}
Expand All @@ -1369,8 +1405,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.
*
Expand Down Expand Up @@ -1412,24 +1448,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');
}

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 {
new Assertion(obj, flagMsg, ssfi, true).is.a('number');
shouldThrow = false;
}

if (typeof start !== 'number' || typeof finish !== 'number') {
flagMsg = flagMsg ? flagMsg + ': ' : '';
throw new AssertionError(
flagMsg + 'the arguments to within must be numbers',
undefined,
ssfi
);
if (shouldThrow) {
throw new AssertionError(errorMessage, undefined, ssfi);
}

if (doLength) {
Expand Down
2 changes: 1 addition & 1 deletion lib/chai/utils/expectTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ module.exports = function expectTypes(obj, types) {
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 ' : '';
Expand Down