rsuite 4.9.3 → 4.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/dist/rsuite.js +18 -601
  3. package/dist/rsuite.min.js +2 -2
  4. package/dist/rsuite.min.js.map +1 -1
  5. package/dist/styles/rsuite-dark-rtl.css +2 -1
  6. package/dist/styles/rsuite-dark-rtl.min.css +1 -1
  7. package/dist/styles/rsuite-dark-rtl.min.css.map +1 -1
  8. package/dist/styles/rsuite-dark.css +2 -1
  9. package/dist/styles/rsuite-dark.min.css +1 -1
  10. package/dist/styles/rsuite-dark.min.css.map +1 -1
  11. package/dist/styles/rsuite-default-rtl.css +2 -1
  12. package/dist/styles/rsuite-default-rtl.min.css +1 -1
  13. package/dist/styles/rsuite-default-rtl.min.css.map +1 -1
  14. package/dist/styles/rsuite-default.css +2 -1
  15. package/dist/styles/rsuite-default.min.css +1 -1
  16. package/dist/styles/rsuite-default.min.css.map +1 -1
  17. package/es/CheckTreePicker/CheckTreePicker.js +8 -7
  18. package/es/MultiCascader/DropdownMenu.js +1 -1
  19. package/es/MultiCascader/MultiCascader.d.ts +8 -0
  20. package/es/MultiCascader/MultiCascader.js +6 -3
  21. package/es/Overlay/OverlayTrigger.d.ts +1 -1
  22. package/es/Overlay/OverlayTrigger.js +12 -1
  23. package/es/Table/styles/common.less +2 -1
  24. package/es/utils/treeUtils.js +5 -1
  25. package/lib/CheckTreePicker/CheckTreePicker.js +8 -7
  26. package/lib/MultiCascader/DropdownMenu.js +1 -1
  27. package/lib/MultiCascader/MultiCascader.d.ts +8 -0
  28. package/lib/MultiCascader/MultiCascader.js +6 -3
  29. package/lib/Overlay/OverlayTrigger.d.ts +1 -1
  30. package/lib/Overlay/OverlayTrigger.js +12 -1
  31. package/lib/Table/styles/common.less +2 -1
  32. package/lib/utils/treeUtils.js +5 -1
  33. package/package.json +3 -3
  34. package/src/CheckTreePicker/CheckTreePicker.tsx +15 -7
  35. package/src/CheckTreePicker/test/CheckTreePickerSpec.js +184 -1
  36. package/src/MultiCascader/DropdownMenu.tsx +1 -1
  37. package/src/MultiCascader/MultiCascader.d.ts +8 -0
  38. package/src/MultiCascader/MultiCascader.tsx +4 -2
  39. package/src/MultiCascader/test/DropdownMenuSpec.js +17 -0
  40. package/src/MultiCascader/test/MultiCascaderSpec.js +14 -1
  41. package/src/Overlay/OverlayTrigger.d.ts +1 -1
  42. package/src/Overlay/OverlayTrigger.tsx +22 -1
  43. package/src/Overlay/test/OverlayTriggerSpec.js +155 -0
  44. package/src/Table/styles/common.less +2 -1
  45. package/src/TreePicker/test/TreePickerSpec.js +43 -15
  46. package/src/utils/treeUtils.ts +4 -1
@@ -4,10 +4,23 @@ import Enzyme, { mount } from 'enzyme';
4
4
  import Adapter from 'enzyme-adapter-react-16';
5
5
  import { getDOMNode, getInstance } from '@test/testUtils';
6
6
  import CheckTreePicker from '../CheckTreePicker';
7
- import { findDOMNode } from 'react-dom';
7
+ import ReactDOM, { findDOMNode } from 'react-dom';
8
+ import { assert } from 'chai';
8
9
 
9
10
  Enzyme.configure({ adapter: new Adapter() });
10
11
 
