React Testing Library: Test if children are passed / rendered correctly

15,908

The problem is that you're rendering once, in the describe block. This probably doesn't work how you think. Code in describe blocks that isn't inside a test (or other jest function like beforeEach) gets run ahead of time by Jest. In general you never want any code inside a describe block but outside a test (or other jest function).

You could either render the component in a beforeEach or have a render helper function you call in each test.

I forked your sandbox here with the above approach and both tests now pass: https://codesandbox.io/s/v3wk1vlx3l

Share:
15,908
J. Hesters
Author by

J. Hesters

Ask better questions.

Updated on July 01, 2022

Comments

  • J. Hesters
    J. Hesters almost 2 years

    I'm writing a React app using TypeScript. I use material-ui for my components and react-testing-library for my unit tests.

    I'm writing a wrapper for material-ui's Grid component so that I always have a container.

    import Grid from "@material-ui/core/Grid";
    import withStyles, { WithStyles } from "@material-ui/core/styles/withStyles";
    import React, { PureComponent } from "react";
    import styles from "./styles";
    
    export interface OwnProps {
      className?: string;
    }
    
    export interface Props extends WithStyles<typeof styles>, OwnProps {}
    
    export interface DefaultProps {
      className: string;
    }
    
    export class GridContainer extends PureComponent<Props & DefaultProps> {
      static defaultProps: DefaultProps = {
        className: ""
      };
    
      render() {
        const { classes, children, className, ...rest } = this.props;
        return (
          <Grid
            data-testid="grid-container"
            container={true}
            {...rest}
            className={classes.grid + " " + className}
          >
            {children}
          </Grid>
        );
      }
    }
    
    export default withStyles(styles)(GridContainer);
    

    I want to write a test that checks if it's children are rendered correctly. Here is what I wrote:

    import "jest-dom/extend-expect";
    import React from "react";
    import { cleanup, render } from "react-testing-library";
    import GridContainer, { OwnProps } from "./GridContainer";
    afterEach(cleanup);
    
    const createTestProps = (props?: object): OwnProps => ({
      ...props
    });
    
    describe("GridContainer", () => {
      const props = createTestProps();
      const { getByTestId } = render(
        <GridContainer {...props}>
          <div data-testid="child" />
        </GridContainer>
      );
      const container = getByTestId("grid-container");
      describe("rendering", () => {
        test("it renders it's children", () => {
          expect(container.children.length).toBe(1);
          expect(getByTestId("child")).toBeDefined();
        });
      });
    });
    

    The problem is the test's first part where I check for the length of the children passes. But the expect(getByTestId("child")).toBeDefined(); fails with:

    ● GridContainer › rendering › it renders it's children
    
        Unable to find an element by: [data-testid="child"]
    
        <body />
    
          24 |     test("it renders it's children", () => {
          25 |       expect(container.children.length).toBe(1);
        > 26 |       expect(getByTestId("child")).toBeDefined();
             |              ^
          27 |     });
          28 |   });
          29 | });
    
          at getElementError (node_modules/dom-testing-library/dist/query-helpers.js:30:10)
          at getAllByTestId (node_modules/dom-testing-library/dist/queries.js:231:45)
          at firstResultOrNull (node_modules/dom-testing-library/dist/query-helpers.js:38:30)
          at getByTestId (node_modules/dom-testing-library/dist/queries.js:241:42)
          at Object.getByTestId (src/components/Grid/GridContainer/GridContainer.test.tsx:26:14)
    

    Is it not possible to give a data-testid to an element in the render function? How could I test that the children get rendered correctly?

    EDIT Here is the output from debug:

    ● Console
    
        console.log node_modules/react-testing-library/dist/index.js:57
          <body>
            <div>
              <div
                class="MuiGrid-container-2 GridContainer-grid-1 "
                data-testid="grid-container"
              >
                <div
                  data-testid="child"
                />
              </div>
            </div>
          </body>