Как проверить метод размонтированного компонента React, который использует setState? - PullRequest
0 голосов
/ 10 февраля 2019

Я реализовал компонент (для учебного приложения для набора текста), который отслеживает нажатия клавиш в глобальной области видимости:

class TrainerApp extends React.Component {
    constructor() {
        // ...
        this.handlePress = this.handlePress.bind(this);
    }
    handlePress(event) {
        const pressedKey = event.key;
        const task = this.state.task;
        const expectedKey = task.line[task.position];

        const pressedCorrectly = pressedKey == expectedKey;
        this.setState(prevState => {
            const newPosition = prevState.task.position +
                (pressedCorrectly ? 1 : 0);
            return {
                // ...prevState, not needed: https://reactjs.org/docs/state-and-lifecycle.html#state-updates-are-merged
                task: {
                    ...prevState.task,
                    position: newPosition,
                    mistakeAtCurrentPosition: !pressedCorrectly
                }
            }
        })
    }
    componentDidMount() {
        document.addEventListener(this.keyEventTypeToHandle,this.handlePress);
    }
    componentWillUnmount () {
        document.removeEventListener(this.keyEventTypeToHandle,this.handlePress);
    }
    ...
}

, и я хотел бы написать несколько юнит-тестов с использованием Jest.Моя первоначальная идея была:

describe('TrainerApp.handlePress should',() => {
    test('move to the next char on correct press',() => {

        const app = new TrainerApp();
        app.state.task.line = 'abc';
        app.state.task.position = 0;
        const fakeEvent = { key: 'a' };

        app.handlePress(fakeEvent);

        expect(app.state.task.position).toBe(1);
    });
    ...
});

, но проблема заключается в app.handlePress, основанном на использовании this.setState, который еще не определен, когда компонент еще не смонтирован.Конечно, я могу изменить app следующим образом:

test('move to the next char on correct press',() => {

    const app = new TrainerApp();
    app.setState = jest.fn(function(handler) {
        this.state = handler(this.state);
    });
    app.state.task.line = 'abc';
    app.state.task.position = 0;
    const fakeEvent = { key: 'a' };

    app.handlePress(fakeEvent);

    expect(app.state.task.position).toBe(1);
});

или даже так:

class ExplorableTrainerApp extends TrainerApp {
    setState(handler) {
        this.state = handler(this.state);
    }
}
test('move to the next char on correct press',() => {

    const app = new ExplorableTrainerApp();
    app.state.task.line = 'abc';
    app.state.task.position = 0;
    const fakeEvent = { key: 'a' };

    app.handlePress(fakeEvent);

    expect(app.state.task.position).toBe(1);
});

, но это кажется очень хрупким подходом (здесь я полагаюсь на тот факт,что .setState вызывается с аргументом функции, тогда как он может вызываться только с аргументом newState, и, следовательно, я проверяю детали реализации, а не только поведение. Есть ли более надежный способ проверить это?

1 Ответ

0 голосов
/ 10 февраля 2019

Существует несколько платформ для тестирования компонентов React, Фермент и реагирующая библиотека-тестирования популярны и хорошо поддерживаются.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...