I have a simple pop-up that I want to test if the clicked button closes the popup using testing-library/react. The way shown in docs doesn't work for me for some reason. I'm able to console log the button, so the query works but fireEvent doesn't trigger the button.
test("close the popup", () => {
render(
<Popup>
<div id="content"></div>
</Popup>
);
const button = screen.getByText("Got It");
fireEvent.click(button);
expect(button).not.toBeInTheDocument();
});
import React, { useEffect, useState } from "react";
import PropTypes from "prop-types";
const Popup = (props) => {
const id = "popup-active"
const [popupActive, setPopupActive] = useState(() => {
const value = window.localStorage.getItem(id);
return value !== null ? JSON.parse(value) : true;
});
useEffect(() => {
window.localStorage.setItem(id, popupActive);
}, [popupActive]);
const handleX = () => {
setPopupActive(!popupActive);
};
return (
<div
style={{
visibility: popupActive ? "visible" : "hidden",
opacity: popupActive ? "1" : "0",
}}
className={popupStyles.overlay}
>
<div className={popupStyles.popup}>
<div className={popupStyles.content}>{props.children}</div>
<button
data-testid="button-popup"
className={popupStyles.button}
onClick={handleX}
>
Got It
</button>
</div>
</div>
);
};
export default Popup;
CodePudding user response:
You should use toBeVisible matcher.
This allows you to check if an element is currently visible to the user. An element is visible if all the following conditions are met:
- it is present in the document
- it does not have its css property display set to none
- it does not have its css property visibility set to either hidden or collapse
- it does not have its css property opacity set to 0
- its parent element is also visible (and so on up to the top of the DOM tree)
- it does not have the hidden attribute
- if
<details />
it has the open attribute
E.g.
index.tsx
:
import React from 'react';
import { useEffect, useState } from 'react';
const id = 'popup-active';
const Popup = (props) => {
const [popupActive, setPopupActive] = useState(() => {
const value = window.localStorage.getItem(id);
return value !== null ? JSON.parse(value) : true;
});
useEffect(() => {
window.localStorage.setItem(id, popupActive);
}, [popupActive]);
const handleX = () => {
setPopupActive(!popupActive);
};
return (
<div
style={{
visibility: popupActive ? 'visible' : 'hidden',
opacity: popupActive ? '1' : '0',
}}
>
<div>
<div>{props.children}</div>
<button data-testid="button-popup" onClick={handleX}>
Got It
</button>
</div>
</div>
);
};
export default Popup;
index.test.tsx
:
import { fireEvent, render, screen } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import React from 'react';
import Popup from './';
describe('73407176', () => {
test('should pass', () => {
render(
<Popup>
<div id="content"></div>
</Popup>
);
const button = screen.getByText('Got It');
fireEvent.click(button);
expect(button).not.toBeVisible();
});
});
Test result:
PASS stackoverflow/73407176/index.test.tsx (11.549 s)
73407176
✓ should pass (73 ms)
-----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-----------|---------|----------|---------|---------|-------------------
All files | 100 | 83.33 | 100 | 100 |
index.tsx | 100 | 83.33 | 100 | 100 | 8
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 12.167 s
Also check this question: What is the difference between toBeInTheDocument() and toBeVisible()?