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?
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");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With