J. Hesters
J. Hesters

Reputation: 14768

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

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>

Upvotes: 5

Views: 19670

Answers (1)

Tom Jardine-McNamara
Tom Jardine-McNamara

Reputation: 2608

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

Upvotes: 3

Related Questions