12
+ let container;
13
+
14
+ beforeEach(() => {
15
+ container = document.createElement('div');
16
+ document.body.appendChild(container);
17
+ });
18
+
19
+ afterEach(() => {
20
+ document.body.removeChild(container);
21
+ container = null;
22
+ });
23
+
11
24
  const data = [
12
25
  {
13
26
  label: 'Master',
@@ -298,6 +311,66 @@ describe('CheckTreePicker', () => {
298
311
  instance.unmount();
299
312
  });
300
313
 
314
+ it('Should return 2 values', done => {
315
+ const customData = [
316
+ {
317
+ value: '1',
318
+ label: '1',
319
+ children: [
320
+ {
321
+ value: '1-1',
322
+ label: '1-1'
323
+ },
324
+ {
325
+ value: '1-2',
326
+ label: '1-2'
327
+ },
328
+ {
329
+ value: '1-3',
330
+ label: '1-3'
331
+ }
332
+ ]
333
+ },
334
+ {
335
+ value: '2',
336
+ label: '2',
337
+ children: [
338
+ {
339
+ value: '2-1',
340
+ label: '2-1'
341
+ },
342
+ {
343
+ value: '2-2',
344
+ label: '2-2'
345
+ },
346
+ {
347
+ value: '2-3',
348
+ label: '2-3'
349
+ }
350
+ ]
351
+ }
352
+ ];
353
+
354
+ const doneOp = values => {
355
+ if (values.length === 2) {
356
+ done();
357
+ }
358
+ };
359
+ const instance = getDOMNode(
360
+ <CheckTreePicker
361
+ data={customData}
362
+ inline
363
+ value={['1-1', '1-2', '1-3']}
364
+ cascade
365
+ defaultExpandAll
366
+ onChange={doneOp}
367
+ />
368
+ );
369
+
370
+ assert.equal(instance.querySelectorAll('.rs-checkbox-checked').length, 4);
371
+ ReactTestUtils.Simulate.change(instance.querySelectorAll('.rs-check-tree-node input')[5]);
372
+ });
373
+
301
374
  it('Should render empty tree when searchKeyword is `name`', () => {
302
375
  const instance = mount(<CheckTreePicker data={data} inline searchKeyword="name" />);
303
376
  assert.equal(instance.find('.rs-check-tree-node').length, 0);
@@ -384,4 +457,114 @@ describe('CheckTreePicker', () => {
384
457
  assert.equal(instance2.querySelector('.rs-picker-toggle-placeholder').innerText, 'Select');
385
458
  assert.equal(instance3.querySelector('.rs-picker-toggle-placeholder').innerText, 'Select');
386
459
  });
460
+
461
+ it('Should controlled by value', () => {
462
+ const TestApp = React.forwardRef((props, ref) => {
463
+ const [value, setValue] = React.useState();
464
+ const pickerRef = React.useRef();
465
+ React.useImperativeHandle(ref, () => ({
466
+ picker: pickerRef.current,
467
+ setValue
468
+ }));
469
+
470
+ return <CheckTreePicker data={data} ref={pickerRef} value={value} defaultExpandAll open />;
471
+ });
472
+
473
+ TestApp.displayName = 'TestCheckTreePicker';
474
+
475
+ const ref = React.createRef();
476
+ ReactTestUtils.act(() => {
477
+ ReactDOM.render(<TestApp ref={ref} />, container);
478
+ });
479
+
480
+ assert.equal(
481
+ ref.current.picker.treeViewRef.current.querySelectorAll('.rs-checkbox-checked').length,
482
+ 0
483
+ );
484
+
485
+ ReactTestUtils.act(() => {
486
+ ref.current.setValue(['Master']);
487
+ });
488
+ assert.equal(
489
+ ref.current.picker.treeViewRef.current.querySelectorAll('.rs-checkbox-checked').length,
490
+ 4
491
+ );
492
+ });
493
+
494
+ it('Should controlled by expandItemValues', () => {
495
+ const TestApp = React.forwardRef((props, ref) => {
496
+ const [expandItemValues, setExpandItemValues] = React.useState();
497
+ const pickerRef = React.useRef();
498
+ React.useImperativeHandle(ref, () => ({
499
+ picker: pickerRef.current,
500
+ setExpandItemValues
501
+ }));
502
+
503
+ return (
504
+ <CheckTreePicker data={data} ref={pickerRef} expandItemValues={expandItemValues} open />
505
+ );
506
+ });
507
+
508
+ TestApp.displayName = 'TestCheckTreePicker';
509
+
510
+ const ref = React.createRef();
511
+ ReactTestUtils.act(() => {
512
+ ReactDOM.render(<TestApp ref={ref} />, container);
513
+ });
514
+
515
+ assert.equal(
516
+ ref.current.picker.treeViewRef.current.querySelectorAll('.rs-check-tree-node-expanded')
517
+ .length,
518
+ 0
519
+ );
520
+
521
+ ReactTestUtils.act(() => {
522
+ ref.current.setExpandItemValues(['Master']);
523
+ });
524
+ assert.equal(
525
+ ref.current.picker.treeViewRef.current.querySelectorAll('.rs-check-tree-node-expanded')
526
+ .length,
527
+ 1
528
+ );
529
+ });
530
+
531
+ it('Should controlled by uncheckableItemValues', () => {
532
+ const TestApp = React.forwardRef((props, ref) => {
533
+ const [uncheckableItemValues, setUncheckableItemValues] = React.useState();
534
+ const pickerRef = React.useRef();
535
+ React.useImperativeHandle(ref, () => ({
536
+ picker: pickerRef.current,
537
+ setUncheckableItemValues
538
+ }));
539
+
540
+ return (
541
+ <CheckTreePicker
542
+ data={data}
543
+ ref={pickerRef}
544
+ uncheckableItemValues={uncheckableItemValues}
545
+ open
546
+ />
547
+ );
548
+ });
549
+
550
+ TestApp.displayName = 'TestCheckTreePicker';
551
+
552
+ const ref = React.createRef();
553
+ ReactTestUtils.act(() => {
554
+ ReactDOM.render(<TestApp ref={ref} />, container);
555
+ });
556
+
557
+ assert.equal(
558
+ ref.current.picker.treeViewRef.current.querySelectorAll('.rs-checkbox-inner').length,
559
+ 5
560
+ );
561
+
562
+ ReactTestUtils.act(() => {
563
+ ref.current.setUncheckableItemValues(['Master']);
564
+ });
565
+ assert.equal(
566
+ ref.current.picker.treeViewRef.current.querySelectorAll('.rs-checkbox-inner').length,
567
+ 4
568
+ );
569
+ });
387
570
  });
@@ -166,7 +166,7 @@ class DropdownMenu extends React.Component<DropdownMenuProps> {
166
166
  className={classes}
167
167
  componentClass="li"
168
168
  indeterminate={cascade && !active && this.utils.isSomeChildChecked(node, value)}
169
- onSelectItem={this.handleSelect.bind(this, layer, node)}
169
+ onSelectItem={this.handleSelect.bind(this, layer)}
170
170
  onCheck={onCheck}
171
171
  checkable={!uncheckable}
172
172
  >
@@ -41,6 +41,14 @@ export interface MultiCascaderProps<ValueType = any> extends FormControlPickerPr
41
41
  event: React.SyntheticEvent<HTMLElement>
42
42
  ) => void;
43
43
 
44
+ /** Called after the checkbox state changes */
45
+ onCheck?: (
46
+ value: ValueType,
47
+ item: any,
48
+ checked: boolean,
49
+ event: React.SyntheticEvent<HTMLElement>
50
+ ) => void;
51
+
44
52
  /** Called when clean */
45
53
  onClean?: (event: React.SyntheticEvent<HTMLElement>) => void;
46
54
 
@@ -57,7 +57,8 @@ class MultiCascader extends React.Component<MultiCascaderProps, MultiCascaderSta
57
57
  renderMenuItem: PropTypes.func,
58
58
  renderMenu: PropTypes.func,
59
59
  onSearch: PropTypes.func,
60
- onSelect: PropTypes.func
60
+ onSelect: PropTypes.func,
61
+ onCheck: PropTypes.func
61
62
  };
62
63
 
63
64
  static defaultProps = {
@@ -187,7 +188,7 @@ class MultiCascader extends React.Component<MultiCascaderProps, MultiCascaderSta
187
188
  }
188
189
 
189
190
  handleCheck = (item: any, event: React.SyntheticEvent<any>, checked: boolean) => {
190
- const { valueKey, onChange, cascade, uncheckableItemValues } = this.props;
191
+ const { valueKey, cascade, uncheckableItemValues, onChange, onCheck } = this.props;
191
192
  const itemValue = item[valueKey];
192
193
  let value = [];
193
194
 
@@ -208,6 +209,7 @@ class MultiCascader extends React.Component<MultiCascaderProps, MultiCascaderSta
208
209
  }
209
210
 
210
211
  onChange?.(value, event);
212
+ onCheck?.(value, item, checked, event);
211
213
  };
