Неожиданное тестирование поведения Реагировать компонент после задержки с Jest / Enzyme - PullRequest
0 голосов
/ 19 сентября 2018

У меня есть довольно простой компонент React, который отображает последовательность точек для того, когда что-то загружается, по умолчанию он отображает до 3 точек и шаг увеличивается на интервале, установленном в функции componentDidMount, сбрасываясь по числуточек.Количество точек и интервал могут быть перезаписаны путем пропускания реквизита.Этот компонент находится ниже.

import * as React from 'react';

export interface Props {
    interval?: number;
    dots?: number;
}

class LoadingDots extends React.Component<Props, object> {
    public static defaultProps: Partial<Props> = {
        interval: 300,
        dots: 3
    };
    interval: any;

    state = {
        frame: 1,
        interval: this.props.interval,
        dots: this.props.dots
    }

    componentDidMount = () => {
        this.interval = setInterval(() => {
            this.setState({
                frame: this.state.frame + 1
            });
        }, this.props.interval);
    }

    componentWillUnmount() {
        clearInterval(this.interval);
    }

    public render() {
        let dots = this.state.frame % (this.props.dots + 1);
        let text = "";
        while (dots > 0) {
            text += ".";
            dots--;
        }
        return (
                <p className="loadingDots" {...this.props}>{text}</p>
        )
    }
}

export default LoadingDots;

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

test('LoadingDots by default renders with 3 dots', () => {
    var loadingDots = Enzyme.shallow(<LoadingDots interval={100} />);
    jest.useFakeTimers();
    jest.runAllTimers();
    setTimeout(() => {
        expect(loadingDots.find('p').text()).toBe("...")
    }, 300);
});

Этот тест проходит, но не должен, он проходит независимо от того, какое значение я положил в .ToBe из expect(loadingDots.find('p').text()).toBe("...").

Я пытался отобразить компонент как var loadingDots = Enzyme.mount(); и var loadingDots = Enzyme.render();, но результат все тот же, кто-нибудь видит, что здесь происходит не так?Как я могу заставить это работать правильно?

1 Ответ

0 голосов
/ 21 сентября 2018

Выпуск 1

jest.useFakeTimers() заменяет функции таймера, такие как setInterval, на имитации таймера, которые отслеживают аргументы, с которыми они были вызваны.Он должен быть вызван до того, как ваш компонент создан, поэтому вызов setInterval в componentDidMount вызывает макет вместо реального setInterval.

Issue 2

jest.runAllTimers() пытается запустить все обратные вызовы таймера, пока не останется ни одного.В этом случае setInterval никогда не отменяется, поэтому jest.runAllTimers будет пытаться выполнить обратные вызовы таймера навсегда, а Jest будет прерывать тест с ошибкой после выполнения 100000 обратных вызовов.

Правильный способ продвижения времени вэтот сценарий должен использовать jest.advanceTimersByTime (или псевдоним jest.runTimersToTime для Jest <22). </p>

выпуск 3

setTimeout не требуется, поскольку Mock-таймеры выполняются синхронно.


Вот обновленный тест для вашего компонента:

test('LoadingDots by default renders with 3 dots', () => {
  jest.useFakeTimers();  // replace timer functions like setInterval with timer mocks
  const dots = 3;
  const interval = 100;
  var loadingDots = Enzyme.shallow(<LoadingDots interval={interval} />);
  for(let i = 1; i <= 8; i++) {
    const expectedDots = i % (dots + 1);
    expect(loadingDots.find('p').first().text()).toBe('.'.repeat(expectedDots));
    jest.runTimersToTime(interval);  // simulate time passing and run any applicable timer callbacks
  }
  jest.useRealTimers();  // restore timer functions
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...