为 material-ui 实施 createMatchMedia()。我在尝试测试按钮时使用 material ui 隐藏组件来隐藏它们

Implementing createMatchMedia() for material-ui. I'm using a material ui hidden component to hide buttons while I'm trying to test them

我正在使用 React-testing-library getByText 查找被名为 Hidden 的 material ui 组件隐藏的按钮。由于 RTL 找不到它,Material ui 在这里 https://material-ui.com/components/use-media-query/#testing 有一个实现。但我无法弄清楚如何实现它来简单地找到一个按钮。一旦我删除 Hidden,该按钮就位于,我只是不确定如何在我的测试中使用他们的 createMatchMedia() 进行查询。

隐藏组件将我的按钮隐藏在 959px 及以下。

import React from "react"
import { render } from '../../../../test/test-utils'
import Collections from "./Collections"
import userEvent from '@testing-library/user-event'
import mediaQuery from 'css-mediaquery'

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

type CollectionsProps = React.ComponentProps<typeof Collections>

const baseProps: CollectionsProps = {
  setValue: () => {},
  setSelectedIndex: () => {},
  pageStyle: {},
  pageAnimations: {transition : {}, variants: {}},
  motions: {animate:'', initial: '', exit: ''},
  jumpTo: (jumpingTarget: string | number | Element): void => {}
}

const renderUI = (props: Partial<CollectionsProps>) =>
     render(<Collections {...baseProps} {...props} />, {}) 

describe('When a filter is clicked', () => {

  beforeAll( () => {
    window.matchMedia = createMatchMedia(window.innerWidth)
  })

  let { getByText } = renderUI({})

    test('items shown are only related to the picked Category', () => {
      userEvent.click(getByText(/Team Colors/))
    })  
}) 

RTL 不是这里的问题。问题出在 jsdom which doesn't have an implementation of matchMedia(). Jest uses jsdom internally and without an existing matchMedia() no media query will match in Material UI's Hidden API.

  1. 您可以先安装 NPM 包来解决这个问题 css-mediaquery and @types/css-mediaquery
  2. 然后像这样为 matchMedia 创建一个模拟:
// matchMedia.mock.ts
export const createMatchMedia = (width: number) => (query: string): MediaQueryList => ({
  matches: mediaQuery.match(query, { width }),
  media: query,
  onchange: null,
  addListener: () => jest.fn(),
  removeListener: () => jest.fn(),
  addEventListener: jest.fn(),
  removeEventListener: jest.fn(),
  dispatchEvent: jest.fn()
});

window.matchMedia = createMatchMedia(window.innerWidth);

export default {};
  1. setupTest.ts(您的 Jest 测试设置文件)中导入上面的模拟文件,如下所示:
// setupTests.ts
import './__mocks__/matchMedia.mock';
...
  1. 像往常一样编写测试。无需使用 beforeAll() 创建新的 window.matchMedia。模拟文件会为您处理。