问题
I'm relatively new to Jest and testing in general. I have a component with an input element:
import * as React from "react";
export interface inputProps{
placeholder: string;
className: string;
value: string;
onSearch: (depID: string) => void;
}
onSearch(event: any){
event.preventDefault();
//the actual onclick event is in another Component
this.props.onSearch(event.target.value.trim());
}
export class InputBox extends React.Component<inputProps, searchState> {
render() {
return (
<input
onChange={this.onSearch} //need to test this
className={this.props.className}
type="text"
value={this.props.value}
placeholder={this.props.placeholder} />
);
}
}
I want a test that checks that input element's onChange
is a function that takes in the input element's value
attribute as the parameter. This is how far I have gotten so far:
//test to see the input element's onchange
//returns a function that takes its value as a param
it("onChange param is the same value as the input value", () => {
const mockFn = jest.fn();
const input = enzyme.shallow(<InputBox
value="TestVal"
placeholder=""
className=""
onSearch={mockFn}/>);
input.find('input').simulate('change', { preventDefault() {} });
expect(mockFn.mock.calls).toBe("TestVal");
});
I am going off of the first solution here Simulate a button click in Jest And: https://facebook.github.io/jest/docs/en/mock-functions.html
Edit: Running the above throws the following error:
TypeError: Cannot read property 'value' of undefined
回答1:
Syntax on your code snippet I think should be:
import React from 'react';
export default class InputBox extends React.Component {
onSearch(event) {
event.preventDefault();
this.props.onSearch(event.target.value.trim());
}
render () { return <input onChange={this.onSearch.bind(this)} />; }
}
The test is failing because, as same you define the preventDefault
function on the event object, you also must define other properties used on the onSearch
function.
it('should call onChange prop', () => {
const onSearchMock = jest.fn();
const event = {
preventDefault() {},
target: { value: 'the-value' }
};
const component = enzyme.shallow(<InputBox onSearch={onSearchMock} />);
component.find('input').simulate('change', event);
expect(onSearchMock).toBeCalledWith('the-value');
});
Previous test code needs to define the event shape because you are using shallow rendering. If you want instead to test that the actual input value is being used on your onSearch
function you need to try a full render with enzyme.mount
:
it('should call onChange prop with input value', () => {
const onSearchMock = jest.fn();
const component = enzyme.mount(<InputBox onSearch={onSearchMock} value="custom value" />);
component.find('input').simulate('change');
expect(onSearchMock).toBeCalledWith('custom value');
});
回答2:
I figured out the solution.
So, instead of passing in the value inside InputBox
, we have to pass it inside the second param of simulate
as shown below. Then we simply check for equality against the first arg of the first call to the mockFn
. Also, we can get rid of the event.preventDefault()
;
it("onChange param is the same value as the input element's value property", () => {
const mockFn = jest.fn();
const input = enzyme.shallow(<InputBox
value=""
placeholder=""
className=""
onSearch={mockFn}/>);
input.find('input').simulate('change', {target: {value: 'matched'} });
expect(mockFn.mock.calls[0][0]).toBe('matched');
});
来源:https://stackoverflow.com/questions/48180499/testing-onchange-function-in-jest