Chai Immutable
このプラグインは、Chaiのために、FacebookのJavaScriptコレクション用Immutableライブラリ用のアサーションセットを提供します。
アサーション
- BDD APIリファレンス (Expect / Should)
- TDD APIリファレンス (Assert)
インストール
Node.js
npm install --save-dev chai-immutable
yarn add --dev chai-immutable
他のChaiプラグインと同様にこのプラグインを使用できます。
const chai = require('chai');
const chaiImmutable = require('chai-immutable');
chai.use(chaiImmutable);
ES6構文 (Babelによるトランスパイルが必要)
import chai from 'chai';
import chaiImmutable from 'chai-immutable';
chai.use(chaiImmutable);
ブラウザ内
ChaiとImmutableを含めた後にこのプラグインを含めます。自動的にChaiにプラグインされ、使用できるようになります。
<script src="chai-immutable.js"></script>
他のプラグインと共にchai-immutable
を使用する
chai-as-promised
またはdirty-chai
と共にこのプラグインを使用する場合は、chai-immutable
をそれらの**前**に読み込む必要があります。例:
const chai = require('chai');
const chaiAsPromised = require('chai-as-promised');
const chaiImmutable = require('chai-immutable');
const dirtyChai = require('dirty-chai');
const { expect } = chai;
chai.use(chaiImmutable);
chai.use(chaiAsPromised);
chai.use(dirtyChai);
const { List } = require('immutable');
/* ... */
expect(Promise.resolve(List.of(1, 2, 3))).to.eventually.have.size(3);
expect(true).to.be.true();
BDD APIリファレンス (Expect / Should)
.empty
Immutableコレクションが空であることをアサートします。
expect(List()).to.be.empty;
expect(List.of(1, 2, 3)).to.not.be.empty;
.equal(collection)
- @param {Collection} collection
ターゲットの値がcollection
の値と等価であることをアサートします。Chaiの元のequal
メソッドのエイリアスもサポートされています。
const a = List.of(1, 2, 3);
const b = List.of(1, 2, 3);
expect(a).to.equal(b);
Immutableデータ構造は、Immutableであると見なされ、.equal()
に対して正しく動作するためには、他のImmutableデータ構造のみを含める必要があります(Array
やObject
とは異なります)。詳細はissue #24を参照してください。
また、Immutableデータ構造に対してテストする場合、deep.equal
とeql
はequal
の同義語であるため、equal
のエイリアスとなります。
.referenceEqual(value)
- @param {Collection} value
ターゲットの参照がcollection
の参照と等価であることをアサートします。このメソッドは、Chaiのequal
の元の動作を維持します。
詳細はissue #210を参照してください。
const a = List.of(1, 2, 3);
const b = a;
const c = List.of(1, 2, 3);
expect(a).to.referenceEqual(b);
expect(a).to.not.referenceEqual(c);
.include(value)
- @param {Mixed} val
include
とcontain
アサーションは、プロパティベースの言語チェーンとして、またはImmutableコレクション内の値またはサブセットの包含をアサートするメソッドとして使用できます。言語チェーンとして使用する場合、keys
アサーションのcontains
フラグを切り替えます。
Immutableデータ構造のコンテキストでは、deep.include
はinclude
とまったく同じ動作をします。
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('bar');
expect(new Map({ a: 1, b: 2, c: 3 })).to.include(new Map({ a: 1, b: 2 }));
expect(new Map({ foo: 'bar', hello: 'world' })).to.include.keys('foo');
.keys(key1[, key2[, …]])
-
@param _{文字列… 配列 オブジェクト コレクション}_ key_N_
ターゲットコレクションに指定されたキーがあることをアサートします。
ターゲットがオブジェクトまたは配列の場合、キーは1つ以上の文字列引数、1つの配列引数、1つのオブジェクト引数、またはImmutableコレクションとして提供できます。最後の2つの場合、指定されたオブジェクト/コレクション内のキーのみが重要で、値は無視されます。
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 });
Immutableデータ構造のコンテキストでは、deep.property
はproperty
とまったく同じ動作をします。
デフォルトでは、ターゲットは指定されたキーをすべて持ち、それ以上は持てません。ターゲットが指定されたキーの少なくとも1つを持つ必要がある場合のみ、チェーンの先頭に.any
を追加します。また、.keys
を否定するには、チェーンの先頭に.not
を追加します。.keys
を否定する場合は.any
を追加し、否定せずに.keys
をアサートする場合は.all
を使用するのが最適な場合が多いです。
.keys
を否定する場合、.not.any.keys
は期待通りの出力を正確にアサートしますが、.not.all.keys
は不確かな期待を作り出します。
// 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');
否定せずに.keys
をアサートする場合、.all.keys
は期待通りの出力を正確にアサートしますが、.any.keys
は不確かな期待を作り出します。
// 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');
チェーンの先頭に.all
も.any
も現れない場合、デフォルトで.all
が使用されます。ただし、可読性が向上するため、.all
を追加するのが最適な場合が多いです。
// 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
ターゲットのキーが期待されるキーのスーパーセットである必要があるようにするには、チェーンの先頭に.include
を追加します。
// 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');
ただし、.any
と.include
を組み合わせると、.any
のみが有効になります。この場合、.include
は無視されます。
// 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');
エイリアスの.key
は.keys
と交換可能に使用できます。
expect(new Map({ foo: 1 })).to.have.key('foo');
.property(path[, val])
-
@param _{文字列 配列 反復可能}_ path_ - @param {Mixed} val (オプション)
ターゲットが指定されたpath
のプロパティを持つことをアサートします。
expect(new Map({ a: 1 })).to.have.property('a');
val
が提供されている場合、.property
は、プロパティの値が指定されたval
と等しいこともアサートします。val
はImmutableコレクションにすることができます。
expect(new Map({ a: 1 })).to.have.property('a', 1);
Immutableデータ構造のコンテキストでは、deep.property
はproperty
とまったく同じ動作をします。
ネストされたプロパティを参照する際にドット表記とブラケット表記を有効にするには、チェーンの先頭に.nested
を追加します。Immutable List
をnested.property
の開始点として使用することもできます。
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'
);
.
または[]
が実際のプロパティ名の一部である場合、その前に2つのバックスラッシュを追加してエスケープできます。
expect(Immutable.fromJS({ '.a': { '[b]': 'x' } })).to.have.nested.property(
'\\.a.\\[b\\]'
);
.property
を否定するには、チェーンの先頭に.not
を追加します。
expect(new Map({ a: 1 })).to.not.have.property('b');
ただし、val
を提供する場合に.property
を否定するのは危険です。問題は、指定されたpath
にプロパティがないこと、または指定されたキーpath
にプロパティがあるがその値が指定されたval
と等しくないことをアサートすることで、不確かな期待を作り出すことです。期待される正確な出力を特定し、その正確な出力のみを受け入れるアサーションを作成するのが最適な場合が多いです。
ターゲットが指定されたpath
にプロパティを持たないことが期待される場合、それを正確にアサートするのが最適な場合が多いです。
expect(new Map({ b: 2 })).to.not.have.property('a'); // Recommended
expect(new Map({ b: 2 })).to.not.have.property('a', 1); // Not recommended
ターゲットが指定されたキーpath
にプロパティを持つことが期待される場合、多くの予期しない値の1つを持たないことをアサートするのではなく、プロパティが期待される値を持つことをアサートするのが最適な場合が多いです。
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
は、チェーン内で続くすべてのアサーションのターゲットを、元のターゲットオブジェクトのプロパティの値に変更します。
expect(new Map({ a: 1 }))
.to.have.property('a')
.that.is.a('number');
.size(value)
- @param {数値} size
Immutableコレクションが期待されるサイズを持つことをアサートします。
expect(List.of(1, 2, 3)).to.have.size(3);
size
プロパティの値の比較に対するチェーンの前処理としても使用できます。
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);
length
/lengthOf
と同様に、sizeOf
はsize
のエイリアスです。
expect(List.of(1, 2, 3)).to.have.sizeOf(3);
TDD APIリファレンス (Assert)
.equal(actual, expected)
- @param { Collection } actual
- @param { Collection } expected
actual
の値がexpected
の値と等価であることをアサートします。.strictEqual()
と.deepEqual()
は、イミュータブルデータ構造のコンテキストでは.equal()
とまったく同じようにアサートします。
const a = List.of(1, 2, 3);
const b = List.of(1, 2, 3);
assert.equal(a, b);
イミュータブルデータ構造は、イミュータブルであるとみなされ、.equal()
、.strictEqual()
、または.deepEqual()
に対して適切に動作するためには、他のイミュータブルデータ構造のみを含んでいる必要があります(Array
やObject
とは異なります)。詳細はissue #24を参照してください。
.referenceEqual(actual, expected)
- @param {Collection} actual
- @param {Collection} expected
actual
の参照がexpected
の参照と等価であることをアサートします。このメソッドは、Chaiのequal
の元の動作を保持します。
詳細はissue #210を参照してください。
const a = List.of(1, 2, 3);
const b = a;
const c = List.of(1, 2, 3);
assert.referenceEqual(a, b);
assert.throws(() => assert.referenceEqual(a, c));
.notEqual(actual, expected)
- @param { Collection } actual
- @param { Collection } expected
actual
の値がexpected
の値と等価でないことをアサートします。.notStrictEqual()
と.notDeepEqual()
は、イミュータブルデータ構造のコンテキストでは.notEqual()
とまったく同じようにアサートします。
const a = List.of(1, 2, 3);
const b = List.of(4, 5, 6);
assert.notEqual(a, b);
.notReferenceEqual(actual, expected)
- @param {Collection} actual
- @param {Collection} expected
actual
の参照がexpected
の参照と等価でないことをアサートします。このメソッドは、ChaiのnotEqual
の元の動作を保持します。
詳細はissue #210を参照してください。
const a = List.of(1, 2, 3);
const b = a;
const c = List.of(1, 2, 3);
assert.throws(() => assert.notReferenceEqual(a, b));
assert.notReferenceEqual(a, c);
.sizeOf(collection, length)
- @param {Collection} collection
- @param {数値} size
Immutableコレクションが期待されるサイズを持つことをアサートします。
assert.sizeOf(List.of(1, 2, 3), 3);
assert.sizeOf(new List(), 0);