{"id":13460674,"url":"https://github.com/astorije/chai-immutable","last_synced_at":"2025-05-15T16:08:15.092Z","repository":{"id":27689601,"uuid":"31176116","full_name":"astorije/chai-immutable","owner":"astorije","description":"Chai assertions for Facebook's Immutable library for JavaScript collections","archived":false,"fork":false,"pushed_at":"2025-05-09T08:13:11.000Z","size":739,"stargazers_count":159,"open_issues_count":21,"forks_count":16,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-05-12T04:41:08.817Z","etag":null,"topics":["chai","immutablejs","javascript","test"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/astorije.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2015-02-22T19:23:33.000Z","updated_at":"2025-04-14T17:47:40.000Z","dependencies_parsed_at":"2023-01-14T07:17:34.037Z","dependency_job_id":"b4eec6bc-b1b2-43d2-b7c8-e88d99380dac","html_url":"https://github.com/astorije/chai-immutable","commit_stats":{"total_commits":422,"total_committers":14,"mean_commits":"30.142857142857142","dds":0.419431279620853,"last_synced_commit":"7be3ba70de16add3cc0e7585da5cc22365970248"},"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/astorije%2Fchai-immutable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/astorije%2Fchai-immutable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/astorije%2Fchai-immutable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/astorije%2Fchai-immutable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/astorije","download_url":"https://codeload.github.com/astorije/chai-immutable/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254374475,"owners_count":22060611,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chai","immutablejs","javascript","test"],"created_at":"2024-07-31T10:00:46.811Z","updated_at":"2025-05-15T16:08:15.052Z","avatar_url":"https://github.com/astorije.png","language":"JavaScript","readme":"[![npm Version](https://img.shields.io/npm/v/chai-immutable.svg)](https://npmjs.org/package/chai-immutable)\n[![License](https://img.shields.io/npm/l/chai-immutable.svg)](LICENSE)\n[![Build Status](https://travis-ci.org/astorije/chai-immutable.svg?branch=master)](https://travis-ci.org/astorije/chai-immutable)\n[![Build Status](https://ci.appveyor.com/api/projects/status/407ts84pq7wd4kt9/branch/master?svg=true)](https://ci.appveyor.com/project/astorije/chai-immutable/branch/master)\n[![Coverage Status](https://coveralls.io/repos/astorije/chai-immutable/badge.svg)](https://coveralls.io/r/astorije/chai-immutable)\n[![devDependencies Status](https://david-dm.org/astorije/chai-immutable/dev-status.svg)](https://david-dm.org/astorije/chai-immutable?type=dev)\n[![peerDependencies Status](https://david-dm.org/astorije/chai-immutable/peer-status.svg)](https://david-dm.org/astorije/chai-immutable?type=peer)\n\n# Chai Immutable\n\nThis plugin provides a set of [Chai](http://chaijs.com/) assertions for [Facebook's Immutable library for JavaScript collections](http://facebook.github.io/immutable-js/).\n\n\u003c!-- fulky:globals\nconst chai = require('chai');\nconst { assert, expect } = chai;\n\nconst Immutable = require('immutable');\nconst {\n  List,\n  Map,\n  Set,\n  Stack,\n} = Immutable;\n\nchai.use(require('./chai-immutable'));\n--\u003e\n\n## Assertions\n\n- BDD API Reference (Expect / Should)\n  - [`.empty`](#empty)\n  - [`.equal(collection)`](#equalcollection)\n  - [`.referenceEqual(value)`](#referenceequalvalue)\n  - [`.include(value)`](#includevalue)\n  - [`.keys(key1[, key2[, ...]])`](#keyskey1-key2-)\n  - [`.property(path[, val])`](#propertypath-val)\n  - [`.size(value)`](#sizevalue)\n- TDD API Reference (Assert)\n  - [`.equal(actual, expected)`](#equalactual-expected)\n  - [`.referenceEqual(actual, expected)`](#referenceequalactual-expected)\n  - [`.notEqual(actual, expected)`](#notequalactual-expected)\n  - [`.notReferenceEqual(actual, expected)`](#notreferenceequalactual-expected)\n  - [`.sizeOf(collection, length)`](#sizeofcollection-length)\n\n## Installation\n\n### Node.js\n\nInstall via [npm](http://npmjs.org) or [yarn](https://yarnpkg.com/):\n\n```bash\nnpm install --save-dev chai-immutable\nyarn add --dev chai-immutable\n```\n\nYou can then use this plugin as any other Chai plugins:\n\n\u003c!-- fulky:skip-test --\u003e\n\n```js\nconst chai = require('chai');\nconst chaiImmutable = require('chai-immutable');\n\nchai.use(chaiImmutable);\n```\n\n### ES6 syntax (needs Babel transpiling)\n\n\u003c!-- fulky:skip-test --\u003e\n\n```js\nimport chai from 'chai';\nimport chaiImmutable from 'chai-immutable';\n\nchai.use(chaiImmutable);\n```\n\n### In the browser\n\nInclude this plugin after including Chai and Immutable. It will automatically\nplug in to Chai and be ready for use:\n\n```html\n\u003cscript src=\"chai-immutable.js\"\u003e\u003c/script\u003e\n```\n\n### Using `chai-immutable` with other plugins\n\nIf you are using this plugin with\n[`chai-as-promised`](https://github.com/domenic/chai-as-promised/) or\n[`dirty-chai`](https://github.com/prodatakey/dirty-chai), note that\n`chai-immutable` must be loaded **before** any of them. For example:\n\n\u003c!-- fulky:skip-test --\u003e\n\n```js\nconst chai = require('chai');\nconst chaiAsPromised = require('chai-as-promised');\nconst chaiImmutable = require('chai-immutable');\nconst dirtyChai = require('dirty-chai');\nconst { expect } = chai;\n\nchai.use(chaiImmutable);\nchai.use(chaiAsPromised);\nchai.use(dirtyChai);\n\nconst { List } = require('immutable');\n\n/* ... */\n\nexpect(Promise.resolve(List.of(1, 2, 3))).to.eventually.have.size(3);\nexpect(true).to.be.true();\n```\n\n## BDD API Reference (Expect / Should)\n\n### .empty\n\nAsserts that the immutable collection is empty.\n\n```js\nexpect(List()).to.be.empty;\nexpect(List.of(1, 2, 3)).to.not.be.empty;\n```\n\n### .equal(collection)\n\n- **@param** _{ Collection }_ collection\n\nAsserts that the values of the target are equivalent to the values of\n`collection`. Aliases of Chai's original `equal` method are also supported.\n\n```js\nconst a = List.of(1, 2, 3);\nconst b = List.of(1, 2, 3);\nexpect(a).to.equal(b);\n```\n\nImmutable data structures should only contain other immutable data\nstructures (unlike `Array`s and `Object`s) to be considered immutable and\nproperly work against `.equal()`. See\n[issue #24](https://github.com/astorije/chai-immutable/issues/24) for more\ninformation.\n\nAlso, note that `deep.equal` and `eql` are synonyms of `equal` when\ntested against immutable data structures, therefore they are aliases to\n`equal`.\n\n### .referenceEqual(value)\n\n- **@param** _{Collection}_ value\n\nAsserts that the reference of the target is equivalent to the reference of\n`collection`. This method preserves the original behavior of Chai's `equal`.\n\nSee [issue #210](https://github.com/astorije/chai-immutable/issues/210) for\nmore details.\n\n```js\nconst a = List.of(1, 2, 3);\nconst b = a;\nconst c = List.of(1, 2, 3);\nexpect(a).to.referenceEqual(b);\nexpect(a).to.not.referenceEqual(c);\n```\n\n### .include(value)\n\n- **@param** _{ Mixed }_ val\n\nThe `include` and `contain` assertions can be used as either property\nbased language chains or as methods to assert the inclusion of a value or\nsubset in an immutable collection. When used as language chains, they toggle\nthe `contains` flag for the `keys` assertion.\n\nNote that `deep.include` behaves exactly like `include` in the context of\nimmutable data structures.\n\n```js\nexpect(new List([1, 2, 3])).to.include(2);\nexpect(new List([1, 2, 3])).to.deep.include(2);\nexpect(new Map({ foo: 'bar', hello: 'world' })).to.include('bar');\nexpect(new Map({ a: 1, b: 2, c: 3 })).to.include(new Map({ a: 1, b: 2 }));\nexpect(new Map({ foo: 'bar', hello: 'world' })).to.include.keys('foo');\n```\n\n### .keys(key1[, key2[, ...]])\n\n- **@param** _{ String... | Array | Object | Collection }_ key*N*\n\nAsserts that the target collection has the given keys.\n\nWhen the target is an object or array, keys can be provided as one or more\nstring arguments, a single array argument, a single object argument, or an\nimmutable collection. In the last 2 cases, only the keys in the given\nobject/collection matter; the values are ignored.\n\n```js\nexpect(new Map({ foo: 1, bar: 2 })).to.have.all.keys('foo', 'bar');\nexpect(new Map({ foo: 1, bar: 2 })).to.have.all.keys(new List(['bar', 'foo']));\nexpect(new Map({ foo: 1, bar: 2 })).to.have.all.keys(new Set(['bar', 'foo']));\nexpect(new Map({ foo: 1, bar: 2 })).to.have.all.keys(new Stack(['bar', 'foo']));\nexpect(new List(['x', 'y'])).to.have.all.keys(0, 1);\n\nexpect(new Map({ foo: 1, bar: 2 })).to.have.all.keys(['foo', 'bar']);\nexpect(new List(['x', 'y'])).to.have.all.keys([0, 1]);\n\n// Values in the passed object are ignored:\nexpect(new Map({ foo: 1, bar: 2 })).to.have.all.keys({ bar: 6, foo: 7 });\nexpect(new Map({ foo: 1, bar: 2 })).to.have.all.keys(\n  new Map({ bar: 6, foo: 7 })\n);\nexpect(new List(['x', 'y'])).to.have.all.keys({ 0: 4, 1: 5 });\n```\n\nNote that `deep.property` behaves exactly like `property` in the context of\nimmutable data structures.\n\nBy default, the target must have all of the given keys and no more. Add\n`.any` earlier in the chain to only require that the target have at least\none of the given keys. Also, add `.not` earlier in the chain to negate\n`.keys`. It's often best to add `.any` when negating `.keys`, and to use\n`.all` when asserting `.keys` without negation.\n\nWhen negating `.keys`, `.any` is preferred because `.not.any.keys` asserts\nexactly what's expected of the output, whereas `.not.all.keys` creates\nuncertain expectations.\n\n```js\n// Recommended; asserts that target doesn't have any of the given keys\nexpect(new Map({ a: 1, b: 2 })).to.not.have.any.keys('c', 'd');\n\n// Not recommended; asserts that target doesn't have all of the given\n// keys but may or may not have some of them\nexpect(new Map({ a: 1, b: 2 })).to.not.have.all.keys('c', 'd');\n```\n\nWhen asserting `.keys` without negation, `.all` is preferred because\n`.all.keys` asserts exactly what's expected of the output, whereas\n`.any.keys` creates uncertain expectations.\n\n```js\n// Recommended; asserts that target has all the given keys\nexpect(new Map({ a: 1, b: 2 })).to.have.all.keys('a', 'b');\n\n// Not recommended; asserts that target has at least one of the given\n// keys but may or may not have more of them\nexpect(new Map({ a: 1, b: 2 })).to.have.any.keys('a', 'b');\n```\n\nNote that `.all` is used by default when neither `.all` nor `.any` appear\nearlier in the chain. However, it's often best to add `.all` anyway because\nit improves readability.\n\n```js\n// Both assertions are identical\nexpect(new Map({ a: 1, b: 2 })).to.have.all.keys('a', 'b'); // Recommended\nexpect(new Map({ a: 1, b: 2 })).to.have.keys('a', 'b'); // Not recommended\n```\n\nAdd `.include` earlier in the chain to require that the target's keys be a\nsuperset of the expected keys, rather than identical sets.\n\n```js\n// Target object's keys are a superset of ['a', 'b'] but not identical\nexpect(new Map({ a: 1, b: 2, c: 3 })).to.include.all.keys('a', 'b');\nexpect(new Map({ a: 1, b: 2, c: 3 })).to.not.have.all.keys('a', 'b');\n```\n\nHowever, if `.any` and `.include` are combined, only the `.any` takes\neffect. The `.include` is ignored in this case.\n\n```js\n// Both assertions are identical\nexpect(new Map({ a: 1 })).to.have.any.keys('a', 'b');\nexpect(new Map({ a: 1 })).to.include.any.keys('a', 'b');\n```\n\nThe alias `.key` can be used interchangeably with `.keys`.\n\n```js\nexpect(new Map({ foo: 1 })).to.have.key('foo');\n```\n\n### .property(path[, val])\n\n- **@param** _{ String | Array | Iterable }_ path\n- **@param** _{ Mixed }_ val (optional)\n\nAsserts that the target has a property with the given `path`.\n\n```js\nexpect(new Map({ a: 1 })).to.have.property('a');\n```\n\nWhen `val` is provided, `.property` also asserts that the property's value\nis equal to the given `val`. `val` can be an immutable collection.\n\n```js\nexpect(new Map({ a: 1 })).to.have.property('a', 1);\n```\n\nNote that `deep.property` behaves exactly like `property` in the context of\nimmutable data structures.\n\nAdd `.nested` earlier in the chain to enable dot- and bracket-notation when\nreferencing nested properties. An immutable `List` can also be used as the\nstarting point of a `nested.property`.\n\n```js\nexpect(Immutable.fromJS({ a: { b: ['x', 'y'] } })).to.have.nested.property(\n  'a.b[1]'\n);\nexpect(Immutable.fromJS({ a: { b: ['x', 'y'] } })).to.have.nested.property(\n  'a.b[1]',\n  'y'\n);\nexpect(Immutable.fromJS({ a: { b: ['x', 'y'] } })).to.have.nested.property(\n  ['a', 'b', 1],\n  'y'\n);\nexpect(Immutable.fromJS({ a: { b: ['x', 'y'] } })).to.have.nested.property(\n  new List(['a', 'b', 1]),\n  'y'\n);\n```\n\nIf `.` or `[]` are part of an actual property name, they can be escaped by\nadding two backslashes before them.\n\n```js\nexpect(Immutable.fromJS({ '.a': { '[b]': 'x' } })).to.have.nested.property(\n  '\\\\.a.\\\\[b\\\\]'\n);\n```\n\nAdd `.not` earlier in the chain to negate `.property`.\n\n```js\nexpect(new Map({ a: 1 })).to.not.have.property('b');\n```\n\nHowever, it's dangerous to negate `.property` when providing `val`. The\nproblem is that it creates uncertain expectations by asserting that the\ntarget either doesn't have a property at the given `path`, or that it\ndoes have a property at the given key `path` but its value isn't equal to\nthe given `val`. It's often best to identify the exact output that's\nexpected, and then write an assertion that only accepts that exact output.\n\nWhen the target isn't expected to have a property at the given\n`path`, it's often best to assert exactly that.\n\n```js\nexpect(new Map({ b: 2 })).to.not.have.property('a'); // Recommended\nexpect(new Map({ b: 2 })).to.not.have.property('a', 1); // Not recommended\n```\n\nWhen the target is expected to have a property at the given key `path`,\nit's often best to assert that the property has its expected value, rather\nthan asserting that it doesn't have one of many unexpected values.\n\n```js\nexpect(new Map({ a: 3 })).to.have.property('a', 3); // Recommended\nexpect(new Map({ a: 3 })).to.not.have.property('a', 1); // Not recommended\n```\n\n`.property` changes the target of any assertions that follow in the chain\nto be the value of the property from the original target object.\n\n```js\nexpect(new Map({ a: 1 }))\n  .to.have.property('a')\n  .that.is.a('number');\n```\n\n### .size(value)\n\n- **@param** _{ Number }_ size\n\nAsserts that the immutable collection has the expected size.\n\n```js\nexpect(List.of(1, 2, 3)).to.have.size(3);\n```\n\nIt can also be used as a chain precursor to a value comparison for the\n`size` property.\n\n```js\nexpect(List.of(1, 2, 3)).to.have.size.least(3);\nexpect(List.of(1, 2, 3)).to.have.size.most(3);\nexpect(List.of(1, 2, 3)).to.have.size.above(2);\nexpect(List.of(1, 2, 3)).to.have.size.below(4);\nexpect(List.of(1, 2, 3)).to.have.size.within(2, 4);\n```\n\nSimilarly to `length`/`lengthOf`, `sizeOf` is an alias of `size`:\n\n```js\nexpect(List.of(1, 2, 3)).to.have.sizeOf(3);\n```\n\n## TDD API Reference (Assert)\n\n### .equal(actual, expected)\n\n- **@param** _{ Collection }_ actual\n- **@param** _{ Collection }_ expected\n\nAsserts that the values of `actual` are equivalent to the values of\n`expected`. Note that `.strictEqual()` and `.deepEqual()` assert\nexactly like `.equal()` in the context of Immutable data structures.\n\n```js\nconst a = List.of(1, 2, 3);\nconst b = List.of(1, 2, 3);\nassert.equal(a, b);\n```\n\nImmutable data structures should only contain other immutable data\nstructures (unlike `Array`s and `Object`s) to be considered immutable and\nproperly work against `.equal()`, `.strictEqual()` or `.deepEqual()`. See\n[issue #24](https://github.com/astorije/chai-immutable/issues/24) for more\ninformation.\n\n### .referenceEqual(actual, expected)\n\n- **@param** _{Collection}_ actual\n- **@param** _{Collection}_ expected\n\nAsserts that the reference of `actual` is equivalent to the reference of\n`expected`. This method preserves the original behavior of Chai's `equal`.\n\nSee [issue #210](https://github.com/astorije/chai-immutable/issues/210) for\nmore details.\n\n```js\nconst a = List.of(1, 2, 3);\nconst b = a;\nconst c = List.of(1, 2, 3);\nassert.referenceEqual(a, b);\nassert.throws(() =\u003e assert.referenceEqual(a, c));\n```\n\n### .notEqual(actual, expected)\n\n- **@param** _{ Collection }_ actual\n- **@param** _{ Collection }_ expected\n\nAsserts that the values of `actual` are not equivalent to the values of\n`expected`. Note that `.notStrictEqual()` and `.notDeepEqual()` assert\nexactly like `.notEqual()` in the context of Immutable data structures.\n\n```js\nconst a = List.of(1, 2, 3);\nconst b = List.of(4, 5, 6);\nassert.notEqual(a, b);\n```\n\n### .notReferenceEqual(actual, expected)\n\n- **@param** _{Collection}_ actual\n- **@param** _{Collection}_ expected\n\nAsserts that the reference of `actual` is not equivalent to the reference of\n`expected`. This method preserves the original behavior of Chai's `notEqual`.\n\nSee [issue #210](https://github.com/astorije/chai-immutable/issues/210) for\nmore details.\n\n```js\nconst a = List.of(1, 2, 3);\nconst b = a;\nconst c = List.of(1, 2, 3);\nassert.throws(() =\u003e assert.notReferenceEqual(a, b));\nassert.notReferenceEqual(a, c);\n```\n\n### .sizeOf(collection, length)\n\n- **@param** _{ Collection }_ collection\n- **@param** _{ Number }_ size\n\nAsserts that the immutable collection has the expected size.\n\n```js\nassert.sizeOf(List.of(1, 2, 3), 3);\nassert.sizeOf(new List(), 0);\n```\n","funding_links":[],"categories":["Unit Testing"],"sub_categories":["Assertion"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fastorije%2Fchai-immutable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fastorije%2Fchai-immutable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fastorije%2Fchai-immutable/lists"}