jest-dom : toBeVisible() 在应该返回 false 时返回 true

Jak*_*ake 7 jsdom jestjs material-ui react-testing-library

类似的问题在这里 -无法检查 expect(elm).not.toBeVisible() 的语义 UI 反应组件- 但是答案表明这应该适用于 CSS-in-JS,这就是我正在使用的。

我正在使用 Material-UI 的<Hidden>组件仅在sm屏幕尺寸及更大尺寸上显示一些文本。这是代码(在生产中完美运行):

<Hidden implementation="css" xsDown>
  <LogoText variant="h5" component="p" />
</Hidden>
Run Code Online (Sandbox Code Playgroud)

我使用的是jest-domreact-testing-library和我想测试我的导航栏,其中包含这个隐藏文本的响应。

我有以下测试:

const initTest = width => {
  Object.defineProperty(window, "innerWidth", {
    writable: true,
    configurable: true,
    value: width
  });
  window.matchMedia = jest.fn().mockImplementation(
    query => {
      return {
        matches: width >= theme.breakpoints.values.sm ? true : false,
        media: query,
        onchange: null,
        addListener: jest.fn(),
        removeListener: jest.fn()
      };
    }
  );
  const height = Math.round((width * 9) / 16);
  return { width, height };
};

describe("Unit: <Navbar> On xs screens", () => {
  it("renders as snapshot at minimum size", async () => {
    const { width, height } = initTest(320);
    const { asFragment, rerender } = render(
      <Container backgroundColor={"#ffffff"}>
        <Navbar />
      </Container>
    );
    rerender(
      <Container backgroundColor={"#ffffff"}>
        <Navbar />
      </Container>
    );
    expect(asFragment()).toMatchSnapshot();
    const screenshot = await generateImage({
      viewport: { width, height }
    });
    expect(screenshot).toMatchImageSnapshot();
  });

  it("renders as snapshot at maximum size", async () => {
    const { width, height } = initTest(theme.breakpoints.values.sm - 1);
    const { asFragment, rerender } = render(
      <Container backgroundColor={"#ffffff"}>
        <Navbar />
      </Container>
    );
    rerender(
      <Container backgroundColor={"#ffffff"}>
        <Navbar />
      </Container>
    );
    expect(asFragment()).toMatchSnapshot();
    const screenshot = await generateImage({
      viewport: { width, height }
    });
    expect(screenshot).toMatchImageSnapshot();
  });

  it("hides logo text", async () => {
    initTest(theme.breakpoints.values.sm - 1);
    const { rerender, getByText } = render(
      <Container backgroundColor={"#ffffff"}>
        <Navbar />
      </Container>
    );
    rerender(
      <Container backgroundColor={"#ffffff"}>
        <Navbar />
      </Container>
    );
    await wait(() => expect(getByText("LOGO TEXT")).not.toBeVisible());
  });
});
Run Code Online (Sandbox Code Playgroud)

前 2 个测试截取了屏幕截图,当我查看屏幕截图时,我可以看到徽标文本不可见:

当我在浏览器中查看 DOMxs大小时,我看到父组件确实隐藏了:https : //i.imgur.com/TfBpePV.​​png

然而,当我运行测试时,它失败并说该元素是可见的:

  ? Unit: <Navbar> On xs screens › hides logo text

    expect(element).not.toBeVisible()

    Received element is visible:
      <p class="MuiTypography-root MuiTypography-h5 makeStyles-typography-237" />
Run Code Online (Sandbox Code Playgroud)

如果我在 aconsole.log(innerWidth)之前添加,expect()那么它会返回正确的宽度,所以问题不在于 jsdom 以错误的屏幕宽度呈现。

此外,如果我将<Hidden>组件的实现从 CSS更改为 JS,它工作正常(因为使用 JS 将元素完全从文档中取出,而不是仅使用媒体查询隐藏)。

我如何解决这个问题以使其正常工作?