TypeScript
reactjs
jest
React
enzyme

jest-enzyme を TypeScript で使う方法

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 から使おうとするとかゆいところに手が届かない。

というのも、上のコードはコンパイルエラーになるからだ。

原因

原因は型定義ファイルの所在とセットアップの手続きにある。

  1. jest-enzyme はパッケージ自体に型定義ファイルをバンドルしており、@types にはない。
  2. jest-enzyme の import は通常 config を通して行われ、テストコードそれ自体に入らない。 create-react-app を利用した場合も事情は同じ。

以上のことから、コンパイラや IDE が前述の型定義ファイルをみつけることができなくなっている。

対策

手動でこのファイルのありかを教えてあげればいい。素朴にやるとほかの型定義ファイルまで見えなくなるので、最低でも以下のようにする。

tsconfig.json
{
  "compilerOptions": {
    ...
    "typeRoots": ["node_modules/@types", "node_modules/jest-enzyme"]
  },
  ...
}

意見

これで解決……なのだが、すべてのプロジェクトでこれをやるのはだるいし、ダサい。

もし TypeScript が @types よりもバンドル方式を——あるいは初めから TypeScript で開発することを——推奨してゆくのならば、こうした環境に組み込まれるタイプのパッケージを扱うための簡便な方法1が必要だと思う。想像してほしい、かりに mocha が同じ状況だったらどれほどの影響が出るだろうか。

あるいは、現状の仕組みのままでも @types にダミーパッケージを作って型定義を転送するなどすれば解決するのかもしれない(未検証)。


  1. node_modules/${package}/package.json に types エントリがあったら自動で参照するなど。