javascript - Jest: `querySelector` returns null in test of a ReactJS component - Stack Overflow

I'm testing a connected functional ponent in ReactJS using jest and the react-testing-library.The

I'm testing a connected functional ponent in ReactJS using jest and the react-testing-library.

The ponent renders some input fields and a button. Here's a simplified version of it, in which I decided to leave the full structure of GridContainer and GridItem ponents (from Material-UI) as they might play a role in this issue:

export function Letter(props) {
  const [letter, setLetter] = useState({
    // not relevant
  });

  return (
    <GridContainer>
      <GridItem md={6} sm={6}>
        <GridContainer>
          <GridItem>
            <LetterImageUpload />
          </GridItem>
          <GridItem>
            <LetterText />
          </GridItem>
        </GridContainer>
      </GridItem>
      <GridItem md={6} sm={6}>
        <LetterAddress />
        <GridContainer>
          <Button
            data-testid="AddToStoreButton"
            onClick={() => {
              props.addToStore(letter);
            }}
          >
            Add to Store
          </Button>
        </GridContainer>
      </GridItem>
    </GridContainer>
  );
}

function mapDispatchToProps(dispatch) {
  return {
    addToStore: letter => {
      dispatch({ type: "ADD_TO_STORE", payload: letter });
    }
  };
}

export default connect(
  null,
  mapDispatchToProps
)(Letter);

As you can see I export both the dumb ponent and the connected ponent (the latter via export default), so that I can just import { Letter } in my tests and not bother about the redux store (is this the right way?).

The acpanying test goes like this:

import { Letter } from "ponents/Letter/Letter.js";

let container = null;
beforeEach(() => {
  container = document.createElement("div");
  document.body.appendChild(container);
});

afterEach(() => {
  unmountComponentAtNode(container);
  container.remove();
  container = null;
});

test("Letter", () => {
  act(() => {
    render(<Letter addToStore={jest.fn()} />, container);
  });
  // FIXME: querySelector returns null
  container.querySelector('[data-testid="AddToStoreButton"]').simulate("click");
  // assert
});

In a debugger I can see that querySelector returns null regardless of the selector I used. For instance, I tried the following in the live debugger:

> container.querySelector('[data-testid="AddToCartButton"]')
null
> container.querySelector("button")
null
> container.querySelector("div")
null

I'm clearly doing something spectacularly wrong. Can anyone spot it?

I'm testing a connected functional ponent in ReactJS using jest and the react-testing-library.

The ponent renders some input fields and a button. Here's a simplified version of it, in which I decided to leave the full structure of GridContainer and GridItem ponents (from Material-UI) as they might play a role in this issue:

export function Letter(props) {
  const [letter, setLetter] = useState({
    // not relevant
  });

  return (
    <GridContainer>
      <GridItem md={6} sm={6}>
        <GridContainer>
          <GridItem>
            <LetterImageUpload />
          </GridItem>
          <GridItem>
            <LetterText />
          </GridItem>
        </GridContainer>
      </GridItem>
      <GridItem md={6} sm={6}>
        <LetterAddress />
        <GridContainer>
          <Button
            data-testid="AddToStoreButton"
            onClick={() => {
              props.addToStore(letter);
            }}
          >
            Add to Store
          </Button>
        </GridContainer>
      </GridItem>
    </GridContainer>
  );
}

function mapDispatchToProps(dispatch) {
  return {
    addToStore: letter => {
      dispatch({ type: "ADD_TO_STORE", payload: letter });
    }
  };
}

export default connect(
  null,
  mapDispatchToProps
)(Letter);

As you can see I export both the dumb ponent and the connected ponent (the latter via export default), so that I can just import { Letter } in my tests and not bother about the redux store (is this the right way?).

The acpanying test goes like this:

import { Letter } from "ponents/Letter/Letter.js";

let container = null;
beforeEach(() => {
  container = document.createElement("div");
  document.body.appendChild(container);
});

afterEach(() => {
  unmountComponentAtNode(container);
  container.remove();
  container = null;
});

test("Letter", () => {
  act(() => {
    render(<Letter addToStore={jest.fn()} />, container);
  });
  // FIXME: querySelector returns null
  container.querySelector('[data-testid="AddToStoreButton"]').simulate("click");
  // assert
});

In a debugger I can see that querySelector returns null regardless of the selector I used. For instance, I tried the following in the live debugger:

> container.querySelector('[data-testid="AddToCartButton"]')
null
> container.querySelector("button")
null
> container.querySelector("div")
null

I'm clearly doing something spectacularly wrong. Can anyone spot it?

Share Improve this question edited Jul 5, 2020 at 17:51 skyboyer 23.8k7 gold badges62 silver badges71 bronze badges asked Jul 4, 2020 at 6:27 JirJir 3,1558 gold badges47 silver badges70 bronze badges 2
  • The docs I just scanned don't use a container like you did, instead an imported screen object. The render() method also returns an object with a container property that can be used for testing the ponent. – Anthony Commented Jul 4, 2020 at 12:45
  • Interesting. I was following the testing recipes from ReactJS, but I realise now that the render ponent there es from "react-dom" rather than the react testing library. I'll try and follow your hint. – Jir Commented Jul 4, 2020 at 14:14
Add a ment  | 

1 Answer 1

Reset to default 1

Following the tip by Anthony, it turned out I was using render from the react testing library, but actually using as it were the one exported by the "react-dom" library.

The plete solution, using the react testing library looks like this:

import { fireEvent, render } from "@testing-library/react";

test("Letter", () => {
  const { getByTestId } = render(<Letter addToStore={() => {}} />);
  fireEvent.click(getByTestId("AddToStoreButton"));
  // assert
});

Just to add a bit of more context, if you follow the approach shown in the Testing Recipes on ReactJS, you'll need to import { render } from "react-dom", instead.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745625364a4636771.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信