Skip to content
Snippets Groups Projects
Commit eb1aa24d authored by Jessie Keck's avatar Jessie Keck
Browse files

Add a generic NestedMenu presentational component.

parent c7370481
Branches
Tags
No related merge requests found
import React from 'react';
import { shallow } from 'enzyme';
import NestedMenu from '../../../src/components/NestedMenu';
/**
* Helper function to wrap creating a NestedMenu component
*/
function createWrapper(props) {
return shallow(
<NestedMenu
icon={<>GivenIcon</>}
label="GivenLabel"
{...props}
>
<>GivenChildren</>
</NestedMenu>,
);
}
describe('NestedMenu', () => {
let wrapper;
it('renders the given icon wrapped in a MUI ListItemIcon', () => {
wrapper = createWrapper();
expect(wrapper.find('WithStyles(ListItemIcon)').children().text()).toEqual('GivenIcon');
});
it('renders the given label wrapped in a MUI Typography', () => {
wrapper = createWrapper();
expect(wrapper.find('WithStyles(Typography)').children().text()).toEqual('GivenLabel');
});
it('renders the given children wrapped in a MUI Collapse', () => {
wrapper = createWrapper();
expect(wrapper.find('WithStyles(Collapse)').children().text()).toEqual('GivenChildren');
});
it('toggles the local nestedMenuIsOpen state when clicking the MenuItem', () => {
wrapper = createWrapper();
expect(wrapper.state().nestedMenuIsOpen).toBe(false);
wrapper.find('WithStyles(MenuItem)').simulate('click');
expect(wrapper.state().nestedMenuIsOpen).toBe(true);
wrapper.find('WithStyles(MenuItem)').simulate('click');
expect(wrapper.state().nestedMenuIsOpen).toBe(false);
});
it('renders the appropriate expand/collapse icon based on the menu open state', () => {
wrapper = createWrapper();
expect(wrapper.state().nestedMenuIsOpen).toBe(false);
expect(wrapper.find('pure(ExpandMoreSharpIcon)').length).toBe(1);
expect(wrapper.find('purl(ExpandLessSharpIcon)').length).toBe(0);
wrapper.setState({ nestedMenuIsOpen: true });
expect(wrapper.find('pure(ExpandMoreSharpIcon)').length).toBe(0);
expect(wrapper.find('pure(ExpandLessSharpIcon)').length).toBe(1);
});
it("the MUI Collapse component's in prop is based on the nestedMenuIsOpen state", () => {
wrapper = createWrapper();
expect(wrapper.state().nestedMenuIsOpen).toBe(false);
expect(wrapper.find('WithStyles(Collapse)').find({ in: false }).length).toBe(1);
expect(wrapper.find('WithStyles(Collapse)').find({ in: true }).length).toBe(0);
wrapper.setState({ nestedMenuIsOpen: true });
expect(wrapper.find('WithStyles(Collapse)').find({ in: true }).length).toBe(1);
expect(wrapper.find('WithStyles(Collapse)').find({ in: false }).length).toBe(0);
});
});
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Collapse from '@material-ui/core/Collapse';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import MenuItem from '@material-ui/core/MenuItem';
import Typography from '@material-ui/core/Typography';
import ExpandLess from '@material-ui/icons/ExpandLessSharp';
import ExpandMore from '@material-ui/icons/ExpandMoreSharp';
/**
* NestedMenu ~ A presentation component to render a menu item and have
* it control the visibility of the MUI List passed in as the children
*/
export default class NestedMenu extends Component {
/**
* constructor -
*/
constructor(props) {
super(props);
this.state = {
nestedMenuIsOpen: false,
};
this.handleMenuClick = this.handleMenuClick.bind(this);
}
/**
* handleMenuClick toggles the nestedMenuIsOpen state
*/
handleMenuClick() {
const { nestedMenuIsOpen } = this.state;
this.setState({
nestedMenuIsOpen: !nestedMenuIsOpen,
});
}
/**
* Returns the rendered component
*/
render() {
const { nestedMenuIsOpen } = this.state;
const { children, icon, label } = this.props;
return (
<>
<MenuItem onClick={this.handleMenuClick}>
<ListItemIcon>{icon}</ListItemIcon>
{/* ListItemText adds left padding and we want this to line-up with menu items */}
<ListItemText style={{ paddingLeft: 0 }}>
<Typography varient="inherit">{label}</Typography>
</ListItemText>
{
nestedMenuIsOpen
? <ExpandLess />
: <ExpandMore />
}
</MenuItem>
<Collapse in={nestedMenuIsOpen} timeout="auto" unmountOnExit>
{children}
</Collapse>
</>
);
}
}
NestedMenu.propTypes = {
children: PropTypes.element.isRequired,
icon: PropTypes.element.isRequired,
label: PropTypes.string.isRequired,
};
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment