最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

jestjs - React Testing Library Fails to Detect :hover Styles in MUI Styled Components - Stack Overflow

programmeradmin2浏览0评论

I'm testing a styled button component in a Next.js 13+ App Router project using Jest and React Testing Library, but my tests fail when checking for style changes on hover.

Component (TestButton.tsx):

import { styled } from "@mui/material/styles";
import type { FC } from "react";

const MyButton = styled("button")({
  color: "red",
  "&:hover": {
    color: "yellow",
  },
});

const TestButton: FC = () => {
  return <MyButton className="button">Test Button</MyButton>;
};

export default TestButton;

Test (TestButton.spec.tsx):

import TestButton from "~/components/testButton/TestButton";
import { Renderer } from "./Renderer";
import { act } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

describe("TestButton", () => {
  it("should change text color on hover", async () => {
    const user = userEvent.setup();
    const { getByRole } = await act(() => new Renderer(<TestButton />).withAllProviders().render());

    const button = getByRole("button", { name: /Test Button/i });

    expect(button).toHaveStyle({
      color: "red",
    });

    await act(async () => {
      await user.hover(button);
    });

    expect(button).toHaveStyle({
      color: "yellow", // ❌ This fails
    });

    await act(async () => {
      await user.unhover(button);
    });

    expect(button).toHaveStyle("color: red");
  });
});

Test failure output:

FAIL  src/__test__/TestButton.spec.tsx
TestButton
  × should change text color on hover (168 ms)

  ● TestButton › should change text color on hover

    expect(element).toHaveStyle()

    - Expected

    - color: yellow;
    + color: red;

so the problem is that toHaveStyle({ color: "yellow" }) fails after triggering user.hover(button). while the hover state works fine in the browser.

How can I properly test hover styles for MUI styled components?

If I manually set the styles using onMouseEnter and onMouseLeave, the test passes:

 const TestButton: FC = () => {
  return (
    <MyButton
      className="button"
      onMouseEnter={(e) => {
        e.currentTarget.style.color = "yellow";
      }}
      onMouseLeave={(e) => {
        e.currentTarget.style.color = "red";
      }}
    >
      Test Button
    </MyButton>
  );
};

I'm testing a styled button component in a Next.js 13+ App Router project using Jest and React Testing Library, but my tests fail when checking for style changes on hover.

Component (TestButton.tsx):

import { styled } from "@mui/material/styles";
import type { FC } from "react";

const MyButton = styled("button")({
  color: "red",
  "&:hover": {
    color: "yellow",
  },
});

const TestButton: FC = () => {
  return <MyButton className="button">Test Button</MyButton>;
};

export default TestButton;

Test (TestButton.spec.tsx):

import TestButton from "~/components/testButton/TestButton";
import { Renderer } from "./Renderer";
import { act } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

describe("TestButton", () => {
  it("should change text color on hover", async () => {
    const user = userEvent.setup();
    const { getByRole } = await act(() => new Renderer(<TestButton />).withAllProviders().render());

    const button = getByRole("button", { name: /Test Button/i });

    expect(button).toHaveStyle({
      color: "red",
    });

    await act(async () => {
      await user.hover(button);
    });

    expect(button).toHaveStyle({
      color: "yellow", // ❌ This fails
    });

    await act(async () => {
      await user.unhover(button);
    });

    expect(button).toHaveStyle("color: red");
  });
});

Test failure output:

FAIL  src/__test__/TestButton.spec.tsx
TestButton
  × should change text color on hover (168 ms)

  ● TestButton › should change text color on hover

    expect(element).toHaveStyle()

    - Expected

    - color: yellow;
    + color: red;

so the problem is that toHaveStyle({ color: "yellow" }) fails after triggering user.hover(button). while the hover state works fine in the browser.

How can I properly test hover styles for MUI styled components?

If I manually set the styles using onMouseEnter and onMouseLeave, the test passes:

 const TestButton: FC = () => {
  return (
    <MyButton
      className="button"
      onMouseEnter={(e) => {
        e.currentTarget.style.color = "yellow";
      }}
      onMouseLeave={(e) => {
        e.currentTarget.style.color = "red";
      }}
    >
      Test Button
    </MyButton>
  );
};
Share Improve this question edited Feb 16 at 18:53 jonrsharpe 122k30 gold badges267 silver badges474 bronze badges asked Feb 16 at 18:46 Haitam-ElgharrasHaitam-Elgharras 1389 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

Your test fails because Jest and React Testing Library (RTL) do not process CSS styles dynamically applied via MUI’s styling system. MUI's styled API uses emotion (CSS-in-JS), which injects styles into the DOM, but JSDOM (the environment Jest runs in) does not support pseudo-classes (:hover) by default.

Since MUI's styled components rely on emotion, you need a proper style injector during tests.

install tooling that do provide this npm install --save-dev jest-styled-components @emotion/react

Modify your test to import jest-styled-components, which enables pseudo-class testing:

import TestButton from "~/components/testButton/TestButton";
import { Renderer } from "./Renderer";
import { act, render } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import "jest-styled-components"; // <---

describe("TestButton", () => {
    it("should change text color on hover", async () => {
        const user = userEvent.setup();
        const { getByRole } = render(<TestButton />); // <---Use direct render

        const button = getByRole("button", { name: /Test Button/i });

        expect(button).toHaveStyleRule("color", "red");

        await act(async () => { await user.hover(button); });

        expect(button).toHaveStyleRule("color", "yellow", { modifier: ":hover" });
    });
});

OR another alternative approach is to check the computed style directly (instead of toHaveStyleRule, retrieve styles via JSDOM):

import TestButton from "~/components/testButton/TestButton";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

describe("TestButton", () => {
    it("should change text color on hover", async () => {
        render(<TestButton />);

        const button = screen.getByRole("button", { name: /Test Button/i });
        expect(window.getComputedStyle(button).color).toBe("red");

        await userEvent.hover(button);
        await new Promise((r) => setTimeout(r, 100)); // optionally wait for styles (paranoia)
        expect(window.getComputedStyle(button).color).toBe("yellow");

        await userEvent.unhover(button);
        expect(window.getComputedStyle(button).color).toBe("red");
    });
});
发布评论

评论列表(0)

  1. 暂无评论