212
214
 
213
215
  handleChangeForSearchItem = (value: any, checked: boolean, event: React.SyntheticEvent<any>) => {
@@ -112,6 +112,23 @@ describe('MultiCascader - DropdownMenu', () => {
112
112
  }, 1);
113
113
  });
114
114
 
115
+ it('Should call onSelect callback with 4 params', done => {
116
+ const doneOp = (node, activePaths, createConcat, event) => {
117
+ if (
118
+ typeof node === 'object' &&
119
+ Array.isArray(activePaths) &&
120
+ typeof createConcat === 'function' &&
121
+ event.target
122
+ ) {
123
+ done();
124
+ }
125
+ };
126
+
127
+ const instance = getInstance(<Dropdown defaultOpen data={items} onSelect={doneOp} />);
128
+ const menuContainer = getDOMNode(instance.menuContainerRef.current);
129
+ ReactTestUtils.Simulate.click(menuContainer.querySelectorAll('.rs-checkbox')[1]);
130
+ });
131
+
115
132
  it('Should not call onSelect callback on disabled item', () => {
116
133
  const onSelectSpy = sinon.spy();
117
134
  const instance = getInstance(
@@ -7,7 +7,6 @@ import Button from '../../Button';
7
7
 
8
8
  const namespace = `${globalKey}-picker`;
9
9
  const toggleClassName = `.${namespace}-toggle-placeholder`;
10
- const activeClassName = '.rs-dropdown-menu-item-active';
11
10
 
12
11
  const items = [
13
12
  {
@@ -209,6 +208,20 @@ describe('MultiCascader', () => {
209
208
  ReactTestUtils.Simulate.click(menu.querySelector('.rs-checkbox'));
210
209
  });
211
210
 
211
+ it('Should call onCheck callback ', done => {
212
+ let checkbox = null;
213
+ const doneOp = (value, item, checked, event) => {
214
+ if (value[0] === 'abc' && item.value === 'abc' && checked && event.target === checkbox) {
215
+ done();
216
+ }
217
+ };
218
+
219
+ const instance = getInstance(<Dropdown data={items} defaultOpen onCheck={doneOp} />);
220
+ const menu = findDOMNode(instance.menuContainerRef.current);
221
+ checkbox = menu.querySelector('.rs-checkbox-wrapper');
222
+ ReactTestUtils.Simulate.click(checkbox);
223
+ });
224
+
212
225
  it('Should call onChange callback ', done => {
213
226
  const doneOp = value => {
214
227
  if (value[0] === 'abc') {
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { AnimationEventProps, StandardProps, TypeAttributes } from '../@types/common';
3
3
 
4
- export type OverlayTriggerTrigger = 'click' | 'hover' | 'focus' | 'active' | 'none';
4
+ export type OverlayTriggerTrigger = 'click' | 'contextMenu' | 'hover' | 'focus' | 'active' | 'none';
5
5
 
6
6
  export interface TriggerProps extends AnimationEventProps, StandardProps {
7
7
  /** Triggering events */
@@ -26,6 +26,7 @@ interface TriggerProps {
26
26
  onMouseOut?: React.MouseEventHandler;
27
27
  onBlur?: React.MouseEventHandler;
28
28
  onClick?: React.MouseEventHandler;
29
+ onContextMenu?: React.MouseEventHandler;
29
30
  onFocus?: React.MouseEventHandler;
30
31
  }
31
32
 
@@ -81,7 +82,11 @@ class OverlayTrigger extends React.Component<OverlayTriggerProps, OverlayTrigger
81
82
  handleSpeakerMouseLeave = () => {
82
83
  const { trigger } = this.props;
83
84
  this.mouseEnteredToSpeaker = false;
84
- if (!isOneOf('click', trigger) && !isOneOf('active', trigger)) {
85
+ if (
86
+ !isOneOf('click', trigger) &&
87
+ !isOneOf('active', trigger) &&
88
+ !isOneOf('contextMenu', trigger)
89
+ ) {
85
90
  this.hideWithCheck();
86
91
  }
87
92
  };
@@ -130,6 +135,10 @@ class OverlayTrigger extends React.Component<OverlayTriggerProps, OverlayTrigger
130
135
  }
131
136
  };
132
137
 
138
+ preventDefault = (event: React.MouseEvent<Element, MouseEvent>) => {
139
+ event.preventDefault();
140
+ };
141
+
133
142
  handleDelayedShow = () => {
134
143
  const { delayShow, enterable } = this.props;
135
144
  const delay = isNil(delayShow) ? this.props.delay : delayShow;
@@ -197,6 +206,8 @@ class OverlayTrigger extends React.Component<OverlayTriggerProps, OverlayTrigger
197
206
 
198
207
  if (isOneOf('click', trigger)) {
199
208
  overlayProps.onHide = createChainedFunction(this.hide, onHide);
209
+ } else if (isOneOf('contextMenu', trigger)) {
210
+ overlayProps.onHide = createChainedFunction(this.hide, onHide);
200
211
  } else if (isOneOf('active', trigger)) {
201
212
  overlayProps.onHide = createChainedFunction(this.hide, onHide);
202
213
  }
@@ -228,6 +239,7 @@ class OverlayTrigger extends React.Component<OverlayTriggerProps, OverlayTrigger
228
239
  children,
229
240
  speaker,
230
241
  onClick,
242
+ onContextMenu,
231
243
  trigger,
232
244
  onMouseOver,
233
245
  onMouseOut,
@@ -254,6 +266,15 @@ class OverlayTrigger extends React.Component<OverlayTriggerProps, OverlayTrigger
254
266
  props.onClick = createChainedFunction(this.toggleHideAndShow, props.onClick);
255
267
  }
256
268
 
269
+ if (isOneOf('contextMenu', trigger)) {
270
+ props.onContextMenu = createChainedFunction(
271
+ this.preventDefault,
272
+ this.toggleHideAndShow,
273
+ triggerProps.onContextMenu,
274
+ onContextMenu
275
+ );
276
+ }
277
+
257
278
  if (isOneOf('active', trigger)) {
258
279
  props.onClick = createChainedFunction(this.handleDelayedShow, props.onClick);
259
280
  }
@@ -0,0 +1,155 @@
1
+ import React from 'react';
2
+ import ReactTestUtils from 'react-dom/test-utils';
3
+ import { getDOMNode } from '@test/testUtils';
4
+
5
+ import OverlayTrigger from '../OverlayTrigger';
6
+ import Tooltip from '../../Tooltip';
7
+
8
+ describe('OverlayTrigger', () => {
9
+ it('Should create Whisper element', () => {
10
+ const instance = getDOMNode(
11
+ <OverlayTrigger speaker={<Tooltip>tooltip</Tooltip>}>
12
+ <button type="button">button</button>
13
+ </OverlayTrigger>
14
+ );
15
+ assert.equal(instance.nodeName, 'BUTTON');
16
+ });
17
+
18
+ it('Should maintain overlay classname when trigger click', () => {
19
+ const whisper = getDOMNode(
20
+ <OverlayTrigger
21
+ trigger="click"
22
+ speaker={<Tooltip className="test-whisper_click">test</Tooltip>}
23
+ >
24
+ <button>button</button>
25
+ </OverlayTrigger>
26
+ );
27
+ ReactTestUtils.Simulate.click(whisper);
28
+ assert.equal(document.getElementsByClassName('test-whisper_click').length, 1);
29
+ });
30
+
31
+ it('Should maintain overlay classname when trigger contextMenu', () => {
32
+ const whisper = getDOMNode(
33
+ <OverlayTrigger
34
+ trigger="contextMenu"
35
+ speaker={<Tooltip className="test-whisper_context-menu">test</Tooltip>}
36
+ >
37
+ <button>button</button>
38
+ </OverlayTrigger>
39
+ );
40
+ ReactTestUtils.Simulate.contextMenu(whisper);
41
+ assert.equal(document.getElementsByClassName('test-whisper_context-menu').length, 1);
42
+ });
43
+
44
+ it('Should maintain overlay classname when trigger focus', () => {
45
+ const whisper = getDOMNode(
46
+ <OverlayTrigger
47
+ trigger="focus"
48
+ speaker={<Tooltip className="test-whisper_focus">test</Tooltip>}
49
+ >
50
+ <button>button</button>
51
+ </OverlayTrigger>
52
+ );
53
+
54
+ ReactTestUtils.Simulate.focus(whisper);
55
+ assert.equal(document.getElementsByClassName('test-whisper_focus').length, 1);
56
+ });
57
+
58
+ it('Should maintain overlay classname when trigger mouseOver and setting [trigger="hover"]', () => {
59
+ const whisper = getDOMNode(
60
+ <OverlayTrigger
61
+ trigger="hover"
62
+ speaker={<Tooltip className="test-whisper_hover">test</Tooltip>}
63
+ >
64
+ <button>button</button>
65
+ </OverlayTrigger>
66
+ );
67
+
68
+ ReactTestUtils.Simulate.mouseOver(whisper);
69
+ assert.equal(document.getElementsByClassName('test-whisper_hover').length, 1);
70
+ });
71
+
72
+ it('Should maintain overlay classname when trigger click and setting [trigger="active"] ', () => {
73
+ const whisper = getDOMNode(
74
+ <OverlayTrigger
75
+ trigger="active"
76
+ speaker={<Tooltip className="test-whisper_active">test</Tooltip>}
77
+ >
78
+ <button>button</button>
79
+ </OverlayTrigger>
80
+ );
81
+
82
+ ReactTestUtils.Simulate.click(whisper);
83
+ assert.equal(document.getElementsByClassName('test-whisper_active').length, 1);
84
+ });
85
+
86
+ it('Should call onClick callback', done => {
87
+ const doneOp = () => {
88
+ done();
89
+ };
90
+
91
+ const whisper = getDOMNode(
92
+ <OverlayTrigger onClick={doneOp} trigger="click" speaker={<Tooltip />}>
93
+ <button>button</button>
94
+ </OverlayTrigger>
95
+ );
96
+
97
+ ReactTestUtils.Simulate.click(whisper);
98
+ });
99
+
100
+ it('Should call onContextMenu callback', done => {
101
+ const doneOp = () => {
102
+ done();
103
+ };
104
+
105
+ const whisper = getDOMNode(
106
+ <OverlayTrigger onContextMenu={doneOp} trigger="contextMenu" speaker={<Tooltip />}>
107
+ <button>button</button>
108
+ </OverlayTrigger>
109
+ );
110
+
111
+ ReactTestUtils.Simulate.contextMenu(whisper);
112
+ });
113
+
114
+ it('Should call onFocus callback', done => {
115
+ const doneOp = () => {
116
+ done();
117
+ };
118
+
119
+ const whisper = getDOMNode(
120
+ <OverlayTrigger onFocus={doneOp} trigger="focus" speaker={<Tooltip />}>
121
+ <button>button</button>
122
+ </OverlayTrigger>
123
+ );
124
+
125
+ ReactTestUtils.Simulate.focus(whisper);
126
+ });
127
+
128
+ it('Should call onMouseOver callback', done => {
129
+ const doneOp = () => {
130
+ done();
131
+ };
132
+
133
+ const whisper = getDOMNode(
134
+ <OverlayTrigger onMouseOver={doneOp} trigger="hover" speaker={<Tooltip />}>
135
+ <button>button</button>
136
+ </OverlayTrigger>
137
+ );
138
+
139
+ ReactTestUtils.Simulate.mouseOver(whisper);
140
+ });
141
+
142
+ it('Should call onMouseOut callback', done => {
143
+ const doneOp = () => {
144
+ done();
145
+ };
146
+
147
+ const whisper = getDOMNode(
148
+ <OverlayTrigger onMouseOut={doneOp} trigger="hover" speaker={<Tooltip />}>
149
+ <button>button</button>
150
+ </OverlayTrigger>
151
+ );
152
+
153
+ ReactTestUtils.Simulate.mouseOut(whisper);
154
+ });
155
+ });
@@ -166,11 +166,12 @@
166
166
  border-style: solid;
167
167
  border-width: 0;
168
168
  border-color: @table-border-color;
169
- display: block;
170
169
  overflow: hidden;
171
170
  position: absolute;
172
171
  white-space: normal;
173
172
  background: @table-body-background;
173
+ display: table;
174
+ table-layout: fixed;
174
175
 
175
176
  &.first {
176
177
  border-left-width: 0;
@@ -2,13 +2,22 @@ import React from 'react';
2
2
  import ReactTestUtils from 'react-dom/test-utils';
3
3
  import Enzyme, { mount } from 'enzyme';
4
4
  import Adapter from 'enzyme-adapter-react-16';
5
- import { findDOMNode } from 'react-dom';
5
+ import ReactDOM, { findDOMNode } from 'react-dom';
6
6
  import { getDOMNode, getInstance } from '@test/testUtils';
7
7
  import TreePicker from '../TreePicker';
8
8
 
9
9
  Enzyme.configure({ adapter: new Adapter() });
10
+ let container;
10
11
 
11
- export const delay = timeout => new Promise(resolve => setTimeout(resolve, timeout));
12
+ beforeEach(() => {
13
+ container = document.createElement('div');
14
+ document.body.appendChild(container);
15
+ });
16
+
17
+ afterEach(() => {
18
+ document.body.removeChild(container);
19
+ container = null;
20
+ });
12
21
 
13
22
  const data = [
14
23
  {
@@ -157,7 +166,7 @@ describe('TreePicker', () => {
157
166
  });
158
167
 
159
168
  it('Should call `onChange` callback', done => {
160
- const doneOp = values => {
169
+ const doneOp = () => {
161
170
  done();
162
171
  };
163
172
  const instance = getDOMNode(<TreePicker inline onChange={doneOp} data={data} />);
@@ -243,7 +252,7 @@ describe('TreePicker', () => {
243
252
  });
244
253
 
245
254
  it('Should focus item by keyCode=13 ', done => {
246
- const doneOp = values => {
255
+ const doneOp = () => {
247
256
  done();
248
257
  };
249
258
  const instance = mount(<TreePicker data={data} onChange={doneOp} inline defaultExpandAll />);
@@ -271,8 +280,6 @@ describe('TreePicker', () => {
271
280
  });
272
281
 
273
282
  it('Should load data async', () => {
274
- let activeNode = null;
275
- let layer = 0;
276
283
  const data = [
277
284
  {
278
285
  label: 'Master',
@@ -293,8 +300,6 @@ describe('TreePicker', () => {
293
300
 
294
301
  let newData = [];
295
302
  const mockOnExpand = (node, l, concat) => {
296
- activeNode = node;
297
- layer = l;
298
303
  newData = concat(data, children);
299
304
  };
300
305
 
@@ -391,13 +396,36 @@ describe('TreePicker', () => {
391
396
  assert.ok(list[0].innerText, 'Louisa');
392
397
  });
393
398
 
394
- it('Should call renderValue', () => {
395
- const instance1 = getDOMNode(<TreePicker value="Test" renderValue={() => '1'} />);
396
- const instance2 = getDOMNode(<TreePicker value="Test" renderValue={() => null} />);
397
- const instance3 = getDOMNode(<TreePicker value="Test" renderValue={() => undefined} />);
399
+ it('Should controlled by expandItemValues', () => {
400
+ const TestApp = React.forwardRef((props, ref) => {
401
+ const [expandItemValues, setExpandItemValues] = React.useState();
402
+ const pickerRef = React.useRef();
403
+ React.useImperativeHandle(ref, () => ({
404
+ picker: pickerRef.current,
405
+ setExpandItemValues
406
+ }));
407
+
408
+ return <TreePicker data={data} ref={pickerRef} expandItemValues={expandItemValues} open />;
409
+ });
410
+
411
+ TestApp.displayName = 'TestCheckTreePicker';
412
+
413
+ const ref = React.createRef();
414
+ ReactTestUtils.act(() => {
415
+ ReactDOM.render(<TestApp ref={ref} />, container);
416
+ });
398
417
 
399
- assert.equal(instance1.querySelector('.rs-picker-toggle-value').innerText, '1');
400
- assert.equal(instance2.querySelector('.rs-picker-toggle-placeholder').innerText, 'Select');
401
- assert.equal(instance3.querySelector('.rs-picker-toggle-placeholder').innerText, 'Select');
418
+ assert.equal(
419
+ ref.current.picker.treeViewRef.current.querySelectorAll('.rs-tree-node-expanded').length,
420
+ 0
421
+ );
422
+
423
+ ReactTestUtils.act(() => {
424
+ ref.current.setExpandItemValues(['Master']);
425
+ });
426
+ assert.equal(
427
+ ref.current.picker.treeViewRef.current.querySelectorAll('.rs-tree-node-expanded').length,
428
+ 1
429
+ );
402
430
  });
403
431
  });
@@ -123,7 +123,10 @@ export function treeDeprecatedWarning(
123
123
  * @param b
124
124
  */
125
125
  export function compareArray(a: any[], b: any[]) {
126
- return _.isArray(a) && _.isArray(b) && !shallowEqualArray(a, b);
126
+ if (!(_.isArray(a) && _.isArray(b))) {
127
+ return a !== b;
128
+ }
129
+ return !shallowEqualArray(a, b);
127
130
  }
128
131
 
129
132
  /**