Test that React prop method has not been called with Jest - reactjs

How do I test a prop(callback) function that is called conditionally
I have a component which passes a prop function to its child on a condition like:
if(this.props.myFun) {
this.props.myFun();
}
to test this, I have two cases here:
1. Where the prop is passed to the component
<ChildComp myFun={value => value } /> and I can test it from the child-
const comp = mountWithIntl(<ChildComp myFun={value => value } />);
expect(comp.instance().props.myFun).toHaveBeenCalled();
Where the prop is not passed: I trying like
const comp = mountWithIntl(<MyComp />);
expect(comp.instance().props.myFun).not.toHaveBeenCalled();
But, Since If I mock the prop while mounting the component, the
method will be called. But how do I test the undefined or unmocked
prop?
If I dont pass the prop and do:
expect(comp.instance().props.myFun).not.toHaveBeenCalled();
I will get:
jest.fn() value must be a mock function or spy
which I cant do as per my code
please help

I don't think you can test that a not passed function does not get called. What you can do to test if it is get rendered without that function. That should be enough

Related

How do I mock the return value of a react hook passd as a prop when testing with jest

I'm trying to write a unit test for a Card compenent using Jest. This component takes a framer-motion value and a ref as Props. This values can only be created using the useMotionValue and useRef hook.
interface Props {
currentIndex: MotionValue<number>;
containerRef: RefObject<HTMLDivElement>;
}
Currently, I'm able to pass in a dummy value for the ref using document.createElement, but when i tried creating a motion value to pass into the component, I get an error saying that react hooks cannot be used ouside a component
it("renders a card", () => {
const container = document.createElement("div");
render(
<Card
containerRef={{ current: container }}
currentIndex={******} // motion value goes here
/>
);
});
I had to render the component in a parent component first and then test the parent Component but i was wondering, is there a way to mock the motion value and pass it in as a prop?
The easiest way would be to mock useMotionValue implementation. You can use jest.mock at the top of your file where you write your test for the component that uses this hook. Remember also to not mock other functionality by requiring actual implementation.
// at the top of the file that tests component with useMotionValue call
jest.mock('framer-motion', () => ({
...jest.requireActual('framer-motion'),
useMotionValue: jest.fn().mockReturnValue({
// put here the mock implementation of MotionValue methods
})
}));

How can I test if a blur event happen in onClick event handler?

I am trying to write a jest test for my inputBox component that include a button.
Have a function 'onClick' as a prop inside this component.
<inputBox
placeholder={'Type here..'}
onClick={() => {inputRef.current.blur()}}
button={true}
ref={inputRef}
/>
I want to test the event 'inputBox is blur once I click the button'.
Below is the test code:
it('invokes blur after click button',() => {
const onBlurSpy = jest.fn();
const { getAllByRole } = render(inputBox);
fireEvent.click(getAllByRole('button'))
expect(onBlurSpy).toHaveBeenCalled();
});
Receive below error:
expect(jest.fn()).toHaveBeenCalled()
Expected number of calls: >= 1
Received number of calls: 0
Any idea for this?
The onBlurSpy mock function isn't being called in the test because it isn't attached to the inputBox component. The blur function would likely need to be passed in as a prop to the component if you wanted to use jest.fn() to mock it.
If you want to check if the blur function has been called without adjusting the component's props, I'd recommend using Jest's spyOn method.
Give the function you want to spy on a name so it can be referenced:
<inputBox
...
onClick={this.blurFunction}
...
/>
Then use Jest's spyOn function in the test:
const onBlurSpy = jest.spyOn(inputBox.instance(), "blurFunction")
I'd also recommend reading this answer from a related StackOverflow question for some additional context.

How to mock a function in jest and enzyme

