Reputation: 804
I have a page with a component that searches request data from a GET
endpoint when a click event happens:
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>
);
}
}
When I do the SearchForm
test of the submit method, even all my test pass successfully, my coverage shows me that handleSubmit
and handleChange
methods are not being tested at all:
My test tries to test these method this way:
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();
});
});
Any help to cover all these methods?
Thanks in advice
Upvotes: 0
Views: 812
Reputation: 102257
You can use .simulate(event[, ...args]) => Self to simulate submit
form event.
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
unit test:
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();
});
});
Unit test result with 100% coverage:
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
Coverage report for SearchForm.tsx
:
Here is the completed demo: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/52944804
Upvotes: 1