Last active
December 31, 2023 09:07
-
-
Save a-h/21df0f432ae02a6dfed941debb0e5950 to your computer and use it in GitHub Desktop.
Testing styled Material UI components with Enzyme
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import { shallow } from 'enzyme'; | |
const Item = text => <p>Item {text}</p>; | |
const Composition = ({ showB }) => ( | |
<p> | |
<Item text="A" /> | |
{showB && <Item text="B" />} | |
</p>); | |
describe('<Composition />', () => { | |
it('should render one item if showB is set to false', () => { | |
const wrapper = shallow(<Composition showB={false} />); | |
expect(wrapper.find(Item)).toHaveLength(1); | |
}); | |
it('should render two items if showB is set to true', () => { | |
const wrapper = shallow(<Composition showB />); | |
expect(wrapper.find(Item)).toHaveLength(2); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import { shallow } from 'enzyme'; | |
import { CircularProgress } from 'material-ui-next/Progress'; | |
const Composition = () => ( | |
<p> | |
<CircularProgress size={24} /> | |
</p>); | |
describe('<Composition />', () => { | |
it('should render a CircularProgress', () => { | |
const wrapper = shallow(<Composition />); | |
expect(wrapper.find(CircularProgress)).toHaveLength(1); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import { shallow } from 'enzyme'; | |
import { CircularProgress } from 'material-ui-next/Progress'; | |
import { withStyles } from 'material-ui-next/styles'; | |
import PropTypes from 'prop-types'; | |
const style = { | |
buttonProgress: { | |
position: 'absolute', | |
top: '50%', | |
left: '50%', | |
marginTop: -12, | |
marginLeft: -12, | |
}, | |
}; | |
const Composer = ({ | |
classes, | |
}) => ( | |
<p> | |
<CircularProgress size={24} className={classes.buttonProgress} /> | |
</p>); | |
Composer.propTypes = { | |
classes: PropTypes.object.isRequired, | |
}; | |
const Composition = withStyles(style)(Composer); | |
describe('<Composition />', () => { | |
it('should render a styled CircularProgress', () => { | |
const wrapper = shallow(<Composition />); | |
// Note the use of dive() because Composition is now wrapped by the withStyles higher order component. | |
expect(wrapper.dive().find(CircularProgress)).toHaveLength(1); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import { CircularProgress } from 'material-ui-next/Progress'; | |
import { createShallow } from 'material-ui-next/test-utils'; | |
import { withStyles } from 'material-ui-next/styles'; | |
import PropTypes from 'prop-types'; | |
const style = { | |
buttonProgress: { | |
position: 'absolute', | |
top: '50%', | |
left: '50%', | |
marginTop: -12, | |
marginLeft: -12, | |
}, | |
}; | |
const Composer = ({ | |
classes, | |
}) => ( | |
<p> | |
<CircularProgress size={24} className={classes.buttonProgress} /> | |
</p>); | |
Composer.propTypes = { | |
classes: PropTypes.object.isRequired, | |
}; | |
const Composition = withStyles(style)(Composer); | |
describe('<Composition />', () => { | |
const shallow = createShallow(); | |
it('should render CircularProgress', () => { | |
const wrapper = shallow(<Composition />); | |
// Still need to dive(). | |
expect(wrapper.dive().find(CircularProgress)).toHaveLength(1); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import { CircularProgress } from 'material-ui-next/Progress'; | |
import { mount } from 'enzyme'; | |
import { withStyles } from 'material-ui-next/styles'; | |
import PropTypes from 'prop-types'; | |
const style = { | |
buttonProgress: { | |
position: 'absolute', | |
top: '50%', | |
left: '50%', | |
marginTop: -12, | |
marginLeft: -12, | |
}, | |
}; | |
const Composer = ({ | |
classes, | |
}) => ( | |
<div> | |
<CircularProgress size={24} className={classes.buttonProgress} /> | |
</div>); | |
Composer.propTypes = { | |
classes: PropTypes.object.isRequired, | |
}; | |
const Composition = withStyles(style)(Composer); | |
describe('<Composition />', () => { | |
it('should render CircularProgress', () => { | |
const wrapper = mount(<Composition />); | |
// No longer need to dive(). | |
expect(wrapper.find(CircularProgress)).toHaveLength(1); | |
}); | |
}); |
Thank you. I am testing button clicks, state and direct API calls, and I agree with you that I shouldn't test state and API to test what is rendered instead. Unfortunately I use react-Konva and the graph is quite complex, I didn't manage to test the rendering yet.
Thanks very much.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, I'm not sure I'm going to be of great help here - I have only ever used Redux for state management and use stateless functional components to populate the props of a component. The props of each styled component are accessible (I put together an example here: https://github.com/a-h/styled-test - run
npx jest
to run the test) so deeper inspection isn't required.Sounds like your code structure is already pretty fixed, but I'd consider restructuring to have stateless functional components to handle the presentation. Those components can be tested simply - e.g. "given a row count of 10, 10 rows are rendered", "when this button is clicked, the onClick prop is called". Then, I'd add a higher-order component that wraps the others. The tests here would be along the lines of "when this function is called, the prop passed to this component changes".
If you find a nice solution, I'd be interested to see it!