mirror of
https://github.com/chaijs/chai
synced 2024-11-15 00:07:11 +00:00
Merge pull request #721 from meeber/property-validation
Throw when non-existent property is read
This commit is contained in:
commit
3ef86fdbf6
8 changed files with 133 additions and 4 deletions
|
@ -33,6 +33,8 @@ module.exports = function (_chai, util) {
|
|||
flag(this, 'ssfi', stack || Assertion);
|
||||
flag(this, 'object', obj);
|
||||
flag(this, 'message', msg);
|
||||
|
||||
return util.proxify(this);
|
||||
}
|
||||
|
||||
Object.defineProperty(Assertion, 'includeStack', {
|
||||
|
|
|
@ -300,7 +300,7 @@ module.exports = function (chai, _) {
|
|||
true === flag(this, 'object')
|
||||
, 'expected #{this} to be true'
|
||||
, 'expected #{this} to be false'
|
||||
, this.negate ? false : true
|
||||
, flag(this, 'negate') ? false : true
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -322,7 +322,7 @@ module.exports = function (chai, _) {
|
|||
false === flag(this, 'object')
|
||||
, 'expected #{this} to be false'
|
||||
, 'expected #{this} to be true'
|
||||
, this.negate ? true : false
|
||||
, flag(this, 'negate') ? true : false
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -1528,7 +1528,7 @@ module.exports = function (chai, _) {
|
|||
result
|
||||
, 'expected #{this} to satisfy ' + _.objDisplay(matcher)
|
||||
, 'expected #{this} to not satisfy' + _.objDisplay(matcher)
|
||||
, this.negate ? false : true
|
||||
, flag(this, 'negate') ? false : true
|
||||
, result
|
||||
);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
var transferFlags = require('./transferFlags');
|
||||
var flag = require('./flag');
|
||||
var proxify = require('./proxify');
|
||||
|
||||
/*!
|
||||
* Module variables
|
||||
|
@ -104,7 +105,7 @@ module.exports = function (ctx, name, method, chainingBehavior) {
|
|||
}
|
||||
|
||||
transferFlags(this, assert);
|
||||
return assert;
|
||||
return proxify(assert);
|
||||
}
|
||||
, configurable: true
|
||||
});
|
||||
|
|
|
@ -152,3 +152,9 @@ exports.getOwnEnumerableProperties = require('./getOwnEnumerableProperties');
|
|||
*/
|
||||
|
||||
exports.checkError = require('check-error');
|
||||
|
||||
/*!
|
||||
* Proxify util
|
||||
*/
|
||||
|
||||
exports.proxify = require('./proxify');
|
||||
|
|
35
lib/chai/utils/proxify.js
Normal file
35
lib/chai/utils/proxify.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*!
|
||||
* Chai - proxify utility
|
||||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* # proxify(object)
|
||||
*
|
||||
* Return a proxy of given object that throws an error when a non-existent
|
||||
* property is read. (If Proxy or Reflect is undefined, then return object
|
||||
* without modification.)
|
||||
*
|
||||
* @param {Object} obj
|
||||
* @namespace Utils
|
||||
* @name proxify
|
||||
*/
|
||||
|
||||
module.exports = function proxify (obj) {
|
||||
if (typeof Proxy === 'undefined' || typeof Reflect === 'undefined')
|
||||
return obj;
|
||||
|
||||
return new Proxy(obj, {
|
||||
get: function getProperty (target, property) {
|
||||
// Don't throw error on Symbol properties such as Symbol.toStringTag, nor
|
||||
// on .then because it's necessary for promise type-checking.
|
||||
if (typeof property === 'string' &&
|
||||
property !== 'then' &&
|
||||
!Reflect.has(target, property))
|
||||
throw Error('Invalid Chai property: ' + property);
|
||||
|
||||
return target[property];
|
||||
}
|
||||
});
|
||||
};
|
|
@ -10,6 +10,31 @@ describe('expect', function () {
|
|||
expect('foo').to.equal('foo');
|
||||
});
|
||||
|
||||
it('invalid property', function () {
|
||||
if (typeof Proxy === 'undefined' || typeof Reflect === 'undefined') return;
|
||||
|
||||
err(function () {
|
||||
expect(42).pizza;
|
||||
}, 'Invalid Chai property: pizza');
|
||||
|
||||
err(function () {
|
||||
expect(42).to.pizza;
|
||||
}, 'Invalid Chai property: pizza');
|
||||
|
||||
err(function () {
|
||||
expect(42).to.be.a.pizza;
|
||||
}, 'Invalid Chai property: pizza');
|
||||
|
||||
err(function () {
|
||||
expect(42).to.equal(42).pizza;
|
||||
}, 'Invalid Chai property: pizza');
|
||||
|
||||
// .then is excluded from property validation for promise support
|
||||
expect(function () {
|
||||
expect(42).then;
|
||||
}).to.not.throw();
|
||||
});
|
||||
|
||||
it('no-op chains', function() {
|
||||
function test(chain) {
|
||||
// tests that chain exists
|
||||
|
|
|
@ -7,6 +7,31 @@ describe('should', function() {
|
|||
should.not.equal('foo', 'bar');
|
||||
});
|
||||
|
||||
it('invalid property', function () {
|
||||
if (typeof Proxy === 'undefined' || typeof Reflect === 'undefined') return;
|
||||
|
||||
err(function () {
|
||||
(42).should.pizza;
|
||||
}, 'Invalid Chai property: pizza');
|
||||
|
||||
err(function () {
|
||||
(42).should.be.pizza;
|
||||
}, 'Invalid Chai property: pizza');
|
||||
|
||||
err(function () {
|
||||
(42).should.be.a.pizza;
|
||||
}, 'Invalid Chai property: pizza');
|
||||
|
||||
err(function () {
|
||||
(42).should.equal(42).pizza;
|
||||
}, 'Invalid Chai property: pizza');
|
||||
|
||||
// .then is excluded from property validation for promise support
|
||||
(function () {
|
||||
(42).should.then;
|
||||
}).should.not.throw();
|
||||
});
|
||||
|
||||
it('no-op chains', function() {
|
||||
function test(chain) {
|
||||
// tests that chain exists
|
||||
|
|
|
@ -844,4 +844,39 @@ describe('utilities', function () {
|
|||
expect(gettem(obj)).to.have.same.members([cat, dog, bird]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('proxified object', function () {
|
||||
if (typeof Proxy === 'undefined' || typeof Reflect === 'undefined') return;
|
||||
|
||||
var proxify;
|
||||
|
||||
beforeEach(function () {
|
||||
chai.use(function (_chai, _) {
|
||||
proxify = _.proxify;
|
||||
});
|
||||
});
|
||||
|
||||
it('returns property value if an existing property is read', function () {
|
||||
var pizza = proxify({mushrooms: 42});
|
||||
|
||||
expect(pizza.mushrooms).to.equal(42);
|
||||
});
|
||||
|
||||
it('throws error if a non-existent property is read', function () {
|
||||
var pizza = proxify({});
|
||||
|
||||
expect(function () {
|
||||
pizza.mushrooms;
|
||||
}).to.throw('Invalid Chai property: mushrooms');
|
||||
});
|
||||
|
||||
// .then is excluded from property validation for promise support
|
||||
it('doesn\'t throw error if non-existent `then` is read', function () {
|
||||
var pizza = proxify({});
|
||||
|
||||
expect(function () {
|
||||
pizza.then;
|
||||
}).to.not.throw();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue