While migrating existing v2 tests.
Seems to be simulating correctly but I dont see the state updated correctly.
Am I missing something ?
const wrapper = mount(<TestComponent {...properties} />);
wrapper.setState({
focusedColumn: 4
});
wrapper.find('div.base-columns').simulate('mouseleave');
wrapper.update();
expect(wrapper.state('focusedColumn')).toEqual(null); // equals 4 instead
Similar thing is happening in this case
const wrapper = mount(<TestComponent {...properties} />);
wrapper.setState({
focusedColumn: 1
});
wrapper.instance().changeFocus({ col: 2 });
// ideally this should've updated the state. IDK
wrapper.update();
expect(wrapper.state('focusedColumn')).toEqual(2);
Same here
const component = mount(<XYZComponent {...properties} />);
const captionIcon = component.find('.xyz-caption > i');
captionIcon.simulate('click');
component.instance().forceUpdate();
component.update();
expect(captionIcon.prop('className')).toBe('correctclass'); // but I get the incorrect class coz update isn't updating it .
| library | version
| ---------------- | -------
| Enzyme | latest
| React | 15.5.4
@smoholkar In my environment, the state is updated correctly.
Could you create a repository to reproduce it?
I find similar issue with where i'm not able to get the state value updated:
import React from 'react';
import { connect } from 'react-redux';
import {bindActionCreators} from 'redux';
import * as getData from '../../services/DataService';
class Container extends React.Component {
constructor(props){
super(props)
this.props.actions.getTemplates(1);
this.state = {
value: 1
}
}
handlelistOfTemplates = (value, index) => {
this.setState({ value });
};
componentDidMount() {
}
render() {
return(
<ListOfTemplates listOfTemplates={this.props.listOfTemplates} value={this.state.value} onChange={this.handlelistOfTemplates}/>
);
}
}
function mapStateToProps({state}) {
return {
listOfTemplates: state.listOfTemplates
}
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(getData, dispatch)
};
}
module.exports = connect(mapStateToProps, mapDispatchToProps)(Container);
And its test :
import React from 'react';
import sinon from 'sinon';
import expect from 'expect';
import { shallow } from 'enzyme';
import PropTypes from 'prop-types';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import { createMockStore, createMockDispatch } from 'redux-test-utils';
import Container from './Container';
const shallowWithStore = (component, store) => {
const context = {
store,
muiTheme: getMuiTheme(),
};
const childContextTypes = {
muiTheme: React.PropTypes.object.isRequired,
store: PropTypes.object.isRequired
}
return shallow(component, { context, childContextTypes });
};
let store;
const loadComponent = (testState) => {
const props = {
actions: {
getTemplates: () => {return Promise.resolve()}
}
}
store = createMockStore(testState)
return shallowWithStore(<Container {...props}/>, store);
}
const getFakeState = () => {
return {
listOfTemplates: [],
};
}
export default shallowWithStore;
describe('Container', () => {
let testState, component;
describe("when Appeal template is selected from select template dropdown", () => {
beforeAll(() => {
testState = getFakeState();
component = loadComponent(testState);
});
fit('should update the content in editor', (done) => {
component.dive().find('ListOfTemplates').props().onChange(2, 1);
component.dive().instance().forceUpdate();
component.dive().update();
expect(component.dive().state().value).toEqual(2); // it return 1 instead of 2
done();
});
});
});
Am i missing something?
@Sinha06 every time you call .dive() you create a new wrapper. You'll need to do const wrapper = component.dive(), and then all all those methods on wrapper instead.
Happy to reopen if there's a need.
@ljharb I have similar problem:
function setup(props, state) {
const store = {
subscribe: Function.prototype,
getState: () => state || Map({ byId: Map({ memberRoles: [] }) }),
dispatch: jest.fn(),
};
const defaultProps = {
permissions: [],
};
const container = shallow(
<MemberRoleDialog store={store} {...defaultProps} {...props} />
);
const wrapper = container.dive().dive();
return {
wrapper,
container,
store,
};
}
test('always renders a save <Button />, which sends only the changed fields', () => {
const { wrapper, store } = setup(
{ id: 0 },
Map({ byId: Map({ memberRoles: [role] }) })
);
wrapper.setState({ name: 'someOtherName' })
wrapper.update();
wrapper.find({ children: 'Save' }).simulate('click');
expect(store.dispatch).toHaveBeenCalledWith(
sendMemberRole('memberRoleDialog', 0, {
name: 'someOtherName',
})
);
});
@AnaRobynn ~Did you try [email protected]?~
This might be solved by https://github.com/airbnb/enzyme/pull/1742, which hasn't been released yet.
@koba04
I'm unsure. I usually don't use setState, but it seemed that neither simulate, nor invoking the "onEdit" prop would result in a state change. So I thought, I must be doing something wrong, let me setState to sanity check.
Fully moubting the component has the same issue, if I remember it correctly.
As soon as I get to work today, I'm going to sanity check by exporting the class itself in stead of the container and diving two times. Do you think it's better to open a new issue?
@AnaRobynn Yeah, it's very helpful to open a new issue with a test case that reproduces your problem 馃憤
@koba04 Sanity check resulted in a green test, restored the original test and it seems to be working now. I think there was an artifact in the docker image, because we recently bumped versions for enzyme. All good now! Yay! :)
Note to self and others: Clean repo, when having weird issues. Like deleting node_modules.
@Sinha06 every time you call
.dive()you create a new wrapper. You'll need to doconst wrapper = component.dive(), and then all all those methods onwrapperinstead.
You are damn genius!
Hi, as per @smoholkar question from a while back, I'm facing a similar issue when mounting my component for testing as well. I can't seem to find anyone else other than this post who is facing the issue of states not updating other than this post - is there a solution that I'm missing?
Most helpful comment
@Sinha06 every time you call
.dive()you create a new wrapper. You'll need to doconst wrapper = component.dive(), and then all all those methods onwrapperinstead.