Input.tsx :
import React from "react";
export type InputProps = {
name: string;
label: string;
value: any;
onChange: React.FormEventHandler<HTMLInputElement>;
};
export const Input = ({ name, label, value, onChange }: InputProps) => {
return (
<div>
<label htmlFor={name}>{label}</label>
<input value={value} name={name} type="text" onChange={onChange} />
</div>
);
};
Input.test.tsx :
import React from "react";
import { mount } from "enzyme";
import { act } from "react-dom/test-utils";
import { Input, InputProps } from "./Input";
describe("Input tests", () => {
test("renders without crashing", () => {
const handleChange = jest.fn();
const props: InputProps = {
name: "login",
label: "Your Login:",
value: "",
onChange: handleChange,
};
const wrapper = mount(<Input {...props} />);
const mockEvent = {
target: {
value: "Administrator",
name: "login",
},
} as React.ChangeEvent<HTMLInputElement>;
act(() => {
wrapper.find("input").simulate("change", mockEvent);
});
expect(handleChange).toHaveBeenCalledTimes(1);
expect(handleChange).toHaveBeenCalledWith(mockEvent); // fails here
});
});
The last line with .toHaveBeenCalledWith(mockEvent)
fails with the following message:
expect(jest.fn()).toHaveBeenCalledWith(...expected)
- Expected
+ Received
+ SyntheticBaseEvent {
+ "_dispatchInstances": null,
+ "_dispatchListeners": null,
+ "_reactName": "onChange",
+ "_targetInst": FiberNode {
+ "_debugHookTypes": null,
I have tried:
onChange={onChange}
to onChange={e => onChange(e)}
target: {...
to currentTarget: {...
But nothing helped. At this point I'm not sure if its because my input is a functional component, or if there is a problem with the versions ? Any help would be highly appreciated!
P.S. The purpose of the test is to learn the syntax rather than achieving meaningful coverage.
simulate
merges your mock-event object with a SyntheticEvent
object coming from ReactWrapper
(see the documentation of simulate
), so testing for equality will fail. Instead you can do something like this:
expect(handleChange).toHaveBeenCalledWith(expect.objectContaining(mockEvent));
This does not work for currentTarget
though, as the SyntheticEvent
already has a property currentTarget: null
, so it will also be null
in the merged result. For target
it does work. Here's a sandbox that passes the tests.
It's probably better to just test the handler functions directly and stay away from simulate
though, as it's a bit hacky and doesn't really simulate the events. It even seems to be deprecated: https://github.com/enzymejs/enzyme/issues/2173