I have a small React/TypeScript/GraphQL app that connects to an API, fetches products, and displays them on the page.
I'm trying to create a test that checks if the product's name is in the document after a GraphQL mock, by using getByText, but I keep getting TestingLibraryElementError: Unable to find an element with the text: iPad 5g. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
I also tried using getByRole (see below), but that gives me the error TestingLibraryElementError: Unable to find an accessible element with the role "paragraph" and name '/month to month/i'
Is there a better way to do this? How can I check if the name of the product rendered correctly? I appreciate any help.
ProductCard.test.js
import React from "react";
import { render, screen } from "@testing-library/react";
import TestRenderer from 'react-test-renderer';
import { MockedProvider } from '@apollo/client/testing';
import ProductCard from "../ProductCard";
import { LOAD_PRODUCTS } from "../GraphQL/Queries";
import '@testing-library/jest-dom';
it('renders ProductCard successfully', async () => {
const productMock = {
request: {
query: LOAD_PRODUCTS,
},
result: {
data: { products: { productName: 'iPad 5g', code: 'i5g', price: 599.99 } },
},
};
const component = TestRenderer.create(
<MockedProvider mocks={[productMock]} addTypename={false}>
<ProductCard displayName={productMock.result.data.products.productName} price={productMock.result.data.products.price} />
</MockedProvider>,
);
await new Promise(resolve => setTimeout(resolve, 0));
expect(screen.getByText(`iPad 5g`)).toBeInTheDocument();
// expect(screen.getByRole('paragraph', { name: /iPad 5g/i })).toBeInTheDocument();
});
ProductCard.tsx
// imports
// ...
// ...
// TypeScript types
// ...
// ...
const ProductCard: React.FC<Props> = ({ productName, price }) => {
return (
<>
<Typography>{productName}</Typography>
<Typography>{price}</Typography>
<Typography><p>Great new features</p></Typography>
<Button>Buy Now</Button>
</>
);
}
Looks like you have no need for MockedProvider if you're just testing a "dumb" component (aka one that just renders some HTML and has no other logic). You only need MockedProvider if you're testing a component that uses useQuery or useMutation, in which case those hooks would return the mock.result value you provide. Try removing the MockedProvider altogether and just render the component with some props and see if that helps.