🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Book a DemoInstallSign in
Socket

chai-immutable

Package Overview
Dependencies
Maintainers
1
Versions
21
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

chai-immutable - npm Package Compare versions

Comparing version

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