I want to make a test mocking a function in my react component, for example I have:
const app=()=>{
const [state,setState]=useState("");
const func=(item)=>{
setState(item)
}
return(
<div>{state}<div/>
)
}
and I want to test that function called "func" with jest and enzyme
for this example I have :
let wrapper=mount(<App/>)
test("testing",()=>{
let item="test"
//mock function -> func(item)
// how to mock that function
}
)
can someone help me with the syntax?
While you can spy on and mock results from method properties in class based components, you can't use the same approach for functional components.
What you should do is to trigger or simulate the particular behaviour that calls the func method in your functional components, and then test the expected behaviour (i.e if the props method is called, or changes in DOM elements, etc).
If it is triggered by the useEffect() hook, you will have to trigger that hook by updating the props (using setProps) that is used in the dependency array.

Testing onChange event with Jest

According to my code coverage, I need to test the function called in my onChange event. This is actually where I update my functional component's state using the useState hook.
Here is my component :
const Component:React.FC<{}> = () => {
const {value, setState} = useState('');
return(
<View>
<CustomComponent
onChange={(value) => setState(value)}
/>
</View>
)
}
The customComponent is a component derived from the React Input component.
When text is changed inside of it, it calls the onChange function passed as its prop with the text. This is how it comes up to the parent Component which sets the value of the text input in its state as displayed above.
My code coverage returns this analysis :
onChange={//(value) => setState(value)//}
Where the code between the // has to be covered. I don't really understand how I can cover this. First thought was use mock functions, but I can't seem to find how to mock it to the onChange event since I don't pass anything as prop to the main Component.
After a few tests, I finally understood that the coverage wasn't asking for the actual test of the onChange function but actually the value that is evaluated. Therefore, here is what I am doing:
Fetching the TextInput Child component
Changing its Text
Evaluating what it renders
I am using #testing-library/react-native here because it makes selecting tree components easier with the use of accessibilityLabel for example (It actually made me understand the importance of that prop).
Here is what a test looks like:
describe('Testing useState functions', () => {
test('test', () => {
//Rendering the component and its tree
const { container, getByLabelText } = render(<SignupView />);
//Extracting the child, username_input component with his accessibilityLabel
const username_input = getByLabelText('username_input');
const email_input = getByLabelText('email_input');
//Fire a native changeText event with a specific value
fireEvent.changeText(username_input, 'doe');
fireEvent.changeText(email_input, 'doe#joe.com');
//Checking the rendered value
expect(username_input.props.value).toEqual('doe');
expect(email_input.props.value).toEqual('doe#joe.com');
});
});

Jest - test method that passes to child component

I'm new in testing React component, so I'm trying test some method in parent component that passes to child component as props. I use Jest and Enzyme for this.
My test:
it('should be able to call myMethod callback', () => {
const mockFn = jest.fn();
ParentComponent.prototype.myMethod = mockFn;
const wrapper = Enzyme.shallow(<ParentComponent />);
wrapper.find('ChildComponent').props().myMethod();
expect(mockFn).toHaveBeenCalledTimes(1);
});
The test passed but myMethod didn't invoke (myMethod doesn't covered by tests).
When I use:
wrapper.instance().myMethod = mockFn;
instead of:
ParentComponent.prototype.myMethod = mockFn;
everything is the opposite - myMethod is invoked, but the test is failed with error:
expect(jest.fn()).toHaveBeenCalledTimes(1)
Expected mock function to have been called one time, but it was called zero times.
How can I solve this? Thanks in advance.
You are assigning myMethod to a mock function which doesn't do anything, not even your original myMethod. When you are creating jest.fn(), what it basically does is creating a dummy mock function which doesn't do anything. So when you call wrapper.find('ChildComponent').props().myMethod(), it just call that function but not your myMethod.
What you might want to do is to spy on your method instead.
jest.spyOn(ParentComponent.prototype, 'myMethod'); // ParentComponent.prototype.myMethod is now a mock function
expect(ParentComponent.prototype.myMethod).toHaveBeenCalledTimes(1); // it works

Resources