Jest + Material-UI:正确模拟 useMediaQuery

Jak*_*ake 4 jestjs material-ui

我在我的useMediaQuery()一个组件中使用 Material-UI 的函数来确定size<Button>在组件内使用的道具。

我正在尝试测试它在玩笑测试中是否按预期工作,但是我当前的实现不起作用:

describe("Unit: <Navbar> On xs screens", () => {

  // Incorrectly returns `matches` as `false` ****************************
  window.matchMedia = jest.fn().mockImplementation(
    query => {
      return {
        matches: true,
        media: query,
        onchange: null,
        addListener: jest.fn(),
        removeListener: jest.fn()
      };
    }
  );

  it("renders as snapshot", async () => {
    const width = theme.breakpoints.values.sm - 1;
    const height = Math.round((width * 9) / 16);
    Object.defineProperty(window, "innerWidth", {
      writable: true,
      configurable: true,
      value: width
    });
    const { asFragment } = render(
      <Container backgroundColor={"#ffffff"}>
        <Navbar />
      </Container>
    );
    expect(asFragment()).toMatchSnapshot();
    const screenshot = await generateImage({
      viewport: { width, height }
    });
    expect(screenshot).toMatchImageSnapshot();
  });
});

describe("Unit: <Navbar> On md and up screens", () => {

  // Correctly returns `matches` as `false` ****************************
  window.matchMedia = jest.fn().mockImplementation(
    query => {
      return {
        matches: false,
        media: query,
        onchange: null,
        addListener: jest.fn(),
        removeListener: jest.fn()
      };
    }
  );

  it("renders as snapshot", async () => {
    const width = theme.breakpoints.values.md;
    const height = Math.round((width * 9) / 16);
    Object.defineProperty(window, "innerWidth", {
      writable: true,
      configurable: true,
      value: width
    });
    const { asFragment } = render(
      <Container backgroundColor={"#ffffff"}>
        <Navbar />
      </Container>
    );
    expect(asFragment()).toMatchSnapshot();
    const screenshot = await generateImage({
      viewport: { width, height }
    });
    expect(screenshot).toMatchImageSnapshot();
  });
});
Run Code Online (Sandbox Code Playgroud)

我正在测试的组件(删除了不相关的部分):

const Navbar = () => {
  const theme = useTheme();
  const matchXs = useMediaQuery(theme.breakpoints.down("xs"));
  return (
    <Button size={matchXs ? "medium" : "large"}>
      Login
    </Button>
  );
};
export default Navbar;

Run Code Online (Sandbox Code Playgroud)

它返回matchesfalse第一次测试,即使我已经将它设置为返回为真。我知道这一点是因为它正在生成一个屏幕截图,我可以看到按钮大小large在第一次测试时应该设置为medium.

它在生产中按预期工作。

如何useMediaQuery()在玩笑测试中正确模拟?

Ima*_*sab 5

推荐的方法是使用css-mediaquery现在在MUI 文档中提到

import mediaQuery from 'css-mediaquery';

function createMatchMedia(width) {
  return query => ({
    matches: mediaQuery.match(query, { width }),
    addListener: () => {},
    removeListener: () => {},
  });
}

describe('MyTests', () => {
  beforeAll(() => {
    window.matchMedia = createMatchMedia(window.innerWidth);
  });
});
Run Code Online (Sandbox Code Playgroud)