Я хочу проверить историю. Нажмите в шутку

Я новичок в тестировании.

Я пишу тест, используя шутку и фермент. Однако, когда я попытался написать тест для history.push(), я получил следующую ошибку.

TypeError: Cannot read property 'pathname' of undefined.

Вот мой тестовый код и код компонента.

export default function Tags() {
  const classes = useStyles();
  const history = useHistory();

  const isSelected = (category: string) => {
    history.push(`/?category=${category}`);
  };

  return (
    <>
      <List className = {classes.root} aria-label = "contacts">
        <ListItem button onClick = {() => isSelected("backend")}>
          <ListItemText primary = "#backend" id = "backend" />
        </ListItem>
        <ListItem button onClick = {() => isSelected("frontend")}>
          <ListItemText primary = "#frontend" id = "frontend" />
        </ListItem>
      </List>
    </>
  );
}
import * as React from "react";
import ReactDOM, * as ReactDom from "react-dom";
import Tags from "../Tags";
import { configure, mount, shallow } from "enzyme";
import Adapter from "enzyme-adapter-react-16";
import { fireEvent } from "@testing-library/react";
import { useHistory } from "react-router-dom";

configure({ adapter: new Adapter() });

jest.mock("react-router-dom", () => ({
  useHistory: (): any => ({
    push: jest.fn(),
  }),
}));

describe("Tags", () => {
  it("should be pushed correct path", () => {
    const wrapper = mount(<Tags />);
    const history: any = useHistory();
    const backend = wrapper.find("div#backend").getDOMNode();
    fireEvent.click(backend);
    expect(history.location.pathname).toBe("?category=backend");
  });
});

Чего я хочу добиться, так это того, что если я нажму на кнопку, она получит доступ к правильному URL-адресу или нет.

Я не знаю, где и как переписать код, чтобы тест заработал. Не могли бы вы рассказать мне, как это сделать?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
1
0
6 080
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Обновление: насмешка над useHistory больше не рекомендуется. Вместо этого мы должны использовать <MemoryRouter initialEntries = {['/']}/> или createMemoryHistory, см. https://testing-library.com/docs/example-react-router/

Вы можете сделать это:

Tags.tsx:

import { useHistory } from "react-router-dom";
import React from "react";

export default function Tags() {
  const history = useHistory();

  const isSelected = (category: string) => {
    history.push(`/?category=${category}`);
  };

  return (
    <>
      <ul aria-label = "contacts">
        <li id = "backend" onClick = {() => isSelected("backend")}></li>
        <li id = "frontend" onClick = {() => isSelected("frontend")}></li>
      </ul>
    </>
  );
}

Tags.test.tsx:

import React from "react";
import Tags from "./Tags";
import { mount } from "enzyme";
import ReactRouterDom from "react-router-dom";

const mHistory = {
  push: jest.fn(),
};

jest.mock("react-router-dom", () => ({
  ...(jest.requireActual("react-router-dom") as typeof ReactRouterDom),
  useHistory: jest.fn(() => mHistory),
}));

describe("Tags", () => {
  afterAll(() => {
    jest.resetAllMocks();
  });
  it("should be pushed correct path", () => {
    const wrapper = mount(<Tags />);
    const backend = wrapper.find("#backend");
    backend.simulate("click");
    expect(mHistory.push).toBeCalledWith("/?category=backend");
  });
});

результат модульного теста:

 PASS  examples/65245622/Tags.test.tsx
  Tags
    ✓ should be pushed correct path (33 ms)

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |   88.89 |      100 |      75 |   88.89 |                   
 Tags.tsx |   88.89 |      100 |      75 |   88.89 | 15                
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        6.056 s

исходный код: https://github.com/mrdulin/jest-v26-codelab/tree/main/examples/65245622

Прекрасный ответ, но это дает мне ошибку: ReferenceError: C:\src\....test.tsx: The module factory of 'jest.mock()' is not allowed to reference any out-of-scope variables. И выделяет ReactRouterDom. шутка 26.6.3.

Ian Grainger 23.03.2022 08:22

@Ian Grainger Mocking useHistory больше не рекомендуется. Вместо этого мы должны использовать <MemoryRouter initialEntries = {['/']}/> или createMemoryHistory, см. testing-library.com/docs/example-react-router. Кроме того, если у вас есть новый вопрос, пожалуйста, задайте новый вопрос вместо комментария.

Lin Du 23.03.2022 08:42

Спасибо! Почему вы сказали, что я должен задавать вопрос, а не комментировать? У меня не было нового вопроса?

Ian Grainger 23.03.2022 13:48

Другие вопросы по теме