Фермент и шут тестирование приложения реагирования, которое обновляет состояние после setTimeout - PullRequest
0 голосов
/ 13 апреля 2019

Я использую enzyme и jest для тестирования приложения, которое обновляет state и DOM через определенное время после его монтирования (используя setTimout()).Но как я могу убедиться, что прошло время, и выполнить проверку?

Я пытался использовать jest.advanceTimersByTime(), но он дал мне предупреждение.Warning: An update to %s inside a test was not wrapped in act(...). Так что я сделал именно это, но все равно ничего не изменилось.

const someComponents = () => {
  return (<div className="child"></div>);
}

const App = () => {
  const [remove, setRemove] = useState(false);
  setTimeout(() => setRemove(true), 5000);
  return (
    <div className="App">
      { remove &&
         <someComponent/>
      }
    </div>
  );
};

и что касается моего теста:

import React from 'react';
import ReactDOM from 'react-dom';
import { act } from 'react-dom/test-utils';
import { mount } from 'enzyme';

describe('test', () => {
  it('should remove child at end of timer', () => {
    const wrapper = mount(<App />);
    expect(wrapper.find('.child')).toHaveLength(1);

    act(() => {
      jest.advanceTimersByTime(1000000);

      wrapper.update(); //Do I need this?
      console.log(wrapper.debug())// Still shows child in DOM
      expect(wrapper.find('.child')).toHaveLength(0);
    });
  };
}

Через 5 с someComponent должен был размонтироваться, но еговсе еще там, когда я пытаюсь проверить это. Кроме того, каков правильный способ получить доступ к remove и setRemove с помощью фермента?Существует не так много информации об использовании enzyme с react hooks.

1 Ответ

0 голосов
/ 14 апреля 2019

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

В примечании к вашему примеру хука необходимо использовать useEffect, чтобы работать.

import React, { useState, useEffect } from "react";

const Example = () => <div className="child">child</div>;

const App = () => {
  const [showChild, setShowChild] = useState(true);
  useEffect(() => {
    const timer = setTimeout(() => setShowChild(false), 5000);

    return () => {
      clearTimeout(timer);
    };
  }, []);

  return <div className="App">{showChild && <Example />}</div>;
};

export default App;

Рабочий пример :

Edit Hook Timer


Тем не менее, обходной путь - использовать классы на данный момент.

Вот локальный пример, демонстрирующий проблему с ловушкой, и пример рабочего класса : https://github.com/mattcarlotta/hooks-versus-classes

Для установки:

  • открыть терминал на рабочий стол.
  • введите git clone git@github.com:mattcarlotta/hooks-versus-classes.git и введите.
  • тип cd hooks-versus-classes.
  • тип yarn install или npm install.
  • введите yarn test или npm run test для запуска тестов (они все пройдут, но one сгенерирует console.error и будет утверждено, что не работает должным образом) .
  • введите yarn dev или npm run dev для запуска проекта.

Пример кода рабочего класса:

App.js

import React, { Component } from 'react';

const Example = () => <div className="child">child</div>;

class App extends Component {
  state = { showChild: true };

  componentDidMount = () => this.setTimer(); // setup timeout on mount

  componentWillUnmount = () => this.clearTimer(); // remove timeout in case of component unmount

  clearTimer = () => clearTimeout(this.timeout); // clear timeout

  timer = () => this.setState({ showChild: false }, () => this.clearTimer()); // update state and clear timeout

  setTimer = () => (this.timeout = setTimeout(this.timer, 5000)); // setup a 5s timeout

  render = () => <div>{this.state.showChild && <Example />}</div>;
}

export default App;

App.test.js

import App from './App';

describe('App', () => {
  it('initially renders a child component', () => {
    expect(wrapper.find('.child')).toHaveLength(1);
  });

  it('removes child component after a 5 second timeout', () => {
    jest.advanceTimersByTime(5000);
    expect(wrapper.find('.child')).toHaveLength(0);
  });
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...