diff --git a/lib/chai/core/assertions.js b/lib/chai/core/assertions.js index d6b9f3444..330dc03e4 100644 --- a/lib/chai/core/assertions.js +++ b/lib/chai/core/assertions.js @@ -1635,7 +1635,7 @@ module.exports = function (chai, _) { * @alias changes * @alias Change * @param {String} object - * @param {String} property name + * @param {String} property name _optional_ * @param {String} message _optional_ * @namespace BDD * @api public @@ -1644,16 +1644,26 @@ module.exports = function (chai, _) { function assertChanges (object, prop, msg) { if (msg) flag(this, 'message', msg); var fn = flag(this, 'object'); - new Assertion(object, msg).to.have.property(prop); new Assertion(fn).is.a('function'); - var initial = object[prop]; + var initial; + if (!prop) { + new Assertion(object).is.a('function'); + initial = object(); + } else { + new Assertion(object, msg).to.have.property(prop); + initial = object[prop]; + } + fn(); + var final = prop === undefined ? object() : object[prop]; + var msgObj = prop === undefined ? initial : '.' + prop; + this.assert( - initial !== object[prop] - , 'expected .' + prop + ' to change' - , 'expected .' + prop + ' to not change' + initial !== final + , 'expected ' + msgObj + ' to change' + , 'expected ' + msgObj + ' to not change' ); } @@ -1682,16 +1692,26 @@ module.exports = function (chai, _) { function assertIncreases (object, prop, msg) { if (msg) flag(this, 'message', msg); var fn = flag(this, 'object'); - new Assertion(object, msg).to.have.property(prop); new Assertion(fn).is.a('function'); - var initial = object[prop]; + var initial; + if (!prop) { + new Assertion(object).is.a('function'); + initial = object(); + } else { + new Assertion(object, msg).to.have.property(prop); + initial = object[prop]; + } + fn(); + var final = prop === undefined ? object() : object[prop]; + var msgObj = prop === undefined ? initial : '.' + prop; + this.assert( - object[prop] - initial > 0 - , 'expected .' + prop + ' to increase' - , 'expected .' + prop + ' to not increase' + final - initial > 0 + , 'expected ' + msgObj + ' to increase' + , 'expected ' + msgObj + ' to not increase' ); } @@ -1720,16 +1740,26 @@ module.exports = function (chai, _) { function assertDecreases (object, prop, msg) { if (msg) flag(this, 'message', msg); var fn = flag(this, 'object'); - new Assertion(object, msg).to.have.property(prop); new Assertion(fn).is.a('function'); - var initial = object[prop]; + var initial; + if (!prop) { + new Assertion(object).is.a('function'); + initial = object(); + } else { + new Assertion(object, msg).to.have.property(prop); + initial = object[prop]; + } + fn(); + var final = prop === undefined ? object() : object[prop]; + var msgObj = prop === undefined ? initial : '.' + prop; + this.assert( - object[prop] - initial < 0 - , 'expected .' + prop + ' to decrease' - , 'expected .' + prop + ' to not decrease' + final - initial < 0 + , 'expected ' + msgObj + ' to decrease' + , 'expected ' + msgObj + ' to not decrease' ); } diff --git a/lib/chai/interface/assert.js b/lib/chai/interface/assert.js index 5099ea1d0..415264571 100644 --- a/lib/chai/interface/assert.js +++ b/lib/chai/interface/assert.js @@ -1354,14 +1354,19 @@ module.exports = function (chai, util) { * * @name changes * @param {Function} modifier function - * @param {Object} object - * @param {String} property name + * @param {Object} object or getter function + * @param {String} property name _optional_ * @param {String} message _optional_ * @namespace Assert * @api public */ assert.changes = function (fn, obj, prop, msg) { + if (arguments.length === 3 && typeof obj === 'function') { + msg = prop; + prop = null; + } + new Assertion(fn, msg).to.change(obj, prop); } @@ -1376,14 +1381,19 @@ module.exports = function (chai, util) { * * @name doesNotChange * @param {Function} modifier function - * @param {Object} object - * @param {String} property name + * @param {Object} object or getter function + * @param {String} property name _optional_ * @param {String} message _optional_ * @namespace Assert * @api public */ assert.doesNotChange = function (fn, obj, prop, msg) { + if (arguments.length === 3 && typeof obj === 'function') { + msg = prop; + prop = null; + } + new Assertion(fn, msg).to.not.change(obj, prop); } @@ -1398,14 +1408,19 @@ module.exports = function (chai, util) { * * @name increases * @param {Function} modifier function - * @param {Object} object - * @param {String} property name + * @param {Object} object or getter function + * @param {String} property name _optional_ * @param {String} message _optional_ * @namespace Assert * @api public */ assert.increases = function (fn, obj, prop, msg) { + if (arguments.length === 3 && typeof obj === 'function') { + msg = prop; + prop = null; + } + new Assertion(fn, msg).to.increase(obj, prop); } @@ -1420,14 +1435,19 @@ module.exports = function (chai, util) { * * @name doesNotIncrease * @param {Function} modifier function - * @param {Object} object - * @param {String} property name + * @param {Object} object or getter function + * @param {String} property name _optional_ * @param {String} message _optional_ * @namespace Assert * @api public */ assert.doesNotIncrease = function (fn, obj, prop, msg) { + if (arguments.length === 3 && typeof obj === 'function') { + msg = prop; + prop = null; + } + new Assertion(fn, msg).to.not.increase(obj, prop); } @@ -1442,14 +1462,19 @@ module.exports = function (chai, util) { * * @name decreases * @param {Function} modifier function - * @param {Object} object - * @param {String} property name + * @param {Object} object or getter function + * @param {String} property name _optional_ * @param {String} message _optional_ * @namespace Assert * @api public */ assert.decreases = function (fn, obj, prop, msg) { + if (arguments.length === 3 && typeof obj === 'function') { + msg = prop; + prop = null; + } + new Assertion(fn, msg).to.decrease(obj, prop); } @@ -1464,14 +1489,19 @@ module.exports = function (chai, util) { * * @name doesNotDecrease * @param {Function} modifier function - * @param {Object} object - * @param {String} property name + * @param {Object} object or getter function + * @param {String} property name _optional_ * @param {String} message _optional_ * @namespace Assert * @api public */ assert.doesNotDecrease = function (fn, obj, prop, msg) { + if (arguments.length === 3 && typeof obj === 'function') { + msg = prop; + prop = null; + } + new Assertion(fn, msg).to.not.decrease(obj, prop); } diff --git a/test/assert.js b/test/assert.js index 2432d64c2..29b98fb5e 100644 --- a/test/assert.js +++ b/test/assert.js @@ -873,17 +873,26 @@ describe('assert', function () { it('change', function() { var obj = { value: 10, str: 'foo' }, + heroes = ['spiderman', 'superman'], fn = function() { obj.value += 5 }, bangFn = function() { obj.str += '!' }, - smFn = function() { 'foo' + 'bar' }; + smFn = function() { 'foo' + 'bar' }, + batFn = function() { heroes.push('batman') }, + lenFn = function() { return heroes.length }; assert.changes(fn, obj, 'value'); assert.doesNotChange(smFn, obj, 'value'); assert.changes(bangFn, obj, 'str'); + assert.changes(batFn, lenFn); + assert.doesNotChange(smFn, lenFn); }); it('increase, decrease', function() { var obj = { value: 10 }, + arr = ['one', 'two'], + pFn = function() { arr.push('three') }, + popFn = function() { arr.pop() }, + lenFn = function() { return arr.length }, incFn = function() { obj.value += 2 }, decFn = function() { obj.value -= 3 }, smFn = function() { obj.value += 0 }; @@ -893,6 +902,12 @@ describe('assert', function () { assert.increases(incFn, obj, 'value'); assert.doesNotIncrease(smFn, obj, 'value'); + + assert.decreases(popFn, lenFn); + assert.doesNotDecrease(pFn, lenFn); + + assert.increases(pFn, lenFn); + assert.doesNotIncrease(popFn, lenFn); }); it('isExtensible / extensible', function() { diff --git a/test/expect.js b/test/expect.js index 79068e444..df4d142be 100644 --- a/test/expect.js +++ b/test/expect.js @@ -1121,18 +1121,28 @@ describe('expect', function () { it('change', function() { var obj = { value: 10, str: 'foo' }, + heroes = ['spiderman', 'superman'], fn = function() { obj.value += 5 }, sameFn = function() { 'foo' + 'bar' }, - bangFn = function() { obj.str += '!' }; + bangFn = function() { obj.str += '!' }, + batFn = function() { heroes.push('batman') }, + lenFn = function() { return heroes.length }; expect(fn).to.change(obj, 'value'); expect(sameFn).to.not.change(obj, 'value'); expect(sameFn).to.not.change(obj, 'str'); expect(bangFn).to.change(obj, 'str'); + expect(batFn).to.change(lenFn); + expect(sameFn).to.not.change(lenFn); }); it('increase, decrease', function() { var obj = { value: 10 }, + arr = ['one', 'two'], + pFn = function() { arr.push('three') }, + popFn = function() { arr.pop() }, + nFn = function() { return null }, + lenFn = function() { return arr.length }, incFn = function() { obj.value += 2 }, decFn = function() { obj.value -= 3 }, smFn = function() { obj.value += 0 }; @@ -1144,6 +1154,14 @@ describe('expect', function () { expect(smFn).to.not.decrease(obj, 'value'); expect(incFn).to.not.decrease(obj, 'value'); expect(decFn).to.decrease(obj, 'value'); + + expect(popFn).to.not.increase(lenFn); + expect(nFn).to.not.increase(lenFn); + expect(pFn).to.increase(lenFn); + + expect(popFn).to.decrease(lenFn); + expect(nFn).to.not.decrease(lenFn); + expect(pFn).to.not.decrease(lenFn); }); it('extensible', function() { diff --git a/test/should.js b/test/should.js index 0fde10b9d..ced29651d 100644 --- a/test/should.js +++ b/test/should.js @@ -950,19 +950,30 @@ describe('should', function() { it('change', function() { var obj = { value: 10, str: 'foo' }, + heroes = ['spiderman', 'superman'], fn = function() { obj.value += 5 }, sameFn = function() { obj.value += 0 }, decFn = function() { obj.value -= 3 }, - bangFn = function() { obj.str += '!' }; + bangFn = function() { obj.str += '!' }, + batFn = function() { heroes.push('batman') }, + lenFn = function() { return heroes.length }, + noFn = function() { return null }; fn.should.change(obj, 'value'); sameFn.should.not.change(obj, 'value'); sameFn.should.not.change(obj, 'str'); bangFn.should.change(obj, 'str'); + batFn.should.change(lenFn); + noFn.should.not.change(lenFn); }); it('increase, decrease', function() { var obj = { value: 10 }, + arr = ['one', 'two'], + pFn = function() { arr.push('three') }, + popFn = function() { arr.pop() }, + lenFn = function() { return arr.length }, + nFn = function() { return null }, incFn = function() { obj.value += 2 }, decFn = function() { obj.value -= 3 }, smFn = function() { obj.value += 0 }; @@ -974,6 +985,14 @@ describe('should', function() { smFn.should.not.decrease(obj, 'value'); incFn.should.not.decrease(obj, 'value'); decFn.should.decrease(obj, 'value'); + + nFn.should.not.increase(lenFn); + popFn.should.not.increase(lenFn); + pFn.should.increase(lenFn); + + nFn.should.not.decrease(lenFn); + pFn.should.not.decrease(lenFn); + popFn.should.decrease(lenFn); }); it('extensible', function() {