Skip to content

Commit f79c40c

Browse files
Merge pull request #5514 from oliviertassinari/list-item-control
[ListItem] Fix an issue with the controlled behavior
2 parents 0a1fab8 + 62b83d0 commit f79c40c

2 files changed

Lines changed: 64 additions & 26 deletions

File tree

src/List/ListItem.js

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -434,9 +434,21 @@ class ListItem extends Component {
434434

435435
handleNestedListToggle = (event) => {
436436
event.stopPropagation();
437-
this.setState({open: !this.state.open}, () => {
438-
this.props.onNestedListToggle(this);
439-
});
437+
438+
if (this.props.open === null) {
439+
this.setState({open: !this.state.open}, () => {
440+
this.props.onNestedListToggle(this);
441+
});
442+
} else {
443+
// Exposing `this` in the callback is quite a bad API.
444+
// I'm doing a one level deep clone to expose a fake state.open.
445+
this.props.onNestedListToggle({
446+
...this,
447+
state: {
448+
open: !this.state.open,
449+
},
450+
});
451+
}
440452
};
441453

442454
handleRightIconButtonKeyboardFocus = (event, isKeyboardFocused) => {

src/List/ListItem.spec.js

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ import React from 'react';
33
import {shallow} from 'enzyme';
44
import {assert} from 'chai';
55
import ListItem from './ListItem';
6-
import NestedList from './NestedList';
6+
import EnhancedButton from '../internal/EnhancedButton';
77
import getMuiTheme from '../styles/getMuiTheme';
8+
import NestedList from './NestedList';
89

910
describe('<ListItem />', () => {
1011
const muiTheme = getMuiTheme();
@@ -14,7 +15,7 @@ describe('<ListItem />', () => {
1415
const wrapper = shallowWithContext(
1516
<ListItem />
1617
);
17-
const enhancedButton = wrapper.find('EnhancedButton');
18+
const enhancedButton = wrapper.find(EnhancedButton);
1819
assert.ok(enhancedButton.length);
1920
});
2021

@@ -25,7 +26,7 @@ describe('<ListItem />', () => {
2526
primaryText={testText}
2627
/>
2728
);
28-
const enhancedButton = wrapper.find('EnhancedButton');
29+
const enhancedButton = wrapper.find(EnhancedButton);
2930

3031
assert.strictEqual(enhancedButton.children().text(), testText);
3132
});
@@ -37,7 +38,7 @@ describe('<ListItem />', () => {
3738
className={testClass}
3839
/>
3940
);
40-
const enhancedButton = wrapper.find('EnhancedButton');
41+
const enhancedButton = wrapper.find(EnhancedButton);
4142
assert.strictEqual(enhancedButton.prop('className'), testClass);
4243
});
4344

@@ -47,7 +48,7 @@ describe('<ListItem />', () => {
4748
disabled={true}
4849
/>
4950
);
50-
assert.notOk(wrapper.find('EnhancedButton').length, 'should not have an EnhancedButton');
51+
assert.notOk(wrapper.find(EnhancedButton).length, 'should not have an EnhancedButton');
5152
});
5253

5354
it('should display a disabled list-item with a class if specified.', () => {
@@ -59,7 +60,7 @@ describe('<ListItem />', () => {
5960
/>
6061
);
6162

62-
assert.notOk(wrapper.find('EnhancedButton').length, 'should not have an EnhancedButton');
63+
assert.notOk(wrapper.find(EnhancedButton).length, 'should not have an EnhancedButton');
6364
assert.strictEqual(wrapper.find(`.${testClass}`).length, 1, 'should have a div with the test class');
6465
});
6566

@@ -75,19 +76,17 @@ describe('<ListItem />', () => {
7576
assert.strictEqual(wrapper.find(`.${testClass}`).length, 1, 'should have a div with the test class');
7677
});
7778

78-
describe('props: primaryTogglesNestedList', () => {
79+
describe('prop: primaryTogglesNestedList', () => {
7980
it('should toggle nested list when true', () => {
8081
const wrapper = shallowWithContext(
8182
<ListItem
82-
leftCheckbox={<div />}
83-
primaryText="Item text"
8483
primaryTogglesNestedList={true}
8584
nestedItems={[
86-
<ListItem key={1} primaryText="Nested item text" />,
85+
<ListItem key={1} />,
8786
]}
8887
/>
8988
);
90-
const primaryTextButton = wrapper.find('EnhancedButton');
89+
const primaryTextButton = wrapper.find(EnhancedButton);
9190

9291
assert.strictEqual(wrapper.find(NestedList).props().open, false);
9392

@@ -101,20 +100,18 @@ describe('<ListItem />', () => {
101100
it('should not render primary text button when false', () => {
102101
const wrapper = shallowWithContext(
103102
<ListItem
104-
leftCheckbox={<div />}
105-
primaryText="Item text"
106103
primaryTogglesNestedList={false}
107104
nestedItems={[
108-
<ListItem key={1} primaryText="Nested item text" />,
105+
<ListItem key={1} />,
109106
]}
110107
/>
111108
);
112109

113-
assert.strictEqual(wrapper.filter('EnhancedButton').length, 0);
110+
assert.strictEqual(wrapper.filter(EnhancedButton).length, 0);
114111
});
115112
});
116113

117-
describe('props: open', () => {
114+
describe('prop: open', () => {
118115
it('should initially open nested list', () => {
119116
const wrapper = shallowWithContext(
120117
<ListItem
@@ -145,19 +142,48 @@ describe('<ListItem />', () => {
145142
});
146143
assert.strictEqual(wrapper.find(NestedList).props().open, true);
147144
});
145+
146+
it('should not control the state', () => {
147+
const wrapper = shallowWithContext(
148+
<ListItem
149+
initiallyOpen={false}
150+
primaryTogglesNestedList={true}
151+
nestedItems={[
152+
<ListItem key={1} />,
153+
]}
154+
/>
155+
);
156+
157+
const primaryTextButton = wrapper.find(EnhancedButton);
158+
primaryTextButton.simulate('touchTap', {stopPropagation: () => {}});
159+
assert.strictEqual(wrapper.find(NestedList).props().open, true);
160+
});
161+
162+
it('should control the state', () => {
163+
const wrapper = shallowWithContext(
164+
<ListItem
165+
open={false}
166+
primaryTogglesNestedList={true}
167+
nestedItems={[
168+
<ListItem key={1} />,
169+
]}
170+
/>
171+
);
172+
173+
const primaryTextButton = wrapper.find(EnhancedButton);
174+
primaryTextButton.simulate('touchTap', {stopPropagation: () => {}});
175+
assert.strictEqual(wrapper.find(NestedList).props().open, false);
176+
});
148177
});
149178

150-
describe('props: hoverColor', () => {
179+
describe('prop: hoverColor', () => {
151180
it('should use a background color on hover if hoverColor is specified', () => {
152181
const testColor = '#ededed';
153182
const wrapper = shallowWithContext(
154-
<ListItem
155-
hoverColor={testColor}
156-
/>
183+
<ListItem hoverColor={testColor} />
157184
);
158-
wrapper.find('EnhancedButton').simulate('mouseEnter');
159-
wrapper.update();
160-
assert.strictEqual(wrapper.find('EnhancedButton').prop('style').backgroundColor, testColor);
185+
wrapper.find(EnhancedButton).simulate('mouseEnter');
186+
assert.strictEqual(wrapper.find(EnhancedButton).props().style.backgroundColor, testColor);
161187
});
162188
});
163189
});

0 commit comments

Comments
 (0)