Hi All, I'm following the following tutorial and having trouble implementing as I'm getting a warning when I run my tests.
https://egghead.io/courses/test-react-components-with-enzyme-and-jest
I have the following component which contains a function called onBlurItem
export class AdvancedItemSelection extends React.Component<ComponentProps> {
constructor(props) {
super(props);
}
onBlurItem(value, excluded = false) {
if (!value.length) return;
// call action here
}
render() {
const { classes } = this.props;
return (
<>
<Grid item lg={4}>
<Card elevation={2}>
<CardHeader className={classes.cardHeader} title={<Typography variant="title" >Include</Typography>} />
<CardContent>
<Grid item lg={12}>
<TextField
fullWidth
id="include-input"
label="Include by Value"
placeholder="Include"
className={classes.textField}
margin="normal"
onBlur={e => e && this.onBlurItem(e.target.value)}
/>
</Grid>
</CardContent>
</Card>
</Grid>
</>
);
}
}
I also have a test to simulate the onBlur event of the text field and whether that triggers my member function.
it("calls onBlur function when textField is blurred", () => {
const tree = shallow(<AdvancedItemSelection />);
const input = tree.find("#include-input");
input.simulate("change", {currentTarget: {value: "val123"}});
input.simulate("blur");
expect(tree.instance().onBlurItem).toBeCalledWith("val123", false);
});
when I execute the tests my output is:
jest.fn() value must be a mock function or spy.
Received:
function: [Function onBlurItem]
my current version of react and enzyme are:
react: "16.2.0"
enzyme: "3.3.0"
Any help with this would be greatly appreciated.
@sean-killeen .toBeCalledWith() has to be called with jest's mock fn
https://facebook.github.io/jest/docs/en/expect.html#tohavebeencalledwitharg1-arg2-
Hi @sean-killeen
tree.instance().onBlurItem is an original function of AdvancedItemSelection class which is
onBlurItem(value, excluded = false) {
if (!value.length) return;
// call action here
}
and you can not expect toBeCalledWith function as it available with mocked functions only.
In order to test that it was called you need to mock it first. In order to do it you can use spyOn. And your test suite may look like
it("calls onBlur function when textField is blurred ", () => {
// spy before creating an instance of a class
const spy = jest.spyOn(AdvancedItemSelection.prototype, "onBlurItem");
// preconditions
// simlute method call
// assertion
// it's important to restore an orginal method as next test suite will use mocked version.
spy.mockRestore();
});
Also, I noticed that you simulate change with currentTarget and in your code you use target. So if your input implementation uses target simulate with currentTarget would not help you.
I hope it helps you.
Thanks @mykhailo-riabokon , @twclark0 this was very useful. My final test looks like this.
it("calls onBlur function when textField is blurred", () => {
const props: ComponentProps = {
// omitted
};
const wrapper = shallow(<AdvancedItemSelection {...props} />) as any;
const spy = jest.spyOn(wrapper.instance(), "onBlurItem");
wrapper.instance().forceUpdate();
wrapper.find("#include-input").simulate("blur", { currentTarget: { value: "foo"}}, spy);
expect(spy).toBeCalledWith("foo");
});
This is working as expected
馃憤
Hi @sean-killeen
tree.instance().onBlurItemis an original function of AdvancedItemSelection class which isonBlurItem(value, excluded = false) { if (!value.length) return; // call action here }and you can not expect
toBeCalledWithfunction as it available with mocked functions only.In order to test that it was called you need to mock it first. In order to do it you can use spyOn. And your test suite may look like
it("calls onBlur function when textField is blurred ", () => { // spy before creating an instance of a class const spy = jest.spyOn(AdvancedItemSelection.prototype, "onBlurItem"); // preconditions // simlute method call // assertion // it's important to restore an orginal method as next test suite will use mocked version. spy.mockRestore(); });Also, I noticed that you simulate change with
currentTargetand in your code you usetarget. So if your input implementation usestargetsimulate withcurrentTargetwould not help you.I hope it helps you.
@mykhailo-riabokon what if i have a functional component.. hooks i.e. ?
React provides no hooks into hooks, so there's no advanced testing tools available for them.
Please file a new issue if you have new questions.
Most helpful comment
Thanks @mykhailo-riabokon , @twclark0 this was very useful. My final test looks like this.
This is working as expected
馃憤