(Better) Chai Shallow Deep Equal プラグイン

このモジュールは、chai のドロップイン置換アサーション shallowDeepEqual を提供します。このアサーションは厳密なセマンティクスと、直感的に理解できる出力の差分を使用します。

NPM version Build Status Coverage Status

このライブラリは内部的に Unexpected ライブラリをラップし、特に構造的な “to satisfy” アサーションを使用します。

使用

インストールすると、プラグインをインポートして、プラグインとして簡単に使用できます。

const chai = require("chai");
const expect = chai.expect;

chai.use(require("chai-better-shallow-deep-equal"));

その後、追加の .shallowDeepEqual() アサーションが使用でき、エラーが発生すると詳しい差分が出力されます。

expect({ foo: true, bar: 0 }).to.shallowDeepEqual({ foo: true, bar: 1 });
expected { foo: true, bar: 0 } to satisfy { foo: true, bar: 1 }

{
  foo: true,
  bar: 0 // should equal 1
}

このアサーションは、expectshouldassert の 3 つの chai API すべてで動作します。

ES6 型のサポート

このプラグインは、Map オブジェクトと Set オブジェクトの構造的な比較をサポートしています。

expect(
  new Map([
    ["foo", 1],
    ["bar", false]
  ])
).to.shallowDeepEqual(
  new Map([
    ["foo", 1],
    ["bar", true]
  ])
);
expected new Map[ ['foo', 1], ['bar', false] ])
to satisfy new Map[ ['foo', 1], ['bar', true] ])

new Map[
  ['foo', 1,]
  ['bar',
    false // should equal true
  ]
])
expect(new Set(["foo", "baz"])).to.shallowDeepEqual(
  new Set(["foo", "bar"])
);
expected new Set([ 'foo', 'baz' ]) to satisfy new Set([ 'foo', 'bar' ])

new Set([
  'foo',
  'baz' // should be removed
  // missing 'bar'
])

カスタマイズ

型の追加

テストスイート内で特定の型を識別することが有益な場合があります。おそらくは、それらの表示をカスタマイズしたり、それらを別的方式で扱ったりするためでしょう。これは addType() API を使用することで実現できます。

const chaiBetterShallowDeepEqual = require("chai-better-shallow-deep-equal");

chaiBetterShallowDeepEqual.addType({
  name: "CustomDate",
  base: "date",
  identify: obj => obj && obj._isCustomDate
});

上記の例では、自前の日付を使用する架空のテストスイート内で発生する特定のオブジェクトを、「isCustomDate」プロパティを持っているかどうかを確認することで特定しようとしています。

上記の identify() メソッドの定義に従うと、プラグインはこのようなオブジェクトを CustomDate として考慮します。また、それらが組み込みの日付型の動作を拡張していることを認識します。

この API は Unexpected の addType() メソッドと同じオプションを受け入れます。より詳しい説明は、リンク先をご覧ください。

カスタムマッチング

カスタム型が使用可能になると、よく考えられることは、識別された型のマッチング方法をカスタマイズしたいということでしょう。

デフォルトでは、同じ種類の型のみが比較されます。しかし、テスト内で、どの CustomDate オブジェクトも ISO タイム文字列と比較できるようにしたいとします。

先ほどの架空の例を続けましょう。 addMatch() API を使用すると、比較できるように定義できます。

chaiBetterShallowDeepEqual.addMatch({
  leftType: "CustomDate",
  rightType: "string",
  handler: (lhs, rhs) => [lhs.toISOString(), rhs]
});

ここで定義したことは、 CustomDate が文字列と比較されるとき、最初に ISO 文字列に変換してから比較することです。テストスイートでは、その効果により、非常に読み取りやすい方法で期待を定義できます。

const fooDate = new Date(1583947016326);

expect({ fooDate }).to.shallowDeepEqual({
  fooDate: "2020-03-11T17:16:56.326Z"
});
expected { fooDate: new Date('2020-03-11T17:16:56.326Z') }
to satisfy { fooDate: '2020-03-11T17:16:56.326Z' }

{
  fooDate: new Date('2020-03-11T17:16:56.326Z') // should equal '2020-03-11T17:16:56.326Z'
}