Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test if a component is rendered with the right props when using react-testing-library?

I have some components that are rendering another component (FetchNextPageButton) that is already tested in isolation, like these ones:

const News = () => (   <div>     <h1>News</h1>     ...     <FetchNextPageButton query={NEWS_QUERY} path="viewer.news" />   </div> )  const Jobs = () => (   <div>     <h1>Jobs</h1>     ...     <FetchNextPageButton query={JOBS_QUERY} path="viewer.jobs" />   </div> )  const Posts = () => (   <div>     <h1>Posts</h1>     ...     <FetchNextPageButton query={POSTS_QUERY} path="viewer.posts" />   </div> ) 

The thing is that I'd not like having to add tests on each of these components for a functionality that is already tested somewhere else, so I think that should be enough just to test that the component is rendered and that I'm passing the right props to it.

I'd have been able to test this easily with Enzyme with something like this:

expect(wrapper.find('FetchNextPageButton').props()).toMatchObject({   query: NEWS_QUERY,   path: "viewer.news" }) 

So I'm wondering what's the best approach to test it by using React testing library instead.

like image 839
Emi Avatar asked Oct 30 '19 10:10

Emi


People also ask

How do you check if react component is rendered?

Using React DevTools to highlight what components rerendered To enable it, go to "Profiler" >> click the "Cog wheel" on the right side of the top bar >> "General" tab >> Check the "Highlight updates when components render." checkbox.

How do you test a specific component in react?

There are a few ways to test React components. Broadly, they divide into two categories: Rendering component trees in a simplified test environment and asserting on their output. Running a complete app in a realistic browser environment (also known as “end-to-end” tests).

Where does react testing library render components?

By default, React Testing Library will create a div and append that div to the document. body and this is where your React component will be rendered.


2 Answers

This is the approach that Kent C. Dodds (the creator of RTL) shared with me after discussing it with him:

import FetchNextPageButton from 'FetchNextPageButton'  jest.mock('FetchNextPageButton', () => {   return jest.fn(() => null) })  // ... in your test expect(FetchNextPageButton).toHaveBeenCalledWith(props, context) 
like image 68
Emi Avatar answered Sep 22 '22 23:09

Emi


Don't believe it's possible. RTL looks like focusing on validating against DOM not React's components tree.

The only workaround I see is to mock FetchNextPageButton to make it rendering all props into attributes.

jest.mock("../../../FetchNextPageButton.js", () =>    (props) => <div data-test-id="FetchNextPageButton" {...props} />); .... const { getByTestId } = render(<YourComponent />); expect(getByTestId("FetchNextPageButton")).toHaveAttribute("query", NEWS_QUERY); expect(getByTestId("FetchNextPageButton")).toHaveAttribute("path", "viewer.news"); 

Sure, this is smoothly only for primitive values in props, but validating something like object or function would be harder.

Think, it's not RTL-way, but I agree it would be massive work to check that in scope of each container(and completely ignoring that would be rather a risk).

PS toHaveAttribute is from jest-dom

like image 30
skyboyer Avatar answered Sep 23 '22 23:09

skyboyer