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

Assertion subject (obj) changes when using ownProperty assertion #641

Merged
merged 2 commits into from Mar 15, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
48 changes: 40 additions & 8 deletions lib/chai/core/assertions.js
Expand Up @@ -880,27 +880,59 @@ module.exports = function (chai, _) {


/**
* ### .ownProperty(name)
* ### .ownProperty(name, [value])
*
* Asserts that the target has an own property `name`.
* Asserts that the target has an own property `name` and, optionally, if it has
* (or not, if using `.not`) the desired `value`.
*
* expect('test').to.have.ownProperty('length');
* expect('test').to.haveOwnProperty('length');
* expect('test').to.not.have.ownProperty('foo');
* expect('test').to.not.haveOwnProperty('foo');
* expect({ length: 12 }).to.have.ownProperty('length', 12);
* expect({ length: 1337 }).to.not.have.ownProperty('length', 20);
* expect({ length: 12 }).to.haveOwnProperty('length', 12);
* expect({ length: 1337 }).to.not.haveOwnProperty('length', 20);
*
* @name ownProperty
* @alias haveOwnProperty
* @param {String} name
* @param {Mixed} value (optional)
* @param {String} message _optional_
* @namespace BDD
* @api public
*/

function assertOwnProperty (name, msg) {
function assertOwnProperty (name, value, msg) {
if (msg) flag(this, 'message', msg);
var obj = flag(this, 'object');
this.assert(
obj.hasOwnProperty(name)
, 'expected #{this} to have own property ' + _.inspect(name)
, 'expected #{this} to not have own property ' + _.inspect(name)
);
var negate = flag(this, 'negate');
var objHasProperty = obj.hasOwnProperty(name);
var actualValue = obj[name];

if (negate && value !== undefined) {
if (actualValue === undefined) {
throw new Error(_.inspect(obj) + ' does not have own property ' + _.inspect(name));
}
} else {
this.assert(
objHasProperty
, 'expected #{this} to have own property ' + _.inspect(name)
, 'expected #{this} to not have own property ' + _.inspect(name)
);
}

if (value !== undefined) {
this.assert(
actualValue === value
, 'expected #{this} to have own property ' + _.inspect(name) + ' of #{exp}, but got #{act}'
, 'expected #{this} to not have own property ' + _.inspect(name) + ' of #{act}'
, value
, actualValue
);
}

flag(this, 'object', actualValue);
}

Assertion.addMethod('ownProperty', assertOwnProperty);
Expand Down
76 changes: 76 additions & 0 deletions lib/chai/interface/assert.js
Expand Up @@ -976,6 +976,82 @@ module.exports = function (chai, util) {
new Assertion(obj, msg).to.not.have.deep.property(prop, val);
};

/**
* ### .ownProperty(object, property, [message])
*
* Asserts that `object` has an own property named by `property`.
*
* assert.ownProperty({ tea: { green: 'matcha' }}, 'tea');
*
* @name ownProperty
* @param {Object} object
* @param {String} property
* @param {String} message
* @api public
*/

assert.ownProperty = function (obj, prop, msg) {
new Assertion(obj, msg).to.have.ownProperty(prop);
};

/**
* ### .notOwnProperty(object, property, [message])
*
* Asserts that `object` does not have an own property named by `property`.
*
* assert.notOwnProperty({ tea: { green: 'matcha' }}, 'coffee');
*
* @name notOwnProperty
* @param {Object} object
* @param {String} property
* @param {String} message
* @api public
*/

assert.notOwnProperty = function (obj, prop, msg) {
new Assertion(obj, msg).to.not.have.ownProperty(prop);
};

/**
* ### .ownPropertyVal(object, property, value, [message])
*
* Asserts that `object` has an own property named by `property` and a value
* equal to the provided `value`.
*
* assert.ownPropertyVal({ coffee: 'is good'}, 'coffee', 'is good');
*
* @name ownPropertyVal
* @param {Object} object
* @param {String} property
* @param {Mixed} value
* @param {String} message
* @api public
*/

assert.ownPropertyVal = function (obj, prop, value, msg) {
new Assertion(obj, msg).to.have.ownProperty(prop, value);
};

/**
* ### .notOwnPropertyVal(object, property, value, [message])
*
* Asserts that `object` has an own property named by `property`, but with a value
* different from that given by `value`.
*
* assert.notOwnPropertyVal({ tea: 'is better'}, 'tea', 'is worse');
*
* @name notOwnPropertyVal
* @param {Object} object
* @param {String} property
* @param {Mixed} value
* @param {String} message
* @api public
*/

assert.notOwnPropertyVal = function (obj, prop, value, msg) {
new Assertion(obj, msg).to.not.have.ownProperty(prop, value);
};

/**
* ### .lengthOf(object, length, [message])
*
Expand Down
47 changes: 47 additions & 0 deletions test/assert.js
Expand Up @@ -547,6 +547,53 @@ describe('assert', function () {
}, "expected { foo: { bar: 'baz' } } to not have a deep property 'foo.bar' of 'baz'");
});

it('ownProperty', function() {
var coffeeObj = { coffee: 'is good' };

// This has length = 17
var teaObj = 'but tea is better';

assert.ownProperty(coffeeObj, 'coffee');
assert.ownProperty(teaObj, 'length');

assert.ownPropertyVal(coffeeObj, 'coffee', 'is good');
assert.ownPropertyVal(teaObj, 'length', 17);

assert.notOwnProperty(coffeeObj, 'length');
assert.notOwnProperty(teaObj, 'calories');

assert.notOwnPropertyVal(coffeeObj, 'coffee', 'is bad');
assert.notOwnPropertyVal(teaObj, 'length', 1);

err(function () {
assert.ownProperty(coffeeObj, 'calories');
}, "expected { coffee: 'is good' } to have own property 'calories'");

err(function () {
assert.notOwnProperty(coffeeObj, 'coffee');
}, "expected { coffee: 'is good' } to not have own property 'coffee'");

err(function () {
assert.ownPropertyVal(teaObj, 'length', 1);
}, "expected 'but tea is better' to have own property 'length' of 1, but got 17");

err(function () {
assert.notOwnPropertyVal(teaObj, 'length', 17);
}, "expected 'but tea is better' to not have own property 'length' of 17");

err(function () {
assert.ownPropertyVal(teaObj, 'calories', 17);
}, "expected 'but tea is better' to have own property 'calories'");

err(function () {
assert.ownPropertyVal(teaObj, 'calories', 17);
}, "expected 'but tea is better' to have own property 'calories'");

err(function () {
assert.notOwnPropertyVal(coffeeObj, 'sugar', 1337);
}, "{ coffee: 'is good' } does not have own property 'sugar'");
});

it('throws / throw / Throw', function() {
['throws', 'throw', 'Throw'].forEach(function (throws) {
assert[throws](function() { throw new Error('foo'); });
Expand Down
74 changes: 72 additions & 2 deletions test/expect.js
Expand Up @@ -593,11 +593,81 @@ describe('expect', function () {
it('ownProperty(name)', function(){
expect('test').to.have.ownProperty('length');
expect('test').to.haveOwnProperty('length');
expect('test').to.not.have.ownProperty('iDontExist');
expect('test').to.not.haveOwnProperty('iDontExist');

expect({ length: 12 }).to.have.ownProperty('length');
expect({ length: 12 }).to.haveOwnProperty('length');
expect({ length: 12 }).to.not.have.ownProperty('iDontExist');
expect({ length: 12 }).to.not.haveOwnProperty('iDontExist');

// Chaining property's value
expect('test').to.have.ownProperty('length').that.is.a('number');
expect('test').to.haveOwnProperty('length').that.is.a('number');

err(function(){
expect({ length: 12 }).to.have.ownProperty('iDontExist');
}, "expected { length: 12 } to have own property 'iDontExist'");

err(function(){
expect({ length: 12 }).to.not.have.ownProperty('length');
}, "expected { length: 12 } to not have own property 'length'");

err(function(){
expect({ length: 12 }).to.haveOwnProperty('iDontExist');
}, "expected { length: 12 } to have own property 'iDontExist'");

err(function(){
expect({ length: 12 }).to.not.haveOwnProperty('length');
}, "expected { length: 12 } to not have own property 'length'");
});

it('ownProperty(name, value)', function(){
expect('test').to.have.ownProperty('length', 4);
expect('test').to.haveOwnProperty('length', 4);
expect('test').to.not.have.ownProperty('length', 1337);
expect('test').to.not.haveOwnProperty('length', 1337);

expect({ length: 12 }).to.have.ownProperty('length', 12);
expect({ length: 12 }).to.haveOwnProperty('length', 12);
expect({ length: 12 }).to.not.have.ownProperty('length', 15);
expect({ length: 12 }).to.not.haveOwnProperty('length', 15);

// Chaining property's value
expect('test').to.have.ownProperty('length', 4).that.is.a('number');
expect('test').to.haveOwnProperty('length', 4).that.is.a('number');

err(function(){
expect({ length: 12 }).to.not.have.ownProperty('length', 'blah');
}, "blah: expected { length: 12 } to not have own property 'length'");
expect({ length: 12 }).to.have.ownProperty('iDontExist', 12);
}, "expected { length: 12 } to have own property 'iDontExist'");

err(function() {
expect({ length: 12 }).to.not.have.ownProperty('length', 12);
}, "expected { length: 12 } to not have own property 'length' of 12");

err(function() {
expect({ length: 12 }).to.have.ownProperty('length', 15);
}, "expected { length: 12 } to have own property 'length' of 15, but got 12");

err(function() {
expect({ length: 12 }).to.not.have.ownProperty('iDontExist', 15);
}, "{ length: 12 } does not have own property 'iDontExist'");

err(function(){
expect({ length: 12 }).to.haveOwnProperty('iDontExist', 12);
}, "expected { length: 12 } to have own property 'iDontExist'");

err(function() {
expect({ length: 12 }).to.not.haveOwnProperty('length', 12);
}, "expected { length: 12 } to not have own property 'length' of 12");

err(function() {
expect({ length: 12 }).to.haveOwnProperty('length', 15);
}, "expected { length: 12 } to have own property 'length' of 15, but got 12");

err(function() {
expect({ length: 12 }).to.not.haveOwnProperty('iDontExist', 15);
}, "{ length: 12 } does not have own property 'iDontExist'");
});

it('ownPropertyDescriptor(name)', function(){
Expand Down
74 changes: 72 additions & 2 deletions test/should.js
Expand Up @@ -424,11 +424,81 @@ describe('should', function() {
it('ownProperty(name)', function(){
'test'.should.have.ownProperty('length');
'test'.should.haveOwnProperty('length');
'test'.should.not.have.ownProperty('iDontExist');
'test'.should.not.haveOwnProperty('iDontExist');

({ length: 12 }).should.have.ownProperty('length');
({ length: 12 }).should.haveOwnProperty('length');
({ length: 12 }).should.not.have.ownProperty('iDontExist');
({ length: 12 }).should.not.haveOwnProperty('iDontExist');

// Chaining property's value
'test'.should.have.ownProperty('length').that.is.a('number');
'test'.should.haveOwnProperty('length').that.is.a('number');

err(function(){
({ length: 12 }).should.have.ownProperty('iDontExist');
}, "expected { length: 12 } to have own property 'iDontExist'");

err(function(){
({ length: 12 }).should.not.have.ownProperty('length');
}, "expected { length: 12 } to not have own property 'length'");

err(function(){
({ length: 12 }).should.haveOwnProperty('iDontExist');
}, "expected { length: 12 } to have own property 'iDontExist'");

err(function(){
({ length: 12 }).should.not.haveOwnProperty('length');
}, "expected { length: 12 } to not have own property 'length'");
});

it('ownProperty(name, value)', function(){
'test'.should.have.ownProperty('length', 4);
'test'.should.haveOwnProperty('length', 4);
'test'.should.not.have.ownProperty('length', 1337);
'test'.should.not.haveOwnProperty('length', 1337);

({ length: 12 }).should.have.ownProperty('length', 12);
({ length: 12 }).should.haveOwnProperty('length', 12);
({ length: 12 }).should.not.have.ownProperty('length', 15);
({ length: 12 }).should.not.haveOwnProperty('length', 15);

// Chaining property's value
'test'.should.have.ownProperty('length', 4).that.is.a('number');
'test'.should.haveOwnProperty('length', 4).that.is.a('number');

err(function(){
({ length: 12 }).should.not.have.ownProperty('length', 'blah');
}, "blah: expected { length: 12 } to not have own property 'length'");
({ length: 12 }).should.have.ownProperty('iDontExist', 12);
}, "expected { length: 12 } to have own property 'iDontExist'");

err(function() {
({ length: 12 }).should.not.have.ownProperty('length', 12);
}, "expected { length: 12 } to not have own property 'length' of 12");

err(function() {
({ length: 12 }).should.have.ownProperty('length', 15);
}, "expected { length: 12 } to have own property 'length' of 15, but got 12");

err(function() {
({ length: 12 }).should.not.have.ownProperty('iDontExist', 15);
}, "{ length: 12 } does not have own property 'iDontExist'");

err(function(){
({ length: 12 }).should.haveOwnProperty('iDontExist', 12);
}, "expected { length: 12 } to have own property 'iDontExist'");

err(function() {
({ length: 12 }).should.not.haveOwnProperty('length', 12);
}, "expected { length: 12 } to not have own property 'length' of 12");

err(function() {
({ length: 12 }).should.haveOwnProperty('length', 15);
}, "expected { length: 12 } to have own property 'length' of 15, but got 12");

err(function() {
({ length: 12 }).should.not.haveOwnProperty('iDontExist', 15);
}, "{ length: 12 } does not have own property 'iDontExist'");
});

it('ownPropertyDescriptor(name)', function(){
Expand Down