Skip to content

Commit

Permalink
[ExpansioPanel] use context
Browse files Browse the repository at this point in the history
  • Loading branch information
eps1lon committed Feb 26, 2019
1 parent dd79b24 commit ab39b2f
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 70 deletions.
63 changes: 33 additions & 30 deletions packages/material-ui/src/ExpansionPanel/ExpansionPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Collapse from '../Collapse';
import Paper from '../Paper';
import withStyles from '../styles/withStyles';
import { isMuiElement } from '../utils/reactHelpers';
import { PureProvider } from './ExpansionPanelContext';

export const styles = theme => {
const transition = {
Expand Down Expand Up @@ -112,12 +113,15 @@ function ExpansionPanel(props) {

const [expanded, setExpanded] = useMaybeControlled(expandedProp, defaultExpanded);

function handleChange(event) {
setExpanded(isExpanded => !isExpanded);
if (onChange) {
onChange(event, !expanded);
}
}
const handleChange = React.useCallback(
event => {
setExpanded(isExpanded => !isExpanded);
if (onChange) {
onChange(event, !expanded);
}
},
[expanded, setExpanded, onChange],
);

let summary = null;

Expand All @@ -135,37 +139,35 @@ function ExpansionPanel(props) {
);

if (isMuiElement(child, ['ExpansionPanelSummary'])) {
summary = React.cloneElement(child, {
disabled,
expanded,
onChange: handleChange,
});
summary = child;
return null;
}

return child;
});

return (
<Paper
className={clsx(
classes.root,
{
[classes.expanded]: expanded,
[classes.disabled]: disabled,
[classes.rounded]: !square,
},
classNameProp,
)}
elevation={1}
square={square}
{...other}
>
{summary}
<Collapse in={expanded} timeout="auto" {...CollapseProps}>
{children}
</Collapse>
</Paper>
<PureProvider disabled={disabled} expanded={expanded} onChange={handleChange}>
<Paper
className={clsx(
classes.root,
{
[classes.expanded]: expanded,
[classes.disabled]: disabled,
[classes.rounded]: !square,
},
classNameProp,
)}
elevation={1}
square={square}
{...other}
>
{summary}
<Collapse in={expanded} timeout="auto" {...CollapseProps}>
{children}
</Collapse>
</Paper>
</PureProvider>
);
}

