使用jest-dom与styled-components测试按钮hover样式时异常:hover测试匹配到active样式
我之前碰到过类似的问题,结合你的代码和错误信息来看,大概率是这几个原因导致的:
问题根源分析
CSS伪类顺序引发的样式覆盖
你在Button.styles.ts里把:active伪类写在了:hover之后,这两个伪类的CSS优先级完全相同,所以当元素同时触发:hover和:active状态时,:active的样式会直接覆盖:hover的。测试环境里的模拟行为和真实浏览器有差异,导致hover测试时按钮意外触发了active状态,从而读取到了错误的样式。测试用例的小错误
你的点击测试用例里,期望的transform样式是scale(0.95),但实际:active定义的是translateY(0.3rem),这个错误本身就会导致点击测试失败,虽然不是hover问题的直接原因,但也需要修正。测试工具的状态模拟差异
@testing-library/user-event的hover方法在JSDom环境下的模拟可能和真实浏览器有差异,没有正确隔离hover和active的状态。
解决方案
方案一:修正测试用例,改用更直接的事件模拟
先把点击测试的期望样式修正正确,然后给hover测试改用fireEvent来模拟鼠标事件,它的行为更贴近真实DOM事件,能减少状态混淆:
// 记得导入fireEvent import { screen, render, fireEvent } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import Button from "./Button"; import Theme from "../../Theme"; describe("Button", () => { it("should render with correct children", () => { render( <Theme> <Button>Entrar</Button> </Theme> ); const button = screen.getByText(/entrar/i); expect(button).toBeInTheDocument(); }); it("should not render any children if isLoading is passed as true", () => { render( <Theme> <Button isLoading={true}>Entrar</Button> </Theme> ); const button = screen.queryByText(/entrar/i); expect(button).not.toBeInTheDocument(); }); it("should apply proper style when user hovers over it", () => { render( <Theme> <Button>Entrar</Button> </Theme> ); const button = screen.getByText(/entrar/i); // 用mouseEnter模拟hover状态 fireEvent.mouseEnter(button); expect(button).toHaveStyle({ backgroundColor: "#000000", transform: "scale(1.05)" }); // 测试完成后模拟鼠标离开,避免影响后续测试 fireEvent.mouseLeave(button); }); it("should apply proper style when user clicks it", () => { render( <Theme> <Button>Entrar</Button> </Theme> ); const button = screen.getByText(/entrar/i); userEvent.click(button); // 修正为:active实际定义的样式 expect(button).toHaveStyle("transform: translateY(0.3rem)"); }); });
方案二:确保测试用例的独立性
把所有测试用例都放在describe块内部,这样jest会更稳定地按顺序执行,减少跨测试的状态残留风险(虽然testing-library默认会自动清理,但规范的结构能避免很多意外)。
方案三:检查依赖兼容性
如果上面的方法都不行,可以尝试更新jest-environment-jsdom、@testing-library/react和styled-components到最新的兼容版本,有时候旧版本的工具链会存在伪类模拟的bug。
备注:内容来源于stack exchange,提问作者joaovitorfelix

