Search code examples
reactjsjestjstesting-library

React jest snapshot only returning empty DocumentFragment


I am using React and writing a Modal component like so:

const MyModal: FC<MyModalProps> = memo((props) => {
    return (
        <Modal isOpen={true} data-client-id={modal-client-id}>
            ...
        </Modal>
    );
});

I am trying to test this using testing-library and jest like so:

    const { asFragment } = render(<MyModal {...myTestProps} />);
    const renderFragment = asFragment();
    expect(renderFragment).toMatchSnapshot();

However, when I check the snapshot I only see <DocumentFragment />. I can test whether the modal is there by a getByTestId(modal-client-id) and I can see that the modal is rendering and appearing when I run in Storybook with the exact same props. The snapshot also works and returns the inner components when I remove the surrounding Modal component. Is there a reason why Snapshot would only return the DocumentFragment and not the full snapshot? Would it just imply that within the unit test the component is not rendering?


Solution

  • Testing-Library render appends the passed in component to a parent div. This corresponds with the Container option of the render function. By default Testing-Library creates a div and appends to it. In the case of the modal, the modal is a separate pop up that was not being rendered as a child of the div, which explains why the fragment only rendered as:

    <DocumentFragment>
        <div />
    </DocumentFragment>
    

    To debug this, printing out the rendered screen gave the clue with: screen.debug(). This showed that the modal was being rendered outside of the container div, which is why other queries/gets were able to find components. Alternatively, we can also override the baseElement option, which defaults to document.body if not specified. In my case because any modal rendered would correctly be rendered on top of a component, I instead did:

    const result = render(<MyModal {...myTestProps} />);
    const modalComponent = screen.getByTestId('modal-client-id');
    expect(modalComponent).toMatchSnapshot();
    

    This avoids messing around with attempting to specify the container or baseElement options since anything rendered will be rendered on top.