Edited at

React+Material-UIなコンポーネントをEnzymeでテスト

More than 1 year has passed since last update.

通常ReactのコンポーネントをEnzymeを使ってテストするには以下のように記述する感じ。

import React from 'react';

import { expect } from 'chai';
import { shallow, mount } from 'enzyme';
import sinon from 'sinon';
import MyComponent from './MyComponent';

it('renders without crashing', () => {
const wrapper = mount(<MyComponent />);
expect(wrapper.find("input[type='text']").length).to.equal(0);
});

しかし、この MyComponent が Material-UI に依存している場合はテストを実行すると以下のようなエラーが出てしまいます。

Warning: Failed context type: The context `muiTheme` is marked as required in `TextField`, but its value is `undefined`.

このエラーの意味は、MyComponentmuiTheme を必要としているよということなので、以下のように <MuiThemeProvider /> で囲むとエラーが出なくなります。

const wrapper = mount(<MuiThemeProvider><MyComponent /></MuiThemeProvider>);

でもこれでエラーが引っ込んだとしても、wrapper.props()wrapper.state() にうまいことアクセスできなかったりするので、テストをいい感じに記述することができません。


解決策

この問題を解決するには、以下のようにテストを記述することで解決できます。

import React from 'react';

import { expect } from 'chai';
import { shallow, mount } from 'enzyme';
import sinon from 'sinon';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import PropTypes from 'prop-types';
import MyComponent from './MyComponent';

const muiTheme = getMuiTheme();

it('renders without crashing', () => {
const wrapper = mount(<MyComponent />, {
context: { muiTheme },
childContextTypes: { muiTheme: PropTypes.object },
});

expect(wrapper.find("input[type='text']").length).to.equal(0);
});

ポイントは以下の部分。

const wrapper = mount(<PasswordField id="hello" name="world" />, {

context: { muiTheme },
childContextTypes: { muiTheme: PropTypes.object },
});

あと、これに必要な以下のモジュールをロードしているところです。

import getMuiTheme from 'material-ui/styles/getMuiTheme';

import PropTypes from 'prop-types';

const muiTheme = getMuiTheme();