React-testing-library: having ref in react component causes renderIntoDocument DOM to become empty

Created on 25 May 2018  路  5Comments  路  Source: testing-library/react-testing-library

  • react-testing-library version: 3.1.0
  • react version: 16.3.2
  • node version: 8.9.1
  • npm (or yarn) version: 5.5.1

Relevant code or config:

describe("WebhookSender Fetch", () => {

    beforeEach(() => {
        Rendered = renderIntoDocument(componentMarkup);
    });

    afterEach(() => {
        cleanup();
        fetch.resetMocks();
    });

    it("should show render results", async (done) => {

        fetch.mockReject(fetchRejectMsg);
        const sendBtnNode = Rendered.getByText('Send');
        fireEvent(sendBtnNode, new MouseEvent('click', {
            bubbles: true, 
            cancelable: true,
          }));

        await wait(() => Rendered.getByText(fetchRejectMsg));
        expect(Rendered.getByText(fetchRejectMsg, {exact: false})).toBeInTheDOM();
        done();
    });

});

What you did:

The test is successful if I comment out the following div with ref, in my react component being tested:

<div ref={(bottom) => { this.fetchBottom = bottom; }}>
    <p>&nbsp;</p>
</div>

What happened:


When the div with ref is there, the test fails and the console shows

console.error node_modules/react-dom/cjs/react-dom.development.js:9643
  The above error occurred in the <WebhookSender> component:
      in WebhookSender (at WebhookSender.spec.js:18)
      in MuiThemeProvider (at WebhookSender.spec.js:17)

  Consider adding an error boundary to your tree to customize error handling behavior.
  Visit https://fb.me/react-error-boundaries to learn more about error boundaries.
console.error node_modules/fbjs/lib/warning.js:33
  Warning: Can't call setState (or forceUpdate) on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
      in WebhookSender (at WebhookSender.spec.js:18)
      in MuiThemeProvider (at WebhookSender.spec.js:17)

Reproduction:

Problem description:

I find that if I have the ref in my react component, after the button click, the DOM (look at PrettyDOM(Rendered.container)) becomes just an empty div , thus failing the subsequent getByText.

Is there known issue with having ref for such tests?

Suggested solution:

needs investigation

Most helpful comment

Yes, we should probably have an example of how to test for this, even though it's not specific to react-testing-library. Most people are using Jest + jsdom so they'll probably run into this issue.

Here's a working "solution"

beforeAll(() => {
  if (!HTMLElement.prototype.scrollIntoView) {
    HTMLElement.prototype.scrollIntoView = () => {}
  }
})

All 5 comments

Could you please create a reproduction of this in codesandbox? That will help a lot I think. Fork this one: http://kcd.im/rtl-example

I am not able to reproduce it in codesandbox, however, when running the code downloaded from codesandbox it reproduces. So it may be an issue with my environment. I wonder how codesandbox runs the test (is it in the browser?). In my local env it's run using jest with env=jsdom so maybe that's the issue?

If you share the sandbox you used I'll verify that. Maybe there really is a problem.

Thanks for your patience. I finally figured it out. The problem was that scrollIntoView is not in jsdom (https://github.com/jsdom/jsdom/issues/1695). I was expecting it to be there as a no-op.

The reproducer is here - https://codesandbox.io/s/8853vq24xl

Test passes on codesandbox. Download to local and run 'npm i' followed by 'npm test' will show failure.

So it seems I should explore setting up a browser test env instead of jsdom, vs mocking the functions not in jsdom. Do you recommend running rtl with some other test runners (like cypress, karma)? jest+rtl works very well for me so far but I would need such tests working.

Yes, we should probably have an example of how to test for this, even though it's not specific to react-testing-library. Most people are using Jest + jsdom so they'll probably run into this issue.

Here's a working "solution"

beforeAll(() => {
  if (!HTMLElement.prototype.scrollIntoView) {
    HTMLElement.prototype.scrollIntoView = () => {}
  }
})
Was this page helpful?
0 / 5 - 0 ratings