Expand Down Expand Up @@ -220,6 +222,7 @@ ExpansionPanel.propTypes = {
ExpansionPanel.defaultProps = {
defaultExpanded: false,
disabled: false,
onChange: noop,
square: false,
TransitionComponent: Collapse,
};
Expand Down
57 changes: 27 additions & 30 deletions packages/material-ui/src/ExpansionPanel/ExpansionPanel.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,16 @@ import React from 'react';
import PropTypes from 'prop-types';
import { assert } from 'chai';
import { spy } from 'sinon';
import { createShallow, createMount, getClasses } from '@material-ui/core/test-utils';
import Collapse from '../Collapse';
import { createMount, getClasses } from '@material-ui/core/test-utils';
import Paper from '../Paper';
import ExpansionPanel from './ExpansionPanel';
import ExpansionPanelSummary from '../ExpansionPanelSummary';

describe('<ExpansionPanel />', () => {
let mount;
let shallow;
let classes;

before(() => {
shallow = createShallow({ dive: true });
mount = createMount();
classes = getClasses(<ExpansionPanel>foo</ExpansionPanel>);
});
Expand Down Expand Up @@ -48,23 +45,29 @@ describe('<ExpansionPanel />', () => {
});

it('should render the custom className and the root class', () => {
const wrapper = shallow(<ExpansionPanel className="test-class-name">foo</ExpansionPanel>);
assert.strictEqual(wrapper.hasClass('test-class-name'), true);
assert.strictEqual(wrapper.hasClass(classes.root), true);
const wrapper = mount(<ExpansionPanel className="test-class-name">foo</ExpansionPanel>);
const root = wrapper.find(`.${classes.root}`).first();
assert.strictEqual(root.hasClass('test-class-name'), true);
});

it('should render the summary and collapse elements', () => {
const wrapper = shallow(
<ExpansionPanel>
<ExpansionPanelSummary />
const wrapper = mount(
<ExpansionPanel expanded>
<ExpansionPanelSummary>summary</ExpansionPanelSummary>
<div>Hello</div>
</ExpansionPanel>,
);

assert.strictEqual(wrapper.childAt(0).type(), ExpansionPanelSummary);
const collapse = wrapper.childAt(1);
assert.strictEqual(collapse.type(), Collapse);
assert.strictEqual(collapse.children().length, 1, 'collapse should have 1 children div');
assert.strictEqual(
wrapper
.find('[aria-expanded=true]')
.first()
.text(),
'summary',
);

const collapse = wrapper.find('Collapse');
assert.strictEqual(collapse.text(), 'Hello');
});

it('should handle the expanded prop', () => {
Expand Down Expand Up @@ -101,21 +104,15 @@ describe('<ExpansionPanel />', () => {
assert.strictEqual(handleChange.args[0][1], false);
});

it('when undefined onChange and controlled should not call the onChange', () => {
const handleChange = spy();
const wrapper = mount(
<ExpansionPanel onChange={handleChange} expanded>
<ExpansionPanelSummary />
</ExpansionPanel>,
);
wrapper.setProps({ onChange: undefined });
wrapper.find(ExpansionPanelSummary).simulate('click');
assert.strictEqual(handleChange.callCount, 0);
});

it('when disabled should have the disabled class', () => {
const wrapper = shallow(<ExpansionPanel disabled>foo</ExpansionPanel>);
assert.strictEqual(wrapper.hasClass(classes.disabled), true);
const wrapper = mount(<ExpansionPanel disabled>foo</ExpansionPanel>);
assert.strictEqual(
wrapper
.find(`.${classes.root}`)
.first()
.hasClass(classes.disabled),
true,
);
});

it('should handle the TransitionComponent prop', () => {
Expand Down Expand Up @@ -149,8 +146,8 @@ describe('<ExpansionPanel />', () => {

describe('prop: children', () => {
it('should accept an empty child', () => {
shallow(
<ExpansionPanel>
mount(
<ExpansionPanel expanded>
<ExpansionPanelSummary />
{null}
</ExpansionPanel>,
Expand Down
11 changes: 11 additions & 0 deletions packages/material-ui/src/ExpansionPanel/ExpansionPanelContext.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import PropTypes from 'prop-types';
import warning from 'warning';

const ExpansionPanelContext = React.createContext({
Expand All @@ -15,4 +16,14 @@ const ExpansionPanelContext = React.createContext({
},
});

export const PureProvider = React.memo(props => {
const { children, ...value } = props;

return <ExpansionPanelContext.Provider value={value}>{children}</ExpansionPanelContext.Provider>;
});

PureProvider.propTypes = {
children: PropTypes.node,
};

export default ExpansionPanelContext;
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import clsx from 'clsx';
import ButtonBase from '../ButtonBase';
import { useExpansionPanel } from '../ExpansionPanel';
import withStyles from '../styles/withStyles';

export const styles = theme => {
Expand Down Expand Up @@ -75,17 +76,15 @@ function ExpansionPanelSummary(props) {
children,
classes,
className,
disabled,
expanded,
expandIcon,
IconButtonProps,
onBlur,
onChange,
onClick,
onFocusVisible,
...other
} = props;
const [focused, setFocused] = React.useState(false);
const { disabled, expanded, onChange } = useExpansionPanel();

function handleFocusVisible(event) {
setFocused(true);
Expand Down Expand Up @@ -191,7 +190,6 @@ const noop = () => {};
ExpansionPanelSummary.defaultProps = {
disabled: false,
onBlur: noop,
onChange: noop,
onClick: noop,
onFocusVisible: noop,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ import {
getClasses,
} from '@material-ui/core/test-utils';
import ButtonBase from '../ButtonBase';
import ExpansionPanel from '../ExpansionPanel';
import ExpansionPanelSummary from './ExpansionPanelSummary';

describe('<ExpansionPanelSummary />', () => {
describe.only('<ExpansionPanelSummary />', () => {
let mount;
let shallow;
let classes;
Expand Down Expand Up @@ -105,11 +106,17 @@ describe('<ExpansionPanelSummary />', () => {
return result;
}, {});

const wrapper = shallow(<ExpansionPanelSummary {...handlers} />);
const wrapper = mount(
<ExpansionPanel expanded>
<ExpansionPanelSummary {...handlers} />
</ExpansionPanel>,
);

const summary = wrapper.find('[aria-expanded]').first();

events.forEach(n => {
const event = n.charAt(2).toLowerCase() + n.slice(3);
wrapper.simulate(event, { persist: () => {} });
summary.simulate(event, { persist: () => {} });
assert.strictEqual(handlers[n].callCount, 1, `should have called the ${n} handler`);
});
});
Expand All @@ -118,7 +125,11 @@ describe('<ExpansionPanelSummary />', () => {
describe('prop: onChange', () => {
it('fires onChange if the summary control is clicked', () => {
const handleChange = spy();
const wrapper = mount(<ExpansionPanelSummary expanded={false} onChange={handleChange} />);
const wrapper = mount(
<ExpansionPanel expanded={false} onChange={handleChange}>
<ExpansionPanelSummary />
</ExpansionPanel>,
);

const control = findOutermostIntrinsic(wrapper.find('[aria-expanded]'));
const eventMock = 'woofExpansionPanelSummary';
Expand All @@ -132,8 +143,15 @@ describe('<ExpansionPanelSummary />', () => {
describe('prop: click', () => {
it('should trigger onClick', () => {
const handleClick = spy();
const wrapper = shallow(<ExpansionPanelSummary onClick={handleClick} />);
wrapper.simulate('click');
const wrapper = mount(
<ExpansionPanel expanded={false} onChange={() => {}}>
<ExpansionPanelSummary onClick={handleClick} />
</ExpansionPanel>,
);
wrapper
.find('[aria-expanded]')
.first()
.simulate('click');
assert.strictEqual(handleClick.callCount, 1);
});
});
Expand Down

0 comments on commit ab39b2f

Please sign in to comment.