Я использую Jest 0.4.0. У меня есть компонент, завернутый в это (из документации по реакции-маршрутизатору):
var stubRouterContext = (Component, props, stubs) => {
function RouterStub() { }
Object.assign(RouterStub, {
makePath () {},
makeHref () {},
transitionTo () {},
replaceWith () {},
goBack () {},
getCurrentPath () {},
getCurrentRoutes () {},
getCurrentPathname () {},
getCurrentParams () {},
getCurrentQuery () {},
isActive () {},
getRouteAtDepth() {},
setRouteComponentAtDepth() {}
}, stubs)
return React.createClass({
childContextTypes: {
router: React.PropTypes.func,
routeDepth: React.PropTypes.number
},
getChildContext () {
return {
router: RouterStub,
routeDepth: 0
};
},
render () {
return <Component {...props} />
}
});
};
Мой компонент использует componentWillUpdate
:
getInitialState: function(){
return {something: ""};
},
componentWillUpdate: function(nextProps, nextState) {
if(nextState.something === "12345"){
this.context.router.transitionTo("MyRoute", {id: nextState.something});
}
},
В моем тесте:
var ComponentWrapper = stubRouterContext(MyComponent, {});
var myComponentInstance = TestUtils.renderIntoDocument(<ComponentWrapper />);
it('expects to do something on componentWillUpdate', function(){
myComponentInstance.setState({something: "12345"});
expect(myComponentInstance.getChildContext().router.transitionTo.mock.calls[0][0]).toEqual('MyRoute');
expect(myComponentInstance.getChildContext().router.transitionTo.mock.calls[0][1]).toEqual({id: '12345'});
});
Сколько бы я ни называл setState
, мой nextState
в componentWillUpdate
всегда something: ""
. Однако в тесте, если я проверю содержимое myComponentInstance.state
, это будет something: "12345"
. Таким образом, componentWillUpdate
вызывается, но не имеет нового состояния, даже если оно есть у моего компонента экземпляра.
Любые идеи по этому поводу?
--
РЕДАКТИРОВАТЬ 1
Приведенные ниже предложения основаны на том, что setState является асинхронной функцией, но это не решило проблему. Я также пытался смоделировать изменение магазина (шаблон Flux) таким образом:
myStore.getState = jest.genMockFunction().mockImplementation(function() {
return{
something: "12345",
};
});
myComponentInstance.onChange(); //Simulate store change (this function has setState inside taking values from the store)
Ну, это тоже не сработало, на самом деле мне говорили, что onChange
не определено. Итак, моя проблема связана с оболочкой реактивного маршрутизатора. Я нашел решение, но я не уверен, что есть лучшие, потому что это выглядит очень хакерским. Это следующее:
var RouterWrapper = stubRouterContext(Component, {ref: "myRealComponentInstance"});
var renderedComponent = TestUtils.renderIntoDocument(<RouterWrapper />);
var myComponentInstance = renderedComponent.refs.myRealComponentInstance;
Таким образом, и myComponentInstance.setState
, и имитация myComponentInstance.onChange
, имитирующая магазин, работают, и мне не нужно использовать асинхронные функции.