0

You can reproduce the problem in the following codesandbox:

Edit Continuous Meme Delivery

As an example I've made a component which uses the following code to get a random image each time the form button is clicked:

import { Button } from "antd";
...
class ContinuousMemeDeliveryApi extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

  static defaultProps = { getImage };
  state = { image: images[0], random: 0 };

  handleClick = async e => {
    e.preventDefault();
    const { data } = await this.props.getImage();
    this.setState({ image: data.image, random: data.random });
  };
  ...
  render() {
    return (
      <form onSubmit={this.handleClick}>
        <Button htmlType="submit">Click Me</Button>
        ...
      </form>
    );
  }

This works as expected, and I've made the following code to test the implementation:

test("loads random memes on click", async () => {
  const mockGetImage = jest.fn(() =>
    Promise.resolve({ data: { image: "testImage.jpg" } })
  );
  const { getByText } = render(
    <ContinuousMemeDeliveryApi getImage={mockGetImage} />
  );

  const clickMeButton = getByText(/click/i);

  fireEvent.click(clickMeButton);
  // @TODO: fix assertion
  expect(mockGetImage).toHaveBeenCalledTimes(1);
});

However the test fails with the following error message:

expect(jest.fn()).toHaveBeenCalledTimes(1)

Expected mock function to have been called one time, but it was called zero times.

Any ideas on why this is failing?

1 Answer 1

1

Since you have 2 react roots rendering within the same document (your application and tests) you can't use default document.body as base element for react testing library.

With current approach your queries actually find elements within your application not within the rendered test because they are bound to baseElement = document.body and your div#container comes first. That is why mock is not being called at all.

Working Example

You could add additional container to isolate test DOM tree

// index.html
<div id="test-container"></div>

Now you could specify container when rendering a test

import { render as rtlRender, fireEvent, wait } from "react-testing-library";

// get the container
const container = document.getElementById('test-container')

// override render to provide custom container
const render = (ui, options = {}) => rtlRender(ui, { container, ...options })
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.