Reputation: 195
Using Jest and Enzyme, how can I mock a Child component's callback function to return a specific value, and then test its effect elsewhere in the Parent component?
In the example below, when the Child
callback onSelectionChange
occurs, it changes the state, which enables the Button
which was previously disabled by passing that state value in props <Button disabled={disableButton} />
I want to mock the Child component to return false from onSelectionChange and test that the Button disabled prop has changed.
import React, { useState } from "react";
import Button from "./Button";
import Child from "./Child";
const Parent = () => {
const [disableButton, setDisableButton] = useState(true);
return (
<>
<Button disabled={disableButton} />
<Child onSelectionChange={(isDisabled) => setDisableButton(isDisabled)} />
</>
);
};
export default Parent;
Upvotes: 1
Views: 8883
Reputation: 102237
You don't need to mock any component. You can use .invoke(invokePropName)(...args) => Any API invokes a function prop. You don't even have to care about how to trigger the onSelectionChange
. Just invoke it with a correct argument, you need to make sure about this.
E.g.
Parent.tsx
:
import React, { useState } from 'react';
import Button from './Button';
import Child from './Child';
const Parent = () => {
const [disableButton, setDisableButton] = useState(true);
return (
<>
<Button disabled={disableButton} />
<Child onSelectionChange={(isDisabled) => setDisableButton(isDisabled)} />
</>
);
};
export default Parent;
Child.tsx
:
import React from 'react';
const Child = ({ onSelectionChange }) => {
return <div>Child</div>;
};
export default Child;
Button.tsx
:
import React from 'react';
const Button = (props) => {
return <button {...props}>click me</button>;
};
Parent.test.tsx
:
import { shallow } from 'enzyme';
import React from 'react';
import Button from './Button';
import Child from './Child';
import Parent from './parent';
describe('71713192', () => {
test('should pass', () => {
const wrapper = shallow(<Parent />);
expect(wrapper.find(Button).exists()).toBeTruthy();
expect(wrapper.find(Button).prop('disabled')).toBeTruthy();
wrapper.find(Child).invoke('onSelectionChange')(false);
expect(wrapper.find(Button).prop('disabled')).toBeFalsy();
});
});
Test result:
PASS stackoverflow/71713192/parent.test.tsx (9.794 s)
71713192
✓ should pass (26 ms)
------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
------------|---------|----------|---------|---------|-------------------
All files | 87.5 | 100 | 50 | 87.5 |
Button.tsx | 75 | 100 | 0 | 75 | 4
Child.tsx | 75 | 100 | 0 | 75 | 4
parent.tsx | 100 | 100 | 100 | 100 |
------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 10.596 s, estimated 12 s
package version:
"enzyme": "^3.11.0",
"react": "^16.14.0",
"jest": "^26.6.3"
Upvotes: 1