ReactにJestでテストしようとしているコンポーネントがありますが、残念ながらテストはパスしません。
コンポーネントコード:
import React, {Component} from 'react';
import ProductItem from '../ProductItem/ProductItem';
import AppBar from "@material-ui/core/es/AppBar/AppBar";
import Tabs from "@material-ui/core/es/Tabs/Tabs";
import Tab from "@material-ui/core/es/Tab/Tab";
import {connect} from 'react-redux';
class ProductsTabsWidget extends Component {
state = {
value: 0
}
renderTabs = () => {
return this.props.tabs.map((item, index) => {
return item.products.length > 0 ? (<Tab key={index} label={item.title}/>) : false;
})
}
handleChange = (event, value) => {
this.setState({value});
};
renderConentActiveTab = () => {
if (this.props.tabs[this.state.value]) {
return this.props.tabs[this.state.value].products.map((productIndex) => {
return (<ProductItem key={productIndex} {...this.props.products[productIndex]} />);
});
}
}
render() {
let tabs = null;
let content = null;
if (this.props.tabs) {
tabs = this.renderTabs();
content = this.renderConentActiveTab();
}
return (
<div>
<AppBar position="static" color="default">
<Tabs
value={this.state.value}
onChange={this.handleChange}
indicatorColor="primary"
textColor="primary"
centered
scrollButtons="auto"
>
{tabs}
</Tabs>
</AppBar>
<div className="productWidget">
<div className="wrapper">
{content}
</div>
</div>
</div>
)
}
}
const mapStateToProps = state => {
return {
products: state.product.products,
}
}
export default connect(mapStateToProps)(ProductsTabsWidget);
このコンポーネントの適切なテストを作成しようとしましたが、コードは以下のとおりです。
import React from 'react';
import {configure, shallow} from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import ProductsTabsWidget from "./ProductsTabsWidget";
configure({adapter: new Adapter()});
describe('ProductsTabsWidget - component', () => {
let wrapper;
beforeEach(() => {
wrapper = shallow(<ProductsTabsWidget/>);
});
it('renders with minimum props without exploding', () => {
wrapper.setProps({
tabs: [],
products:[]
});
expect(wrapper).toHaveLength(1);
});
})
しかし、テストを実行しているときにエラーが発生します:
Test suite failed to run
F:\PRACA\reactiveShop\node_modules\@material-ui\core\es\AppBar\AppBar.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import _extends from "@babel/runtime/helpers/builtin/extends";
^^^^^^
SyntaxError: Unexpected token import
at new Script (vm.js:51:7)
at Object.<anonymous> (src/components/product/ProductsTabsWidget/ProductsTabsWidget.js:3:15)
shallow
、mount
、render
でテストしてみましたが、役に立ちませんでした。私は何が欠けていますか?
私のアプリケーションはcreate-react-app
で作成されます。
@material-ui
を使用しているときは、何か違うものです。
@material-ui
の組み込みAPIを使用する必要があります。 createMount
、createShallow
、createRender
など、酵素のshallow
、mount
、およびrender
を使用するため。
これらのAPIはenzyme
の上に構築されるため、@material-ui
をテストするためにenzyme
を直接使用することはできません。
Shallow
レンダリングの例import { createShallow } from '@material-ui/core/test-utils';
describe('<MyComponent />', () => {
let shallow;
before(() => {
shallow = createShallow();
});
it('should work', () => {
const wrapper = shallow(<MyComponent />);
});
});
リファレンス: @ material-uiの公式ドキュメント
以下は、_create-react-app
_および_@material-ui
_の観点からより完全な回答を提供するための謙虚な試みです。
_1.
_ src
フォルダーに_setupTests.js
_を直接作成し、次のコードを貼り付けます。
_import { configure } from "enzyme";
import Adapter from "enzyme-adapter-react-16";
configure({ adapter: new Adapter() });
_
_2.
_以下は、_material-ui
_コンポーネントを使用するリアクティブステートレスコンポーネントです。
_import React from "react";
import TextField from "@material-ui/core/TextField";
const SearchField = props => (
<TextField InputProps={{ disableUnderline: true }} fullWidth
placeholder={props.placeholder}
onChange={props.onChange}
/>
);
export default SearchField;
_
上記のコンポーネントでは、コンポーネントは親コンポーネントがplaceholder
およびonChange()
イベントハンドラーのプロパティを渡すことを期待していることに注意してください。
_3.
_上記のコンポーネントのテストケースに来ると、_material-ui
_が示唆する方法で、または_pure enzyme
_スタイルで書くことができます。両方とも機能します。
_Pure Enzyme
_スタイル
_import React from "react";
import { mount } from "enzyme";
import TextField from "@material-ui/core/TextField";
import SearchField from "../SearchField";
describe("SearchField Enzyme mount() ", () => {
const fieldProps = {
placeholder: "A placeholder",
onChange: jest.fn()
};
const Composition = props => {
return <SearchField {...fieldProps} />;
};
it("renders a <TextField/> component with expected props", () => {
const wrapper = mount(<Composition />);
expect(wrapper.childAt(0).props().placeholder).toEqual("A placeholder");
expect(wrapper.childAt(0).props().onChange).toBeDefined();
});
it("should trigger onChange on <SearchField/> on key press", () => {
const wrapper = mount(<Composition />);
wrapper.find("input").simulate("change");
expect(fieldProps.onChange).toHaveBeenCalled();
});
it("should render <TextField />", () => {
const wrapper = mount(<Composition />);
expect(wrapper.find(TextField)).toHaveLength(1);
expect(wrapper.find(TextField).props().InputProps.disableUnderline).toBe(
true
);
});
});
_
_Material UI
_スタイル
_import React from "react";
import { createMount } from "@material-ui/core/test-utils";
import TextField from "@material-ui/core/TextField";
import SearchField from "../SearchField";
describe("SearchField", () => {
let mount;
const fieldProps = {
placeholder: "A placeholder",
onChange: jest.fn()
};
beforeEach(() => {
mount = createMount();
});
afterEach(() => {
mount.cleanUp();
});
it("renders a <TextField/> component with expected props", () => {
const wrapper = mount(<SearchField {...fieldProps} />);
expect(wrapper.props().placeholder).toEqual("A placeholder");
expect(wrapper.props().onChange).toBeDefined();
});
it("should trigger onChange on <SearchField/> on key press", () => {
const wrapper = mount(<SearchField {...fieldProps} />);
wrapper.find("input").simulate("change");
expect(fieldProps.onChange).toHaveBeenCalled();
});
});
_
_5.
_取得しているエラーは、babel
がファイルを処理する機会を得ていないという事実によるものです。 _create-react-app
_は、_yarn run test
_ではなく_jest your/test/file.js
_のようなテストを実行することを期待しています。後者を使用する場合、babel
はemployed
にはなりません。
jest
を使用してファイルを実行する場合は、_jest.config.js
_ファイルを作成するか、_package.json
_ファイルにjest
を構成して_babel-jest
_を使用する必要があります+ _other babel dependencies
_は、jestがテストを実行する前にコードを変換します。
_@material-ui
_を初めて使用しようとしたとき、昨日と同じボートに乗って、より完全な答えを得るためにここに来ました。
このような何かが私のために働いた:
import {createMount} from '@material-ui/core/test-utils';
const WrappedComponent = () =>
<MUIThemeStuffEtc>
<MyComponent />
</MUIThemeStuffEtc>
const render = createMount();
const wrapper = render(<WrappedComponent />);
const state = wrapper.find(MyComponent).instance().wrappedInstance.state