Задать вопрос

Как замокать конкретную переменную из хука useState в тестируемом компоненте?

Всем привет, имеется вот такой вот компонент
import logo from "../../images/HeaderLogo.svg";
import MenuList from "../MenuList/MenuList.tsx";
import AddClips from "../AddClips/AddClips.tsx";
import React, { useState } from "react";
import useScreenResolution from "../../../../hooks/useScreenResolution.ts";
import BurgerIcon from "../Burger/BurgerIcon.tsx";
import { Link } from "react-router-dom";
import { ReactComponent as PersonalLogo } from "../../images/ProfileIcon.svg";
import CloseButton from "src/components/CloseButton/CloseButton.tsx";
import classes from "./SideBar.module.scss";

const Sidebar = React.memo(() => {
  const [openMenu, setOpenMenu] = useState(false);

  // Переменная адаптации (mobile, desktop)
  const isMedia = useScreenResolution();

  // Функция закрытия навигации по сайту
  const handleClose = () => setOpenMenu((state) => !state);

  return (
    <>
      {openMenu ? <div>open</div> : <div>not open</div>}
      {/*Появляется в случае мобильного меню*/}
      {isMedia === "mobile" && (
        <BurgerIcon stateOpen={openMenu} open={setOpenMenu} />
      )}

      {((openMenu && isMedia === "mobile") || isMedia === "desktop") && (
        <div data-testid="sidebar" className={classes.sidebar}>
          <div className={classes.wrapper}>
            <CloseButton
              className={classes.buttonClose}
              onClick={handleClose}
            />

            <div className={classes.content}>
              {/*логотип*/}
              <img src={logo} alt="Логотип" className={classes.logo} />

              {/*Компонент "Заказать ролик"*/}
              <AddClips />

              {/*Список меню*/}
              <MenuList />

              {/*Личный кабинет*/}
              <Link
                data-testid="btnPersonalAccount"
                className={classes.person}
                to={"/lk"}
              >
                <PersonalLogo className={classes.icon} />

                <div className={classes.title}>Личный кабинет</div>
              </Link>
            </div>
          </div>
        </div>
      )}
    </>
  );
});

export default Sidebar;


Я хочу его протестировать и мне нужно установить для openMenu true, как я могу это сделать в тестах. Тесты я пишу на vitest, по факту тоже самое что и jest

import { describe, it, expect, vi, Mock } from "vitest";
import { render, screen } from "@helpers/test-utils.tsx";
import { Sidebar } from "../../../index.ts";
import RenderWithRouter from "@helpers/RenderWithRouter.tsx";
import useScreenResolution from "src/hooks/useScreenResolution.ts";
import React, { useState } from "react";

vi.mock("src/hooks/useScreenResolution.ts");

describe("SIDEBAR TEST COMPONENT", () => {
  it("render sidebar", () => {
    // Мокаем данные на отрисовку desktop версии
    (useScreenResolution as Mock).mockReturnValue("desktop");
    render(
      <RenderWithRouter>
        <Sidebar />
      </RenderWithRouter>
    );
    // Отрисовка SideBar
    const sidebar = screen.getByTestId("sidebar");
    expect(sidebar).toBeInTheDocument();

    // Отрисовка кнопки "Личный кабинет"
    const btnPersonalAccount = screen.getByTestId("btnPersonalAccount");
    expect(btnPersonalAccount).toBeInTheDocument();

    // отрисовка бургер меню
    const burgerIcon = screen.queryByTestId("burgerIcon");
    expect(burgerIcon).toBeNull();
  });

  it("render mobile version sidebar is close state", () => {
    // Мокаем данные на отрисовку mobile версии
    (useScreenResolution as Mock).mockReturnValue("mobile");

    render(
      <RenderWithRouter>
        <Sidebar />
      </RenderWithRouter>
    );

    // Отрисовка SideBar
    const sidebar = screen.queryByTestId("sidebar");
    expect(sidebar).toBeNull();

    // Отрисовка бургер меню
    const burgerIcon = screen.getByTestId("burgerIcon");
    expect(burgerIcon).toBeInTheDocument();
  });

  it("render mobile version is open state", () => {
    // Мокаем данные на отрисовку mobile версии
    (useScreenResolution as Mock).mockReturnValue("mobile");

    render(
      <RenderWithRouter>
        <Sidebar />
      </RenderWithRouter>
    );
  });
});


Вот, самый последний тест, и вот надо как то сделать openMenu в true, подскажите, пожалуйста
  • Вопрос задан
  • 171 просмотр
Подписаться 1 Простой Комментировать
Пригласить эксперта
Ответы на вопрос 1
miraage
@miraage
Старый прогер
Я бы в тесте просто нашел burgericon, кликнул по нему, и затем уже писал expect ниже.
Либо создайте опциональный проп initialOpen, который передайте в useState.
Это вполне себе нормальная практика иметь такие опциональные props (а-ля dependency injection), чтобы легко в тестах мокать было. Например, api всякие и прочее.

Оффтоп: насколько я помню, методы getBy* кидают ошибку, если элемент не найден, в отличие от findBy* => можно не проверять результат через toBeinTheDocument, а просто писать одну строчку screen.getBy*("selector")

//edit

Как подметили в комментах, то можно и для findBy не делать проверку, ибо я перепутал findBy с queryBy.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы