Skip to content

Commit

Permalink
Add ES6 Symbol support
Browse files Browse the repository at this point in the history
- Fix bug when testing Symbol equality with should syntax (#669)
- Fix bug when testing Symbol keys in Map and Set
- Add Symbol tests for assert, expect, and should
  • Loading branch information
meeber committed Apr 8, 2016
1 parent 816d526 commit ff8bba8
Show file tree
Hide file tree
Showing 5 changed files with 220 additions and 4 deletions.
10 changes: 7 additions & 3 deletions lib/chai/core/assertions.js
Original file line number Diff line number Diff line change
Expand Up @@ -1160,6 +1160,7 @@ module.exports = function (chai, _) {
var obj = flag(this, 'object')
, str
, ok = true
, isMapOrSet
, mixedArgsMsg = 'when testing keys against an object or an array you must give a single Array|Object|String argument or multiple String arguments';

if (_.type(obj) === 'map' || _.type(obj) === 'set') {
Expand All @@ -1169,6 +1170,7 @@ module.exports = function (chai, _) {
keys = Array.prototype.slice.call(arguments);
}

isMapOrSet = false;
} else {
actual = Object.keys(obj);

Expand All @@ -1185,6 +1187,8 @@ module.exports = function (chai, _) {
}

keys = keys.map(String);

isMapOrSet = true;
}

if (!keys.length) throw new Error('keys required');
Expand Down Expand Up @@ -1243,13 +1247,13 @@ module.exports = function (chai, _) {
// Have / include
str = (flag(this, 'contains') ? 'contain ' : 'have ') + str;

// Assertion
// Assertion (don't sort if isMapOrSet because keys could be Symbols)
this.assert(
ok
, 'expected #{this} to ' + str
, 'expected #{this} to not ' + str
, expected.slice(0).sort()
, actual.sort()
, isMapOrSet ? expected.slice(0).sort() : expected
, isMapOrSet ? actual.sort() : actual
, true
);
}
Expand Down
5 changes: 4 additions & 1 deletion lib/chai/interface/should.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ module.exports = function (chai, util) {
function loadShould () {
// explicitly define this method as function as to have it's name to include as `ssfi`
function shouldGetter() {
if (this instanceof String || this instanceof Number || this instanceof Boolean ) {
if (this instanceof String
|| this instanceof Number
|| this instanceof Boolean
|| typeof Symbol === 'function' && this instanceof Symbol) {
return new Assertion(this.valueOf(), null, shouldGetter);
}
return new Assertion(this, null, shouldGetter);
Expand Down
77 changes: 77 additions & 0 deletions test/assert.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,22 @@ describe('assert', function () {
it('equal', function () {
var foo;
assert.equal(foo, undefined);

if (typeof Symbol === 'function') {
var sym = Symbol();
assert.equal(sym, sym);
}
});

it('typeof', function () {
assert.typeOf('test', 'string');
assert.typeOf(true, 'boolean');
assert.typeOf(5, 'number');

if (typeof Symbol === 'function') {
assert.typeOf(Symbol(), 'symbol');
}

err(function () {
assert.typeOf(5, 'string');
}, "expected 5 to be a string");
Expand Down Expand Up @@ -182,6 +191,12 @@ describe('assert', function () {
it('notEqual', function() {
assert.notEqual(3, 4);

if (typeof Symbol === 'function') {
var sym1 = Symbol()
, sym2 = Symbol();
assert.notEqual(sym1, sym2);
}

err(function () {
assert.notEqual(5, 5);
}, "expected 5 to not equal 5");
Expand All @@ -190,6 +205,11 @@ describe('assert', function () {
it('strictEqual', function() {
assert.strictEqual('foo', 'foo');

if (typeof Symbol === 'function') {
var sym = Symbol();
assert.strictEqual(sym, sym);
}

err(function () {
assert.strictEqual('5', 5);
}, "expected \'5\' to equal 5");
Expand All @@ -198,6 +218,12 @@ describe('assert', function () {
it('notStrictEqual', function() {
assert.notStrictEqual(5, '5');

if (typeof Symbol === 'function') {
var sym1 = Symbol()
, sym2 = Symbol();
assert.notStrictEqual(sym1, sym2);
}

err(function () {
assert.notStrictEqual(5, 5);
}, "expected 5 to not equal 5");
Expand Down Expand Up @@ -435,6 +461,12 @@ describe('assert', function () {
assert.include([ 1, 2, 3], 3);
assert.include({a:1, b:2}, {b:2});

if (typeof Symbol === 'function') {
var sym1 = Symbol()
, sym2 = Symbol();
assert.include([sym1, sym2], sym1);
}

err(function () {
assert.include('foobar', 'baz');
}, "expected \'foobar\' to include \'baz\'");
Expand All @@ -460,6 +492,13 @@ describe('assert', function () {
assert.notInclude('foobar', 'baz');
assert.notInclude([ 1, 2, 3 ], 4);

if (typeof Symbol === 'function') {
var sym1 = Symbol()
, sym2 = Symbol()
, sym3 = Symbol();
assert.notInclude([sym1, sym2], sym3);
}

err(function(){
assert.notInclude(true, true);
}, "object tested must be an array, an object, or a string, but boolean given");
Expand Down Expand Up @@ -538,6 +577,19 @@ describe('assert', function () {
assert.doesNotHaveAnyKeys(new Map([[aKey, 'aValue'], [anotherKey, 'anotherValue']]), [ 'thisDoesNotExist', 'thisToo', {iDoNot: 'exist'} ]);
assert.doesNotHaveAllKeys(new Map([[aKey, 'aValue'], [anotherKey, 'anotherValue']]), [ aKey, {iDoNot: 'exist'} ]);

if (typeof Symbol === 'function') {
var symKey1 = Symbol()
, symKey2 = Symbol()
, symKey3 = Symbol();

assert.hasAllKeys(new Map([[symKey1, 'symValue1'], [symKey2, 'symValue2']]), [symKey1, symKey2]);
assert.hasAnyKeys(new Map([[symKey1, 'symValue1'], [symKey2, 'symValue2']]), [symKey1, symKey3]);
assert.containsAllKeys(new Map([[symKey1, 'symValue1'], [symKey2, 'symValue2']]), [symKey2, symKey1]);

assert.doesNotHaveAllKeys(new Map([[symKey1, 'symValue1'], [symKey2, 'symValue2']]), [symKey1, symKey3]);
assert.doesNotHaveAnyKeys(new Map([[symKey1, 'symValue1'], [symKey2, 'symValue2']]), [symKey3]);
}

err(function(){
assert.hasAllKeys(new Map([[{1: 20}, 'number']]));
}, "keys required");
Expand Down Expand Up @@ -598,6 +650,19 @@ describe('assert', function () {
assert.doesNotHaveAnyKeys(new Set([aKey, anotherKey]), [ 20, 1, {iDoNot: 'exist'} ]);
assert.doesNotHaveAllKeys(new Set([aKey, anotherKey]), [ 'thisDoesNotExist', 'thisToo', {iDoNot: 'exist'} ]);

if (typeof Symbol === 'function') {
var symKey1 = Symbol()
, symKey2 = Symbol()
, symKey3 = Symbol();

assert.hasAllKeys(new Set([symKey1, symKey2]), [symKey1, symKey2]);
assert.hasAnyKeys(new Set([symKey1, symKey2]), [symKey1, symKey3]);
assert.containsAllKeys(new Set([symKey1, symKey2]), [symKey2, symKey1]);

assert.doesNotHaveAllKeys(new Set([symKey1, symKey2]), [symKey1, symKey3]);
assert.doesNotHaveAnyKeys(new Set([symKey1, symKey2]), [symKey3]);
}

err(function(){
assert.hasAllKeys(new Set([{1: 20}, 'number']));
}, "keys required");
Expand Down Expand Up @@ -1256,6 +1321,10 @@ describe('assert', function () {
assert[isNotExtensible]('foo');
assert[isNotExtensible](false);
assert[isNotExtensible](undefined);

if (typeof Symbol === 'function') {
assert[isNotExtensible](Symbol());
}
});
});

Expand All @@ -1276,6 +1345,10 @@ describe('assert', function () {
assert[isSealed]('foo');
assert[isSealed](false);
assert[isSealed](undefined);

if (typeof Symbol === 'function') {
assert[isSealed](Symbol());
}
});
});

Expand Down Expand Up @@ -1330,6 +1403,10 @@ describe('assert', function () {
assert[isFrozen]('foo');
assert[isFrozen](false);
assert[isFrozen](undefined);

if (typeof Symbol === 'function') {
assert[isFrozen](Symbol());
}
});
});

Expand Down
66 changes: 66 additions & 0 deletions test/expect.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ describe('expect', function () {
expect(function() {}).to.be.a('function');
expect(null).to.be.a('null');

if (typeof Symbol === 'function') {
expect(Symbol()).to.be.a('symbol');
}

err(function(){
expect(5).to.not.be.a('number', 'blah');
}, "blah: expected 5 not to be a number");
Expand Down Expand Up @@ -300,6 +304,11 @@ describe('expect', function () {
expect(1).to.eql(1);
expect('4').to.not.eql(4);

if (typeof Symbol === 'function') {
var sym = Symbol();
expect(sym).to.eql(sym);
}

err(function(){
expect(4).to.eql(3, 'blah');
}, 'blah: expected 4 to deeply equal 3');
Expand All @@ -319,6 +328,11 @@ describe('expect', function () {
expect('test').to.equal('test');
expect(1).to.equal(1);

if (typeof Symbol === 'function') {
var sym = Symbol();
expect(sym).to.equal(sym);
}

err(function(){
expect(4).to.equal(3, 'blah');
}, 'blah: expected 4 to equal 3');
Expand Down Expand Up @@ -624,6 +638,14 @@ describe('expect', function () {
expect([{a:1}]).to.include({a:1});
expect([{a:1}]).to.not.include({b:1});

if (typeof Symbol === 'function') {
var sym1 = Symbol()
, sym2 = Symbol()
, sym3 = Symbol();
expect([sym1, sym2]).to.include(sym1);
expect([sym1, sym2]).to.not.include(sym3);
}

err(function(){
expect(['foo']).to.include('bar', 'blah');
}, "blah: expected [ 'foo' ] to include 'bar'");
Expand Down Expand Up @@ -744,6 +766,22 @@ describe('expect', function () {
expect(new Map([[aKey, 'aValue'], [anotherKey, 'anotherValue']])).to.not.have.any.keys([20, 1, {13: 37}]);
expect(new Map([[aKey, 'aValue'], [anotherKey, 'anotherValue']])).to.not.have.all.keys([aKey, {'iDoNot': 'exist'}]);

if (typeof Symbol === 'function') {
var symKey1 = Symbol()
, symKey2 = Symbol()
, symKey3 = Symbol();

expect(new Map([[symKey1, 'symValue1'], [symKey2, 'symValue2']])).to.have.all.keys(symKey1, symKey2);
expect(new Map([[symKey1, 'symValue1'], [symKey2, 'symValue2']])).to.have.any.keys(symKey1, symKey3);
expect(new Map([[symKey1, 'symValue1'], [symKey2, 'symValue2']])).to.contain.all.keys(symKey2, symKey1);
expect(new Map([[symKey1, 'symValue1'], [symKey2, 'symValue2']])).to.contain.any.keys(symKey3, symKey1);

expect(new Map([[symKey1, 'symValue1'], [symKey2, 'symValue2']])).to.not.have.all.keys(symKey1, symKey3);
expect(new Map([[symKey1, 'symValue1'], [symKey2, 'symValue2']])).to.not.have.any.keys(symKey3);
expect(new Map([[symKey1, 'symValue1'], [symKey2, 'symValue2']])).to.not.contain.all.keys(symKey3, symKey1);
expect(new Map([[symKey1, 'symValue1'], [symKey2, 'symValue2']])).to.not.contain.any.keys(symKey3);
}

err(function(){
expect(new Map().set({ foo: 1 })).to.have.keys();
}, "keys required");
Expand Down Expand Up @@ -784,6 +822,22 @@ describe('expect', function () {
expect(new Set([aKey, anotherKey])).to.not.have.any.keys([20, 1, {13: 37}]);
expect(new Set([aKey, anotherKey])).to.not.have.all.keys([aKey, {'iDoNot': 'exist'}]);

if (typeof Symbol === 'function') {
var symKey1 = Symbol()
, symKey2 = Symbol()
, symKey3 = Symbol();

expect(new Set([symKey1, symKey2])).to.have.all.keys(symKey1, symKey2);
expect(new Set([symKey1, symKey2])).to.have.any.keys(symKey1, symKey3);
expect(new Set([symKey1, symKey2])).to.contain.all.keys(symKey2, symKey1);
expect(new Set([symKey1, symKey2])).to.contain.any.keys(symKey3, symKey1);

expect(new Set([symKey1, symKey2])).to.not.have.all.keys(symKey1, symKey3);
expect(new Set([symKey1, symKey2])).to.not.have.any.keys(symKey3);
expect(new Set([symKey1, symKey2])).to.not.contain.all.keys(symKey3, symKey1);
expect(new Set([symKey1, symKey2])).to.not.contain.any.keys(symKey3);
}

err(function(){
expect(new Set().add({ foo: 1 })).to.have.keys();
}, "keys required");
Expand Down Expand Up @@ -1283,6 +1337,10 @@ describe('expect', function () {
expect(false).to.not.be.extensible;
expect(undefined).to.not.be.extensible;

if (typeof Symbol === 'function') {
expect(Symbol()).to.not.be.extensible;
}

err(function() {
expect(42).to.be.extensible;
}, 'expected 42 to be extensible');
Expand Down Expand Up @@ -1326,6 +1384,10 @@ describe('expect', function () {
expect(false).to.be.sealed;
expect(undefined).to.be.sealed;

if (typeof Symbol === 'function') {
expect(Symbol()).to.be.sealed;
}

err(function() {
expect(42).to.not.be.sealed;
}, 'expected 42 to not be sealed');
Expand Down Expand Up @@ -1369,6 +1431,10 @@ describe('expect', function () {
expect(false).to.be.frozen;
expect(undefined).to.be.frozen;

if (typeof Symbol === 'function') {
expect(Symbol()).to.be.frozen;
}

err(function() {
expect(42).to.not.be.frozen;
}, 'expected 42 to not be frozen');
Expand Down

0 comments on commit ff8bba8

Please sign in to comment.