Итак, у Jest есть очень удивительная функция, позволяющая проводить динамический повторный рендеринг компонентов в середине теста в результате изменений состояния. Это показано в React учебник на их сайте:Как вызвать повторное рендеринг в Jest, используя изменения состояния state, а не setState внутри компонентов?
https://facebook.github.io/jest/docs/tutorial-react.html
Вот дистиллированная версия соответствующего кода:
test('Link changes the class when hovered',() => {
const component = renderer.create(
<Link page="http://www.facebook.com">Facebook</Link>
);
let tree = component.toJSON();
expect(tree).toMatchSnapshot();
// manually trigger the callback
tree.props.onMouseEnter();
// AUTOMATIC RE-RENDERING MID-TEST!!!!
tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
Это является удивительным, за исключением идиоматических образом, как в 2017 году, чтобы написать Реагировать это с как можно меньше компонентов состояния, что означает использование Redux. Тем не менее, я не могу заставить вышеупомянутое работать с Redux. Вот что у меня есть:
export function renderWithStore(store, Component, mapStateToProps) {
return renderer.create(
<Provider store={store}>
<Component {...mapStateToProps(store.getState())} />
</Provider>
)
}
Если вам интересно, что mapStateToProps
есть, это функция, обеспечиваемая для создания опоры для тестируемого компонента (так же, как вы бы с connect
). Я намеренно переместил на вызов, который должен быть вставлен в пределах <Provider>
, потому что, очевидно, если вы просто передали экземпляр компонента с его реквизитами (как обычно, до renderer.create
), он не сможет реагировать на изменения состояния в магазине. Вот почему завод передается с его реквизитами отдельно.
И для ясности, вот что mapStateToProps
выглядит следующим образом:
({total}) => {
return {total}
}
Так как мы можем достичь «живых» компонентов, как мы можем при использовании setState
? Как мы можем сделать возврат renderer.create
продолжать реагировать на изменения состояния редукции?
Возможно, почему-то вызов forceUpdate
в ответ на store.subscribe
- это решение? Я собираюсь попробовать это сейчас. Любые идеи будут высоко оценены.
UPDATE:
Я изменил мою renderWithStore
функцию подписываться и вынудит обновление, как описано выше, так как:
export function renderWithStore(store, Component, mapStateToProps) {
let comp;
store.subscribe(() => {
comp.forceUpdate();
});
return renderer.create(
<Provider ref={c => comp = c} store={store}>
<Component {...mapStateToProps(store.getState())} />
</Provider>
)
}
и это не работает. Но это прогресс. Принудительное обновление корректно вызывается, и я вызывал console.log()
в пределах Component
, чтобы проверить, происходит ли повторное рендеринг. И это происходит на самом деле. Однако вызов component.toJSON
, похоже, повторно отображает исходный компонент, а не обновленный, который по-прежнему отличается от того, как он реагирует на setState
. Как бы то ни было, похоже, что Jest внесло особое исключение для setState
- испробовав, что вместо forceUpdate
...