Attempting to teach myself testing for React with react-testing library and jest as this is what my work uses. For the life of me I can not figure out why the mock function testClick is not being called. I have researched articles and watched videos however most seem outdated as it appears the testing world changes how code should be written super fast. Anyone have thoughts? Here's the code :
Products.js component :
import React, { useState } from 'react';
import { fetchProducts } from '../service';
const Products = () => {
const [product, setProduct] = useState('');
const handleSubmit = (event) => {
event.preventDefault();
fetchProducts();
};
const hasBeenClicked = () => {
console.log('clicked!');
};
return (
<form onSubmit={handleSubmit}>
<label>
<input
type="text"
value={product}
onChange={(e) => setProduct(e.target.value)}
/>
</label>
<input
type="submit"
onClick={hasBeenClicked}
data-testid="button"
label="Search"
/>
</form>
);
};
export default Products;
Products.test.js :
import React from 'react';
import { render, screen, cleanup, fireEvent } from '@testing-library/react';
import Products from './Products';
test('Button click triggers click event', () => {
const testClick = jest.fn();
const { getByTestId } = render(<Products click={testClick} />);
const button = getByTestId('button');
fireEvent.click(button);
expect(testClick).toBeCalled();
});
Results in :
PASS src/App.test.js
FAIL src/components/Products.test.js
● Console
console.log
clicked!
at apply (src/components/Products.js:13:13)
● Button clicks triggers click event
expect(jest.fn()).toBeCalled()
Expected number of calls: >= 1
Received number of calls: 0
11 | fireEvent.click(button);
12 |
> 13 | expect(testClick).toBeCalled();
| ^
14 | });
15 |
at Object.<anonymous> (src/components/Products.test.js:13:21)
Test Suites: 1 failed, 1 passed, 2 total
Tests: 1 failed, 1 passed, 2 total
Snapshots: 0 total
Time: 3.18 s, estimated 4 s
CodePudding user response:
You are passing your mocked function to Products
via a click
prop which it doesn't receive in the first place. This mocked click function is not wired in any way to the button you're clicking on your test.
To pass this test:
Products.js:
import React, { useState } from "react";
import { fetchProducts } from '../service';
const Products = ({ click }) => {
const [product, setProduct] = useState("");
const handleSubmit = (event) => {
event.preventDefault();
fetchProducts()
};
return (
<form onSubmit={handleSubmit}>
<label>
<input
type="text"
value={product}
onChange={(e) => setProduct(e.target.value)}
/>
</label>
<input
type="submit"
onClick={click}
data-testid="button"
label="Search"
/>
</form>
);
};
export default Products;
Products.test.js:
import React from "react";
import { render, screen, fireEvent } from "@testing-library/react";
import Products from "./Products";
test("Button click triggers click event", () => {
const testClick = jest.fn();
render(<Products click={testClick} />);
const button = screen.getByTestId("button");
fireEvent.click(button);
expect(testClick).toBeCalled();
});