'Test correct SVG component renders with jest and react-testing-library

I have an svg inside a React component that renders conditionally.

<div className='avatar'>
      {gender === true ? <MaleAvatar /> : <FemaleAvatar />}
    </div>

MaleAvatar and FemaleAvatar are components containing svgs. Initially, I want the MaleAvatar svg to render and then if the value of gender is changed to false the FemaleAvatar svg renders - but the male avatar should render first and that's what I want to test.

The component the conditional is in is a child of a child, but I am testing elements in that component by text and the test works fine eg:

const personDetailsText = screen.getByText('Personal details')

I am testing with jest and react-testing-library, but using a testing id on the parent div then grabbing the first child doesn't work because it can't recognise the testing id. So if I have:

<div data-testid='avatar' className='avatar'>
          {gender === true ? <MaleAvatar /> : <FemaleAvatar />}
        </div>

...then the test below fails at 'const avatarSVG = screen.getByTestId('avatar')':

test('gender avatar is male on initialisation', () => {
    const avatarSVG = screen.getByTestId('avatar')
    expect(avatarSVG).toBeInTheDocument()
    expect(() => screen.getByTestId('female-avatar').toThrow())
    expect(avatar.firstChild.nodeName).toBe('MaleAvatar')
  })

I'm using React hooks and I've read I also need to somehow compensate for React rendering the SVGs after the initial render - after useEffect is finished, but I can't find how to do this with react-testing-library and hooks?

This also does not work:

const avatarSVG = document.querySelector('MaleAvatar')

How can I grab the SVG components to check the correct one renders?



Solution 1:[1]

You can view the content of any elements with screen.debug(), in your case svg element and according to this content you can use a selector:

import { render, screen } from "@testing-library/react";
screen.debug() // it shows the "dom" 

In my case, I use FontAwesomeIcon and after to use debug I can see:

<svg
            aria-hidden="true"
            class="svg-inline--fa fa-fire fa-w-12 "
            color="#FF9C31"
            data-icon="fire"
            data-prefix="fas"
            focusable="false"
            role="img"
            viewBox="0 0 384 512"
            xmlns="http://www.w3.org/2000/svg"
          >
          
          <path
              d="M216 23.86c0-23.8-30.65-32.77-44.15-13.04C48 191.85 224 200 224 288c0 35.63-29.11 64.46-64.85 63.99-35.17-.45-63.15-29.77-63.15-64.94v-85.51c0-21.7-26.47-32.23-41.43-16.5C27.8 213.16 0 261.33 0 320c0 105.87 86.13 192 192 192s192-86.13 192-192c0-170.29-168-193-168-296.14z"
              fill="currentColor"
            />
          </svg>

So, I can use

const { container } = render(<MyComponent />);

And use some selector in my case [data-icon='fire']

const svgEl = container.querySelector("[data-icon='fire']") as HTMLImageElement;`

It is done, additionally, I can validate if it has a specific class

expect(svgEl.classList.toString()).toContain("fa-fire");

Solution 2:[2]

You can put await to find the svg:

await screen.getByTestId('id')

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Cristhian D
Solution 2 JW Geertsma