treeSelect.test.js 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940
  1. import { TreeSelect, Icon } from '../../index';
  2. import { BASE_CLASS_PREFIX } from '../../../semi-foundation/base/constants';
  3. const treeChildren = [
  4. {
  5. label: '北京',
  6. value: 'Beijing',
  7. key: 'beijing',
  8. },
  9. {
  10. label: '上海',
  11. value: 'Shanghai',
  12. key: 'shanghai',
  13. },
  14. ];
  15. const treeData = [
  16. {
  17. label: '亚洲',
  18. value: 'Yazhou',
  19. key: 'yazhou',
  20. children: [
  21. {
  22. label: '中国',
  23. value: 'Zhongguo',
  24. key: 'zhongguo',
  25. children: treeChildren,
  26. },
  27. {
  28. label: '日本',
  29. value: 'Riben',
  30. key: 'riben',
  31. children: [
  32. {
  33. label: '东京',
  34. value: 'Dongjing',
  35. key: 'dongjing'
  36. },
  37. {
  38. label: '大阪',
  39. value: 'Daban',
  40. key: 'daban'
  41. }
  42. ]
  43. },
  44. ],
  45. },
  46. {
  47. label: '北美洲',
  48. value: 'Beimeizhou',
  49. key: 'beimeizhou',
  50. children: [
  51. {
  52. label: '美国',
  53. value: 'Meiguo',
  54. key: 'meiguo'
  55. },
  56. {
  57. label: '加拿大',
  58. value: 'Jianada',
  59. key: 'jianada'
  60. }
  61. ]
  62. },
  63. ];
  64. const treeData2 = [
  65. {
  66. label: '亚洲',
  67. value: 'Asia',
  68. key: '0',
  69. children: [
  70. {
  71. label: '中国',
  72. value: 'China',
  73. key: '0-0',
  74. children: [
  75. {
  76. label: '北京',
  77. value: 'Beijing',
  78. key: '0-0-0',
  79. },
  80. {
  81. label: '上海',
  82. value: 'Shanghai',
  83. key: '0-0-1',
  84. },
  85. ],
  86. },
  87. ],
  88. },
  89. {
  90. label: '北美洲',
  91. value: 'North America',
  92. key: '1',
  93. }
  94. ];
  95. const treeData3 = [
  96. {
  97. label: '亚洲',
  98. value: 'Asia',
  99. key: '0',
  100. children: [
  101. {
  102. label: '中国',
  103. value: 'China',
  104. key: '0-0',
  105. },
  106. ],
  107. },
  108. {
  109. label: '北美洲',
  110. value: 'North America',
  111. key: '1',
  112. }
  113. ];
  114. let commonProps = {
  115. motion: false,
  116. motionExpand: false,
  117. mouseEnterDelay: 0,
  118. mouseLeaveDelay: 0,
  119. };
  120. function getTreeSelect(props) {
  121. props = { treeData: treeData, ...props }
  122. return mount(
  123. <TreeSelect
  124. {...commonProps}
  125. defaultOpen={true}
  126. {...props}
  127. />,
  128. {
  129. attachTo: document.getElementById('container')
  130. }
  131. );
  132. }
  133. describe('TreeSelect', () => {
  134. beforeEach(() => {
  135. // Avoid `attachTo: document.body` Warning
  136. const div = document.createElement('div');
  137. div.setAttribute('id', 'container');
  138. document.body.appendChild(div);
  139. });
  140. afterEach(() => {
  141. const div = document.getElementById('container');
  142. if (div) {
  143. document.body.removeChild(div);
  144. }
  145. document.body.innerHTML = '';
  146. });
  147. it('className / style', () => {
  148. let props = {
  149. className: 'test',
  150. style: { height: 420 },
  151. };
  152. let treeSelect = getTreeSelect(props);
  153. expect(treeSelect.hasClass('test')).toEqual(true);
  154. expect(treeSelect.find('div.test')).toHaveStyle('height', 420);
  155. });
  156. it('placeholder', () => {
  157. const props = {
  158. placeholder: 'semi'
  159. };
  160. const treeSelect = getTreeSelect(props);
  161. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select-selection-placeholder`).instance().textContent).toEqual('semi');
  162. });
  163. it('validateStatus', () => {
  164. const props = {};
  165. const treeSelect = getTreeSelect(props);
  166. expect(treeSelect.exists(`.${BASE_CLASS_PREFIX}-tree-select-error`)).toEqual(false);
  167. expect(treeSelect.exists(`.${BASE_CLASS_PREFIX}-tree-select-warning`)).toEqual(false);
  168. treeSelect.setProps({ validateStatus: 'error' });
  169. expect(treeSelect.exists(`.${BASE_CLASS_PREFIX}-tree-select-error`)).toEqual(true);
  170. treeSelect.setProps({ validateStatus: 'warning' });
  171. expect(treeSelect.exists(`.${BASE_CLASS_PREFIX}-tree-select-warning`)).toEqual(true);
  172. });
  173. it('outerBottomSlot', () => {
  174. let outerBottomSlot = <div class="outer-slot">outer</div>;
  175. let props = {
  176. outerBottomSlot: outerBottomSlot,
  177. };
  178. const treeSelect = getTreeSelect(props);
  179. expect(treeSelect.contains(outerBottomSlot)).toEqual(true);
  180. });
  181. it('size', () => {
  182. const props = {};
  183. const treeSelect = getTreeSelect(props);
  184. expect(treeSelect.exists(`.${BASE_CLASS_PREFIX}-tree-select-large`)).toEqual(false);
  185. expect(treeSelect.exists(`.${BASE_CLASS_PREFIX}-tree-select-small`)).toEqual(false);
  186. treeSelect.setProps({ size: 'large' });
  187. expect(treeSelect.exists(`.${BASE_CLASS_PREFIX}-tree-select-large`)).toEqual(true);
  188. treeSelect.setProps({ size: 'small' });
  189. expect(treeSelect.exists(`.${BASE_CLASS_PREFIX}-tree-select-small`)).toEqual(true);
  190. });
  191. it('custom dropdownClassName / dropdownStyle / zIndex', () => {
  192. let props = {
  193. dropdownClassName: 'test',
  194. dropdownStyle: {
  195. color: 'red',
  196. },
  197. zIndex: 2000,
  198. };
  199. let treeSelect = getTreeSelect(props);
  200. expect(treeSelect.exists('.test')).toEqual(true);
  201. expect(treeSelect.find('.test')).toHaveStyle('color', 'red');
  202. expect(document.querySelector(`.${BASE_CLASS_PREFIX}-portal`).style.zIndex).toEqual("2000");
  203. });
  204. it('dropdownMatchSelectWidth = true', () => {
  205. // dropdownMatchSelectWidth default is true
  206. let props = {
  207. style: { width: 90 },
  208. defaultValue: 'abc',
  209. };
  210. let treeSelect = getTreeSelect(props);
  211. // cause jsdom doesn't support layout engine like browser, so you can't access offsetWidth/scrollWidth or use getBoundingRect(), it will always return 0;
  212. // just use getComputedStyle to avoid this problem.
  213. let selector = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select`).getDOMNode();
  214. let selectorWidth = window.getComputedStyle(selector).width; // expect 90px
  215. let list = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select-popover`).getDOMNode();
  216. let listWidth = window.getComputedStyle(list).minWidth;
  217. expect(selectorWidth).toEqual(listWidth);
  218. treeSelect.unmount();
  219. });
  220. it('dropdownMatchSelectWidth = false', () => {
  221. let props = {
  222. style: { width: 90 },
  223. defaultValue: 'abc',
  224. dropdownMatchSelectWidth: false,
  225. };
  226. let treeSelect = getTreeSelect(props);
  227. let selector = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select`).getDOMNode();
  228. let selectorWidth = window.getComputedStyle(selector).width; // expect 90px
  229. let list = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select-popover`).getDOMNode();
  230. let listWidth = window.getComputedStyle(list).minWidth;
  231. expect(selectorWidth).not.toEqual(listWidth);
  232. treeSelect.unmount();
  233. });
  234. it('getPopupContainer', () => {
  235. let treeSelect = getTreeSelect({
  236. getPopupContainer: () => document.querySelector(`.${BASE_CLASS_PREFIX}-tree-select`),
  237. });
  238. let dom = document.querySelector(`.${BASE_CLASS_PREFIX}-tree-select`);
  239. expect(dom.querySelectorAll(`.${BASE_CLASS_PREFIX}-tree-select-popover`).length).toEqual(1);
  240. });
  241. it('custom prefix / suffix / insetLabel', () => {
  242. let prefix = <div className="prefix">prefix content</div>;
  243. let suffix = <div className="suffix">suffix content</div>;
  244. let insetLabel = 'semi';
  245. const props = {
  246. prefix: prefix,
  247. suffix: suffix,
  248. };
  249. let treeSelect = getTreeSelect(props);
  250. expect(treeSelect.contains(prefix)).toEqual(true);
  251. expect(treeSelect.contains(suffix)).toEqual(true);
  252. treeSelect.unmount();
  253. let ntreeSelect = getTreeSelect({ insetLabel: insetLabel });
  254. expect(ntreeSelect.contains(insetLabel)).toEqual(true);
  255. ntreeSelect.unmount();
  256. });
  257. it('empty data', () => {
  258. let treeSelect = getTreeSelect({
  259. treeData: [],
  260. emptyContent: 'empty'
  261. });
  262. let node = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option`);
  263. expect(node.length).toEqual(1);
  264. expect(node.hasClass(`${BASE_CLASS_PREFIX}-tree-option-empty`)).toEqual(true);
  265. expect(node.instance().textContent).toEqual('empty');
  266. });
  267. it('defaultOpen', () => {
  268. let props = {
  269. defaultOpen: false,
  270. };
  271. let treeSelect = getTreeSelect(props);
  272. expect(treeSelect.state().isOpen).toEqual(false);
  273. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select-popover`).exists()).toEqual(false);
  274. treeSelect.unmount();
  275. let ntreeSelect = getTreeSelect({ defaultOpen: true, });
  276. expect(ntreeSelect.state().isOpen).toEqual(true);
  277. expect(ntreeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select-popover`).exists()).toEqual(true);
  278. let options = ntreeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option`);
  279. expect(ntreeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option`).length).toEqual(2);
  280. expect(options.at(0).getDOMNode().textContent).toEqual('亚洲');
  281. expect(options.at(1).getDOMNode().textContent).toEqual('北美洲');
  282. });
  283. it('defaultValue', () => {
  284. // auto expand parent, if node exist means parent is open
  285. let treeSelect = getTreeSelect({
  286. defaultValue: 'Beijing'
  287. });
  288. let selectedNode = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-selected`);
  289. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select-selection`).getDOMNode().textContent).toEqual('北京');
  290. expect(selectedNode.instance().textContent).toEqual('北京');
  291. treeSelect.unmount();
  292. // array case only select first item
  293. let tree2 = getTreeSelect({
  294. defaultValue: ['Riben', 'Beijing']
  295. });
  296. let selectedNode2 = tree2.find(`.${BASE_CLASS_PREFIX}-tree-option-selected`);
  297. expect(selectedNode2.instance().textContent).toEqual('日本');
  298. expect(tree2.find(`.${BASE_CLASS_PREFIX}-tree-select-selection`).getDOMNode().textContent).toEqual('日本');
  299. expect(tree2.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-2`).at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(true);
  300. })
  301. it('defaultExpandedKeys', () => {
  302. // auto expand parent
  303. let treeSelect = getTreeSelect({
  304. defaultExpandedKeys: ['zhongguo', 'beimeizhou']
  305. });
  306. // yazhou beimeizhou
  307. let topNode = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`);
  308. expect(topNode.at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(false);
  309. expect(topNode.at(1).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(false);
  310. // zhongguo riben
  311. let children = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-2`);
  312. expect(children.at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(false);
  313. expect(children.at(1).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(true);
  314. })
  315. it('defaultExpandAll', () => {
  316. let treeSelect = getTreeSelect({
  317. defaultExpandAll: true
  318. });
  319. let nodes = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option`);
  320. let collapsed = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-collapsed`);
  321. expect(nodes.length).toEqual(10);
  322. expect(collapsed.length).toEqual(0);
  323. treeSelect.setProps({ treeData: treeData2});
  324. treeSelect.update();
  325. const nodes2 = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option`);
  326. const collapsed2 = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-collapsed`);
  327. expect(nodes2.length).toEqual(2);
  328. expect(collapsed2.length).toEqual(2);
  329. })
  330. it('expandAll', () => {
  331. const treeSelect = getTreeSelect({
  332. expandAll: true
  333. });
  334. const nodes = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option`);
  335. const collapsed = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-collapsed`);
  336. expect(nodes.length).toEqual(10);
  337. expect(collapsed.length).toEqual(0);
  338. treeSelect.setProps({ treeData: treeData2});
  339. treeSelect.update();
  340. const nodes2 = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option`);
  341. const collapsed2 = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-collapsed`);
  342. expect(nodes2.length).toEqual(5);
  343. expect(collapsed2.length).toEqual(0);
  344. })
  345. it('if expandedKeys values work', () => {
  346. // auto expand parent
  347. let treeSelect = getTreeSelect({
  348. expandedKeys: ['beimeizhou']
  349. });
  350. // yazhou beimeizhou
  351. let topNode = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`);
  352. expect(topNode.at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(true);
  353. expect(topNode.at(1).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(false);
  354. treeSelect.setProps({ expandedKeys: ['yazhou', 'zhongguo', 'beimeizhou'] });
  355. treeSelect.update();
  356. // zhongguo riben
  357. let children = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-2`);
  358. expect(children.at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(false);
  359. expect(children.at(1).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(true);
  360. });
  361. it('if expand behavior works / onExpand', () => {
  362. const nativeEvent = { nativeEvent: { stopImmediatePropagation: () => { } } }
  363. let spyOnExpand = sinon.spy(() => { });
  364. let treeSelect = getTreeSelect({
  365. onExpand: spyOnExpand,
  366. });
  367. // yazhou
  368. let topNodeAsia = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`).at(0);
  369. let expandIcon = topNodeAsia.find(`.${BASE_CLASS_PREFIX}-tree-option-expand-icon`).at(0);
  370. // expand yazhou
  371. expandIcon.simulate('click', nativeEvent);
  372. expect(spyOnExpand.calledOnce).toBe(true);
  373. expect(spyOnExpand.calledWithMatch(["yazhou"], { expanded: true, node: { key: 'yazhou' } })).toEqual(true);
  374. // zhongguo riben
  375. let topNode = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`);
  376. expect(topNode.at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(false);
  377. expect(topNode.at(1).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(true);
  378. // collapse yazhou
  379. expandIcon.simulate('click', nativeEvent);
  380. expect(spyOnExpand.calledWithMatch([], { expanded: false, node: { key: 'yazhou' } })).toEqual(true);
  381. topNode = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`);
  382. expect(topNode.at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(true);
  383. });
  384. it('if expandedKeys controlled work / onExpand', () => {
  385. const nativeEvent = { nativeEvent: { stopImmediatePropagation: () => { } } }
  386. let spyOnExpand = sinon.spy(() => { });
  387. let treeSelect = getTreeSelect({
  388. expandedKeys: ['beimeizhou'],
  389. onExpand: spyOnExpand,
  390. });
  391. // yazhou
  392. let topNodeAsia = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`).at(0);
  393. let expandIcon = topNodeAsia.find(`.${BASE_CLASS_PREFIX}-tree-option-expand-icon`).at(0);
  394. // expand yazhou
  395. expandIcon.simulate('click', nativeEvent);
  396. expect(spyOnExpand.calledWithMatch(["beimeizhou", "yazhou"], { expanded: true, node: { key: 'yazhou' } })).toEqual(true);
  397. // zhongguo riben
  398. let topNode = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`);
  399. expect(topNode.at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(true);
  400. });
  401. it('select item / onSelect / onChange', () => {
  402. let spyOnSelect = sinon.spy(() => { });
  403. let spyOnChange = sinon.spy(() => { });
  404. let treeSelect = getTreeSelect({
  405. defaultExpandAll: true,
  406. onSelect: spyOnSelect,
  407. onChange: spyOnChange,
  408. });
  409. let nodeBeijing = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-3`).at(0);
  410. // select beijing
  411. nodeBeijing.simulate('click');
  412. // onSelect & onChange
  413. expect(spyOnSelect.calledOnce).toBe(true);
  414. expect(spyOnChange.calledOnce).toBe(true);
  415. expect(spyOnSelect.calledWithMatch('beijing', true, { key: "beijing" })).toEqual(true);
  416. expect(spyOnChange.calledWithMatch('Beijing', { key: "beijing" })).toEqual(true);
  417. let selectBox = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select`).at(0);
  418. selectBox.simulate('click');
  419. // classname
  420. nodeBeijing = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-3`).at(0);
  421. expect(nodeBeijing.hasClass(`${BASE_CLASS_PREFIX}-tree-option-selected`)).toEqual(true);
  422. // render in input box
  423. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select-selection`).getDOMNode().textContent).toEqual('北京');
  424. // change
  425. let nodeAsia = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`).at(0);
  426. // select asia
  427. nodeAsia.simulate('click');
  428. // onSelect & onChange
  429. expect(spyOnSelect.calledWithMatch('yazhou', true, { key: "yazhou" })).toEqual(true);
  430. expect(spyOnChange.calledWithMatch('Yazhou', { key: "yazhou" })).toEqual(true);
  431. selectBox.simulate('click');
  432. // classname
  433. nodeAsia = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`).at(0);
  434. expect(nodeAsia.hasClass(`${BASE_CLASS_PREFIX}-tree-option-selected`)).toEqual(true);
  435. // render in input box
  436. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select-selection`).getDOMNode().textContent).toEqual('亚洲');
  437. });
  438. it('onChange + value not changed', () => {
  439. let spyOnSelect = sinon.spy(() => { });
  440. let spyOnChange = sinon.spy(() => { });
  441. let treeSelect = getTreeSelect({
  442. defaultExpandAll: true,
  443. onSelect: spyOnSelect,
  444. onChange: spyOnChange,
  445. defaultValue: 'Beijing'
  446. });
  447. let nodeBeijing = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-3`).at(0);
  448. // select beijing
  449. nodeBeijing.simulate('click');
  450. // onSelect & onChange
  451. expect(spyOnSelect.calledOnce).toBe(true);
  452. expect(spyOnChange.notCalled).toBe(true);
  453. });
  454. it('onChange + onChangeWithObject', () => {
  455. let spyOnChange = sinon.spy(() => { });
  456. let treeSelect = getTreeSelect({
  457. defaultExpandAll: true,
  458. onChangeWithObject: true,
  459. onChange: spyOnChange,
  460. });
  461. let nodeBeijing = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-3`).at(0);
  462. // select beijing
  463. nodeBeijing.simulate('click');
  464. // onSelect & onChange
  465. expect(spyOnChange.calledOnce).toBe(true);
  466. expect(spyOnChange.calledWithMatch({ key: "beijing" })).toEqual(true);
  467. });
  468. it('treeNodeLabelProp', () => {
  469. // auto expand parent, if node exist means parent is open
  470. let treeSelect = getTreeSelect({
  471. defaultValue: 'Beijing',
  472. treeNodeLabelProp: 'value'
  473. });
  474. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select-selection`).getDOMNode().textContent).toEqual('Beijing');
  475. // select asia
  476. let nodeAsia = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`).at(0);
  477. nodeAsia.simulate('click');
  478. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select-selection`).getDOMNode().textContent).toEqual('Yazhou');
  479. })
  480. it('filterTreeNode = true shows input box', () => {
  481. let treeSelect = getTreeSelect({});
  482. let searchWrapper = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`)
  483. expect(searchWrapper.exists()).toEqual(false);
  484. treeSelect.setProps({
  485. filterTreeNode: true
  486. });
  487. treeSelect.update();
  488. searchWrapper = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`)
  489. expect(searchWrapper.exists()).toEqual(true);
  490. });
  491. it('searchPlaceholder', () => {
  492. let treeSelect = getTreeSelect({
  493. filterTreeNode: true,
  494. searchPlaceholder: 'test',
  495. });
  496. let searchWrapper = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`)
  497. expect(searchWrapper.find('input').instance().getAttribute('placeholder')).toEqual('test');
  498. });
  499. it('onSearch', () => {
  500. let onSearch = value => { };
  501. let spyOnSearch = sinon.spy(onSearch);
  502. let treeSelect = getTreeSelect({
  503. filterTreeNode: true,
  504. onSearch: spyOnSearch,
  505. });
  506. const searchWrapper = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  507. let searchValue = 'semi';
  508. let event = { target: { value: searchValue } };
  509. searchWrapper.find('input').simulate('change', event);
  510. expect(spyOnSearch.calledOnce).toBe(true);
  511. expect(spyOnSearch.calledWithMatch(searchValue)).toBe(true);
  512. });
  513. it('filterTreeNode shows correct result', () => {
  514. let treeSelect1 = getTreeSelect({
  515. filterTreeNode: true,
  516. });
  517. const searchWrapper = treeSelect1.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  518. let searchValue = '北';
  519. let event = { target: { value: searchValue } };
  520. searchWrapper.find('input').simulate('change', event);
  521. expect(treeSelect1.find(`.${BASE_CLASS_PREFIX}-tree-option`).length).toEqual(6);
  522. expect(treeSelect1.find(`.${BASE_CLASS_PREFIX}-tree-option-highlight`).length).toEqual(2);
  523. expect(treeSelect1.find(`.${BASE_CLASS_PREFIX}-tree-option-highlight`).at(0).instance().textContent).toEqual('北');
  524. expect(treeSelect1.find(`.${BASE_CLASS_PREFIX}-tree-option-highlight`).at(1).instance().textContent).toEqual('北');
  525. treeSelect1.unmount();
  526. let treeSelect2 = getTreeSelect({
  527. filterTreeNode: true,
  528. treeNodeFilterProp: 'value',
  529. });
  530. const searchWrapper2 = treeSelect2.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  531. let searchValue2 = 'an';
  532. let event2 = { target: { value: searchValue2 } };
  533. searchWrapper2.find('input').simulate('change', event2);
  534. expect(treeSelect2.find(`.${BASE_CLASS_PREFIX}-tree-option`).length).toEqual(10);
  535. expect(treeSelect2.find(`.${BASE_CLASS_PREFIX}-tree-option-filtered`).length).toEqual(3);
  536. expect(treeSelect2.find(`.${BASE_CLASS_PREFIX}-tree-option-filtered`).at(0).instance().textContent).toEqual('上海');
  537. expect(treeSelect2.find(`.${BASE_CLASS_PREFIX}-tree-option-filtered`).at(1).instance().textContent).toEqual('大阪');
  538. expect(treeSelect2.find(`.${BASE_CLASS_PREFIX}-tree-option-filtered`).at(2).instance().textContent).toEqual('加拿大');
  539. });
  540. it('filterTreeNode + no result', () => {
  541. let treeSelect1 = getTreeSelect({
  542. filterTreeNode: true,
  543. });
  544. const searchWrapper = treeSelect1.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  545. let searchValue = 'Bei';
  546. let event = { target: { value: searchValue } };
  547. searchWrapper.find('input').simulate('change', event);
  548. expect(treeSelect1.find(`.${BASE_CLASS_PREFIX}-tree-option`).length).toEqual(2);
  549. expect(treeSelect1.find(`.${BASE_CLASS_PREFIX}-tree-option-highlight`).length).toEqual(0);
  550. treeSelect1.unmount();
  551. let treeSelect2 = getTreeSelect({
  552. filterTreeNode: true,
  553. treeNodeFilterProp: 'value',
  554. });
  555. const searchWrapper2 = treeSelect2.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  556. let searchValue2 = '北';
  557. let event2 = { target: { value: searchValue2 } };
  558. searchWrapper2.find('input').simulate('change', event2);
  559. expect(treeSelect2.find(`.${BASE_CLASS_PREFIX}-tree-option`).length).toEqual(2);
  560. expect(treeSelect2.find(`.${BASE_CLASS_PREFIX}-tree-option-filtered`).length).toEqual(0);
  561. });
  562. it('async load data', () => {
  563. const nativeEvent = { nativeEvent: { stopImmediatePropagation: () => { } } }
  564. const then = jest.fn(() => Promise.resolve());
  565. const loadData = jest.fn(() => ({ then }));
  566. const data = {
  567. label: '亚洲',
  568. value: 'Asia',
  569. key: 'asia',
  570. };
  571. const treeSelect = getTreeSelect({
  572. loadData,
  573. loadedKeys: ['0-1'],
  574. treeData: [data]
  575. });
  576. const topNodeAsia = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`).at(0);
  577. const expandIcon = topNodeAsia.find(`.${BASE_CLASS_PREFIX}-tree-option-expand-icon`).at(0);
  578. expandIcon.simulate('click', nativeEvent);
  579. expect(loadData).toHaveBeenCalledWith(data);
  580. expect(then).toHaveBeenCalled();
  581. });
  582. it('filterTreeNode + treeNodeFilterProp', () => {
  583. let treeSelect = getTreeSelect({
  584. filterTreeNode: true,
  585. treeNodeFilterProp: 'value',
  586. });
  587. const searchWrapper = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  588. let searchValue = 'Bei';
  589. let event = { target: { value: searchValue } };
  590. searchWrapper.find('input').simulate('change', event);
  591. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option`).length).toEqual(6);
  592. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-filtered`).length).toEqual(2);
  593. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-filtered`).at(0).instance().textContent).toEqual('北京');
  594. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-filtered`).at(1).instance().textContent).toEqual('北美洲');
  595. });
  596. it('filterTreeNode + showFilteredOnly + no result', () => {
  597. let treeSelect = getTreeSelect({
  598. filterTreeNode: true,
  599. showFilteredOnly: true,
  600. });
  601. const searchWrapper = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  602. let searchValue = 'Bei';
  603. let event = { target: { value: searchValue } };
  604. searchWrapper.find('input').simulate('change', event);
  605. let node = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option`);
  606. expect(node.length).toEqual(1);
  607. expect(node.hasClass(`${BASE_CLASS_PREFIX}-tree-option-empty`)).toEqual(true);
  608. });
  609. it('filterTreeNode + showFilteredOnly shows correct result', () => {
  610. let treeSelect = getTreeSelect({
  611. filterTreeNode: true,
  612. showFilteredOnly: true,
  613. });
  614. const searchWrapper = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  615. let searchValue = '北';
  616. let event = { target: { value: searchValue } };
  617. searchWrapper.find('input').simulate('change', event);
  618. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option`).length).toEqual(4);
  619. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-highlight`).length).toEqual(2);
  620. });
  621. it('filterTreeNode as a func', () => {
  622. let treeSelect = getTreeSelect({
  623. filterTreeNode: (inputValue, treeNode) => treeNode === inputValue,
  624. });
  625. const searchWrapper = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  626. searchWrapper.find('input').simulate('change', { target: { value: '北' } });
  627. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-highlight`).length).toEqual(0);
  628. // update
  629. searchWrapper.find('input').simulate('change', { target: { value: '北京' } });
  630. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-highlight`).length).toEqual(1);
  631. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-highlight`).instance().textContent).toEqual('北京');
  632. });
  633. it('controlled: value shows correct', () => {
  634. let treeSelect = getTreeSelect({
  635. value: 'Beijing'
  636. });
  637. let selectedNode = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-selected`);
  638. expect(selectedNode.instance().textContent).toEqual('北京');
  639. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select-selection`).getDOMNode().textContent).toEqual('北京');
  640. treeSelect.unmount();
  641. // array case only select first item
  642. let treeSelect2 = getTreeSelect({
  643. value: ['Riben', 'Beijing']
  644. });
  645. let selectedNode2 = treeSelect2.find(`.${BASE_CLASS_PREFIX}-tree-option-selected`);
  646. expect(selectedNode2.instance().textContent).toEqual('日本');
  647. expect(treeSelect2.find(`.${BASE_CLASS_PREFIX}-tree-select-selection`).getDOMNode().textContent).toEqual('日本');
  648. expect(treeSelect2.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-2`).at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(true);
  649. });
  650. it('controlled: fire onChange and ui not update', () => {
  651. let spyOnChange = sinon.spy(() => { });
  652. let treeSelect = getTreeSelect({
  653. value: '',
  654. defaultExpandAll: true,
  655. onChange: spyOnChange,
  656. });
  657. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-selected`).exists()).toEqual(false);
  658. let nodeBeijing = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-3`).at(0);
  659. // select beijing
  660. nodeBeijing.simulate('click');
  661. // onSelect & onChange
  662. expect(spyOnChange.calledOnce).toBe(true);
  663. expect(spyOnChange.calledWithMatch("Beijing")).toEqual(true);
  664. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-selected`).exists()).toEqual(false);
  665. });
  666. it('controlled: value + onChangeWithObject', () => {
  667. let spyOnChange = sinon.spy(() => { });
  668. let treeSelect = getTreeSelect({
  669. value: {
  670. label: '北京',
  671. value: 'Beijing',
  672. key: 'beijing',
  673. },
  674. defaultExpandAll: true,
  675. onChange: spyOnChange,
  676. onChangeWithObject: true,
  677. });
  678. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-selected`).exists()).toEqual(true);
  679. });
  680. it('virtualized: fixed height', () => {
  681. let treeSelect = getTreeSelect({
  682. defaultExpandAll: true,
  683. virtualize: {
  684. itemSize: 28,
  685. height: 84,
  686. },
  687. });
  688. // virtual list
  689. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-virtual-list`).exists()).toEqual(true);
  690. // fewer nodes
  691. let nodes = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option`);
  692. expect(nodes.length).toBeLessThan(10);
  693. });
  694. it('disabled', () => {
  695. let treeSelect = getTreeSelect({
  696. disabled: true,
  697. });
  698. let inputBox = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select-disabled`);
  699. expect(inputBox.exists()).toEqual(true);
  700. expect(treeSelect.state().isOpen).toEqual(false);
  701. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-wrapper`).exists()).toEqual(false);
  702. inputBox.simulate('click');
  703. expect(treeSelect.state().isOpen).toEqual(false);
  704. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-wrapper`).exists()).toEqual(false);
  705. });
  706. it('renderSelectedItem', () => {
  707. let spyOnSelect = sinon.spy(() => { });
  708. let spyOnChange = sinon.spy(() => { });
  709. let treeSelect = getTreeSelect({
  710. renderSelectedItem: treeNode => treeNode.value,
  711. defaultExpandAll: true,
  712. onSelect: spyOnSelect,
  713. onChange: spyOnChange,
  714. });
  715. const yaZhouKey = 'yazhou';
  716. const yaZhouValue = 'Yazhou';
  717. let nodeYaZhou = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`).at(0);
  718. nodeYaZhou.simulate('click');
  719. // 判断回调,这里其实没有更新,不是很重要
  720. expect(spyOnSelect.calledOnce).toBe(true);
  721. expect(spyOnChange.calledOnce).toBe(true);
  722. expect(spyOnSelect.getCall(0).args[0]).toEqual(yaZhouKey);
  723. expect(spyOnChange.getCall(0).args[0]).toEqual(yaZhouValue);
  724. // 判断已选项的渲染
  725. const innerHTML = document.querySelector('.semi-tree-select-selection span').textContent;
  726. expect(innerHTML).toEqual(yaZhouValue);
  727. });
  728. it('search autofocus', () => {
  729. let treeSelect = getTreeSelect({
  730. filterTreeNode: true,
  731. searchAutoFocus: true,
  732. });
  733. let selectEle = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select`)
  734. selectEle.simulate('click');
  735. setTimeout(() => {
  736. let searchWrapper = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`)
  737. const searchInput = searchWrapper.find(`input`)
  738. expect(searchInput.matchesElement(document.activeElement)).toEqual(true);
  739. done();
  740. }, 100);
  741. });
  742. it('treeData is updated should not clear value when uncontrolled mode and single selection', () => {
  743. const nativeEvent = { nativeEvent: { stopImmediatePropagation: () => { } } }
  744. const treeSelect = getTreeSelect({
  745. defaultExpandAll: true
  746. });
  747. treeSelect
  748. .find(`.${BASE_CLASS_PREFIX}-tree-option-list .${BASE_CLASS_PREFIX}-tree-option`)
  749. .at(2)
  750. .simulate('click', nativeEvent);
  751. expect(
  752. treeSelect
  753. .find(`.${BASE_CLASS_PREFIX}-tree-select .${BASE_CLASS_PREFIX}-tree-select-selection span`)
  754. .getDOMNode()
  755. .textContent
  756. ).toEqual('北京');
  757. treeSelect.setProps({ treeData: treeChildren});
  758. treeSelect.update();
  759. expect(
  760. treeSelect
  761. .find(`.${BASE_CLASS_PREFIX}-tree-select .${BASE_CLASS_PREFIX}-tree-select-selection span`)
  762. .getDOMNode()
  763. .textContent
  764. ).toEqual('北京');
  765. treeSelect.setProps({ treeData: treeData2});
  766. treeSelect.update();
  767. expect(
  768. treeSelect
  769. .find(`.${BASE_CLASS_PREFIX}-tree-select .${BASE_CLASS_PREFIX}-tree-select-selection span`)
  770. .getDOMNode()
  771. .textContent
  772. ).toEqual('');
  773. });
  774. it('treeData is updated should not clear value when uncontrolled mode and multiple selection', () => {
  775. const nativeEvent = { nativeEvent: { stopImmediatePropagation: () => { } } }
  776. const treeSelect = getTreeSelect({
  777. defaultExpandAll: true,
  778. multiple: true,
  779. });
  780. treeSelect
  781. .find(`.${BASE_CLASS_PREFIX}-tree-option-list .${BASE_CLASS_PREFIX}-tree-option`)
  782. .at(2)
  783. .simulate('click', nativeEvent);
  784. expect(
  785. treeSelect
  786. .find(`.${BASE_CLASS_PREFIX}-tree-select-selection .${BASE_CLASS_PREFIX}-tag-group .${BASE_CLASS_PREFIX}-tag`)
  787. .at(0)
  788. .find(`.${BASE_CLASS_PREFIX}-tag-content`)
  789. .getDOMNode()
  790. .textContent
  791. ).toEqual('北京');
  792. treeSelect.setProps({ treeData: treeChildren});
  793. treeSelect.update();
  794. expect(
  795. treeSelect
  796. .find(`.${BASE_CLASS_PREFIX}-tree-select-selection .${BASE_CLASS_PREFIX}-tag-group .${BASE_CLASS_PREFIX}-tag`)
  797. .at(0)
  798. .find(`.${BASE_CLASS_PREFIX}-tag-content`)
  799. .getDOMNode()
  800. .textContent
  801. ).toEqual('北京');
  802. treeSelect.setProps({ treeData: treeData2});
  803. treeSelect.update();
  804. expect(
  805. treeSelect
  806. .find(`.${BASE_CLASS_PREFIX}-tree-select-selection .${BASE_CLASS_PREFIX}-tag-group .${BASE_CLASS_PREFIX}-tag`)
  807. .at(0)
  808. .find(`.${BASE_CLASS_PREFIX}-tag-content`)
  809. .length
  810. ).toEqual(0);
  811. });
  812. it('treeData is updated should not clear value when controlled mode and single selection', () => {
  813. const treeSelect = getTreeSelect({
  814. defaultExpandAll: true,
  815. value: 'Beijing'
  816. });
  817. expect(
  818. treeSelect
  819. .find(`.${BASE_CLASS_PREFIX}-tree-select .${BASE_CLASS_PREFIX}-tree-select-selection span`)
  820. .getDOMNode()
  821. .textContent
  822. ).toEqual('北京');
  823. treeSelect.setProps({ treeData: treeChildren});
  824. treeSelect.update();
  825. expect(
  826. treeSelect
  827. .find(`.${BASE_CLASS_PREFIX}-tree-select .${BASE_CLASS_PREFIX}-tree-select-selection span`)
  828. .getDOMNode()
  829. .textContent
  830. ).toEqual('北京');
  831. treeSelect.setProps({ treeData: treeData3});
  832. treeSelect.update();
  833. expect(
  834. treeSelect
  835. .find(`.${BASE_CLASS_PREFIX}-tree-select .${BASE_CLASS_PREFIX}-tree-select-selection span`)
  836. .getDOMNode()
  837. .textContent
  838. ).toEqual('');
  839. });
  840. it('treeData is updated should not clear value when controlled mode and multiple selection', () => {
  841. const treeSelect = getTreeSelect({
  842. defaultExpandAll: true,
  843. multiple: true,
  844. value: 'Beijing'
  845. });
  846. expect(
  847. treeSelect
  848. .find(`.${BASE_CLASS_PREFIX}-tree-select-selection .${BASE_CLASS_PREFIX}-tag-group .${BASE_CLASS_PREFIX}-tag`)
  849. .at(0)
  850. .find(`.${BASE_CLASS_PREFIX}-tag-content`)
  851. .getDOMNode()
  852. .textContent
  853. ).toEqual('北京');
  854. treeSelect.setProps({ treeData: treeChildren});
  855. treeSelect.update();
  856. expect(
  857. treeSelect
  858. .find(`.${BASE_CLASS_PREFIX}-tree-select-selection .${BASE_CLASS_PREFIX}-tag-group .${BASE_CLASS_PREFIX}-tag`)
  859. .at(0)
  860. .find(`.${BASE_CLASS_PREFIX}-tag-content`)
  861. .getDOMNode()
  862. .textContent
  863. ).toEqual('北京');
  864. treeSelect.setProps({ treeData: treeData3});
  865. treeSelect.update();
  866. expect(
  867. treeSelect
  868. .find(`.${BASE_CLASS_PREFIX}-tree-select-selection .${BASE_CLASS_PREFIX}-tag-group .${BASE_CLASS_PREFIX}-tag`)
  869. .at(0)
  870. .find(`.${BASE_CLASS_PREFIX}-tag-content`)
  871. .length
  872. ).toEqual(0);
  873. });
  874. })