1

How can I test whether or not a React component is visible in the DOM when that component is hidden using a CSS transition with transform: scale(0)?

jest-dom has a .toBeVisible() matcher, but this doesn't work because transform: scale(0) is not one of the supported visible/hidden triggers. Per the docs:

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

I am not using the hidden attribute because interfered with my transition animations. I am using aria-hidden, but that is also not one of the supported triggers.

The simplified version of my component is basically this. I am using Tailwind CSS for the transform and the transition.

import React from "react";
import clsx from "clsx";

const MyComponent = ({isVisible = true, text}) => (
  <div
    className={clsx(
      isSelected ? "transform scale-1" : "transform scale-0",
      "transition-all duration-500"
    )}
    aria-hidden={!isVisible}
  >
     <span>{text}</span>
  </div>
)

I could potentially check for hidden elements with:

  • toHaveClass("scale-0")
  • toHaveAttribute("aria-hidden", true)

But unlike toBeVisible, which evaluates the entire parent tree, these matchers only look at the element itself.

If I use getByText from react-testing-library then I am accessing the <span> inside the <div> rather than the <div> which I want to be examining. So this doesn't work:

import React from "react";
import { render } from "@testing-library/react";
import "@testing-library/jest-dom/extend-expect";
import { MyComponent } from "./MyComponent";

it("is visible when isSelected={true}", () => {
  const {getByText} = render(
    <MyComponent
      isSelected={true}
      text="Hello World"
    />
  );
  expect(getByText("Hello World")).toHaveClass("scale-1");
});

What's the best way to approach this?

Linda Paiste
  • 28,886
  • 4
  • 42
  • 71
  • I ended up using `getByTestId` and `toHaveClass` but this feels really hacky and I'd love to know if there's a better solution. Like a way to extend `toBeVisible`? I did `expect(getByTestId("prefix-Hello World")).toHaveClass("scale-1");` – Linda Paiste Jun 15 '21 at 00:57

1 Answers1

1

I believe the issue you're experiencing here is related to this question. My understanding is the problem isn't so much that the effective visibility calculation is wrong, but that tailwind's CSS isn't being included in the jsdom document.

Dennis
  • 690
  • 9
  • 14