Socket
Socket
Sign inDemoInstall

chai-immutable

Package Overview
Dependencies
9
Maintainers
1
Versions
21
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 2.0.0-alpha.1 to 2.0.0-alpha.2

.eslintrc.yml

1408

chai-immutable.js
'use strict';
(function (context, factory) {
((context, factory) => {
if (typeof require === 'function' &&

@@ -9,743 +9,827 @@ typeof exports === 'object' &&

module.exports = factory(require('immutable'));
}
else if (typeof define === 'function' && define.amd) {
// AMD
throw new Error('chai-immutable is not compatible with an AMD loader yet.');
}
else {
} else {
// Other environments (usually <script> tag)
context.chai.use(factory(context.Immutable));
}
}(this, function (Immutable) {
return function (chai, utils) {
var Assertion = chai.Assertion;
})(this, Immutable => (chai, utils) => {
const Assertion = chai.Assertion;
function assertIsIterable(obj) {
new Assertion(obj).assert(
Immutable.Iterable.isIterable(obj),
'expected #{this} to be an Iterable'
);
}
function assertIsIterable(obj) {
new Assertion(obj).assert(
Immutable.Iterable.isIterable(obj),
'expected #{this} to be an Iterable'
);
}
/**
* ## BDD API Reference
*/
/**
* ## BDD API Reference
*/
/**
* ### .empty
*
* Asserts that the immutable collection is empty.
*
* ```js
* expect(List()).to.be.empty;
* expect(List.of(1, 2, 3)).to.not.be.empty;
* ```
*
* @name empty
* @namespace BDD
* @api public
*/
/**
* ### .empty
*
* Asserts that the immutable collection is empty.
*
* ```js
* expect(List()).to.be.empty;
* expect(List.of(1, 2, 3)).to.not.be.empty;
* ```
*
* @name empty
* @namespace BDD
* @api public
*/
Assertion.overwriteProperty('empty', function (_super) {
return function () {
var obj = this._obj;
Assertion.overwriteProperty('empty', _super => function () {
const obj = this._obj;
if (Immutable.Iterable.isIterable(obj)) {
var size = obj.size;
new Assertion(size).a('number');
if (Immutable.Iterable.isIterable(obj)) {
const size = obj.size;
new Assertion(size).a('number');
this.assert(
size === 0,
'expected #{this} to be empty but got size #{act}',
'expected #{this} to not be empty'
);
}
else _super.apply(this, arguments);
};
});
this.assert(
size === 0,
'expected #{this} to be empty but got size #{act}',
'expected #{this} to not be empty'
);
} else {
_super.apply(this, arguments);
}
});
/**
* ### .equal(collection)
*
* Asserts that the values of the target are equivalent to the values of
* `collection`. Aliases of Chai's original `equal` method are also supported.
*
* ```js
* var a = List.of(1, 2, 3);
* var b = List.of(1, 2, 3);
* expect(a).to.equal(b);
* ```
*
* Immutable data structures should only contain other immutable data
* structures (unlike `Array`s and `Object`s) to be considered immutable and
* properly work against `.equal()`. See
* [this issue](https://github.com/astorije/chai-immutable/issues/24) for
* more information.
*
* Also, note that `deep.equal` and `eql` are synonyms of `equal` when
* tested against immutable data structures, therefore they are aliases to
* `equal`.
*
* @name equal
* @alias equals
* @alias eq
* @alias eql
* @alias eqls
* @alias deep.equal
* @param {Collection} value
* @namespace BDD
* @api public
*/
/**
* ### .equal(collection)
*
* Asserts that the values of the target are equivalent to the values of
* `collection`. Aliases of Chai's original `equal` method are also supported.
*
* ```js
* const a = List.of(1, 2, 3);
* const b = List.of(1, 2, 3);
* expect(a).to.equal(b);
* ```
*
* Immutable data structures should only contain other immutable data
* structures (unlike `Array`s and `Object`s) to be considered immutable and
* properly work against `.equal()`. See
* [this issue](https://github.com/astorije/chai-immutable/issues/24) for
* more information.
*
* Also, note that `deep.equal` and `eql` are synonyms of `equal` when
* tested against immutable data structures, therefore they are aliases to
* `equal`.
*
* @name equal
* @alias equals
* @alias eq
* @alias eql
* @alias eqls
* @alias deep.equal
* @param {Collection} value
* @namespace BDD
* @api public
*/
function assertCollectionEqual(_super) {
return function (collection) {
var obj = this._obj;
function assertCollectionEqual(_super) {
return function (collection) {
const obj = this._obj;
if (Immutable.Iterable.isIterable(obj)) {
this.assert(
Immutable.is(obj, collection),
'expected #{act} to equal #{exp}',
'expected #{act} to not equal #{exp}',
collection.toString(),
obj.toString(),
true
);
}
else _super.apply(this, arguments);
};
}
if (Immutable.Iterable.isIterable(obj)) {
this.assert(
Immutable.is(obj, collection),
'expected #{act} to equal #{exp}',
'expected #{act} to not equal #{exp}',
collection.toJS(),
obj.toJS(),
true
);
} else {
_super.apply(this, arguments);
}
};
}
Assertion.overwriteMethod('equal', assertCollectionEqual);
Assertion.overwriteMethod('equals', assertCollectionEqual);
Assertion.overwriteMethod('eq', assertCollectionEqual);
Assertion.overwriteMethod('eql', assertCollectionEqual);
Assertion.overwriteMethod('eqls', assertCollectionEqual);
Assertion.overwriteMethod('equal', assertCollectionEqual);
Assertion.overwriteMethod('equals', assertCollectionEqual);
Assertion.overwriteMethod('eq', assertCollectionEqual);
Assertion.overwriteMethod('eql', assertCollectionEqual);
Assertion.overwriteMethod('eqls', assertCollectionEqual);
/**
* ### .include(value)
*
* The `include` and `contain` assertions can be used as either property
* based language chains or as methods to assert the inclusion of a value
* in an immutable collection. When used as language chains, they toggle the
* `contains` flag for the `keys` assertion.
*
* ```js
* expect(new List([1, 2, 3])).to.include(2);
* expect(new Map({ foo: 'bar', hello: 'universe' })).to.include.keys('foo');
* ```
*
* @name include
* @alias contain
* @alias includes
* @alias contains
* @param {Mixed} val
* @namespace BDD
* @api public
*/
/**
* ### .include(value)
*
* The `include` and `contain` assertions can be used as either property
* based language chains or as methods to assert the inclusion of a value
* in an immutable collection. When used as language chains, they toggle the
* `contains` flag for the `keys` assertion.
*
* Note that `deep.include` behaves exactly like `include` in the context of
* immutable data structures.
*
* ```js
* expect(new List([1, 2, 3])).to.include(2);
* expect(new List([1, 2, 3])).to.deep.include(2);
* expect(new Map({ foo: 'bar', hello: 'world' })).to.include.keys('foo');
* ```
*
* @name include
* @alias contain
* @alias includes
* @alias contains
* @param {Mixed} val
* @namespace BDD
* @api public
*/
function assertCollectionInclude(_super) {
return function (val) {
var obj = this._obj;
function assertCollectionInclude(_super) {
return function (val) {
const obj = this._obj;
if (Immutable.Iterable.isIterable(obj)) {
this.assert(
obj.includes(val),
'expected #{act} to include #{exp}',
'expected #{act} to not include #{exp}',
val,
obj.toString()
);
}
else _super.apply(this, arguments);
};
}
function chainCollectionInclude(_super) {
return function () {
if (Immutable.Iterable.isIterable(obj)) {
this.assert(
obj.includes(val),
'expected #{act} to include #{exp}',
'expected #{act} to not include #{exp}',
val,
obj.toString()
);
} else {
_super.apply(this, arguments);
};
}
}
};
}
['include', 'contain', 'contains', 'includes'].forEach(function (keyword) {
Assertion.overwriteChainableMethod(
keyword,
assertCollectionInclude,
chainCollectionInclude
);
});
function chainCollectionInclude(_super) {
return function () {
_super.apply(this, arguments);
};
}
/**
* ### .keys(key1[, key2, ...[, keyN]])
*
* Asserts that the keyed collection contains any or all of the passed-in
* keys. Use in combination with `any`, `all`, `contains`, or `have` will
* affect what will pass.
*
* When used in conjunction with `any`, at least one key that is passed in
* must exist in the target object. This is regardless whether or not
* the `have` or `contain` qualifiers are used. Note, either `any` or `all`
* should be used in the assertion. If neither are used, the assertion is
* defaulted to `all`.
*
* When both `all` and `contain` are used, the target object must have at
* least all of the passed-in keys but may have more keys not listed.
*
* When both `all` and `have` are used, the target object must both contain
* all of the passed-in keys AND the number of keys in the target object must
* match the number of keys passed in (in other words, a target object must
* have all and only all of the passed-in keys).
*
* `key` is an alias to `keys`.
*
* ```js
* expect(new Map({ foo: 1 })).to.have.key('foo');
* expect(new Map({ foo: 1, bar: 2 })).to.have.keys('foo', 'bar');
* expect(new Map({ foo: 1, bar: 2 })).to.have.keys(new List(['bar', 'foo']));
* expect(new Map({ foo: 1, bar: 2 })).to.have.keys(new Set(['bar', 'foo']));
* expect(new Map({ foo: 1, bar: 2 })).to.have.keys(new Stack(['bar', 'foo']));
* expect(new Map({ foo: 1, bar: 2 })).to.have.keys(['bar', 'foo']);
* expect(new Map({ foo: 1, bar: 2 })).to.have.keys({ 'bar': 6, 'foo': 7 });
* expect(new Map({ foo: 1, bar: 2 })).to.have.keys(new Map({ 'bar': 6, 'foo': 7 }));
* expect(new Map({ foo: 1, bar: 2 })).to.have.any.keys('foo', 'not-foo');
* expect(new Map({ foo: 1, bar: 2 })).to.have.all.keys('foo', 'bar');
* expect(new Map({ foo: 1, bar: 2 })).to.contain.key('foo');
* ```
*
* @name keys
* @param {String...|Array|Object|Collection} keyN
* @alias key
* @namespace BDD
* @api public
*/
['include', 'contain', 'contains', 'includes'].forEach(keyword => {
Assertion.overwriteChainableMethod(
keyword,
assertCollectionInclude,
chainCollectionInclude
);
});
function assertKeyedCollectionKeys(_super) {
return function (keys) {
function has(key) { return obj.has(key); }
/**
* ### .keys(key1[, key2[, ...]])
*
* Asserts that the target collection has the given keys.
*
* When the target is an object or array, keys can be provided as one or more
* string arguments, a single array argument, a single object argument, or an
* immutable collection. In the last 2 cases, only the keys in the given
* object/collection matter; the values are ignored.
*
* ```js
* expect(new Map({ foo: 1, bar: 2 })).to.have.all.keys('foo', 'bar');
* expect(new Map({ foo: 1, bar: 2 })).to.have.all.keys(new List(['bar', 'foo']));
* expect(new Map({ foo: 1, bar: 2 })).to.have.all.keys(new Set(['bar', 'foo']));
* expect(new Map({ foo: 1, bar: 2 })).to.have.all.keys(new Stack(['bar', 'foo']));
* expect(new List(['x', 'y'])).to.have.all.keys(0, 1);
*
* expect(new Map({ foo: 1, bar: 2 })).to.have.all.keys(['foo', 'bar']);
* expect(new List(['x', 'y'])).to.have.all.keys([0, 1]);
*
* // Values in the passed object are ignored:
* expect(new Map({ foo: 1, bar: 2 })).to.have.all.keys({ 'bar': 6, 'foo': 7 });
* expect(new Map({ foo: 1, bar: 2 })).to.have.all.keys(new Map({ 'bar': 6, 'foo': 7 }));
* expect(new List(['x', 'y'])).to.have.all.keys({0: 4, 1: 5});
* ```
*
* Note that `deep.property` behaves exactly like `property` in the context of
* immutable data structures.
*
* By default, the target must have all of the given keys and no more. Add
* `.any` earlier in the chain to only require that the target have at least
* one of the given keys. Also, add `.not` earlier in the chain to negate
* `.keys`. It's often best to add `.any` when negating `.keys`, and to use
* `.all` when asserting `.keys` without negation.
*
* When negating `.keys`, `.any` is preferred because `.not.any.keys` asserts
* exactly what's expected of the output, whereas `.not.all.keys` creates
* uncertain expectations.
*
* ```js
* // Recommended; asserts that target doesn't have any of the given keys
* expect(new Map({a: 1, b: 2})).to.not.have.any.keys('c', 'd');
*
* // Not recommended; asserts that target doesn't have all of the given
* // keys but may or may not have some of them
* expect(new Map({a: 1, b: 2})).to.not.have.all.keys('c', 'd');
* ```
*
* When asserting `.keys` without negation, `.all` is preferred because
* `.all.keys` asserts exactly what's expected of the output, whereas
* `.any.keys` creates uncertain expectations.
*
* ```js
* // Recommended; asserts that target has all the given keys
* expect(new Map({a: 1, b: 2})).to.have.all.keys('a', 'b');
*
* // Not recommended; asserts that target has at least one of the given
* // keys but may or may not have more of them
* expect(new Map({a: 1, b: 2})).to.have.any.keys('a', 'b');
* ```
*
* Note that `.all` is used by default when neither `.all` nor `.any` appear
* earlier in the chain. However, it's often best to add `.all` anyway because
* it improves readability.
*
* ```js
* // Both assertions are identical
* expect(new Map({a: 1, b: 2})).to.have.all.keys('a', 'b'); // Recommended
* expect(new Map({a: 1, b: 2})).to.have.keys('a', 'b'); // Not recommended
* ```
*
* Add `.include` earlier in the chain to require that the target's keys be a
* superset of the expected keys, rather than identical sets.
*
* ```js
* // Target object's keys are a superset of ['a', 'b'] but not identical
* expect(new Map({a: 1, b: 2, c: 3})).to.include.all.keys('a', 'b');
* expect(new Map({a: 1, b: 2, c: 3})).to.not.have.all.keys('a', 'b');
* ```
*
* However, if `.any` and `.include` are combined, only the `.any` takes
* effect. The `.include` is ignored in this case.
*
* ```js
* // Both assertions are identical
* expect(new Map({a: 1})).to.have.any.keys('a', 'b');
* expect(new Map({a: 1})).to.include.any.keys('a', 'b');
* ```
*
* The alias `.key` can be used interchangeably with `.keys`.
*
* ```js
* expect(new Map({ foo: 1 })).to.have.key('foo');
* ```
*
* @name keys
* @alias key
* @alias deep.key
* @param {...String|Array|Object|Collection} keys
* @namespace BDD
* @api public
*/
var obj = this._obj;
function assertKeyedCollectionKeys(_super) {
return function (keys) {
const obj = this._obj;
if (Immutable.Iterable.isKeyed(obj)) {
switch (utils.type(keys)) {
case 'Object':
if (Immutable.Iterable.isIndexed(keys))
keys = keys.toJS();
else if (Immutable.Iterable.isIterable(keys))
keys = keys.keySeq().toJS();
else keys = Object.keys(keys);
case 'Array':
if (arguments.length > 1) throw new Error(
'keys must be given single argument of ' +
'Array|Object|String|Collection, ' +
'or multiple String arguments'
if (Immutable.Iterable.isIterable(obj)) {
const ssfi = utils.flag(this, 'ssfi');
switch (utils.type(keys)) {
case 'Object':
if (Immutable.Iterable.isIndexed(keys)) {
keys = keys.toJS();
} else if (Immutable.Iterable.isIterable(keys)) {
keys = keys.keySeq().toJS();
} else {
keys = Object.keys(keys);
}
// `keys` is now an array so this statement safely falls through
case 'Array':
if (arguments.length > 1) {
throw new chai.AssertionError(
'when testing keys against an immutable collection, you must ' +
'give a single Array|Object|String|Collection argument or ' +
'multiple String arguments',
null,
ssfi
);
break;
default:
keys = Array.prototype.slice.call(arguments);
break;
}
}
break;
default:
keys = Array.prototype.slice.call(arguments);
break;
}
if (!keys.length) throw new Error('keys required');
// Only stringify non-Symbols because Symbols would become "Symbol()"
keys = keys.map(val => typeof val === 'symbol' ? val : String(val));
var any = utils.flag(this, 'any');
var contains = utils.flag(this, 'contains');
var ok;
var str = (contains ? 'contain' : 'have') + ' ';
if (!keys.length) {
throw new chai.AssertionError('keys required', null, ssfi);
}
if (any) ok = keys.some(has);
else {
ok = keys.every(has);
if (!contains) {
ok = ok && keys.length === obj.count();
}
}
let all = utils.flag(this, 'all');
const any = utils.flag(this, 'any');
const contains = utils.flag(this, 'contains');
let ok;
let str = contains ? 'contain ' : 'have ';
if (keys.length > 1) {
keys = keys.map(utils.inspect);
var last = keys.pop();
var conjunction = any ? 'or' : 'and';
str += 'keys ' + keys.join(', ') + ', ' + conjunction + ' ' + last;
if (!any && !all) {
all = true;
}
if (any) {
ok = keys.some(key => obj.has(key));
} else {
ok = keys.every(key => obj.has(key));
if (!contains) {
ok = ok && keys.length === obj.count();
}
else str += 'key ' + utils.inspect(keys[0]);
}
this.assert(
ok,
'expected #{act} to ' + str,
'expected #{act} to not ' + str,
keys,
obj.toString()
);
if (keys.length > 1) {
keys = keys.map(utils.inspect);
const last = keys.pop();
const conjunction = any ? 'or' : 'and';
str += `keys ${keys.join(', ')}, ${conjunction} ${last}`;
} else {
str += `key ${utils.inspect(keys[0])}`;
}
else _super.apply(this, arguments);
};
}
Assertion.overwriteMethod('keys', assertKeyedCollectionKeys);
Assertion.overwriteMethod('key', assertKeyedCollectionKeys);
this.assert(
ok,
`expected #{act} to ${str}`,
`expected #{act} to not ${str}`,
keys.slice(0).sort(utils.compareByInspect),
obj.toString(),
true
);
} else {
_super.apply(this, arguments);
}
};
}
/*!
* ## parsePath(path)
*
* Helper function used to parse string paths into arrays of keys and
* indices.
*
* ```js
* var parsed = parsePath('myobject.key.subkey');
* ```
*
* ### Paths:
*
* - Can be as near infinitely deep and nested
* - Arrays are also valid using the formal `myobject.document[3].key`.
* - Literal dots and brackets (not delimiter) must be backslash-escaped.
*
* This function is inspired from Chai's original `parsePath` function:
* https://github.com/chaijs/chai/blob/d664ef4/lib/chai/utils/getPathInfo.js#L46-L74
*
* @param {String} path
* @returns {Array} parsed
* @api private
*/
function parsePath(path) { // Given the following path: 'a.b[1]'
// Separates keys followed by indices with a dot: 'a.b.[1]'
var str = path.replace(/([^\\])\[/g, '$1.[');
// Extracts all indices and keys into an array: ['a', 'b', '[1]']
var parts = str.match(/(\\\.|[^.]+?)+/g);
Assertion.overwriteMethod('keys', assertKeyedCollectionKeys);
Assertion.overwriteMethod('key', assertKeyedCollectionKeys);
// Removes brackets and escaping backslashes, and extracts digits from
// each value in the array: ['a', 'b', 1]
return parts.map(function (value) {
// Extracts indices wrapped in brackets
var re = /^\[(\d+)\]$/;
// Builds ['[<index>]', '<index>'] if value is a digit, null otherwise
var mArr = re.exec(value);
/*!
* ## parsePath(path)
*
* Helper function used to parse string paths into arrays of keys and
* indices.
*
* ```js
* const parsed = parsePath('myobject.key.subkey');
* ```
*
* ### Paths:
*
* - Can be as near infinitely deep and nested
* - Arrays are also valid using the formal `myobject.document[3].key`.
* - Literal dots and brackets (not delimiter) must be backslash-escaped.
*
* This function is inspired from Chai's original `parsePath` function:
* https://github.com/chaijs/chai/blob/d664ef4/lib/chai/utils/getPathInfo.js#L46-L74
*
* @param {String} path
* @returns {Array} parsed
* @api private
*/
function parsePath(path) { // Given the following path: 'a.b[1]'
// Separates keys followed by indices with a dot: 'a.b.[1]'
const str = path.replace(/([^\\])\[/g, '$1.[');
// Extracts all indices and keys into an array: ['a', 'b', '[1]']
const parts = str.match(/(\\\.|[^.]+?)+/g);
// If the value was of form '[<index>]', returns <index>
// Otherwise, returns the key without the escaping backslashes
if (mArr) return parseFloat(mArr[1]);
else return value.replace(/\\([.\[\]])/g, '$1');
});
}
// Removes brackets and escaping backslashes, and extracts digits from
// each value in the array: ['a', 'b', 1]
return parts.map(value => {
// Extracts indices wrapped in brackets
const re = /^\[(\d+)\]$/;
// Builds ['[<index>]', '<index>'] if value is a digit, null otherwise
const mArr = re.exec(value);
/**
* ### .property(name, [value])
*
* Asserts that the target has a property `name`, optionally asserting that
* the value of that property is equal to `value`. `value` can be an
* Immutable object.
* If the `nested` flag is set, you can use dot- and bracket-notation for
* nested references into objects and arrays.
*
* ```js
* // Simple referencing
* var map = new Map({ foo: 'bar' });
* expect(map).to.have.property('foo');
* expect(map).to.have.property('foo', 'bar');
*
* // Deep referencing
* var nestedMap = new Map({
* green: new Map({ tea: 'matcha' }),
* teas: new List(['chai', 'matcha', new Map({ tea: 'konacha' })])
* });
*
* expect(nestedMap).to.have.nested.property('green.tea', 'matcha');
* expect(nestedMap).to.have.nested.property(['green', 'tea'], 'matcha');
* expect(nestedMap).to.have.nested.property(new List(['green', 'tea']), 'matcha');
* expect(nestedMap).to.have.nested.property('teas[1]', 'matcha');
* expect(nestedMap).to.have.nested.property(['teas', 1], 'matcha');
* expect(nestedMap).to.have.nested.property(new List(['teas', 1]), 'matcha');
* expect(nestedMap).to.have.nested.property('teas[2].tea', 'konacha');
* expect(nestedMap).to.have.nested.property(['teas', 2, 'tea'], 'konacha');
* expect(nestedMap).to.have.nested.property(new List(['teas', 2, 'tea']), 'konacha');
* ```
*
* You can also use a `List` as the starting point of a `nested.property`
* assertion, or traverse nested `List`s.
*
* ```js
* var list = new List([
* new List(['chai', 'matcha', 'konacha']),
* new List([
* new Map({ tea: 'chai' }),
* new Map({ tea: 'matcha' }),
* new Map({ tea: 'konacha' })
* ])
* ]);
*
* expect(list).to.have.nested.property('[0][1]', 'matcha');
* expect(list).to.have.nested.property([0, 1], 'matcha');
* expect(list).to.have.nested.property(new List([0, 1]), 'matcha');
* expect(list).to.have.nested.property('[1][2].tea', 'konacha');
* expect(list).to.have.nested.property([1, 2, 'tea'], 'konacha');
* expect(list).to.have.nested.property(new List([1, 2, 'tea']), 'konacha');
* ```
*
* Furthermore, `property` changes the subject of the assertion
* to be the value of that property from the original object. This
* permits for further chainable assertions on that property.
*
* ```js
* expect(map).to.have.property('foo')
* .that.is.a('string');
* expect(nestedMap).to.have.property('green')
* .that.is.an.instanceof(Map)
* .that.equals(new Map({ tea: 'matcha' }));
* expect(nestedMap).to.have.property('teas')
* .that.is.an.instanceof(List)
* .with.nested.property([2])
* .that.equals(new Map({ tea: 'konacha' }));
* ```
*
* Note that dots and brackets in `name` must be backslash-escaped when
* the `nested` flag is set, while they must NOT be escaped when the
* `nested` flag is not set.
*
* ```js
* // Simple referencing
* var css = new Map({ '.link[target]': 42 });
* expect(css).to.have.property('.link[target]', 42);
*
* // Deep referencing
* var nestedCss = new Map({ '.link': new Map({ '[target]': 42 }) });
* expect(nestedCss).to.have.nested.property('\\.link.\\[target\\]', 42);
* ```
*
* @name property
* @param {String|Array|Iterable} name
* @param {Mixed} value (optional)
* @namespace BDD
* @api public
*/
function assertProperty(_super) {
return function (path, val) {
var obj = this._obj;
// If the value was of form '[<index>]', returns <index>
// Otherwise, returns the key without the escaping backslashes
if (mArr) {
return parseFloat(mArr[1]);
} else {
return value.replace(/\\([.[\]])/g, '$1');
}
});
}
if (Immutable.Iterable.isIterable(this._obj)) {
var isNested = Boolean(utils.flag(this, 'nested'));
var negate = Boolean(utils.flag(this, 'negate'));
/**
* ### .property(path[, val])
*
* Asserts that the target has a property with the given `path`.
*
* ```js
* expect(new Map({a: 1})).to.have.property('a');
* ```
*
* When `val` is provided, `.property` also asserts that the property's value
* is equal to the given `val`. `val` can be an immutable collection.
*
* ```js
* expect(new Map({a: 1})).to.have.property('a', 1);
* ```
*
* Note that `deep.property` behaves exactly like `property` in the context of
* immutable data structures.
*
* Add `.nested` earlier in the chain to enable dot- and bracket-notation when
* referencing nested properties. An immutable `List` can also be used as the
* starting point of a `nested.property`.
*
* ```js
* expect(Immutable.fromJS({a: {b: ['x', 'y']}})).to.have.nested.property('a.b[1]');
* expect(Immutable.fromJS({a: {b: ['x', 'y']}})).to.have.nested.property('a.b[1]', 'y');
* expect(Immutable.fromJS({a: {b: ['x', 'y']}})).to.have.nested.property(['a', 'b', 1], 'y');
* expect(Immutable.fromJS({a: {b: ['x', 'y']}})).to.have.nested.property(new List(['a', 'b', 1]), 'y');
* ```
*
* If `.` or `[]` are part of an actual property name, they can be escaped by
* adding two backslashes before them.
*
* ```js
* expect(Immutable.fromJS({'.a': {'[b]': 'x'}})).to.have.nested.property('\\.a.\\[b\\]');
* ```
*
* Add `.not` earlier in the chain to negate `.property`.
*
* ```js
* expect(new Map({a: 1})).to.not.have.property('b');
* ```
*
* However, it's dangerous to negate `.property` when providing `val`. The
* problem is that it creates uncertain expectations by asserting that the
* target either doesn't have a property at the given `path`, or that it
* does have a property at the given key `path` but its value isn't equal to
* the given `val`. It's often best to identify the exact output that's
* expected, and then write an assertion that only accepts that exact output.
*
* When the target isn't expected to have a property at the given
* `path`, it's often best to assert exactly that.
*
* ```js
* expect(new Map({b: 2})).to.not.have.property('a'); // Recommended
* expect(new Map({b: 2})).to.not.have.property('a', 1); // Not recommended
* ```
*
* When the target is expected to have a property at the given key `path`,
* it's often best to assert that the property has its expected value, rather
* than asserting that it doesn't have one of many unexpected values.
*
* ```js
* expect(new Map({a: 3})).to.have.property('a', 3); // Recommended
* expect(new Map({a: 3})).to.not.have.property('a', 1); // Not recommended
* ```
*
* `.property` changes the target of any assertions that follow in the chain
* to be the value of the property from the original target object.
*
* ```js
* expect(new Map({a: 1})).to.have.property('a').that.is.a('number');
* ```
*
* @name property
* @alias deep.equal
* @param {String|Array|Iterable} path
* @param {Mixed} val (optional)
* @returns value of property for chaining
* @namespace BDD
* @api public
*/
var descriptor;
var hasProperty;
var value;
function assertProperty(_super) {
return function (path, val) {
const obj = this._obj;
if (isNested) {
descriptor = 'nested property ';
if (typeof path === 'string') {
path = parsePath(path);
}
value = obj.getIn(path);
hasProperty = obj.hasIn(path);
}
else {
descriptor = 'property ';
value = obj.get(path);
hasProperty = obj.has(path);
}
if (Immutable.Iterable.isIterable(obj)) {
const isNested = utils.flag(this, 'nested');
const negate = utils.flag(this, 'negate');
// In the negate case, we only throw if property is missing so we can
// check the value later.
if (negate && arguments.length > 1) {
if (!hasProperty) {
throw new chai.AssertionError('expected ' + utils.inspect(obj) +
' to have a ' + descriptor + utils.inspect(path));
}
let descriptor;
let hasProperty;
let value;
if (isNested) {
descriptor = 'nested ';
if (typeof path === 'string') {
path = parsePath(path);
}
else {
this.assert(
hasProperty,
'expected #{this} to have a ' + descriptor + utils.inspect(path),
'expected #{this} not to have ' + descriptor + utils.inspect(path)
);
}
value = obj.getIn(path);
hasProperty = obj.hasIn(path);
} else {
value = obj.get(path);
hasProperty = obj.has(path);
}
if (arguments.length > 1) {
var isEqual;
if (Immutable.Iterable.isIterable(val)) {
isEqual = Immutable.is(val, value);
}
else {
isEqual = val === value;
}
// When performing a negated assertion for both name and val, merely
// having a property with the given name isn't enough to cause the
// assertion to fail. It must both have a property with the given name,
// and the value of that property must equal the given val. Therefore,
// skip this assertion in favor of the next.
if (!negate || arguments.length === 1) {
this.assert(
hasProperty,
`expected #{this} to have ${descriptor}property ` +
`${utils.inspect(path)}`,
`expected #{this} to not have ${descriptor}property ` +
`${utils.inspect(path)}`
);
}
this.assert(
isEqual,
'expected #{this} to have a ' + descriptor + utils.inspect(path) +
' of #{exp}, but got #{act}',
'expected #{this} not to have a ' + descriptor + utils.inspect(path) +
' of #{act}',
val,
value
);
if (arguments.length > 1) {
let isEqual;
if (Immutable.Iterable.isIterable(val)) {
isEqual = Immutable.is(val, value);
} else {
isEqual = val === value;
}
utils.flag(this, 'object', value);
this.assert(
hasProperty && isEqual,
`expected #{this} to have ${descriptor}property ` +
`${utils.inspect(path)} of #{exp}, but got #{act}`,
`expected #{this} to not have ${descriptor}property ` +
`${utils.inspect(path)} of #{act}`,
val,
value
);
}
else return _super.apply(this, arguments);
};
}
Assertion.overwriteMethod('property', assertProperty);
utils.flag(this, 'object', value);
} else {
_super.apply(this, arguments);
}
};
}
/**
* ### .size(value)
*
* Asserts that the immutable collection has the expected size.
*
* ```js
* expect(List.of(1, 2, 3)).to.have.size(3);
* ```
*
* It can also be used as a chain precursor to a value comparison for the
* `size` property.
*
* ```js
* expect(List.of(1, 2, 3)).to.have.size.least(3);
* expect(List.of(1, 2, 3)).to.have.size.most(3);
* expect(List.of(1, 2, 3)).to.have.size.above(2);
* expect(List.of(1, 2, 3)).to.have.size.below(4);
* expect(List.of(1, 2, 3)).to.have.size.within(2,4);
* ```
*
* Similarly to `length`/`lengthOf`, `sizeOf` is an alias of `size`:
*
* ```js
* expect(List.of(1, 2, 3)).to.have.sizeOf(3);
* ```
*
* @name size
* @alias sizeOf
* @param {Number} size
* @namespace BDD
* @api public
*/
Assertion.overwriteMethod('property', assertProperty);
function assertCollectionSize(n) {
assertIsIterable(this._obj);
/**
* ### .size(value)
*
* Asserts that the immutable collection has the expected size.
*
* ```js
* expect(List.of(1, 2, 3)).to.have.size(3);
* ```
*
* It can also be used as a chain precursor to a value comparison for the
* `size` property.
*
* ```js
* expect(List.of(1, 2, 3)).to.have.size.least(3);
* expect(List.of(1, 2, 3)).to.have.size.most(3);
* expect(List.of(1, 2, 3)).to.have.size.above(2);
* expect(List.of(1, 2, 3)).to.have.size.below(4);
* expect(List.of(1, 2, 3)).to.have.size.within(2,4);
* ```
*
* Similarly to `length`/`lengthOf`, `sizeOf` is an alias of `size`:
*
* ```js
* expect(List.of(1, 2, 3)).to.have.sizeOf(3);
* ```
*
* @name size
* @alias sizeOf
* @param {Number} size
* @namespace BDD
* @api public
*/
var size = this._obj.size;
new Assertion(size).a('number');
function assertCollectionSize(n) {
assertIsIterable(this._obj);
this.assert(
size === n,
'expected #{this} to have size #{exp} but got #{act}',
'expected #{this} to not have size #{act}',
n,
size
);
}
const size = this._obj.size;
new Assertion(size).a('number');
function chainCollectionSize() {
utils.flag(this, 'immutable.collection.size', true);
}
this.assert(
size === n,
'expected #{this} to have size #{exp} but got #{act}',
'expected #{this} to not have size #{act}',
n,
size
);
}
Assertion.addChainableMethod('size', assertCollectionSize, chainCollectionSize);
Assertion.addMethod('sizeOf', assertCollectionSize);
function chainCollectionSize() {
utils.flag(this, 'immutable.collection.size', true);
}
// Numerical comparator overwrites
Assertion.addChainableMethod(
'size',
assertCollectionSize,
chainCollectionSize
);
Assertion.addMethod('sizeOf', assertCollectionSize);
function assertCollectionSizeLeast(_super) {
return function (n) {
if (utils.flag(this, 'immutable.collection.size')) {
assertIsIterable(this._obj);
// Numerical comparator overwrites
var size = this._obj.size;
new Assertion(size).a('number');
function assertCollectionSizeLeast(_super) {
return function (n) {
if (utils.flag(this, 'immutable.collection.size')) {
assertIsIterable(this._obj);
this.assert(
size >= n,
'expected #{this} to have a size of at least #{exp} but got #{act}',
'expected #{this} to not have a size of at least #{exp} but got #{act}',
n,
size
);
}
else _super.apply(this, arguments);
};
}
const size = this._obj.size;
new Assertion(size).a('number');
function assertCollectionSizeMost(_super) {
return function (n) {
if (utils.flag(this, 'immutable.collection.size')) {
assertIsIterable(this._obj);
this.assert(
size >= n,
'expected #{this} to have a size of at least #{exp} but got #{act}',
'expected #{this} to not have a size of at least #{exp} but got ' +
'#{act}',
n,
size
);
} else {
_super.apply(this, arguments);
}
};
}
var size = this._obj.size;
new Assertion(size).a('number');
function assertCollectionSizeMost(_super) {
return function (n) {
if (utils.flag(this, 'immutable.collection.size')) {
assertIsIterable(this._obj);
this.assert(
size <= n,
'expected #{this} to have a size of at most #{exp} but got #{act}',
'expected #{this} to not have a size of at most #{exp} but got #{act}',
n,
size
);
}
else _super.apply(this, arguments);
};
}
const size = this._obj.size;
new Assertion(size).a('number');
function assertCollectionSizeAbove(_super) {
return function (n) {
if (utils.flag(this, 'immutable.collection.size')) {
assertIsIterable(this._obj);
this.assert(
size <= n,
'expected #{this} to have a size of at most #{exp} but got #{act}',
'expected #{this} to not have a size of at most #{exp} but got ' +
'#{act}',
n,
size
);
} else {
_super.apply(this, arguments);
}
};
}
var size = this._obj.size;
new Assertion(size).a('number');
function assertCollectionSizeAbove(_super) {
return function (n) {
if (utils.flag(this, 'immutable.collection.size')) {
assertIsIterable(this._obj);
this.assert(
size > n,
'expected #{this} to have a size above #{exp} but got #{act}',
'expected #{this} to not have a size above #{exp} but got #{act}',
n,
size
);
}
else _super.apply(this, arguments);
};
}
const size = this._obj.size;
new Assertion(size).a('number');
function assertCollectionSizeBelow(_super) {
return function (n) {
if (utils.flag(this, 'immutable.collection.size')) {
assertIsIterable(this._obj);
this.assert(
size > n,
'expected #{this} to have a size above #{exp} but got #{act}',
'expected #{this} to not have a size above #{exp} but got #{act}',
n,
size
);
} else {
_super.apply(this, arguments);
}
};
}
var size = this._obj.size;
new Assertion(size).a('number');
function assertCollectionSizeBelow(_super) {
return function (n) {
if (utils.flag(this, 'immutable.collection.size')) {
assertIsIterable(this._obj);
this.assert(
size < n,
'expected #{this} to have a size below #{exp} but got #{act}',
'expected #{this} to not have a size below #{exp} but got #{act}',
n,
size
);
}
else _super.apply(this, arguments);
};
}
const size = this._obj.size;
new Assertion(size).a('number');
Assertion.overwriteMethod('least', assertCollectionSizeLeast);
Assertion.overwriteMethod('gte', assertCollectionSizeLeast);
this.assert(
size < n,
'expected #{this} to have a size below #{exp} but got #{act}',
'expected #{this} to not have a size below #{exp} but got #{act}',
n,
size
);
} else {
_super.apply(this, arguments);
}
};
}
Assertion.overwriteMethod('most', assertCollectionSizeMost);
Assertion.overwriteMethod('lte', assertCollectionSizeMost);
Assertion.overwriteMethod('least', assertCollectionSizeLeast);
Assertion.overwriteMethod('gte', assertCollectionSizeLeast);
Assertion.overwriteMethod('above', assertCollectionSizeAbove);
Assertion.overwriteMethod('gt', assertCollectionSizeAbove);
Assertion.overwriteMethod('greaterThan', assertCollectionSizeAbove);
Assertion.overwriteMethod('most', assertCollectionSizeMost);
Assertion.overwriteMethod('lte', assertCollectionSizeMost);
Assertion.overwriteMethod('below', assertCollectionSizeBelow);
Assertion.overwriteMethod('lt', assertCollectionSizeBelow);
Assertion.overwriteMethod('lessThan', assertCollectionSizeBelow);
Assertion.overwriteMethod('above', assertCollectionSizeAbove);
Assertion.overwriteMethod('gt', assertCollectionSizeAbove);
Assertion.overwriteMethod('greaterThan', assertCollectionSizeAbove);
Assertion.overwriteMethod('within', function (_super) {
return function (min, max) {
if (utils.flag(this, 'immutable.collection.size')) {
assertIsIterable(this._obj);
Assertion.overwriteMethod('below', assertCollectionSizeBelow);
Assertion.overwriteMethod('lt', assertCollectionSizeBelow);
Assertion.overwriteMethod('lessThan', assertCollectionSizeBelow);
var size = this._obj.size;
new Assertion(size).a('number');
Assertion.overwriteMethod('within', _super => function (min, max) {
if (utils.flag(this, 'immutable.collection.size')) {
assertIsIterable(this._obj);
this.assert(
min <= size && size <= max,
'expected #{this} to have a size within #{exp} but got #{act}',
'expected #{this} to not have a size within #{exp} but got #{act}',
min + '..' + max,
size
);
}
else _super.apply(this, arguments);
};
});
const size = this._obj.size;
new Assertion(size).a('number');
/**
* ## TDD API Reference
*/
this.assert(
min <= size && size <= max,
'expected #{this} to have a size within #{exp} but got #{act}',
'expected #{this} to not have a size within #{exp} but got #{act}',
`${min}..${max}`,
size
);
} else {
_super.apply(this, arguments);
}
});
var assert = chai.assert;
var originalEqual = assert.equal;
var originalNotEqual = assert.notEqual;
/**
* ## TDD API Reference
*/
/**
* ### .equal(actual, expected)
*
* Asserts that the values of `actual` are equivalent to the values of
* `expected`. Note that `.strictEqual()` and `.deepEqual()` assert
* exactly like `.equal()` in the context of Immutable data structures.
*
* ```js
* var a = List.of(1, 2, 3);
* var b = List.of(1, 2, 3);
* assert.equal(a, b);
* ```
*
* Immutable data structures should only contain other immutable data
* structures (unlike `Array`s and `Object`s) to be considered immutable and
* properly work against `.equal()`, `.strictEqual()` or `.deepEqual()`. See
* [this issue](https://github.com/astorije/chai-immutable/issues/24) for
* more information.
*
* @name equal
* @param {Collection} actual
* @param {Collection} expected
* @namespace Assert
* @api public
*/
const assert = chai.assert;
const originalEqual = assert.equal;
const originalNotEqual = assert.notEqual;
assert.equal = function (actual, expected) {
// It seems like we shouldn't actually need this check, however,
// `assert.equal` actually behaves differently than its BDD counterpart!
// Namely, the BDD version is strict while the "assert" one isn't.
if (Immutable.Iterable.isIterable(actual)) {
return new Assertion(actual).equal(expected);
}
else return originalEqual(actual, expected);
};
/**
* ### .equal(actual, expected)
*
* Asserts that the values of `actual` are equivalent to the values of
* `expected`. Note that `.strictEqual()` and `.deepEqual()` assert
* exactly like `.equal()` in the context of Immutable data structures.
*
* ```js
* const a = List.of(1, 2, 3);
* const b = List.of(1, 2, 3);
* assert.equal(a, b);
* ```
*
* Immutable data structures should only contain other immutable data
* structures (unlike `Array`s and `Object`s) to be considered immutable and
* properly work against `.equal()`, `.strictEqual()` or `.deepEqual()`. See
* [this issue](https://github.com/astorije/chai-immutable/issues/24) for
* more information.
*
* @name equal
* @param {Collection} actual
* @param {Collection} expected
* @namespace Assert
* @api public
*/
/**
* ### .notEqual(actual, expected)
*
* Asserts that the values of `actual` are not equivalent to the values of
* `expected`. Note that `.notStrictEqual()` and `.notDeepEqual()` assert
* exactly like `.notEqual()` in the context of Immutable data structures.
*
* ```js
* var a = List.of(1, 2, 3);
* var b = List.of(4, 5, 6);
* assert.notEqual(a, b);
* ```
*
* @name notEqual
* @param {Collection} actual
* @param {Collection} expected
* @namespace Assert
* @api public
*/
assert.equal = (actual, expected) => {
// It seems like we shouldn't actually need this check, however,
// `assert.equal` actually behaves differently than its BDD counterpart!
// Namely, the BDD version is strict while the "assert" one isn't.
if (Immutable.Iterable.isIterable(actual)) {
return new Assertion(actual).equal(expected);
} else {
return originalEqual(actual, expected);
}
};
assert.notEqual = function (actual, expected) {
if (Immutable.Iterable.isIterable(actual)) {
return new Assertion(actual).not.equal(expected);
}
else return originalNotEqual(actual, expected);
};
/**
* ### .notEqual(actual, expected)
*
* Asserts that the values of `actual` are not equivalent to the values of
* `expected`. Note that `.notStrictEqual()` and `.notDeepEqual()` assert
* exactly like `.notEqual()` in the context of Immutable data structures.
*
* ```js
* const a = List.of(1, 2, 3);
* const b = List.of(4, 5, 6);
* assert.notEqual(a, b);
* ```
*
* @name notEqual
* @param {Collection} actual
* @param {Collection} expected
* @namespace Assert
* @api public
*/
/**
* ### .sizeOf(collection, length)
*
* Asserts that the immutable collection has the expected size.
*
* ```js
* assert.sizeOf(List.of(1, 2, 3), 3);
* assert.sizeOf(new List(), 0);
* ```
*
* @name sizeOf
* @param {Collection} collection
* @param {Number} size
* @namespace Assert
* @api public
*/
assert.notEqual = (actual, expected) => {
if (Immutable.Iterable.isIterable(actual)) {
return new Assertion(actual).not.equal(expected);
} else {
return originalNotEqual(actual, expected);
}
};
assert.sizeOf = function (collection, expected) {
new Assertion(collection).size(expected);
};
/**
* ### .sizeOf(collection, length)
*
* Asserts that the immutable collection has the expected size.
*
* ```js
* assert.sizeOf(List.of(1, 2, 3), 3);
* assert.sizeOf(new List(), 0);
* ```
*
* @name sizeOf
* @param {Collection} collection
* @param {Number} size
* @namespace Assert
* @api public
*/
assert.sizeOf = (collection, expected) => {
new Assertion(collection).size(expected);
};
}));
});
{
"name": "chai-immutable",
"version": "2.0.0-alpha.1",
"version": "2.0.0-alpha.2",
"description": "Chai assertions for Facebook's Immutable library for JavaScript collections",
"publishConfig": {
"tag": "next"
},
"main": "chai-immutable.js",

@@ -13,9 +10,7 @@ "directories": {

"scripts": {
"check-style": "jscs chai-immutable.js test/test.js",
"test": "npm run test-mocha; npm run test-phantomjs; npm run test-readme; npm run check-style",
"test-readme": "mocha --compilers md:fulky/mocha-md-compiler README.md",
"test-mocha": "mocha",
"test-phantomjs": "mocha-phantomjs test/index.html",
"coverage": "istanbul cover _mocha",
"coveralls": "npm run coverage && cat ./coverage/lcov.info | coveralls"
"lint": "eslint --ignore-path .gitignore . --report-unused-disable-directives",
"test": "npm run test-mocha; npm run test-readme; npm run lint",
"test-readme": "mocha --compilers md:fulky/md-compiler README.md",
"test-mocha": "nyc mocha",
"coveralls": "nyc report --reporter=text-lcov | coveralls"
},

@@ -39,2 +34,5 @@ "repository": {

"license": "MIT",
"engines": {
"node": ">=6"
},
"bugs": {

@@ -45,14 +43,17 @@ "url": "https://github.com/astorije/chai-immutable/issues"

"peerDependencies": {
"chai": "^4.0.0"
"chai": "^4.0.0",
"immutable": "^3.0.0"
},
"devDependencies": {
"chai": "^4.0.0",
"coveralls": "^2.11.9",
"fulky": "^0.1.0",
"immutable": "^3.7.5",
"istanbul": "^0.4.3",
"jscs": "^2.5.0",
"mocha": "^2.4.5",
"mocha-phantomjs": "^4.1.0"
"chai": "4.1.2",
"coveralls": "3.0.1",
"eslint": "4.19.1",
"eslint-plugin-chai-expect": "1.1.1",
"eslint-plugin-chai-friendly": "0.4.1",
"eslint-plugin-mocha": "5.0.0",
"fulky": "0.2.0",
"immutable": "3.8.2",
"mocha": "5.2.0",
"nyc": "11.8.0"
}
}

@@ -37,2 +37,4 @@ [![npm Version](https://img.shields.io/npm/v/chai-immutable.svg)](https://npmjs.org/package/chai-immutable)

⚠️ To use `chai-immutable` with Chai v4, you need to use `npm install chai-immutable@next` instead, until I am done with the v2 release of this plugin. I apologize for the inconvenience in the meantime.
You can then use this plugin as any other Chai plugins:

@@ -126,132 +128,183 @@

Note that `deep.include` behaves exactly like `include` in the context of
immutable data structures.
```js
expect(new List([1, 2, 3])).to.include(2);
expect(new Map({ foo: 'bar', hello: 'universe' })).to.include.keys('foo');
expect(new List([1, 2, 3])).to.deep.include(2);
expect(new Map({ foo: 'bar', hello: 'world' })).to.include.keys('foo');
```
### .keys(key1[, key2, ...[, keyN]])
### .keys(key1[, key2[, ...]])
- **@param** *{ String... | Array | Object | Collection }* key*N*
Asserts that the keyed collection contains any or all of the passed-in
keys. Use in combination with `any`, `all`, `contains`, or `have` will
affect what will pass.
Asserts that the target collection has the given keys.
When used in conjunction with `any`, at least one key that is passed in
must exist in the target object. This is regardless whether or not
the `have` or `contain` qualifiers are used. Note, either `any` or `all`
should be used in the assertion. If neither are used, the assertion is
defaulted to `all`.
When the target is an object or array, keys can be provided as one or more
string arguments, a single array argument, a single object argument, or an
immutable collection. In the last 2 cases, only the keys in the given
object/collection matter; the values are ignored.
When both `all` and `contain` are used, the target object must have at
least all of the passed-in keys but may have more keys not listed.
```js
expect(new Map({ foo: 1, bar: 2 })).to.have.all.keys('foo', 'bar');
expect(new Map({ foo: 1, bar: 2 })).to.have.all.keys(new List(['bar', 'foo']));
expect(new Map({ foo: 1, bar: 2 })).to.have.all.keys(new Set(['bar', 'foo']));
expect(new Map({ foo: 1, bar: 2 })).to.have.all.keys(new Stack(['bar', 'foo']));
expect(new List(['x', 'y'])).to.have.all.keys(0, 1);
When both `all` and `have` are used, the target object must both contain
all of the passed-in keys AND the number of keys in the target object must
match the number of keys passed in (in other words, a target object must
have all and only all of the passed-in keys).
expect(new Map({ foo: 1, bar: 2 })).to.have.all.keys(['foo', 'bar']);
expect(new List(['x', 'y'])).to.have.all.keys([0, 1]);
`key` is an alias to `keys`.
// Values in the passed object are ignored:
expect(new Map({ foo: 1, bar: 2 })).to.have.all.keys({ bar: 6, foo: 7 });
expect(new Map({ foo: 1, bar: 2 })).to.have.all.keys(new Map({ bar: 6, foo: 7 }));
expect(new List(['x', 'y'])).to.have.all.keys({ 0: 4, 1: 5 });
```
Note that `deep.property` behaves exactly like `property` in the context of
immutable data structures.
By default, the target must have all of the given keys and no more. Add
`.any` earlier in the chain to only require that the target have at least
one of the given keys. Also, add `.not` earlier in the chain to negate
`.keys`. It's often best to add `.any` when negating `.keys`, and to use
`.all` when asserting `.keys` without negation.
When negating `.keys`, `.any` is preferred because `.not.any.keys` asserts
exactly what's expected of the output, whereas `.not.all.keys` creates
uncertain expectations.
```js
// Recommended; asserts that target doesn't have any of the given keys
expect(new Map({a: 1, b: 2})).to.not.have.any.keys('c', 'd');
// Not recommended; asserts that target doesn't have all of the given
// keys but may or may not have some of them
expect(new Map({a: 1, b: 2})).to.not.have.all.keys('c', 'd');
```
When asserting `.keys` without negation, `.all` is preferred because
`.all.keys` asserts exactly what's expected of the output, whereas
`.any.keys` creates uncertain expectations.
```js
// Recommended; asserts that target has all the given keys
expect(new Map({a: 1, b: 2})).to.have.all.keys('a', 'b');
// Not recommended; asserts that target has at least one of the given
// keys but may or may not have more of them
expect(new Map({a: 1, b: 2})).to.have.any.keys('a', 'b');
```
Note that `.all` is used by default when neither `.all` nor `.any` appear
earlier in the chain. However, it's often best to add `.all` anyway because
it improves readability.
```js
// Both assertions are identical
expect(new Map({a: 1, b: 2})).to.have.all.keys('a', 'b'); // Recommended
expect(new Map({a: 1, b: 2})).to.have.keys('a', 'b'); // Not recommended
```
Add `.include` earlier in the chain to require that the target's keys be a
superset of the expected keys, rather than identical sets.
```js
// Target object's keys are a superset of ['a', 'b'] but not identical
expect(new Map({a: 1, b: 2, c: 3})).to.include.all.keys('a', 'b');
expect(new Map({a: 1, b: 2, c: 3})).to.not.have.all.keys('a', 'b');
```
However, if `.any` and `.include` are combined, only the `.any` takes
effect. The `.include` is ignored in this case.
```js
// Both assertions are identical
expect(new Map({a: 1})).to.have.any.keys('a', 'b');
expect(new Map({a: 1})).to.include.any.keys('a', 'b');
```
The alias `.key` can be used interchangeably with `.keys`.
```js
expect(new Map({ foo: 1 })).to.have.key('foo');
expect(new Map({ foo: 1, bar: 2 })).to.have.keys('foo', 'bar');
expect(new Map({ foo: 1, bar: 2 })).to.have.keys(new List(['bar', 'foo']));
expect(new Map({ foo: 1, bar: 2 })).to.have.keys(new Set(['bar', 'foo']));
expect(new Map({ foo: 1, bar: 2 })).to.have.keys(new Stack(['bar', 'foo']));
expect(new Map({ foo: 1, bar: 2 })).to.have.keys(['bar', 'foo']);
expect(new Map({ foo: 1, bar: 2 })).to.have.keys({ 'bar': 6, 'foo': 7 });
expect(new Map({ foo: 1, bar: 2 })).to.have.keys(new Map({ 'bar': 6, 'foo': 7 }));
expect(new Map({ foo: 1, bar: 2 })).to.have.any.keys('foo', 'not-foo');
expect(new Map({ foo: 1, bar: 2 })).to.have.all.keys('foo', 'bar');
expect(new Map({ foo: 1, bar: 2 })).to.contain.key('foo');
```
### .property(name, [value])
### .property(path[, val])
- **@param** *{ String | Array | Iterable }* name
- **@param** *{ Mixed }* value (optional)
- **@param** *{ String | Array | Iterable }* path
- **@param** *{ Mixed }* val (optional)
Asserts that the target has a property `name`, optionally asserting that
the value of that property is equal to `value`. `value` can be an
Immutable object.
If the `nested` flag is set, you can use dot- and bracket-notation for nested
references into objects and arrays.
Asserts that the target has a property with the given `path`.
<!-- fulky:define maps -->
```js
// Simple referencing
var map = new Map({ foo: 'bar' });
expect(map).to.have.property('foo');
expect(map).to.have.property('foo', 'bar');
expect(new Map({a: 1})).to.have.property('a');
```
// Deep referencing
var nestedMap = new Map({
green: new Map({ tea: 'matcha' }),
teas: new List(['chai', 'matcha', new Map({ tea: 'konacha' })])
});
When `val` is provided, `.property` also asserts that the property's value
is equal to the given `val`. `val` can be an immutable collection.
expect(nestedMap).to.have.nested.property('green.tea', 'matcha');
expect(nestedMap).to.have.nested.property(['green', 'tea'], 'matcha');
expect(nestedMap).to.have.nested.property(new List(['green', 'tea']), 'matcha');
expect(nestedMap).to.have.nested.property('teas[1]', 'matcha');
expect(nestedMap).to.have.nested.property(['teas', 1], 'matcha');
expect(nestedMap).to.have.nested.property(new List(['teas', 1]), 'matcha');
expect(nestedMap).to.have.nested.property('teas[2].tea', 'konacha');
expect(nestedMap).to.have.nested.property(['teas', 2, 'tea'], 'konacha');
expect(nestedMap).to.have.nested.property(new List(['teas', 2, 'tea']), 'konacha');
```js
expect(new Map({a: 1})).to.have.property('a', 1);
```
You can also use a `List` as the starting point of a `nested.property`
assertion, or traverse nested `List`s.
Note that `deep.property` behaves exactly like `property` in the context of
immutable data structures.
Add `.nested` earlier in the chain to enable dot- and bracket-notation when
referencing nested properties. An immutable `List` can also be used as the
starting point of a `nested.property`.
```js
var list = new List([
new List(['chai', 'matcha', 'konacha']),
new List([
new Map({ tea: 'chai' }),
new Map({ tea: 'matcha' }),
new Map({ tea: 'konacha' })
])
]);
expect(Immutable.fromJS({a: {b: ['x', 'y']}})).to.have.nested.property('a.b[1]');
expect(Immutable.fromJS({a: {b: ['x', 'y']}})).to.have.nested.property('a.b[1]', 'y');
expect(Immutable.fromJS({a: {b: ['x', 'y']}})).to.have.nested.property(['a', 'b', 1], 'y');
expect(Immutable.fromJS({a: {b: ['x', 'y']}})).to.have.nested.property(new List(['a', 'b', 1]), 'y');
```
expect(list).to.have.nested.property('[0][1]', 'matcha');
expect(list).to.have.nested.property([0, 1], 'matcha');
expect(list).to.have.nested.property(new List([0, 1]), 'matcha');
expect(list).to.have.nested.property('[1][2].tea', 'konacha');
expect(list).to.have.nested.property([1, 2, 'tea'], 'konacha');
expect(list).to.have.nested.property(new List([1, 2, 'tea']), 'konacha');
If `.` or `[]` are part of an actual property name, they can be escaped by
adding two backslashes before them.
```js
expect(Immutable.fromJS({'.a': {'[b]': 'x'}})).to.have.nested.property('\\.a.\\[b\\]');
```
Furthermore, `property` changes the subject of the assertion
to be the value of that property from the original object. This
permits for further chainable assertions on that property.
Add `.not` earlier in the chain to negate `.property`.
<!-- fulky:use maps -->
```js
expect(map).to.have.property('foo')
.that.is.a('string');
expect(nestedMap).to.have.property('green')
.that.is.an.instanceof(Map)
.that.equals(new Map({ tea: 'matcha' }));
expect(nestedMap).to.have.property('teas')
.that.is.an.instanceof(List)
.with.nested.property([2])
.that.equals(new Map({ tea: 'konacha' }));
expect(new Map({a: 1})).to.not.have.property('b');
```
Note that dots and brackets in `name` must be backslash-escaped when
the `nested` flag is set, while they must NOT be escaped when the `nested`
flag is not set.
However, it's dangerous to negate `.property` when providing `val`. The
problem is that it creates uncertain expectations by asserting that the
target either doesn't have a property at the given `path`, or that it
does have a property at the given key `path` but its value isn't equal to
the given `val`. It's often best to identify the exact output that's
expected, and then write an assertion that only accepts that exact output.
When the target isn't expected to have a property at the given
`path`, it's often best to assert exactly that.
```js
// Simple referencing
var css = new Map({ '.link[target]': 42 });
expect(css).to.have.property('.link[target]', 42);
expect(new Map({b: 2})).to.not.have.property('a'); // Recommended
expect(new Map({b: 2})).to.not.have.property('a', 1); // Not recommended
```
// Deep referencing
var nestedCss = new Map({ '.link': new Map({ '[target]': 42 }) });
expect(nestedCss).to.have.nested.property('\\.link.\\[target\\]', 42);
When the target is expected to have a property at the given key `path`,
it's often best to assert that the property has its expected value, rather
than asserting that it doesn't have one of many unexpected values.
```js
expect(new Map({a: 3})).to.have.property('a', 3); // Recommended
expect(new Map({a: 3})).to.not.have.property('a', 1); // Not recommended
```
`.property` changes the target of any assertions that follow in the chain
to be the value of the property from the original target object.
```js
expect(new Map({a: 1})).to.have.property('a').that.is.a('number');
```
### .size(value)

@@ -258,0 +311,0 @@

@@ -5,29 +5,35 @@ 'use strict';

function clone(obj) {
if (null === obj || 'object' !== typeof obj) return obj;
var copy = obj.constructor();
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
if (obj === null || typeof obj !== 'object') {
return obj;
}
const copy = obj.constructor();
for (const attr in obj) {
if (Object.prototype.hasOwnProperty.call(obj, attr)) {
copy[attr] = obj[attr];
}
}
return copy;
}
var typeEnv;
// These can be global if they are coming from a browser environment, so `let`
// cannot be used here.
var chai; // eslint-disable-line no-var
var chaiImmutable; // eslint-disable-line no-var
var Immutable; // eslint-disable-line no-var
if (!chai) {
var chai = require('chai');
var chaiImmutable = require('../chai-immutable');
var Immutable = require('immutable');
chai = require('chai');
chaiImmutable = require('../chai-immutable');
Immutable = require('immutable');
chai.use(chaiImmutable);
typeEnv = 'Node.js';
}
else typeEnv = 'PhantomJS';
var clonedImmutable = clone(Immutable);
const clonedImmutable = clone(Immutable);
var assert = chai.assert;
var expect = chai.expect;
var List = Immutable.List;
var Map = Immutable.Map;
var Set = Immutable.Set;
var Stack = Immutable.Stack;
const assert = chai.assert;
const expect = chai.expect;
const List = Immutable.List;
const Map = Immutable.Map;
const Set = Immutable.Set;
const Stack = Immutable.Stack;

@@ -39,37 +45,27 @@ /*!

function fail(fn, msg) {
if (msg !== undefined) expect(fn).to.throw(chai.AssertionError, msg);
else expect(fn).to.throw(chai.AssertionError);
if (msg) {
expect(fn).to.throw(chai.AssertionError, msg);
} else {
expect(fn).to.throw(chai.AssertionError);
}
}
describe('chai-immutable (' + typeEnv + ')', function () {
var list3 = List.of(1, 2, 3);
describe('chai-immutable', function () { // eslint-disable-line prefer-arrow-callback
const list3 = List.of(1, 2, 3);
const deepMap = new Map({ foo: 'bar', list: List.of(1, 2, 3) });
const sameDeepMap = new Map({ foo: 'bar', list: List.of(1, 2, 3) });
const differentDeepMap = new Map({ foo: 'bar', list: List.of(42) });
const clonedImmutableList = clonedImmutable.List.of(1, 2, 3);
var deepMap = new Map({
foo: 'bar',
list: List.of(1, 2, 3),
});
var sameDeepMap = new Map({
foo: 'bar',
list: List.of(1, 2, 3),
});
var differentDeepMap = new Map({
foo: 'bar',
list: List.of(42),
});
var clonedImmutableList = clonedImmutable.List.of(1, 2, 3);
describe('BDD interface', function () {
describe('empty property', function () {
it('should pass given an empty collection', function () {
describe('BDD interface', function () { // eslint-disable-line prefer-arrow-callback
describe('empty property', function () { // eslint-disable-line prefer-arrow-callback
it('should pass given an empty collection', function () { // eslint-disable-line prefer-arrow-callback
expect(new List()).to.be.empty;
});
it('should pass using `not` given a non-empty collection', function () {
it('should pass using `not` given a non-empty collection', function () { // eslint-disable-line prefer-arrow-callback
expect(list3).to.not.be.empty;
});
it('should not affect the original assertions', function () {
it('should not affect the original assertions', function () { // eslint-disable-line prefer-arrow-callback
expect([]).to.be.empty;

@@ -80,25 +76,25 @@ expect('').to.be.empty;

it('should fail given a non-empty collection', function () {
fail(function () { expect(list3).to.be.empty; });
it('should fail given a non-empty collection', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(list3).to.be.empty);
});
it('should fail using `not` given an empty collection', function () {
fail(function () { expect(new List()).to.not.be.empty; });
it('should fail using `not` given an empty collection', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(new List()).to.not.be.empty);
});
it('should work if using different copies of Immutable', function () {
expect(clonedImmutable.List()).to.be.empty;
it('should work if using different copies of Immutable', function () { // eslint-disable-line prefer-arrow-callback
expect(new clonedImmutable.List()).to.be.empty;
});
});
describe('equal method', function () {
it('should pass given equal values', function () {
describe('equal method', function () { // eslint-disable-line prefer-arrow-callback
it('should pass given equal values', function () { // eslint-disable-line prefer-arrow-callback
expect(list3).to.equal(List.of(1, 2, 3));
});
it('should pass using `not` given different values', function () {
it('should pass using `not` given different values', function () { // eslint-disable-line prefer-arrow-callback
expect(list3).to.not.equal(new List());
});
it('aliases of equal should also work', function () {
it('aliases of equal should also work', function () { // eslint-disable-line prefer-arrow-callback
expect(list3).to.equal(List.of(1, 2, 3));

@@ -118,3 +114,3 @@ expect(list3).to.not.equal(new List());

it('should not affect the original assertions', function () {
it('should not affect the original assertions', function () { // eslint-disable-line prefer-arrow-callback
expect('hello').to.equal('hello');

@@ -127,3 +123,3 @@ expect(42).to.equal(42);

it('should pass given deeply equal values', function () {
it('should pass given deeply equal values', function () { // eslint-disable-line prefer-arrow-callback
expect(deepMap).to.equal(sameDeepMap);

@@ -137,3 +133,3 @@ expect(deepMap).to.equals(sameDeepMap);

it('should pass using `not` given deeply different values', function () {
it('should pass using `not` given deeply different values', function () { // eslint-disable-line prefer-arrow-callback
expect(deepMap).to.not.equal(differentDeepMap);

@@ -147,46 +143,54 @@ expect(deepMap).to.not.equals(differentDeepMap);

it('should pass using `not` given a non-Immutable value', function () {
expect([]).to.not.equal(List());
it('should pass using `not` given a non-Immutable value', function () { // eslint-disable-line prefer-arrow-callback
expect([]).to.not.equal(new List());
});
// See https://github.com/astorije/chai-immutable/issues/7
it('should display a helpful failure output on big objects', function () {
var actual = new Map({ foo: 'foo foo foo foo foo foo foo foo' });
var expected = new Map({ bar: 'bar bar bar bar bar bar bar bar' });
fail(function () {
expect(actual).to.equal(expected);
}, /(foo ?){8}.+(bar ?){8}/);
it('should display a helpful failure output on big objects', function () { // eslint-disable-line prefer-arrow-callback
const actual = new Map({ foo: 'foo foo foo foo foo foo foo foo' });
const expected = new Map({ bar: 'bar bar bar bar bar bar bar bar' });
// AssertionError: expected { Object (foo) } to equal { Object (bar) }
// + expected - actual
//
// {
// - "foo": "foo foo foo foo foo foo foo foo"
// + "bar": "bar bar bar bar bar bar bar bar"
// }
fail(
() => expect(actual).to.equal(expected),
'expected { Object (foo) } to equal { Object (bar) }'
);
});
it('should fail given a non-Immutable value', function () {
fail(function () { expect([]).to.equal(List()); });
it('should fail given a non-Immutable value', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect([]).to.equal(new List()));
});
it('should fail given different values', function () {
fail(function () { expect(list3).to.equal(new List()); });
it('should fail given different values', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(list3).to.equal(new List()));
});
it('should fail using `not` given equal values', function () {
fail(function () { expect(list3).to.not.equal(List.of(1, 2, 3)); });
it('should fail using `not` given equal values', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(list3).to.not.equal(List.of(1, 2, 3)));
});
it('should fail given deeply different values', function () {
fail(function () { expect(deepMap).to.equal(differentDeepMap); });
fail(function () { expect(deepMap).to.equals(differentDeepMap); });
fail(function () { expect(deepMap).to.eq(differentDeepMap); });
fail(function () { expect(deepMap).to.eql(differentDeepMap); });
fail(function () { expect(deepMap).to.eqls(differentDeepMap); });
fail(function () { expect(deepMap).to.deep.equal(differentDeepMap); });
it('should fail given deeply different values', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(deepMap).to.equal(differentDeepMap));
fail(() => expect(deepMap).to.equals(differentDeepMap));
fail(() => expect(deepMap).to.eq(differentDeepMap));
fail(() => expect(deepMap).to.eql(differentDeepMap));
fail(() => expect(deepMap).to.eqls(differentDeepMap));
fail(() => expect(deepMap).to.deep.equal(differentDeepMap));
});
it('should fail using `not` given deeply equal values', function () {
fail(function () { expect(deepMap).to.not.equal(sameDeepMap); });
fail(function () { expect(deepMap).to.not.equals(sameDeepMap); });
fail(function () { expect(deepMap).to.not.eq(sameDeepMap); });
fail(function () { expect(deepMap).to.not.eql(sameDeepMap); });
fail(function () { expect(deepMap).to.not.eqls(sameDeepMap); });
fail(function () { expect(deepMap).to.not.deep.equal(sameDeepMap); });
it('should fail using `not` given deeply equal values', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(deepMap).to.not.equal(sameDeepMap));
fail(() => expect(deepMap).to.not.equals(sameDeepMap));
fail(() => expect(deepMap).to.not.eq(sameDeepMap));
fail(() => expect(deepMap).to.not.eql(sameDeepMap));
fail(() => expect(deepMap).to.not.eqls(sameDeepMap));
fail(() => expect(deepMap).to.not.deep.equal(sameDeepMap));
});
it('should work if using different copies of Immutable', function () {
it('should work if using different copies of Immutable', function () { // eslint-disable-line prefer-arrow-callback
expect(clonedImmutableList).to.equal(List.of(1, 2, 3));

@@ -196,26 +200,27 @@ });

describe('include method', function () {
it('should pass given an existing value', function () {
describe('include method', function () { // eslint-disable-line prefer-arrow-callback
it('should pass given an existing value', function () { // eslint-disable-line prefer-arrow-callback
expect(new List([1, 2, 3])).to.include(2);
expect(new List([1, 2, 3])).to.deep.include(2);
});
it('should pass using `not` given an inexisting value', function () {
it('should pass using `not` given an inexisting value', function () { // eslint-disable-line prefer-arrow-callback
expect(new List([1, 2, 3])).to.not.include(42);
expect(new List([1, 2, 3])).to.not.deep.include(42);
});
it('should chain and pass given an existing key', function () {
expect(new Map({
foo: 'bar',
hello: 'universe',
})).to.include.keys('foo');
it('should chain and pass given an existing key', function () { // eslint-disable-line prefer-arrow-callback
expect(new Map({ foo: 'bar', hello: 'world' })).to.include.keys('foo');
expect(new Map({ foo: 'bar', hello: 'world' }))
.to.deep.include.keys('foo');
});
it('should chain and pass using `not` given an inexisting key', function () {
expect(new Map({
foo: 'bar',
hello: 'universe',
})).to.not.include.keys('not-foo');
it('should chain and pass using `not` given an inexisting key', function () { // eslint-disable-line prefer-arrow-callback
expect(new Map({ foo: 'bar', hello: 'world' }))
.to.not.include.keys('not-foo');
expect(new Map({ foo: 'bar', hello: 'world' }))
.to.not.deep.include.keys('not-foo');
});
it('aliases of include should also work', function () {
it('aliases of include should also work', function () { // eslint-disable-line prefer-arrow-callback
expect(new List([1, 2, 3])).contain(2);

@@ -229,300 +234,390 @@ expect(new List([1, 2, 3])).not.contain(42);

it('should not affect the original assertions', function () {
it('should not affect the original assertions', function () { // eslint-disable-line prefer-arrow-callback
expect([1, 2, 3]).to.include(2);
expect([1, 2, 3]).to.deep.include(2);
expect('foobar').to.contain('foo');
expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo');
expect('foobar').to.deep.contain('foo');
expect({ foo: 'bar', hello: 'world' }).to.include.keys('foo');
expect({ foo: 'bar', hello: 'world' }).to.deep.include.keys('foo');
});
// See https://github.com/astorije/chai-immutable/issues/7
it('should display a helpful failure output on big objects', function () {
var lengthyMap = new Map({ foo: 'foo foo foo foo foo foo foo foo ' });
fail(function () {
expect(lengthyMap).to.include('not-foo');
}, /(foo ){8}/);
it('should display a helpful failure output on big objects', function () { // eslint-disable-line prefer-arrow-callback
const lengthyMap = new Map({ foo: 'foo foo foo foo foo foo foo foo ' });
fail(
() => expect(lengthyMap).to.include('not-foo'),
/(foo ){8}/
);
fail(
() => expect(lengthyMap).to.deep.include('not-foo'),
/(foo ){8}/
);
});
it('should fail given an inexisting value', function () {
fail(function () { expect(new List([1, 2, 3])).to.include(42); });
it('should fail given an inexisting value', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(new List([1, 2, 3])).to.include(42));
fail(() => expect(new List([1, 2, 3])).to.deep.include(42));
});
it('should fail using `not` given an existing value', function () {
fail(function () { expect(new List([1, 2, 3])).not.to.include(2); });
it('should fail using `not` given an existing value', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(new List([1, 2, 3])).not.to.include(2));
fail(() => expect(new List([1, 2, 3])).not.to.deep.include(2));
});
it('should chain and fail given an inexisting key', function () {
fail(function () {
expect(new Map({
foo: 'bar',
hello: 'universe',
})).to.include.keys('not-foo');
});
it('should chain and fail given an inexisting key', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(new Map({ foo: 'bar', hello: 'world' }))
.to.include.keys('not-foo'));
fail(() => expect(new Map({ foo: 'bar', hello: 'world' }))
.to.deep.include.keys('not-foo'));
});
it('should chain and fail using `not` given an existing key', function () {
fail(function () {
expect(new Map({
foo: 'bar',
hello: 'universe',
})).to.not.include.keys('foo');
});
it('should chain and fail using `not` given an existing key', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(new Map({ foo: 'bar', hello: 'world' }))
.to.not.include.keys('foo'));
fail(() => expect(new Map({ foo: 'bar', hello: 'world' }))
.to.not.deep.include.keys('foo'));
});
});
describe('keys method', function () {
var map = new Map({ x: 1, y: 2 });
var obj = { x: 1, y: 2 };
describe('keys method', function () { // eslint-disable-line prefer-arrow-callback
const obj = { x: 1, y: 2 };
const map = new Map(obj);
it('should pass given an existing key', function () {
it('should pass given an existing key', function () { // eslint-disable-line prefer-arrow-callback
expect(new Map({ x: 1 })).to.have.key('x');
expect({ x: 1 }).to.have.key('x');
expect(new Map({ x: 1 })).to.have.deep.key('x');
});
it('should pass using `not` given an inexisting key', function () {
it('should pass using `not` given an inexisting key', function () { // eslint-disable-line prefer-arrow-callback
expect(map).to.not.have.key('z');
expect(obj).to.not.have.key('z');
expect(map).to.not.have.deep.key('z');
});
it('should pass given multiple existing keys', function () {
it('should pass given multiple existing keys', function () { // eslint-disable-line prefer-arrow-callback
expect(map).to.have.keys('x', 'y');
expect(obj).to.have.keys('x', 'y');
expect(map).to.have.deep.keys('x', 'y');
});
it('should pass using `not` given multiple inexisting keys', function () {
it('should pass using `not` given multiple inexisting keys', function () { // eslint-disable-line prefer-arrow-callback
expect(map).to.not.have.keys('z1', 'z2');
expect(obj).to.not.have.keys('z1', 'z2');
expect(map).to.not.have.deep.keys('z1', 'z2');
});
it('should accept an Array of keys to check against', function () {
it('should accept an Array of keys to check against', function () { // eslint-disable-line prefer-arrow-callback
expect(map).to.have.keys(['x', 'y']);
expect(obj).to.have.keys(['x', 'y']);
expect(map).to.have.deep.keys(['x', 'y']);
});
it('should accept a List of keys to check against', function () {
it('should accept a List of keys to check against', function () { // eslint-disable-line prefer-arrow-callback
expect(map).to.have.keys(new List(['x', 'y']));
expect(map).to.have.deep.keys(new List(['x', 'y']));
});
it('should accept a Set of keys to check against', function () {
it('should accept a Set of keys to check against', function () { // eslint-disable-line prefer-arrow-callback
expect(map).to.have.keys(new Set(['x', 'y']));
expect(map).to.have.deep.keys(new Set(['x', 'y']));
});
it('should accept a Stack of keys to check against', function () {
it('should accept a Stack of keys to check against', function () { // eslint-disable-line prefer-arrow-callback
expect(map).to.have.keys(new Stack(['x', 'y']));
expect(map).to.have.deep.keys(new Stack(['x', 'y']));
});
it('should accept an Object to check against', function () {
expect(map).to.have.keys({ 'x': 6, 'y': 7 });
expect(obj).to.have.keys({ 'x': 6, 'y': 7 });
it('should accept an Object to check against', function () { // eslint-disable-line prefer-arrow-callback
expect(map).to.have.keys({ x: 6, y: 7 });
expect(map).to.have.deep.keys({ x: 6, y: 7 });
expect(new List(['x', 'y'])).to.have.all.keys({ 0: 4, 1: 5 });
});
it('should accept a Map to check against', function () {
expect(map).to.have.keys(new Map({ 'x': 6, 'y': 7 }));
it('should accept a Map to check against', function () { // eslint-disable-line prefer-arrow-callback
expect(map).to.have.keys(new Map({ x: 6, y: 7 }));
expect(map).to.have.deep.keys(new Map({ x: 6, y: 7 }));
});
it('should pass using `any` given an existing key', function () {
it('should error when given multiple non-scalar arguments', function () { // eslint-disable-line prefer-arrow-callback
const msg = 'when testing keys against an immutable collection, ' +
'you must give a single Array|Object|String|Collection argument or ' +
'multiple String arguments';
fail(() => expect(map).to.have.all.keys(['x'], 'y'), msg);
fail(() => expect(map).to.have.all.keys(new List(['x']), 'y'), msg);
fail(() => expect(map).to.have.all.keys(new Set(['x']), 'y'), msg);
fail(() => expect(map).to.have.all.keys(new Stack(['x']), 'y'), msg);
fail(() => expect(map).to.have.all.keys({ x: 1 }, 'y'), msg);
fail(() => expect(map).to.have.all.keys(new Map({ x: 1 }), 'y'), msg);
});
it('should error when given no arguments', function () { // eslint-disable-line prefer-arrow-callback
const msg = 'keys required';
fail(() => expect(map).to.have.all.keys([]), msg);
fail(() => expect(map).to.have.all.keys(new List()), msg);
fail(() => expect(map).to.have.all.keys(new Set()), msg);
fail(() => expect(map).to.have.all.keys(new Stack()), msg);
fail(() => expect(map).to.have.all.keys({}), msg);
fail(() => expect(map).to.have.all.keys(new Map()), msg);
});
it('should pass using `any` given an existing key', function () { // eslint-disable-line prefer-arrow-callback
expect(map).to.have.any.keys('x', 'z');
expect(obj).to.have.any.keys('x', 'z');
expect(map).to.have.any.deep.keys('x', 'z');
});
it('should pass using `not` and `any` given inexisting keys', function () {
it('should pass using `not` and `any` given inexisting keys', function () { // eslint-disable-line prefer-arrow-callback
expect(map).to.not.have.any.keys('z1', 'z2');
expect(obj).to.not.have.any.keys('z1', 'z2');
expect(map).to.not.have.any.deep.keys('z1', 'z2');
});
it('should pass using `all` given existing keys', function () {
it('should pass using `all` given existing keys', function () { // eslint-disable-line prefer-arrow-callback
expect(map).to.have.all.keys('x', 'y');
expect(obj).to.have.all.keys('x', 'y');
expect(map).to.have.all.deep.keys('x', 'y');
});
it('should pass using `not` and `all` given inexisting keys', function () {
it('should pass using `not` and `all` given inexisting keys', function () { // eslint-disable-line prefer-arrow-callback
expect(map).to.not.have.all.keys('z1', 'y');
expect(obj).to.not.have.all.keys('z1', 'y');
expect(map).to.not.have.all.deep.keys('z1', 'y');
});
it('should pass using `contain` given an existing key', function () {
it('should pass using `contain` given an existing key', function () { // eslint-disable-line prefer-arrow-callback
expect(map).to.contain.key('x');
expect(obj).to.contain.key('x');
expect(map).to.contain.deep.key('x');
});
it('should not affect the original assertions', function () {
it('should not affect the original assertions', function () { // eslint-disable-line prefer-arrow-callback
expect({ x: 1, y: 2 }).to.have.any.keys('x', 'z');
expect({ x: 1, y: 2 }).to.have.any.deep.keys('x', 'z');
expect({ x: 1, y: 2 }).to.have.any.keys('x');
expect({ x: 1, y: 2 }).to.have.any.deep.keys('x');
expect({ x: 1, y: 2 }).to.contain.any.keys('y', 'z');
expect({ x: 1, y: 2 }).to.contain.any.deep.keys('y', 'z');
expect({ x: 1, y: 2 }).to.contain.any.keys(['x']);
expect({ x: 1, y: 2 }).to.contain.any.keys({ 'x': 6 });
expect({ x: 1, y: 2 }).to.contain.any.deep.keys(['x']);
expect({ x: 1, y: 2 }).to.contain.any.keys({ x: 6 });
expect({ x: 1, y: 2 }).to.contain.any.deep.keys({ x: 6 });
expect({ x: 1, y: 2 }).to.have.all.keys(['x', 'y']);
expect({ x: 1, y: 2 }).to.have.all.keys({ 'x': 6, 'y': 7 });
expect({ x: 1, y: 2 }).to.have.all.deep.keys(['x', 'y']);
expect({ x: 1, y: 2 }).to.have.all.keys({ x: 6, y: 7 });
expect({ x: 1, y: 2 }).to.have.all.deep.keys({ x: 6, y: 7 });
expect({ x: 1, y: 2, z: 3 }).to.contain.all.keys(['x', 'y']);
expect({ x: 1, y: 2, z: 3 }).to.contain.all.keys({ 'x': 6 });
expect({ x: 1, y: 2, z: 3 }).to.contain.all.deep.keys(['x', 'y']);
expect({ x: 1, y: 2, z: 3 }).to.contain.all.keys({ x: 6 });
expect({ x: 1, y: 2, z: 3 }).to.contain.all.deep.keys({ x: 6 });
});
// See https://github.com/astorije/chai-immutable/issues/7
it('should display a helpful failure output on big objects', function () {
var lengthyMap = new Map({ foo: 'foo foo foo foo foo foo foo foo ' });
fail(function () {
expect(lengthyMap).to.have.keys('not-foo');
}, /(foo ){8}/);
it('should display a helpful failure output on big objects', function () { // eslint-disable-line prefer-arrow-callback
const lengthyMap = new Map({ foo: 'foo foo foo foo foo foo foo foo ' });
fail(
() => expect(lengthyMap).to.have.keys('not-foo'),
/(foo ){8}/
);
fail(
() => expect(lengthyMap).to.have.deep.keys('not-foo'),
/(foo ){8}/
);
});
it('should fail given an inexisting key', function () {
fail(function () { expect(new Map({ x: 1 })).to.have.key('z'); });
fail(function () { expect({ x: 1 }).to.have.key('z'); });
it('should pass against Lists', function () { // eslint-disable-line prefer-arrow-callback
expect(new List(['x', 'y'])).to.have.all.keys(0, 1);
expect(new List(['x', 'y'])).to.have.all.keys([0, 1]);
});
it('should fail given multiple inexisting keys', function () {
fail(function () { expect(map).to.have.keys('z1', 'z2'); });
fail(function () { expect(obj).to.have.keys('z1', 'z2'); });
it('should fail given an inexisting key', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(new Map({ x: 1 })).to.have.key('z'));
fail(() => expect(new Map({ x: 1 })).to.have.deep.key('z'));
fail(() => expect({ x: 1 }).to.have.key('z'));
fail(() => expect({ x: 1 }).to.have.deep.key('z'));
});
it('should fail using `not` given multiple existing keys', function () {
fail(function () { expect(map).to.not.have.keys('x', 'y'); });
fail(function () { expect(obj).to.not.have.keys('x', 'y'); });
it('should fail given multiple inexisting keys', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(map).to.have.keys('z1', 'z2'));
fail(() => expect(map).to.have.deep.keys('z1', 'z2'));
});
it('should fail using `any` given inexisting keys', function () {
fail(function () { expect(map).to.have.any.keys('z1', 'z2'); });
fail(function () { expect(obj).to.have.any.keys('z1', 'z2'); });
it('should fail using `not` given multiple existing keys', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(map).to.not.have.keys('x', 'y'));
fail(() => expect(map).to.not.have.deep.keys('x', 'y'));
});
it('should fail using `not` and `any` given an existing key', function () {
fail(function () { expect(map).to.not.have.any.keys('x', 'z'); });
fail(function () { expect(obj).to.not.have.any.keys('x', 'z'); });
it('should fail using `any` given inexisting keys', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(map).to.have.any.keys('z1', 'z2'));
fail(() => expect(map).to.have.any.deep.keys('z1', 'z2'));
});
it('should fail using `all` given an inexisting key', function () {
fail(function () { expect(map).to.have.all.keys('z1', 'y'); });
fail(function () { expect(obj).to.have.all.keys('z1', 'y'); });
it('should fail using `not` and `any` given an existing key', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(map).to.not.have.any.keys('x', 'z'));
fail(() => expect(map).to.not.have.any.deep.keys('x', 'z'));
});
it('should fail using `not` and `all` given existing keys', function () {
fail(function () { expect(map).to.not.have.all.keys('x', 'y'); });
fail(function () { expect(obj).to.not.have.all.keys('x', 'y'); });
it('should fail using `all` given an inexisting key', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(map).to.have.all.keys('z1', 'y'));
fail(() => expect(map).to.have.all.deep.keys('z1', 'y'));
});
it('should fail using `contain` given an inexisting key', function () {
fail(function () { expect(map).to.contain.key('z'); });
fail(function () { expect(obj).to.contain.key('z'); });
it('should fail using `not` and `all` given existing keys', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(map).to.not.have.all.keys('x', 'y'));
fail(() => expect(map).to.not.have.all.deep.keys('x', 'y'));
});
it('should work if using different copies of Immutable', function () {
expect(clonedImmutable.Map({ x: 1 })).to.have.key('x');
it('should fail using `contain` given an inexisting key', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(map).to.contain.key('z'));
fail(() => expect(map).to.contain.deep.key('z'));
});
it('should work if using different copies of Immutable', function () { // eslint-disable-line prefer-arrow-callback
expect(new clonedImmutable.Map({ x: 1 })).to.have.key('x');
expect(new clonedImmutable.Map({ x: 1 })).to.have.deep.key('x');
});
});
describe('property property', function () {
it('should not affect the original assertion', function () {
describe('property property', function () { // eslint-disable-line prefer-arrow-callback
it('should not affect the original assertion', function () { // eslint-disable-line prefer-arrow-callback
expect({ x: 1 }).to.have.property('x', 1);
});
it('should fail given an inexisting property', function () {
var obj = Immutable.fromJS({ x: 1 });
fail(function () { expect(obj).to.have.property('z'); });
it('should not affect the original assertion using `not`', function () { // eslint-disable-line prefer-arrow-callback
expect({ x: 1 }).not.to.have.property('z');
expect({ x: 1 }).not.to.have.property('z', 42);
});
it('should pass using `not` given an inexisting property', function () {
var obj = Immutable.fromJS({ x: 1 });
// All following tests assert against regular `.property` and
// `.deep.property`. In the Immutable world, these are supposed to carry
// the same meaning (similar to `.equal` vs. `.deep.equal`).
const obj = Immutable.fromJS({ x: 1 });
const nestedObj = Immutable.fromJS({ x: 1, y: { x: 2, y: 3 } });
it('should fail given an inexisting property', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(obj).to.have.property('z'));
fail(() => expect(obj).to.have.deep.property('z'));
});
it('should pass using `not` given an inexisting property', function () { // eslint-disable-line prefer-arrow-callback
expect(obj).not.to.have.property('z');
expect(obj).not.to.have.deep.property('z');
});
it('should pass given an existing property', function () {
var obj = Immutable.fromJS({ x: 1 });
it('should pass using `not` given an inexisting property and value', function () { // eslint-disable-line prefer-arrow-callback
expect(obj).not.to.have.property('z', 42);
expect(obj).not.to.have.deep.property('z', 42);
});
it('should pass given an existing property', function () { // eslint-disable-line prefer-arrow-callback
expect(obj).to.have.property('x');
expect(obj).to.have.deep.property('x');
});
it('should fail using `not` given an existing property', function () {
var obj = Immutable.fromJS({ x: 1 });
fail(function () { expect(obj).not.to.have.property('x'); });
it('should fail using `not` given an existing property', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(obj).not.to.have.property('x'));
fail(() => expect(obj).not.to.have.deep.property('x'));
});
it('should fail given a property with a bad value', function () {
var obj = Immutable.fromJS({ x: 1 });
fail(function () { expect(obj).to.have.property('x', 'different'); });
it('should fail given a property with a bad value', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(obj).to.have.property('x', 'different'));
fail(() => expect(obj).to.have.deep.property('x', 'different'));
});
it('should pass given a property with the good value', function () {
var obj = Immutable.fromJS({ x: 1 });
it('should pass given a property with the good value', function () { // eslint-disable-line prefer-arrow-callback
expect(obj).to.have.property('x', 1);
expect(obj).to.have.deep.property('x', 1);
});
it('should pass given an immutable value', function () {
var obj = Immutable.fromJS({ foo: { bar: 42 } });
expect(obj).to.have.property('foo', new Map({ bar: 42 }));
it('should pass given an immutable value', function () { // eslint-disable-line prefer-arrow-callback
const obj2 = Immutable.fromJS({ foo: { bar: 42 } });
expect(obj2).to.have.property('foo', new Map({ bar: 42 }));
expect(obj2).to.have.deep.property('foo', new Map({ bar: 42 }));
});
it('should change the subject to the value of that property', function () {
var obj = Immutable.fromJS({ x: 1, y: { x: 2, y: 3 } });
var sub = obj.get('y');
expect(obj).to.have.property('y').that.equal(sub);
it('should change the subject to the value of that property', function () { // eslint-disable-line prefer-arrow-callback
const sub = nestedObj.get('y');
expect(nestedObj).to.have.property('y').that.equal(sub);
expect(nestedObj).to.have.deep.property('y').that.equal(sub);
});
describe('using the `nested` flag', function () {
it('should not affect the original assertion', function () {
describe('using the `nested` flag', function () { // eslint-disable-line prefer-arrow-callback
it('should not affect the original assertion', function () { // eslint-disable-line prefer-arrow-callback
expect({ x: 1, y: { x: 2, y: 3 } }).to.have.nested.property('y.x', 2);
expect({ x: 1, y: { x: 2, y: 3 } })
.to.have.nested.deep.property('y.x', 2);
});
it('should fail given an inexisting property', function () {
var obj = Immutable.fromJS({ x: 1, y: { x: 2, y: 3 } });
fail(function () { expect(obj).to.have.nested.property(['y', 'z']); });
it('should not affect the original assertion using `not`', function () { // eslint-disable-line prefer-arrow-callback
expect({ x: 1, y: { x: 2 } }).not.to.have.nested.property('z.z');
expect({ x: 1, y: { x: 2 } }).not.to.have.nested.deep.property('z.z');
expect({ x: 1, y: { x: 2 } }).not.to.have.nested.property('z.z', 42);
expect({ x: 1, y: { x: 2 } })
.not.to.have.nested.deep.property('z.z', 42);
});
it('should pass using `not` given an inexisting property', function () {
var obj = Immutable.fromJS({ x: 1, y: { x: 2, y: 3 } });
expect(obj).not.to.have.nested.property(['y', 'z']);
it('should fail given an inexisting property', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(nestedObj).to.have.nested.property(['y', 'z']));
fail(() => expect(nestedObj)
.to.have.nested.deep.property(['y', 'z']));
});
it('should pass given an existing property', function () {
var obj = Immutable.fromJS({ x: 1, y: { x: 2, y: 3 } });
expect(obj).to.have.nested.property(['y', 'x']);
it('should pass using `not` given an inexisting property', function () { // eslint-disable-line prefer-arrow-callback
expect(nestedObj).not.to.have.nested.property(['y', 'z']);
expect(nestedObj).not.to.have.nested.deep.property(['y', 'z']);
});
it('should pass given an index', function () {
var obj = Immutable.fromJS({
items: ['a', 'b', 'c'],
});
expect(obj).to.have.nested.property(['items', 2], 'c');
it('should pass using `not` given an inexisting property and value', function () { // eslint-disable-line prefer-arrow-callback
expect(obj).not.to.have.nested.property(['y', 'x'], 'different');
expect(obj).not.to.have.nested.deep.property(['y', 'x'], 'different');
});
it('should fail using `not` given an existing property', function () {
var obj = Immutable.fromJS({ x: 1, y: { x: 2, y: 3 } });
fail(function () { expect(obj).not.to.have.nested.property(['y', 'x']); });
it('should pass given an existing property', function () { // eslint-disable-line prefer-arrow-callback
expect(nestedObj).to.have.nested.property(['y', 'x']);
expect(nestedObj).to.have.nested.deep.property(['y', 'x']);
});
it('should fail given a property with a bad value', function () {
var obj = Immutable.fromJS({ x: 1, y: { x: 2, y: 3 } });
fail(function () {
expect(obj).to.have.property(['y', 'x'], 'different');
});
it('should pass given an index', function () { // eslint-disable-line prefer-arrow-callback
const obj2 = Immutable.fromJS({ items: ['a', 'b', 'c'] });
expect(obj2).to.have.nested.property(['items', 2], 'c');
expect(obj2).to.have.nested.deep.property(['items', 2], 'c');
});
it('should pass given a property with the good value', function () {
var obj = Immutable.fromJS({ x: 1, y: { x: 2, y: 3 } });
expect(obj).to.have.nested.property(['y', 'x'], 2);
it('should fail using `not` given an existing property', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(nestedObj).not.to.have.nested.property(['y', 'x']));
fail(() => expect(nestedObj)
.not.to.have.nested.deep.property(['y', 'x']));
});
it('should fail using `not` given an inexisting property', function () {
var obj = Immutable.fromJS({ x: 1 });
fail(function () {
expect(obj).not.to.have.nested.property(['y', 'x'], 'different');
});
it('should fail given a property with a bad value', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(nestedObj)
.to.have.nested.property(['y', 'x'], 'different'));
fail(() => expect(nestedObj)
.to.have.nested.deep.property(['y', 'x'], 'different'));
});
it('should fail using `not` given a property with good value', function () {
var obj = Immutable.fromJS({ x: 1, y: { x: 2 } });
fail(function () {
expect(obj).not.to.have.nested.property(['y', 'x'], 2);
});
it('should pass given a property with the good value', function () { // eslint-disable-line prefer-arrow-callback
expect(nestedObj).to.have.nested.property(['y', 'x'], 2);
expect(nestedObj).to.have.nested.deep.property(['y', 'x'], 2);
});
it('should pass using `not` given a property with a bad value', function () {
var obj = Immutable.fromJS({ x: 1, y: { x: 2 } });
expect(obj).not.to.have.nested.property(['y', 'x'], 'different');
it('should fail using `not` given a property with good value', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(nestedObj)
.not.to.have.nested.property(['y', 'x'], 2));
fail(() => expect(nestedObj)
.not.to.have.nested.deep.property(['y', 'x'], 2));
});
it('should pass given an immutable value', function () {
var obj = Immutable.fromJS({ foo: [{ bar: 42 }] });
expect(obj).to.have.nested.property('foo[0]', new Map({ bar: 42 }));
it('should pass using `not` given a property with a bad value', function () { // eslint-disable-line prefer-arrow-callback
expect(nestedObj)
.not.to.have.nested.property(['y', 'x'], 'different');
expect(nestedObj)
.not.to.have.nested.deep.property(['y', 'x'], 'different');
});
it('should pass given an immutable value', function () { // eslint-disable-line prefer-arrow-callback
const nestedObj2 = Immutable.fromJS({ foo: [{ bar: 42 }] });
expect(nestedObj2)
.to.have.nested.property('foo[0]', new Map({ bar: 42 }));
expect(nestedObj2)
.to.have.nested.deep.property('foo[0]', new Map({ bar: 42 }));
});
});
describe('given a string-based path', function () {
var obj = Immutable.fromJS({
describe('given a string-based path', function () { // eslint-disable-line prefer-arrow-callback
const nestedObj2 = Immutable.fromJS({
items: [

@@ -535,9 +630,11 @@ { name: 'Jane' },

it('should pass using `nested` given a single index', function () {
expect(obj.get('items')).to.have.nested.property('[1]')
it('should pass using `nested` given a single index', function () { // eslint-disable-line prefer-arrow-callback
expect(nestedObj2.get('items')).to.have.nested.property('[1]')
.that.equals(new Map({ name: 'John' }));
expect(nestedObj2.get('items')).to.have.nested.deep.property('[1]')
.that.equals(new Map({ name: 'John' }));
});
it('should pass using `nested` given a single key', function () {
expect(obj).to.have.nested.property('items')
it('should pass using `nested` given a single key', function () { // eslint-disable-line prefer-arrow-callback
expect(nestedObj2).to.have.nested.property('items')
.that.equals(new List([

@@ -548,25 +645,41 @@ new Map({ name: 'Jane' }),

]));
expect(nestedObj2).to.have.nested.deep.property('items')
.that.equals(new List([
new Map({ name: 'Jane' }),
new Map({ name: 'John' }),
new Map({ name: 'Jim' }),
]));
});
it('should pass using `nested` starting with an index', function () {
expect(obj.get('items')).to.have.nested.property('[0].name', 'Jane');
it('should pass using `nested` starting with an index', function () { // eslint-disable-line prefer-arrow-callback
expect(nestedObj2.get('items'))
.to.have.nested.property('[0].name', 'Jane');
expect(nestedObj2.get('items'))
.to.have.nested.deep.property('[0].name', 'Jane');
});
it('should pass using `nested` ending with an index', function () {
expect(obj).to.have.nested.property('items[1]')
it('should pass using `nested` ending with an index', function () { // eslint-disable-line prefer-arrow-callback
expect(nestedObj2).to.have.nested.property('items[1]')
.that.equals(new Map({ name: 'John' }));
expect(nestedObj2).to.have.nested.deep.property('items[1]')
.that.equals(new Map({ name: 'John' }));
});
it('should pass using `nested` given mix of keys and indices', function () {
expect(obj).to.have.nested.property('items[2].name', 'Jim');
it('should pass using `nested` given mix of keys and indices', function () { // eslint-disable-line prefer-arrow-callback
expect(nestedObj2).to.have.nested.property('items[2].name', 'Jim');
expect(nestedObj2)
.to.have.nested.deep.property('items[2].name', 'Jim');
});
it('should expect unescaped path strings', function () {
var css = new Map({ '.link[target]': 42 });
it('should expect unescaped path strings', function () { // eslint-disable-line prefer-arrow-callback
const css = new Map({ '.link[target]': 42 });
expect(css).to.have.property('.link[target]', 42);
expect(css).to.have.deep.property('.link[target]', 42);
});
it('should expect escaped path strings using `nested`', function () {
var nestedCss = new Map({ '.link': new Map({ '[target]': 42 }) });
it('should expect escaped path strings using `nested`', function () { // eslint-disable-line prefer-arrow-callback
const nestedCss = new Map({ '.link': new Map({ '[target]': 42 }) });
expect(nestedCss).to.have.nested.property('\\.link.\\[target\\]', 42);
expect(nestedCss)
.to.have.nested.deep.property('\\.link.\\[target\\]', 42);
});

@@ -576,12 +689,12 @@ });

describe('size method', function () {
it('should pass given the right size', function () {
describe('size method', function () { // eslint-disable-line prefer-arrow-callback
it('should pass given the right size', function () { // eslint-disable-line prefer-arrow-callback
expect(list3).to.have.size(3);
});
it('should pass using `not` given the wrong size', function () {
it('should pass using `not` given the wrong size', function () { // eslint-disable-line prefer-arrow-callback
expect(list3).to.not.have.size(42);
});
it('should also work with alias sizeOf', function () {
it('should also work with alias sizeOf', function () { // eslint-disable-line prefer-arrow-callback
expect(list3).to.have.sizeOf(3);

@@ -591,11 +704,11 @@ expect(list3).to.not.have.sizeOf(42);

it('should fail given the wrong size', function () {
fail(function () { expect(list3).to.have.size(42); });
it('should fail given the wrong size', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(list3).to.have.size(42));
});
it('should fail using `not` given the right size', function () {
fail(function () { expect(list3).to.not.have.size(3); });
it('should fail using `not` given the right size', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(list3).to.not.have.size(3));
});
it('should work if using different copies of Immutable', function () {
it('should work if using different copies of Immutable', function () { // eslint-disable-line prefer-arrow-callback
expect(clonedImmutableList).to.have.size(3);

@@ -605,12 +718,12 @@ });

describe('size property', function () {
it('above should pass given a good min size', function () {
describe('size property', function () { // eslint-disable-line prefer-arrow-callback
it('above should pass given a good min size', function () { // eslint-disable-line prefer-arrow-callback
expect(list3).to.have.size.above(2);
});
it('above should pass using `not` given a bad min size', function () {
it('above should pass using `not` given a bad min size', function () { // eslint-disable-line prefer-arrow-callback
expect(list3).to.not.have.size.above(42);
});
it('aliases of above should also work', function () {
it('aliases of above should also work', function () { // eslint-disable-line prefer-arrow-callback
expect(list3).to.have.size.gt(2);

@@ -622,3 +735,3 @@ expect(list3).to.have.size.greaterThan(2);

it('should not affect the original assertions of above', function () {
it('should not affect the original assertions of above', function () { // eslint-disable-line prefer-arrow-callback
expect('foo').to.have.length.above(2);

@@ -628,19 +741,19 @@ expect([1, 2, 3]).to.have.length.above(2);

it('above should fail given a bad min size', function () {
fail(function () { expect(list3).to.have.size.above(42); });
it('above should fail given a bad min size', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(list3).to.have.size.above(42));
});
it('above should fail using `not` given a good min size', function () {
fail(function () { expect(list3).to.not.have.size.above(2); });
it('above should fail using `not` given a good min size', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(list3).to.not.have.size.above(2));
});
it('below should pass given a good max size', function () {
it('below should pass given a good max size', function () { // eslint-disable-line prefer-arrow-callback
expect(list3).to.have.size.below(42);
});
it('below should pass using `not` given a bad max size', function () {
it('below should pass using `not` given a bad max size', function () { // eslint-disable-line prefer-arrow-callback
expect(list3).to.not.have.size.below(1);
});
it('aliases of below should also work', function () {
it('aliases of below should also work', function () { // eslint-disable-line prefer-arrow-callback
expect(list3).to.have.size.lt(4);

@@ -652,3 +765,3 @@ expect(list3).to.have.size.lessThan(4);

it('should not affect the original assertions of below', function () {
it('should not affect the original assertions of below', function () { // eslint-disable-line prefer-arrow-callback
expect('foo').to.have.length.below(4);

@@ -658,19 +771,19 @@ expect([1, 2, 3]).to.have.length.below(4);

it('below should fail given a bad max size', function () {
fail(function () { expect(list3).to.have.size.below(1); });
it('below should fail given a bad max size', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(list3).to.have.size.below(1));
});
it('below should fail using `not` given a good max size', function () {
fail(function () { expect(list3).to.not.have.size.below(42); });
it('below should fail using `not` given a good max size', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(list3).to.not.have.size.below(42));
});
it('within should pass given a good range', function () {
it('within should pass given a good range', function () { // eslint-disable-line prefer-arrow-callback
expect(list3).to.have.size.within(2, 42);
});
it('within should pass using `not` given a bad range', function () {
it('within should pass using `not` given a bad range', function () { // eslint-disable-line prefer-arrow-callback
expect(list3).to.not.have.size.within(10, 20);
});
it('should not affect the original assertions of within', function () {
it('should not affect the original assertions of within', function () { // eslint-disable-line prefer-arrow-callback
expect('foo').to.have.length.within(2, 4);

@@ -680,19 +793,19 @@ expect([1, 2, 3]).to.have.length.within(2, 4);

it('within should fail given a bad range', function () {
fail(function () { expect(list3).to.have.size.within(10, 20); });
it('within should fail given a bad range', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(list3).to.have.size.within(10, 20));
});
it('within should fail using `not` given a good range', function () {
fail(function () { expect(list3).to.not.have.size.within(2, 42); });
it('within should fail using `not` given a good range', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(list3).to.not.have.size.within(2, 42));
});
it('least should pass given a good min size', function () {
it('least should pass given a good min size', function () { // eslint-disable-line prefer-arrow-callback
expect(list3).to.have.size.of.at.least(2);
});
it('least should pass using `not` given a bad min size', function () {
it('least should pass using `not` given a bad min size', function () { // eslint-disable-line prefer-arrow-callback
expect(list3).to.not.have.size.of.at.least(42);
});
it('aliases of least should also work', function () {
it('aliases of least should also work', function () { // eslint-disable-line prefer-arrow-callback
expect(list3).to.have.size.gte(2);

@@ -702,3 +815,3 @@ expect(list3).to.not.have.size.gte(42);

it('should not affect the original assertions of least', function () {
it('should not affect the original assertions of least', function () { // eslint-disable-line prefer-arrow-callback
expect('foo').to.have.length.of.at.least(2);

@@ -708,19 +821,19 @@ expect([1, 2, 3]).to.have.length.of.at.least(3);

it('least should fail given a bad min size', function () {
fail(function () { expect(list3).to.have.size.of.at.least(42); });
it('least should fail given a bad min size', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(list3).to.have.size.of.at.least(42));
});
it('least should fail using `not` given a good min size', function () {
fail(function () { expect(list3).to.not.have.size.of.at.least(2); });
it('least should fail using `not` given a good min size', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(list3).to.not.have.size.of.at.least(2));
});
it('most should pass given a good max size', function () {
it('most should pass given a good max size', function () { // eslint-disable-line prefer-arrow-callback
expect(list3).to.have.size.of.at.most(42);
});
it('most should pass using `not` given a bad max size', function () {
it('most should pass using `not` given a bad max size', function () { // eslint-disable-line prefer-arrow-callback
expect(list3).to.not.have.size.of.at.most(2);
});
it('aliases of most should also work', function () {
it('aliases of most should also work', function () { // eslint-disable-line prefer-arrow-callback
expect(list3).to.have.size.lte(42);

@@ -730,3 +843,3 @@ expect(list3).to.not.have.size.lte(2);

it('should not affect the original assertions of most', function () {
it('should not affect the original assertions of most', function () { // eslint-disable-line prefer-arrow-callback
expect('foo').to.have.length.of.at.most(4);

@@ -736,11 +849,11 @@ expect([1, 2, 3]).to.have.length.of.at.most(3);

it('most should fail given a good max size', function () {
fail(function () { expect(list3).to.have.size.of.at.most(2); });
it('most should fail given a good max size', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(list3).to.have.size.of.at.most(2));
});
it('most should fail using `not` given a bad max size', function () {
fail(function () { expect(list3).to.not.have.size.of.at.most(42); });
it('most should fail using `not` given a bad max size', function () { // eslint-disable-line prefer-arrow-callback
fail(() => expect(list3).to.not.have.size.of.at.most(42));
});
it('should work if using different copies of Immutable', function () {
it('should work if using different copies of Immutable', function () { // eslint-disable-line prefer-arrow-callback
expect(clonedImmutableList).to.have.size.above(2);

@@ -751,13 +864,13 @@ });

describe('TDD interface', function () {
describe('equal assertion', function () {
it('should pass given equal values', function () {
describe('TDD interface', function () { // eslint-disable-line prefer-arrow-callback
describe('equal assertion', function () { // eslint-disable-line prefer-arrow-callback
it('should pass given equal values', function () { // eslint-disable-line prefer-arrow-callback
assert.equal(list3, List.of(1, 2, 3));
});
it('should pass given deeply equal values', function () {
it('should pass given deeply equal values', function () { // eslint-disable-line prefer-arrow-callback
assert.equal(deepMap, sameDeepMap);
});
it('should not affect the original assertion', function () {
it('should not affect the original assertion', function () { // eslint-disable-line prefer-arrow-callback
assert.equal(42, 42);

@@ -768,23 +881,31 @@ assert.equal(3, '3');

// See https://github.com/astorije/chai-immutable/issues/7
it('should display a helpful failure output on big objects', function () {
var actual = new Map({ foo: 'foo foo foo foo foo foo foo foo ' });
var expected = new Map({ bar: 'bar bar bar bar bar bar bar bar ' });
fail(function () {
assert.equal(actual, expected);
}, /(foo ){8}.+(bar ){8}/);
it('should display a helpful failure output on big objects', function () { // eslint-disable-line prefer-arrow-callback
const actual = new Map({ foo: 'foo foo foo foo foo foo foo foo ' });
const expected = new Map({ bar: 'bar bar bar bar bar bar bar bar ' });
// AssertionError: expected { Object (foo) } to equal { Object (bar) }
// + expected - actual
//
// {
// - "foo": "foo foo foo foo foo foo foo foo"
// + "bar": "bar bar bar bar bar bar bar bar"
// }
fail(
() => assert.equal(actual, expected),
'expected { Object (foo) } to equal { Object (bar) }'
);
});
it('should fail given a non-Immutable value', function () {
fail(function () { assert.equal([], List()); });
it('should fail given a non-Immutable value', function () { // eslint-disable-line prefer-arrow-callback
fail(() => assert.equal([], new List()));
});
it('should fail given different values', function () {
fail(function () { assert.equal(list3, new List()); });
it('should fail given different values', function () { // eslint-disable-line prefer-arrow-callback
fail(() => assert.equal(list3, new List()));
});
it('should fail given deeply different values', function () {
fail(function () { assert.equal(deepMap, differentDeepMap); });
it('should fail given deeply different values', function () { // eslint-disable-line prefer-arrow-callback
fail(() => assert.equal(deepMap, differentDeepMap));
});
it('should work if using different copies of Immutable', function () {
it('should work if using different copies of Immutable', function () { // eslint-disable-line prefer-arrow-callback
assert.equal(clonedImmutableList, List.of(1, 2, 3));

@@ -794,12 +915,12 @@ });

describe('notEqual assertion', function () {
it('should pass given different values', function () {
describe('notEqual assertion', function () { // eslint-disable-line prefer-arrow-callback
it('should pass given different values', function () { // eslint-disable-line prefer-arrow-callback
assert.notEqual(list3, new List());
});
it('should pass given deeply different values', function () {
it('should pass given deeply different values', function () { // eslint-disable-line prefer-arrow-callback
assert.notEqual(deepMap, differentDeepMap);
});
it('should not affect the original assertion', function () {
it('should not affect the original assertion', function () { // eslint-disable-line prefer-arrow-callback
assert.notEqual('oui', 'non');

@@ -809,15 +930,15 @@ assert.notEqual({ foo: 'bar' }, { foo: 'bar' });

it('should pass given a non-Immutable value', function () {
assert.notEqual([], List());
it('should pass given a non-Immutable value', function () { // eslint-disable-line prefer-arrow-callback
assert.notEqual([], new List());
});
it('should fail given equal values', function () {
fail(function () { assert.notEqual(list3, List.of(1, 2, 3)); });
it('should fail given equal values', function () { // eslint-disable-line prefer-arrow-callback
fail(() => assert.notEqual(list3, List.of(1, 2, 3)));
});
it('should fail given deeply equal values', function () {
fail(function () { assert.notEqual(deepMap, sameDeepMap); });
it('should fail given deeply equal values', function () { // eslint-disable-line prefer-arrow-callback
fail(() => assert.notEqual(deepMap, sameDeepMap));
});
it('should work if using different copies of Immutable', function () {
it('should work if using different copies of Immutable', function () { // eslint-disable-line prefer-arrow-callback
assert.notEqual(clonedImmutableList, List.of());

@@ -827,4 +948,4 @@ });

describe('unoverridden strictEqual and deepEqual assertions', function () {
it('should pass given equal values', function () {
describe('unoverridden strictEqual and deepEqual assertions', function () { // eslint-disable-line prefer-arrow-callback
it('should pass given equal values', function () { // eslint-disable-line prefer-arrow-callback
assert.strictEqual(list3, List.of(1, 2, 3));

@@ -834,3 +955,3 @@ assert.deepEqual(list3, List.of(1, 2, 3));

it('should pass given deeply equal values', function () {
it('should pass given deeply equal values', function () { // eslint-disable-line prefer-arrow-callback
assert.strictEqual(deepMap, sameDeepMap);

@@ -840,13 +961,13 @@ assert.deepEqual(deepMap, sameDeepMap);

it('should fail given different values', function () {
fail(function () { assert.strictEqual(list3, new List()); });
fail(function () { assert.deepEqual(list3, new List()); });
it('should fail given different values', function () { // eslint-disable-line prefer-arrow-callback
fail(() => assert.strictEqual(list3, new List()));
fail(() => assert.deepEqual(list3, new List()));
});
it('should fail given deeply different values', function () {
fail(function () { assert.strictEqual(deepMap, differentDeepMap); });
fail(function () { assert.deepEqual(deepMap, differentDeepMap); });
it('should fail given deeply different values', function () { // eslint-disable-line prefer-arrow-callback
fail(() => assert.strictEqual(deepMap, differentDeepMap));
fail(() => assert.deepEqual(deepMap, differentDeepMap));
});
it('should work if using different copies of Immutable', function () {
it('should work if using different copies of Immutable', function () { // eslint-disable-line prefer-arrow-callback
assert.strictEqual(clonedImmutableList, List.of(1, 2, 3));

@@ -857,4 +978,4 @@ assert.deepEqual(clonedImmutableList, List.of(1, 2, 3));

describe('unoverridden notStrictEqual and notDeepEqual assertions', function () {
it('should pass given different values', function () {
describe('unoverridden notStrictEqual and notDeepEqual assertions', function () { // eslint-disable-line prefer-arrow-callback
it('should pass given different values', function () { // eslint-disable-line prefer-arrow-callback
assert.notStrictEqual(list3, new List());

@@ -864,3 +985,3 @@ assert.notDeepEqual(list3, new List());

it('should pass given deeply different values', function () {
it('should pass given deeply different values', function () { // eslint-disable-line prefer-arrow-callback
assert.notStrictEqual(deepMap, differentDeepMap);

@@ -870,51 +991,86 @@ assert.notDeepEqual(deepMap, differentDeepMap);

it('should fail given equal values', function () {
fail(function () { assert.notStrictEqual(list3, List.of(1, 2, 3)); });
fail(function () { assert.notDeepEqual(list3, List.of(1, 2, 3)); });
it('should fail given equal values', function () { // eslint-disable-line prefer-arrow-callback
fail(() => assert.notStrictEqual(list3, List.of(1, 2, 3)));
fail(() => assert.notDeepEqual(list3, List.of(1, 2, 3)));
});
it('should fail given deeply equal values', function () {
fail(function () { assert.notStrictEqual(deepMap, sameDeepMap); });
fail(function () { assert.notDeepEqual(deepMap, sameDeepMap); });
it('should fail given deeply equal values', function () { // eslint-disable-line prefer-arrow-callback
fail(() => assert.notStrictEqual(deepMap, sameDeepMap));
fail(() => assert.notDeepEqual(deepMap, sameDeepMap));
});
it('should work if using different copies of Immutable', function () {
assert.notStrictEqual(clonedImmutableList, List());
assert.notDeepEqual(clonedImmutableList, List());
it('should work if using different copies of Immutable', function () { // eslint-disable-line prefer-arrow-callback
assert.notStrictEqual(clonedImmutableList, new List());
assert.notDeepEqual(clonedImmutableList, new List());
});
});
describe('property assertions', function () {
it('should fail for missing property', function () {
var obj = Immutable.fromJS({ x: 1 });
fail(function () { assert.property(obj, 'z'); });
describe('property assertions', function () { // eslint-disable-line prefer-arrow-callback
const obj = Immutable.fromJS({ x: 1 });
const nestedObj = Immutable.fromJS({ x: 1, y: { x: 2, y: 3 } });
it('should pass for existing property', function () { // eslint-disable-line prefer-arrow-callback
assert.property(obj, 'x');
});
it('should succeed for equal nested property', function () {
var obj = Immutable.fromJS({ x: 1, y: { x: 2, y: 3 } });
assert.nestedProperty(obj, ['y', 'x']);
it('should fail for missing property', function () { // eslint-disable-line prefer-arrow-callback
fail(() => assert.property(obj, 'z'));
});
it('should fail for unequal deep property', function () {
var obj = Immutable.fromJS({ x: 1, y: { x: 2, y: 3 } });
fail(function () {
assert.nestedPropertyVal(obj, ['y', 'x'], 'different');
});
it('should pass for missing property using `not`', function () { // eslint-disable-line prefer-arrow-callback
assert.notProperty(obj, 'z');
});
it('should fail for existing property using `not`', function () { // eslint-disable-line prefer-arrow-callback
fail(() => assert.notProperty(obj, 'x'));
});
it('should pass for existing property and value', function () { // eslint-disable-line prefer-arrow-callback
assert.propertyVal(obj, 'x', 1);
assert.deepPropertyVal(obj, 'x', 1);
});
it('should fail for wrong property or value', function () { // eslint-disable-line prefer-arrow-callback
fail(() => assert.propertyVal(obj, 'z', 1));
fail(() => assert.deepPropertyVal(obj, 'z', 1));
fail(() => assert.propertyVal(obj, 'x', 42));
fail(() => assert.deepPropertyVal(obj, 'x', 42));
});
it('should pass for wrong property or value using `not`', function () { // eslint-disable-line prefer-arrow-callback
assert.notPropertyVal(obj, 'z', 1);
assert.notDeepPropertyVal(obj, 'z', 1);
assert.notPropertyVal(obj, 'x', 42);
assert.notDeepPropertyVal(obj, 'x', 42);
});
it('should fail for existing property and value using `not`', function () { // eslint-disable-line prefer-arrow-callback
fail(() => assert.notPropertyVal(obj, 'x', 1));
fail(() => assert.notDeepPropertyVal(obj, 'x', 1));
});
it('should succeed for equal nested property', function () { // eslint-disable-line prefer-arrow-callback
assert.nestedProperty(nestedObj, ['y', 'x']);
});
it('should fail for unequal nested property', function () { // eslint-disable-line prefer-arrow-callback
fail(() => assert.nestedPropertyVal(nestedObj, ['y', 'x'], 42));
fail(() => assert.deepNestedPropertyVal(nestedObj, ['y', 'x'], 42));
});
});
describe('sizeOf assertion', function () {
it('should pass given the right size', function () {
describe('sizeOf assertion', function () { // eslint-disable-line prefer-arrow-callback
it('should pass given the right size', function () { // eslint-disable-line prefer-arrow-callback
assert.sizeOf(list3, 3);
});
it('should work with empty collections', function () {
it('should work with empty collections', function () { // eslint-disable-line prefer-arrow-callback
assert.sizeOf(new List(), 0);
});
it('should fail given the wrong size', function () {
fail(function () { assert.sizeOf(list3, 42); });
it('should fail given the wrong size', function () { // eslint-disable-line prefer-arrow-callback
fail(() => assert.sizeOf(list3, 42));
});
it('should work if using different copies of Immutable', function () {
it('should work if using different copies of Immutable', function () { // eslint-disable-line prefer-arrow-callback
assert.sizeOf(clonedImmutableList, 3);

@@ -921,0 +1077,0 @@ });

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc