'how to test button that call submit form using jest and react testing library
so I am trying to test that the onSubmit function is getting triggered if the button is clicked - the way im doing this is through testing the internals of the onSubmit function is getting calles (axios post method)
the test
describe('RecipeSearch', () => {
test('submit button should return post function to recipes/search/', () => {
let mock = new MockAdapter(axios);
userEvent.selectOptions(screen.getByRole('combobox'), 'Sweet');
userEvent.click(screen.getByText('Search'));
const config = {
headers: {
'Content-Type': 'application/json',
},
};
const searchRecipes = mock.onPost(
`${process.env.REACT_APP_API_URL}/recipes/search/`,
{ flavor_type: 'Sweet' },
{ config }
);
expect(searchRecipes).toHaveBeenCalled();
});
});
the Error
expect(received).toHaveBeenCalled()
Matcher error: received value must be a mock or spy function
Received has type: object
Received has value: {"abortRequest": [Function abortRequest], "abortRequestOnce": [Function abortRequestOnce], "networkError": [Function networkError], "networkErrorOnce": [Function networkErrorOnce], "passThrough": [Function passThrough], "reply": [Function reply], "replyOnce": [Function replyOnce], "timeout": [Function timeout], "timeoutOnce": [Function timeoutOnce]}
the function
const recipeSearch = (props) => {
const [formData, setFormData] = useState({
flavor_type: 'Sour',
});
const { flavor_type } = formData;
const [loading, setLoading] = useState(false);
const onChange = (e) => setFormData({ ...formData, [e.target.name]: e.target.value });
const onSubmit = (e) => {
e.preventDefault();
const config = {
headers: {
'Content-Type': 'application/json',
},
};
setLoading(true);
axios
.post(
`${process.env.REACT_APP_API_URL}/recipes/search/`,
{
flavor_type,
},
config
)
.then((res) => {
setLoading(false);
props.setRecipes(res.data);
window.scrollTo(0, 0);
})
.catch((err) => {
setLoading(false);
window.scrollTo(0, 0);
});
};
return (
<form onSubmit={(e) => onSubmit(e)}>
<div>
<div>
<div>
<label htmlFor='flavor_type'>Choose Flavor</label>
<select
name='flavor_type'
onChange={(e) => onChange(e)}
value={flavor_type}
>
<option value='Sour'>Sour</option>
<option>Sweet</option>
<option>Salty</option>
</select>
</div>
<div>
<button type='submit'>Search</button>
</div>
</div>
</div>
</form>
);
};
i have added the whole test and the component code so helping would be easier. thanks in advance
(added the onChange + onSubmit functions)
Solution 1:[1]
Creating an onSubmit
mock and passing it as a prop won't work since the onSubmit
callback is internal to the component and not a prop - you don't have access to it from the test.
Rather than testing if the onSubmit
has been called, you should test the result of triggering the submit event. Which in this case could mean verifying that the axios
request is made.
See How do I test axios in Jest? for examples on how to mock axios
in your test.
Solution 2:[2]
Did you try selecting the button by text :
describe('RecipeSearch', () => {
test('test clicking the button triggers the onSubmit function', () => {
const onSubmit = jest.fn();
render(<RecipeSearch onSubmit={onSubmit} />);
userEvent.selectOptions(screen.getByRole('combobox'), 'Sour');
userEvent.click(screen.getByText('Search'));
expect(onSubmit).toHaveBeenCalled();
});
});
I'm not sure how getByRole handles a second argument in your first try, but getByText should work.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Florian Motteau |