我有一个页面,其中包含一个组件,可在发生点击事件时从GET
端点搜索请求数据:
AppView.jsx
/**
* Request and set a list of test values
* @param {Object} params The response of the search component
*/
fetchData = (params) => {
const { search } = params;
this.props.api.test(search)
.then((response) => {
objectOrder(response, 'dueDate');
this.setState({ test: response });
}).catch(() => {
this.setState({ test: [] });
});
}
render() {
return (
<SearchComponent fetchData={this.fetchData} />
);
}
SearchForm / index.jsx
class SearchForm extends Component {
static propTypes = {
fetchData: PropTypes.func.isRequired,
}
constructor(props) {
super(props);
this.state = {
search: '',
};
}
/**
* Sets the state of the search name
* @param {Object} event
*/
handleChange = (event) => {
const { name, value } = event.target;
this.setState({ [name]: value });
}
/**
* Propagate the submit event
* @param {Object} event
*/
handleSubmit = (event) => {
event.preventDefault();
this.props.fetchData(this.state);
}
render() {
return (
<FormContainer onSubmit={this.handleSubmit}>
<Input value={this.state.search} name='search' placeholder='Search for...' onChange={this.handleChange} />
<Button variant='contained' color='primary'>Buscar</Button>
</FormContainer>
);
}
}
当我对Submit方法进行SearchForm
测试时,即使我的所有测试都成功通过,我的覆盖范围也告诉我handleSubmit
和handleChange
方法根本没有被测试:< / p>
我的测试尝试通过以下方式测试这些方法:
describe('<SearchForm />', () => {
const text = 'This is a text for a test';
const state = { search: text };
let props;
let wrapper;
beforeEach(() => {
props = {
handleSubmit: jest.fn(() => true),
fetchData: jest.fn(() => (state)),
};
wrapper = mount(<SearchForm {...props} />);
});
test('It should call handlesubmit method when submitting the form', (done) => {
wrapper.find(Button).simulate('click', { preventDefault() {} });
expect(wrapper.props().handleSubmit()).toEqual(true);
done();
});
test('It should call handleChange method', (done) => {
const input = wrapper.find(Input);
input.props().value = text;
input.simulate('change', { target: { value: text } });
expect(input.get(0).props.value).toEqual(text);
done();
});
});
涵盖所有这些方法的帮助吗?
感谢您的咨询
答案 0 :(得分:0)
您可以模拟submit
表单事件。
SearchForm.tsx
:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { FormContainer } from './FormContainer';
import { Input } from './Input';
import { Button } from './Button';
interface ISearchFormDispatchProps {
fetchData(params: ISearchFormState): any;
}
type Props = ISearchFormDispatchProps;
interface ISearchFormState {
search: string;
[key: string]: string;
}
export class SearchForm extends Component<Props, ISearchFormState> {
public static propTypes = {
fetchData: PropTypes.func.isRequired
};
constructor(props) {
super(props);
this.state = {
search: ''
};
this.handleSubmit = this.handleSubmit.bind(this);
}
/**
* Sets the state of the search name
* @param {Object} event
*/
public handleChange = event => {
const { name, value } = event.target;
this.setState({ [name]: value });
}
/**
* Propagate the submit event
* @param {Object} event
*/
public handleSubmit = event => {
event.preventDefault();
this.props.fetchData(this.state);
}
public render() {
return (
<FormContainer onSubmit={this.handleSubmit}>
<Input value={this.state.search} name="search" placeholder="Search for..." onChange={this.handleChange} />
<Button variant="contained" color="primary">
Buscar
</Button>
</FormContainer>
);
}
}
FormContainer.tsx
:
import React, { Component } from 'react';
interface IFormContainerOwnProps {
children: React.ReactElement[];
onSubmit(e: React.FormEvent<HTMLFormElement>): any;
}
export class FormContainer extends Component<IFormContainerOwnProps> {
constructor(props: IFormContainerOwnProps) {
super(props);
}
public render() {
return (
<div>
<form onSubmit={this.props.onSubmit}>{this.props.children}</form>
</div>
);
}
}
Button.tsx
:
import React from 'react';
export const Button = props => {
return <button {...props}>{props.children}</button>;
};
Input.tsx
:
import React from 'react';
export const Input = ({ onChange, placeholder, name, value }) => {
return <input placeholder={placeholder} name={name} value={value} onChange={onChange}></input>;
};
SearchForm.spec.ts
单元测试:
import React from 'react';
import { SearchForm } from './SearchForm';
import { mount } from 'enzyme';
import { Input } from './Input';
describe('SearchForm', () => {
const text = 'This is a text for a test';
const state = { search: text };
let props;
let wrapper;
beforeEach(() => {
props = {
fetchData: jest.fn(() => state)
};
wrapper = mount(<SearchForm {...props} />);
});
test('It should call handlesubmit method when submitting the form', done => {
const mockedFormEvent = {
preventDefault: jest.fn()
};
wrapper.find('form').simulate('submit', mockedFormEvent);
expect(wrapper.props().fetchData).toBeCalledWith(wrapper.state());
expect(mockedFormEvent.preventDefault).toBeCalledTimes(1);
done();
});
test('It should call handleChange method', done => {
const input = wrapper.find(Input);
input.props().value = text;
input.simulate('change', { target: { value: text } });
expect(input.get(0).props.value).toEqual(text);
done();
});
});
覆盖率100%的单元测试结果:
PASS src/stackoverflow/52944804/SearchForm.spec.tsx
SearchForm
✓ It should call handlesubmit method when submitting the form (53ms)
✓ It should call handleChange method (16ms)
-------------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
-------------------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
Button.tsx | 100 | 100 | 100 | 100 | |
FormContainer.tsx | 100 | 100 | 100 | 100 | |
Input.tsx | 100 | 100 | 100 | 100 | |
SearchForm.tsx | 100 | 100 | 100 | 100 | |
-------------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 4.953s, estimated 5s
SearchForm.tsx
的覆盖率报告:
以下是完整的演示:https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/52944804