Не уверен, как написать тестовый пример для условно отображаемого компонента ReactJS

#javascript #reactjs #jestjs #enzyme

#javascript #reactjs #jestjs #фермент

Вопрос:

Мое приложение изначально отображается с загрузочным заполнителем внутри компонента, через 5 секунд отображаются разные элементы. Я хочу протестировать этот компонент с помощью jest и enzyme.

Моя проблема в том, что когда я тестирую его и console.log(wrapper.debug()), он показывает только часть загрузки.

Теперь мой вопрос в том, как я могу модульно протестировать условную часть.

Мой App.js

 import React,{useState, useEffect} from 'react';
import logo from './logo.svg';
import './App.css';

const App = () => {
  const [loading, setLoading] = useState(true);
  useEffect(()=>{
    setTimeout(() => {
      setLoading(false)
    }, 5000);
  },[])
  if(loading){
    return <span>loading....</span>
  }
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;
  

Мой App.test.js

 import React from "react";
import App from "./App";
import { shallow } from "enzyme";

describe("app component", () => {
  it("loading state", () => {
    const setState = jest.fn();
    const useStateMock = (initState) => [initState, setState];
    jest.spyOn(React, "useState").mockImplementation(useStateMock);
    jest.spyOn(React, "useEffect").mockImplementation(setState);
    const wrapper = shallow(<App />);
    const result = wrapper.find("#abc");
    result.simulate("click");
    wrapper.update();
    console.log(wrapper.debug());
    expect(setState).toHaveBeenCalledWith(false);
  });
});
  

Комментарии:

1. Честно говоря, я бы не стал размещать таймер в вашем компоненте таким образом, чтобы показывать загружаемый текст. Вместо этого у вас обычно есть глобальный механизм для проверки, был ли завершен вызов страницы или api, и сохранения этого флага в хранилище данных. Если бы вам абсолютно необходимо было сделать это по-своему (что не идеально), я бы извлек <div className=»App»> как отдельный компонент и протестировал его сам.

2. У вас не совсем правильный код компонента, чтобы имитировать перехват реакции, но ваш useState макет также не обновляет значение, которое он возвращает тестируемому компоненту, поэтому могут быть выполнены отдельные условия. Рассматривали ли вы react-testing-library? Это немного проще (ИМХО) для тестирования пользовательского интерфейса, чем enzyme.

Ответ №1:

Вы можете попробовать использовать: jest.setTimeout(6000)

 import React from "react";
import App from "./App";
import { shallow } from "enzyme";

describe("app component", () => {
  it("loading state", () => {
    const setState = jest.fn();
    const useStateMock = (initState) => [initState, setState];
    jest.spyOn(React, "useState").mockImplementation(useStateMock);
    jest.spyOn(React, "useEffect").mockImplementation(setState);
    const wrapper = shallow(<App />);
    const result = wrapper.find("#abc");
    result.simulate("click");
    wrapper.update();
    jest.setTimeout(6000)
    console.log(wrapper.debug());
    expect(setState).toHaveBeenCalledWith(false);
  })