Search code examples
reactjsreact-testing-library

React Testing Library toBeInTheDocument failing despite being in the DOM


I have a test which basically contains the following code:

    const row = await screen.findByText('Test Subject');

    try {
      expect(row).toBeInTheDocument();
    } catch (e) {
      screen.debug();
      throw e;
    }

The debug is for trying to track this down. findByText succeeds, and does find the element. I can log this out, and it appears. But when I do the expect, it fails SOMETIMES. It's unpredictable. I'm pretty certain the DOM isn't changing between calls, as I have logs out on every render and nothing logs out between the find and the assert.

I won't print the whole DOM tree, but on the catch debug, I can clearly see the row.

<tr
                  class="sc-jgrIVw bDPrDC"
                >
                  <td
                    class="sc-jeqYYF hinrdE"
                  >
                    <div
                      class="sc-clIAKW jvtlES"
                    >
                      05-Dec-2022 12:08
                    </div>
                  </td>
                  <td
                    class="sc-jeqYYF ijUrhn"
                  >
                    <div
                      class="sc-clIAKW jvtlES"
                    >
                      <div
                        title="Test"
                      >
                        Test 
                      </div>
                    </div>
                  </td>
                  <td
                    class="sc-jeqYYF ijUrhn"
                  >
                    <div
                      class="sc-clIAKW jvtlES"
                    >
                      Test Subject
                    </div>
                  </td>
                </tr>

So as far as I can tell, RTL knows my DOM is there, the DOM log shows its there, but toBeInTheDocument throws. What could I be missing?


Solution

  • Seeing this get views, and I did solve this.. technically.

    The reason I was getting this was rerendering. I would find an element in my DOM, the DOM would rerender, and by the time my assertion ran, the rerender would have detached the node I just found. So it wasn't in my document, and the assertion failed.

    To fix this, I had to patch all the reasons the component was rerendering, and specifically wait for it to finish.

    For those who have issues with react 18 upgrade, react 18 changes how components are rendered/rerendered with the ability to drop renders halfway through, which may be why you're getting this issue now. It's a real pain, but my solution was to simply ensure my component had finished with all its rerenders/loading of data/updates.