From d10b2d59fde3b6feb0f3e9fea0f77bc6242d6891 Mon Sep 17 00:00:00 2001 From: Guillaume Gautreau Date: Mon, 14 Sep 2015 20:40:39 +0100 Subject: [PATCH] Adds support for properties() --- README.md | 21 +++++++++++++++ index.js | 46 +++++++++++++++++++++++++++++++++ test/expect.js | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+) diff --git a/README.md b/README.md index 7f5b5df..e449b73 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,27 @@ expect({ a: 'b', c: 'd' }).to.only.have.keys(['a', 'c']); expect({ a: 'b', c: 'd' }).to.not.only.have.key('a'); ``` +**properties**: asserts the presence of properties and a value. Supports the `own` modifier. + +```js +expect({a: 'b', c: 'd', e: 'f'}).to.have.properties({a: 'b', c: 'd'}); + +expect({a: 'b', c: 'd', e: 'f'}).not.to.have.properties({a: 'z'}); +expect({a: 'b', c: 'd', e: 'f'}).not.to.have.properties({z: 'z'}); +expect({a: 'b', c: 'd', e: 'f'}).not.to.have.properties({a: 'b', z: 'z'}); + +function Target(){ + this.hello = 'world'; +} + +Target.prototype.foo = 'bar'; + +expect(new Target()).to.have.own.properties({ hello: 'world' }); + +expect(new Target()).not.to.have.own.properties({ foo: 'bar' }); +expect(new Target()).not.to.have.own.properties({ foo: 'bar', hello: 'world' }); +``` + **throw**/**throwException**/**throwError**: asserts that the `Function` throws or not when called ```js diff --git a/index.js b/index.js index 04d8371..e745f7b 100644 --- a/index.js +++ b/index.js @@ -398,6 +398,52 @@ return this; }; + Assertion.prototype.properties = function(expected){ + var testPresence = this.flags.own ? testOwn : testExists, + modifier = this.flags.own ? 'own ' : '', + that = this; + + that.assert( + testProperties(), + function(){ return 'expected ' + i(this.obj) + ' to have ' + modifier + 'properties ' + i(expected) }, + function(){ return 'expected ' + i(this.obj) + ' to not have ' + modifier + 'properties ' + i(expected) } + ) + + //////////////////////////////////////////////////////////////////////////// + + function testProperties(){ + var result = true; + + if (expected === null || expected === undefined){ + return !that.flags.not; + } + + for (var key in expected){ + if (expected.hasOwnProperty(key)){ + result = testPresence(key) && testValue(key) && result; + } + } + + return result; + } + + function testValue(name){ + return expected[name] === that.obj[name]; + } + + function testOwn(name){ + return that.obj && that.obj.hasOwnProperty(name); + } + + function testExists(name){ + try{ + return name in that.obj; + }catch(e){ + return that.obj && (that.obj !== undefined); + } + } + } + /** * Assert that the array contains _obj_ or string contains _obj_. * diff --git a/test/expect.js b/test/expect.js index 0185388..f053d7b 100644 --- a/test/expect.js +++ b/test/expect.js @@ -570,4 +570,73 @@ describe('expect', function () { }, "explicit failure with message"); }); + it('should test properties (object with key=value)', function(){ + expect({ foo: 'bar', hello: 42 }).to.have.properties({ foo: 'bar', hello: 42}); + expect({ foo: 'bar', hello: 42, world: false }).to.have.properties({ foo: 'bar', hello: 42}); + + expect({ foo: 'bar'}).not.to.have.properties({ hello: 'world'}); + expect({ foo: 'bar'}).not.to.have.properties({ foo: 'bar', hello: 'world'}); + expect({ foo: 'bar'}).not.to.have.properties({ foo: 'world'}); + expect({ foo: 'bar'}).not.to.have.properties({ hello: 'bar'}); + + expect({ foo: undefined}).to.have.properties({ foo: undefined}); + expect({ foo: 'bar'}).to.not.have.properties({ foo: undefined}); + expect({}).to.not.have.properties({ foo: undefined}); + + expect({ foo: 'bar'}).to.have.properties(undefined); + expect({ foo: 'bar'}).not.to.have.properties(undefined); + + expect({ foo: 'bar'}).to.have.properties(null); + expect({ foo: 'bar'}).not.to.have.properties(null); + + expect(undefined).not.to.have.properties({ hello: 'world'}); + expect(null).not.to.have.properties({ hello: 'world'}); + + expect(null).to.have.properties(undefined); + expect(null).not.to.have.properties(undefined); + + expect(undefined).to.have.properties(undefined); + expect(undefined).not.to.have.properties(undefined); + + expect('1').to.have.properties({ length: 1 }); + + err(function(){ + expect({ foo: 'bar'}).to.have.properties({ hello: 'world'}); + }, "expected { foo: 'bar' } to have properties { hello: 'world' }"); + + err(function(){ + expect({ foo: 'bar'}).to.have.properties({ foo: 'bar', hello: 'world'}); + }, "expected { foo: 'bar' } to have properties { foo: 'bar', hello: 'world' }"); + + err(function(){ + expect({ foo: 'bar'}).to.have.properties({ foo: 'world'}); + }, "expected { foo: 'bar' } to have properties { foo: 'world' }"); + + err(function(){ + expect({ foo: 'bar'}).to.have.properties({ hello: 'bar'}); + }, "expected { foo: 'bar' } to have properties { hello: 'bar' }"); + + err(function(){ + expect(undefined).to.have.properties({ foo: 'bar'}); + }, "expected undefined to have properties { foo: 'bar' }"); + }); + + it('should test own properties (object with key=value)', function(){ + function Target(){} + Target.prototype.foo = 'bar'; + + expect(new Target()).to.have.properties({ foo: 'bar'}); + expect(new Target()).not.to.have.own.properties({ foo: 'bar'}); + + expect({foo: 'bar'}).to.have.own.properties({ foo: 'bar'}); + + err(function(){ + expect(new Target()).to.have.own.properties({ foo: 'bar'}); + }, "expected {} to have own properties { foo: 'bar' }"); + + err(function(){ + expect({foo: 'bar'}).not.to.have.own.properties({ foo: 'bar'}); + }, "expected { foo: 'bar' } to not have own properties { foo: 'bar' }"); + }); + });