Jest + Material-UI: Правильно издеваться над использованиемMediaQuery - PullRequest
0 голосов
/ 17 мая 2019

Я использую функцию Material-UI useMediaQuery() в одном из моих компонентов, чтобы определить 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();
  });
});

И компонент, который я тестирую (удалены ненужные части):

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

Он возвращает matches как false для первого теста, хотя я установил его как true. Я знаю это, потому что он генерирует скриншот, и я вижу, что размер кнопки установлен на large для первого теста, когда он должен быть установлен на medium.

Работает как положено при производстве.

Как правильно получить макет useMediaQuery() в шутливом тесте?

1 Ответ

0 голосов
/ 17 мая 2019

Я понял это ...

useMediaQuery() необходимо повторно обработать компонент для работы, так как первый рендер вернет все, что вы определили в options.defaultMatches (false по умолчанию).

Кроме того, макет должен быть ограничен для каждого теста (it), а не для describe.

Поскольку я использую реагирующую библиотеку-тестирование, все, что мне нужно сделать, это заново выполнить рендеринг компонента и изменить область макета, и это работает.

Вот рабочий пример:

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", 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();
  });
});

describe("Unit: <Navbar> On md and up screens", () => {
  it("renders as snapshot", async () => {
    const { width, height } = initTest(theme.breakpoints.values.md);
    const { asFragment } = 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();
  });
});
...