30

I have a popover showing on Hover and I want to test it with Jest and React Testing Library to see if the element is hidden by default.

When I test manualy everything is ok by not when I test it with RTL.

I tried using not.toBeInTheDocument and not.toBeVisible but it seems that the element is always present in the DOM, any idea of how could I remove it from the DOM

JSX code:

<label
  htmlFor="terms_and_conditions"
  className="terms_and_conditions_box"
>
  I agree with{" "}
  <span className="terms_and_conditions_text" style={{ color: "blue" }}>
    Terms and conditions
  </span>
  <div className="pop_over">No ice cream will be delivered</div>
</label>

CSS code:

.terms_and_conditions_text:hover + .pop_over {
  display: block;
}

.pop_over {
  background: rgb(199, 196, 196);
  padding: 2rem;
  width: 14rem;
  border-radius: 15px;
  position: absolute;
  right: -18rem;
  top: -2rem;
  display: none;
}

TEST code:

test("popover responds to hover", () => {
  render(<SummaryForm />);

  //* popover initially is hidden
  const nullPopover = screen.queryByText(/No ice cream will be delivered/i);
  expect(nullPopover).not.toBeInTheDocument();
});

2 Answers 2

40

I have reproduced your code and for me the test does not work with toBeInTheDocument, but works with toBeVisible as long as display: none is there.

Here is the code of my test file, the first test does not pass, the second passes:

import React from "react";
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom/extend-expect";
import SummaryForm from "./App";

describe("popover responds to hover", () => {
  test("popover initially is hidden (test with toBeInTheDocument)", () => {
    render(<SummaryForm />);
    const nullPopover = screen.queryByText(/No ice cream will be delivered/i);
    expect(nullPopover).not.toBeInTheDocument();
  });

  test("popover initially is hidden (test with toBeVisible)", () => {
    render(<SummaryForm />);
    const nullPopover = screen.queryByText(/No ice cream will be delivered/i);
    expect(nullPopover).not.toBeVisible();
  });
});

And here is the codesandbox where you can see it in action.

Sign up to request clarification or add additional context in comments.

Comments

0

There is another solution but it's only relevant when you can control the code or some of it yourself. Might not work in case of external libraries. Because Testing-Library uses an accessibility detection to identify element in the DOM what you can do use the role attribute with the aria-hidden attribute, like this:

// MyPopup.jsx
export const MyPopup = () => {
  const [isHidden, setIsHidden] = useState(false)
  return (<div role={'dialog'} 
               style={{display : isHidden ? 'none' : 
                   'block'}}
                aria-hidden={isHidden ? 'false' : 
                   'true'}> 
            My Popup Content  
         </div>)
  }

Then in your test the element will not be found and will be null

//my-test.jsx
...
const myPopup = await screen.findByRole('dialog')
expect(myPopup).toBeNull(); // == true (if is hidden)
// this will work because of the aria-hidden
...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.