为 React JS 编写测试
Writing tests for React JS
我刚刚开始研究测试,我正在尝试测试一个初始状态为 false 的组件。单击时,它应更改为 !state,如果为真,则渲染一个子组件。
我正在尝试至少编写一个测试来检查它是否通过我发现的一些示例更改了点击时的状态。
我正在使用 Jest、测试 Library/React 和 Jest.
index.test.js
/* eslint-disable no-return-assign */
import { render, screen, fireEvent } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import { shallow } from 'enzyme';
import PropTypesExemple from './index';
import ChildComponent from './ChildComponent';
describe('Testing the rendering of components', () => {
let wrapper;
beforeEach(() => {
wrapper = shallow(<PropTypesExemple state={false} />);
});
test('should render component prop types exemple', () => {
render(
<MemoryRouter>
<PropTypesExemple />
</MemoryRouter>,
);
fireEvent(
screen.getByText('Me Aperte!!!'),
new MouseEvent('click'),
);
});
test('should render child component', () => {
render(
<ChildComponent />,
);
});
it('sould render child component on click', () => {
wrapper.setProps({ state: false });
wrapper.find('button').simulate('click');
expect(wrapper.state('state').toEqual(true));
});
});
父组件
import React, { useState } from 'react';
import './index.scss';
import PageDefault from '../../components/PageDefault';
import ChildComponent from './ChildComponent';
function PropTypesExemple() {
const [state, setState] = useState(false);
const [text, setText] = useState();
const handleClick = () => {
setState((prev) => !prev);
};
return (
<PageDefault>
<div className="prop-types-container">
<h1>Olá, Mundo!</h1>
<input
value={text}
onChange={(event) => setText(event.target.value)}
/>
<button type="button" onClick={handleClick}>Me Aperte!!!</button>
{state && (<ChildComponent nome={!text ? undefined : text} />)}
</div>
</PageDefault>
);
}
export default PropTypesExemple;
子组件
/* eslint-disable react/destructuring-assignment */
/* eslint-disable arrow-body-style */
import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
const ChildComponent = (props) => {
useEffect(() => {
document.title = props.nome;
return () => { };
}, [props.nome]);
useEffect(() => {
const intervalId = setInterval(() => { }, 1000);
return () => {
clearInterval(intervalId);
};
}, []);
return (
<div>
Olá,
{props.nome}
!
</div>
);
};
ChildComponent.defaultProps = {
nome: 'React App2',
};
ChildComponent.propTypes = {
nome: PropTypes.string,
};
export default ChildComponent;
我 运行 遇到以下错误
src/pages/PropTypes/index.test.js
● Testing the rendering of components › should render component prop types exemple
Enzyme Internal Error: Enzyme expects an adapter to be configured, but found none.
To configure an adapter, you should call `Enzyme.configure({ adapter: new Adapter() })`
before using any of Enzyme's top level APIs, where `Adapter` is the adapter
corresponding to the library currently being tested. For example:
import Adapter from 'enzyme-adapter-react-15';
To find out more about this, see https://airbnb.io/enzyme/docs/installation/index.html
9 | let wrapper;
10 | beforeEach(() => {
> 11 | wrapper = shallow(<PropTypesExemple state={false} />);
| ^
12 | });
13 | test('should render component prop types exemple', () => {
14 | render(
at validateAdapter (node_modules/enzyme/src/validateAdapter.js:5:11)
at getAdapter (node_modules/enzyme/src/getAdapter.js:10:3)
at makeShallowOptions (node_modules/enzyme/src/ShallowWrapper.js:345:19)
at new ShallowWrapper (node_modules/enzyme/src/ShallowWrapper.js:393:21)
at shallow (node_modules/enzyme/src/shallow.js:10:10)
at Object.<anonymous> (src/pages/PropTypes/index.test.js:11:15)
● Testing the rendering of components › should render child component
Enzyme Internal Error: Enzyme expects an adapter to be configured, but found none.
To configure an adapter, you should call `Enzyme.configure({ adapter: new Adapter() })`
before using any of Enzyme's top level APIs, where `Adapter` is the adapter
corresponding to the library currently being tested. For example:
import Adapter from 'enzyme-adapter-react-15';
To find out more about this, see https://airbnb.io/enzyme/docs/installation/index.html
9 | let wrapper;
10 | beforeEach(() => {
> 11 | wrapper = shallow(<PropTypesExemple state={false} />);
| ^
12 | });
13 | test('should render component prop types exemple', () => {
14 | render(
at validateAdapter (node_modules/enzyme/src/validateAdapter.js:5:11)
at getAdapter (node_modules/enzyme/src/getAdapter.js:10:3)
at makeShallowOptions (node_modules/enzyme/src/ShallowWrapper.js:345:19)
at new ShallowWrapper (node_modules/enzyme/src/ShallowWrapper.js:393:21)
at shallow (node_modules/enzyme/src/shallow.js:10:10)
at Object.<anonymous> (src/pages/PropTypes/index.test.js:11:15)
● Testing the rendering of components › sould render child component on click
Enzyme Internal Error: Enzyme expects an adapter to be configured, but found none.
To configure an adapter, you should call `Enzyme.configure({ adapter: new Adapter() })`
before using any of Enzyme's top level APIs, where `Adapter` is the adapter
corresponding to the library currently being tested. For example:
import Adapter from 'enzyme-adapter-react-15';
To find out more about this, see https://airbnb.io/enzyme/docs/installation/index.html
9 | let wrapper;
10 | beforeEach(() => {
> 11 | wrapper = shallow(<PropTypesExemple state={false} />);
| ^
12 | });
13 | test('should render component prop types exemple', () => {
14 | render(
at validateAdapter (node_modules/enzyme/src/validateAdapter.js:5:11)
at getAdapter (node_modules/enzyme/src/getAdapter.js:10:3)
at makeShallowOptions (node_modules/enzyme/src/ShallowWrapper.js:345:19)
at new ShallowWrapper (node_modules/enzyme/src/ShallowWrapper.js:393:21)
at shallow (node_modules/enzyme/src/shallow.js:10:10)
at Object.<anonymous> (src/pages/PropTypes/index.test.js:11:15)
Test Suites: 1 failed, 7 passed, 8 total
Tests: 3 failed, 7 passed, 10 total
Snapshots: 0 total
Time: 2.118 s
Ran all test suites related to changed files.
正如 Alexander Staroselsky 所说,文档没有提到它,但是有一个非官方的 React 17 适配器。0.x。
您可以在这里找到它:@wojtekmaj/enzyme-adapter-react-17
并这样配置:
import Enzyme from 'enzyme';
import Adapter from '@wojtekmaj/enzyme-adapter-react-17';
Enzyme.configure({ adapter: new Adapter() });
我刚刚开始研究测试,我正在尝试测试一个初始状态为 false 的组件。单击时,它应更改为 !state,如果为真,则渲染一个子组件。 我正在尝试至少编写一个测试来检查它是否通过我发现的一些示例更改了点击时的状态。 我正在使用 Jest、测试 Library/React 和 Jest.
index.test.js
/* eslint-disable no-return-assign */
import { render, screen, fireEvent } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import { shallow } from 'enzyme';
import PropTypesExemple from './index';
import ChildComponent from './ChildComponent';
describe('Testing the rendering of components', () => {
let wrapper;
beforeEach(() => {
wrapper = shallow(<PropTypesExemple state={false} />);
});
test('should render component prop types exemple', () => {
render(
<MemoryRouter>
<PropTypesExemple />
</MemoryRouter>,
);
fireEvent(
screen.getByText('Me Aperte!!!'),
new MouseEvent('click'),
);
});
test('should render child component', () => {
render(
<ChildComponent />,
);
});
it('sould render child component on click', () => {
wrapper.setProps({ state: false });
wrapper.find('button').simulate('click');
expect(wrapper.state('state').toEqual(true));
});
});
父组件
import React, { useState } from 'react';
import './index.scss';
import PageDefault from '../../components/PageDefault';
import ChildComponent from './ChildComponent';
function PropTypesExemple() {
const [state, setState] = useState(false);
const [text, setText] = useState();
const handleClick = () => {
setState((prev) => !prev);
};
return (
<PageDefault>
<div className="prop-types-container">
<h1>Olá, Mundo!</h1>
<input
value={text}
onChange={(event) => setText(event.target.value)}
/>
<button type="button" onClick={handleClick}>Me Aperte!!!</button>
{state && (<ChildComponent nome={!text ? undefined : text} />)}
</div>
</PageDefault>
);
}
export default PropTypesExemple;
子组件
/* eslint-disable react/destructuring-assignment */
/* eslint-disable arrow-body-style */
import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
const ChildComponent = (props) => {
useEffect(() => {
document.title = props.nome;
return () => { };
}, [props.nome]);
useEffect(() => {
const intervalId = setInterval(() => { }, 1000);
return () => {
clearInterval(intervalId);
};
}, []);
return (
<div>
Olá,
{props.nome}
!
</div>
);
};
ChildComponent.defaultProps = {
nome: 'React App2',
};
ChildComponent.propTypes = {
nome: PropTypes.string,
};
export default ChildComponent;
我 运行 遇到以下错误
src/pages/PropTypes/index.test.js
● Testing the rendering of components › should render component prop types exemple
Enzyme Internal Error: Enzyme expects an adapter to be configured, but found none.
To configure an adapter, you should call `Enzyme.configure({ adapter: new Adapter() })`
before using any of Enzyme's top level APIs, where `Adapter` is the adapter
corresponding to the library currently being tested. For example:
import Adapter from 'enzyme-adapter-react-15';
To find out more about this, see https://airbnb.io/enzyme/docs/installation/index.html
9 | let wrapper;
10 | beforeEach(() => {
> 11 | wrapper = shallow(<PropTypesExemple state={false} />);
| ^
12 | });
13 | test('should render component prop types exemple', () => {
14 | render(
at validateAdapter (node_modules/enzyme/src/validateAdapter.js:5:11)
at getAdapter (node_modules/enzyme/src/getAdapter.js:10:3)
at makeShallowOptions (node_modules/enzyme/src/ShallowWrapper.js:345:19)
at new ShallowWrapper (node_modules/enzyme/src/ShallowWrapper.js:393:21)
at shallow (node_modules/enzyme/src/shallow.js:10:10)
at Object.<anonymous> (src/pages/PropTypes/index.test.js:11:15)
● Testing the rendering of components › should render child component
Enzyme Internal Error: Enzyme expects an adapter to be configured, but found none.
To configure an adapter, you should call `Enzyme.configure({ adapter: new Adapter() })`
before using any of Enzyme's top level APIs, where `Adapter` is the adapter
corresponding to the library currently being tested. For example:
import Adapter from 'enzyme-adapter-react-15';
To find out more about this, see https://airbnb.io/enzyme/docs/installation/index.html
9 | let wrapper;
10 | beforeEach(() => {
> 11 | wrapper = shallow(<PropTypesExemple state={false} />);
| ^
12 | });
13 | test('should render component prop types exemple', () => {
14 | render(
at validateAdapter (node_modules/enzyme/src/validateAdapter.js:5:11)
at getAdapter (node_modules/enzyme/src/getAdapter.js:10:3)
at makeShallowOptions (node_modules/enzyme/src/ShallowWrapper.js:345:19)
at new ShallowWrapper (node_modules/enzyme/src/ShallowWrapper.js:393:21)
at shallow (node_modules/enzyme/src/shallow.js:10:10)
at Object.<anonymous> (src/pages/PropTypes/index.test.js:11:15)
● Testing the rendering of components › sould render child component on click
Enzyme Internal Error: Enzyme expects an adapter to be configured, but found none.
To configure an adapter, you should call `Enzyme.configure({ adapter: new Adapter() })`
before using any of Enzyme's top level APIs, where `Adapter` is the adapter
corresponding to the library currently being tested. For example:
import Adapter from 'enzyme-adapter-react-15';
To find out more about this, see https://airbnb.io/enzyme/docs/installation/index.html
9 | let wrapper;
10 | beforeEach(() => {
> 11 | wrapper = shallow(<PropTypesExemple state={false} />);
| ^
12 | });
13 | test('should render component prop types exemple', () => {
14 | render(
at validateAdapter (node_modules/enzyme/src/validateAdapter.js:5:11)
at getAdapter (node_modules/enzyme/src/getAdapter.js:10:3)
at makeShallowOptions (node_modules/enzyme/src/ShallowWrapper.js:345:19)
at new ShallowWrapper (node_modules/enzyme/src/ShallowWrapper.js:393:21)
at shallow (node_modules/enzyme/src/shallow.js:10:10)
at Object.<anonymous> (src/pages/PropTypes/index.test.js:11:15)
Test Suites: 1 failed, 7 passed, 8 total
Tests: 3 failed, 7 passed, 10 total
Snapshots: 0 total
Time: 2.118 s
Ran all test suites related to changed files.
正如 Alexander Staroselsky 所说,文档没有提到它,但是有一个非官方的 React 17 适配器。0.x。 您可以在这里找到它:@wojtekmaj/enzyme-adapter-react-17
并这样配置:
import Enzyme from 'enzyme';
import Adapter from '@wojtekmaj/enzyme-adapter-react-17';
Enzyme.configure({ adapter: new Adapter() });