TLDR
TypeScript で jest-enzyme を使う場合は tsconfig.json の typeRoots
プロパティに "node_modules/jest-enzyme" を追加すること。
jest-enzyme とは
jest-enzyme とは Jest に Enzyme 専用の matcher を追加するプラグインで、 React のテストが以下のように書けるようになる。
import * as React from 'react';
import { shallow } from 'enzyme';
test('example matcher', () => {
const element = <a href="http://www.facebook.com">Facebook</a>;
const wrapper = shallow(element);
// jest
expect(wrapper.find('a').prop('href')).toBe('http://www.facebook.com');
// jest-enzyme
expect(wrapper.find('a')).toHaveProp('href', 'http://www.facebook.com');
});
記述用の違いはちょっとしたものだが、テストの意図を残せることと失敗した時のエラーメッセージがわかりやすくなることから Enzyme を使う場合はマストで入れるようにしている。
問題
そんな便利な jest-enzyme なのだが、 TypeScript から使おうとするとかゆいところに手が届かない。
というのも、上のコードはコンパイルエラーになるからだ。
原因
原因は型定義ファイルの所在とセットアップの手続きにある。
- jest-enzyme はパッケージ自体に型定義ファイルをバンドルしており、@types にはない。
- jest-enzyme の import は通常 config を通して行われ、テストコードそれ自体に入らない。 create-react-app を利用した場合も事情は同じ。
以上のことから、コンパイラや IDE が前述の型定義ファイルをみつけることができなくなっている。
対策
手動でこのファイルのありかを教えてあげればいい。素朴にやるとほかの型定義ファイルまで見えなくなるので、最低でも以下のようにする。
{
"compilerOptions": {
...
"typeRoots": ["node_modules/@types", "node_modules/jest-enzyme"]
},
...
}
意見
これで解決……なのだが、すべてのプロジェクトでこれをやるのはだるいし、ダサい。
もし TypeScript が @types よりもバンドル方式を——あるいは初めから TypeScript で開発することを——推奨してゆくのならば、こうした環境に組み込まれるタイプのパッケージを扱うための簡便な方法1が必要だと思う。想像してほしい、かりに mocha が同じ状況だったらどれほどの影響が出るだろうか。
あるいは、現状の仕組みのままでも @types にダミーパッケージを作って型定義を転送するなどすれば解決するのかもしれない(未検証)。
-
node_modules/${package}/package.json に types エントリがあったら自動で参照するなど。 ↩