treeSelect.test.js 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783
  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. let commonProps = {
  96. motion: false,
  97. motionExpand: false,
  98. mouseEnterDelay: 0,
  99. mouseLeaveDelay: 0,
  100. };
  101. function getTreeSelect(props) {
  102. props = { treeData: treeData, ...props }
  103. return mount(
  104. <TreeSelect
  105. {...commonProps}
  106. defaultOpen={true}
  107. {...props}
  108. />,
  109. {
  110. attachTo: document.getElementById('container')
  111. }
  112. );
  113. }
  114. describe('TreeSelect', () => {
  115. beforeEach(() => {
  116. // Avoid `attachTo: document.body` Warning
  117. const div = document.createElement('div');
  118. div.setAttribute('id', 'container');
  119. document.body.appendChild(div);
  120. });
  121. afterEach(() => {
  122. const div = document.getElementById('container');
  123. if (div) {
  124. document.body.removeChild(div);
  125. }
  126. document.body.innerHTML = '';
  127. });
  128. it('className / style', () => {
  129. let props = {
  130. className: 'test',
  131. style: { height: 420 },
  132. };
  133. let treeSelect = getTreeSelect(props);
  134. expect(treeSelect.hasClass('test')).toEqual(true);
  135. expect(treeSelect.find('div.test')).toHaveStyle('height', 420);
  136. });
  137. it('placeholder', () => {
  138. const props = {
  139. placeholder: 'semi'
  140. };
  141. const treeSelect = getTreeSelect(props);
  142. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select-selection-placeholder`).instance().textContent).toEqual('semi');
  143. });
  144. it('validateStatus', () => {
  145. const props = {};
  146. const treeSelect = getTreeSelect(props);
  147. expect(treeSelect.exists(`.${BASE_CLASS_PREFIX}-tree-select-error`)).toEqual(false);
  148. expect(treeSelect.exists(`.${BASE_CLASS_PREFIX}-tree-select-warning`)).toEqual(false);
  149. treeSelect.setProps({ validateStatus: 'error' });
  150. expect(treeSelect.exists(`.${BASE_CLASS_PREFIX}-tree-select-error`)).toEqual(true);
  151. treeSelect.setProps({ validateStatus: 'warning' });
  152. expect(treeSelect.exists(`.${BASE_CLASS_PREFIX}-tree-select-warning`)).toEqual(true);
  153. });
  154. it('outerBottomSlot', () => {
  155. let outerBottomSlot = <div class="outer-slot">outer</div>;
  156. let props = {
  157. outerBottomSlot: outerBottomSlot,
  158. };
  159. const treeSelect = getTreeSelect(props);
  160. expect(treeSelect.contains(outerBottomSlot)).toEqual(true);
  161. });
  162. it('size', () => {
  163. const props = {};
  164. const treeSelect = getTreeSelect(props);
  165. expect(treeSelect.exists(`.${BASE_CLASS_PREFIX}-tree-select-large`)).toEqual(false);
  166. expect(treeSelect.exists(`.${BASE_CLASS_PREFIX}-tree-select-small`)).toEqual(false);
  167. treeSelect.setProps({ size: 'large' });
  168. expect(treeSelect.exists(`.${BASE_CLASS_PREFIX}-tree-select-large`)).toEqual(true);
  169. treeSelect.setProps({ size: 'small' });
  170. expect(treeSelect.exists(`.${BASE_CLASS_PREFIX}-tree-select-small`)).toEqual(true);
  171. });
  172. it('custom dropdownClassName / dropdownStyle / zIndex', () => {
  173. let props = {
  174. dropdownClassName: 'test',
  175. dropdownStyle: {
  176. color: 'red',
  177. },
  178. zIndex: 2000,
  179. };
  180. let treeSelect = getTreeSelect(props);
  181. expect(treeSelect.exists('.test')).toEqual(true);
  182. expect(treeSelect.find('.test')).toHaveStyle('color', 'red');
  183. expect(document.querySelector(`.${BASE_CLASS_PREFIX}-portal`).style.zIndex).toEqual("2000");
  184. });
  185. it('dropdownMatchSelectWidth = true', () => {
  186. // dropdownMatchSelectWidth default is true
  187. let props = {
  188. style: { width: 90 },
  189. defaultValue: 'tiktok',
  190. };
  191. let treeSelect = getTreeSelect(props);
  192. // cause jsdom doesn't support layout engine like browser, so you can't access offsetWidth/scrollWidth or use getBoundingRect(), it will always return 0;
  193. // just use getComputedStyle to avoid this problem.
  194. let selector = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select`).getDOMNode();
  195. let selectorWidth = window.getComputedStyle(selector).width; // expect 90px
  196. let list = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select-popover`).getDOMNode();
  197. let listWidth = window.getComputedStyle(list).minWidth;
  198. expect(selectorWidth).toEqual(listWidth);
  199. treeSelect.unmount();
  200. });
  201. it('dropdownMatchSelectWidth = false', () => {
  202. let props = {
  203. style: { width: 90 },
  204. defaultValue: 'tiktok',
  205. dropdownMatchSelectWidth: false,
  206. };
  207. let treeSelect = getTreeSelect(props);
  208. let selector = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select`).getDOMNode();
  209. let selectorWidth = window.getComputedStyle(selector).width; // expect 90px
  210. let list = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select-popover`).getDOMNode();
  211. let listWidth = window.getComputedStyle(list).minWidth;
  212. expect(selectorWidth).not.toEqual(listWidth);
  213. treeSelect.unmount();
  214. });
  215. it('getPopupContainer', () => {
  216. let treeSelect = getTreeSelect({
  217. getPopupContainer: () => document.querySelector(`.${BASE_CLASS_PREFIX}-tree-select`),
  218. });
  219. let dom = document.querySelector(`.${BASE_CLASS_PREFIX}-tree-select`);
  220. expect(dom.querySelectorAll(`.${BASE_CLASS_PREFIX}-tree-select-popover`).length).toEqual(1);
  221. });
  222. it('custom prefix / suffix / insetLabel', () => {
  223. let prefix = <div className="prefix">prefix content</div>;
  224. let suffix = <div className="suffix">suffix content</div>;
  225. let insetLabel = 'semi';
  226. const props = {
  227. prefix: prefix,
  228. suffix: suffix,
  229. };
  230. let treeSelect = getTreeSelect(props);
  231. expect(treeSelect.contains(prefix)).toEqual(true);
  232. expect(treeSelect.contains(suffix)).toEqual(true);
  233. treeSelect.unmount();
  234. let ntreeSelect = getTreeSelect({ insetLabel: insetLabel });
  235. expect(ntreeSelect.contains(insetLabel)).toEqual(true);
  236. ntreeSelect.unmount();
  237. });
  238. it('empty data', () => {
  239. let treeSelect = getTreeSelect({
  240. treeData: [],
  241. emptyContent: 'empty'
  242. });
  243. let node = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option`);
  244. expect(node.length).toEqual(1);
  245. expect(node.hasClass(`${BASE_CLASS_PREFIX}-tree-option-empty`)).toEqual(true);
  246. expect(node.instance().textContent).toEqual('empty');
  247. });
  248. it('defaultOpen', () => {
  249. let props = {
  250. defaultOpen: false,
  251. };
  252. let treeSelect = getTreeSelect(props);
  253. expect(treeSelect.state().isOpen).toEqual(false);
  254. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select-popover`).exists()).toEqual(false);
  255. treeSelect.unmount();
  256. let ntreeSelect = getTreeSelect({ defaultOpen: true, });
  257. expect(ntreeSelect.state().isOpen).toEqual(true);
  258. expect(ntreeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select-popover`).exists()).toEqual(true);
  259. let options = ntreeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option`);
  260. expect(ntreeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option`).length).toEqual(2);
  261. expect(options.at(0).getDOMNode().textContent).toEqual('亚洲');
  262. expect(options.at(1).getDOMNode().textContent).toEqual('北美洲');
  263. });
  264. it('defaultValue', () => {
  265. // auto expand parent, if node exist means parent is open
  266. let treeSelect = getTreeSelect({
  267. defaultValue: 'Beijing'
  268. });
  269. let selectedNode = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-selected`);
  270. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select-selection`).getDOMNode().textContent).toEqual('北京');
  271. expect(selectedNode.instance().textContent).toEqual('北京');
  272. treeSelect.unmount();
  273. // array case only select first item
  274. let tree2 = getTreeSelect({
  275. defaultValue: ['Riben', 'Beijing']
  276. });
  277. let selectedNode2 = tree2.find(`.${BASE_CLASS_PREFIX}-tree-option-selected`);
  278. expect(selectedNode2.instance().textContent).toEqual('日本');
  279. expect(tree2.find(`.${BASE_CLASS_PREFIX}-tree-select-selection`).getDOMNode().textContent).toEqual('日本');
  280. 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);
  281. })
  282. it('defaultExpandedKeys', () => {
  283. // auto expand parent
  284. let treeSelect = getTreeSelect({
  285. defaultExpandedKeys: ['zhongguo', 'beimeizhou']
  286. });
  287. // yazhou beimeizhou
  288. let topNode = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`);
  289. expect(topNode.at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(false);
  290. expect(topNode.at(1).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(false);
  291. // zhongguo riben
  292. let children = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-2`);
  293. expect(children.at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(false);
  294. expect(children.at(1).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(true);
  295. })
  296. it('defaultExpandAll', () => {
  297. let treeSelect = getTreeSelect({
  298. defaultExpandAll: true
  299. });
  300. let nodes = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option`);
  301. let collapsed = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-collapsed`);
  302. expect(nodes.length).toEqual(10);
  303. expect(collapsed.length).toEqual(0);
  304. treeSelect.setProps({ treeData: treeData2});
  305. treeSelect.update();
  306. const nodes2 = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option`);
  307. const collapsed2 = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-collapsed`);
  308. expect(nodes2.length).toEqual(2);
  309. expect(collapsed2.length).toEqual(2);
  310. })
  311. it('expandAll', () => {
  312. const treeSelect = getTreeSelect({
  313. expandAll: true
  314. });
  315. const nodes = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option`);
  316. const collapsed = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-collapsed`);
  317. expect(nodes.length).toEqual(10);
  318. expect(collapsed.length).toEqual(0);
  319. treeSelect.setProps({ treeData: treeData2});
  320. treeSelect.update();
  321. const nodes2 = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option`);
  322. const collapsed2 = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-collapsed`);
  323. expect(nodes2.length).toEqual(5);
  324. expect(collapsed2.length).toEqual(0);
  325. })
  326. it('if expandedKeys values work', () => {
  327. // auto expand parent
  328. let treeSelect = getTreeSelect({
  329. expandedKeys: ['beimeizhou']
  330. });
  331. // yazhou beimeizhou
  332. let topNode = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`);
  333. expect(topNode.at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(true);
  334. expect(topNode.at(1).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(false);
  335. treeSelect.setProps({ expandedKeys: ['yazhou', 'zhongguo', 'beimeizhou'] });
  336. treeSelect.update();
  337. // zhongguo riben
  338. let children = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-2`);
  339. expect(children.at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(false);
  340. expect(children.at(1).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(true);
  341. });
  342. it('if expand behavior works / onExpand', () => {
  343. const nativeEvent = { nativeEvent: { stopImmediatePropagation: () => { } } }
  344. let spyOnExpand = sinon.spy(() => { });
  345. let treeSelect = getTreeSelect({
  346. onExpand: spyOnExpand,
  347. });
  348. // yazhou
  349. let topNodeAsia = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`).at(0);
  350. let expandIcon = topNodeAsia.find(`.${BASE_CLASS_PREFIX}-tree-option-expand-icon`).at(0);
  351. // expand yazhou
  352. expandIcon.simulate('click', nativeEvent);
  353. expect(spyOnExpand.calledOnce).toBe(true);
  354. expect(spyOnExpand.calledWithMatch(["yazhou"], { expanded: true, node: { key: 'yazhou' } })).toEqual(true);
  355. // zhongguo riben
  356. let topNode = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`);
  357. expect(topNode.at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(false);
  358. expect(topNode.at(1).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(true);
  359. // collapse yazhou
  360. expandIcon.simulate('click', nativeEvent);
  361. expect(spyOnExpand.calledWithMatch([], { expanded: false, node: { key: 'yazhou' } })).toEqual(true);
  362. topNode = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`);
  363. expect(topNode.at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(true);
  364. });
  365. it('if expandedKeys controlled work / onExpand', () => {
  366. const nativeEvent = { nativeEvent: { stopImmediatePropagation: () => { } } }
  367. let spyOnExpand = sinon.spy(() => { });
  368. let treeSelect = getTreeSelect({
  369. expandedKeys: ['beimeizhou'],
  370. onExpand: spyOnExpand,
  371. });
  372. // yazhou
  373. let topNodeAsia = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`).at(0);
  374. let expandIcon = topNodeAsia.find(`.${BASE_CLASS_PREFIX}-tree-option-expand-icon`).at(0);
  375. // expand yazhou
  376. expandIcon.simulate('click', nativeEvent);
  377. expect(spyOnExpand.calledWithMatch(["beimeizhou", "yazhou"], { expanded: true, node: { key: 'yazhou' } })).toEqual(true);
  378. // zhongguo riben
  379. let topNode = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`);
  380. expect(topNode.at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(true);
  381. });
  382. it('select item / onSelect / onChange', () => {
  383. let spyOnSelect = sinon.spy(() => { });
  384. let spyOnChange = sinon.spy(() => { });
  385. let treeSelect = getTreeSelect({
  386. defaultExpandAll: true,
  387. onSelect: spyOnSelect,
  388. onChange: spyOnChange,
  389. });
  390. let nodeBeijing = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-3`).at(0);
  391. // select beijing
  392. nodeBeijing.simulate('click');
  393. // onSelect & onChange
  394. expect(spyOnSelect.calledOnce).toBe(true);
  395. expect(spyOnChange.calledOnce).toBe(true);
  396. expect(spyOnSelect.calledWithMatch('beijing', true, { key: "beijing" })).toEqual(true);
  397. expect(spyOnChange.calledWithMatch('Beijing', { key: "beijing" })).toEqual(true);
  398. let selectBox = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select`).at(0);
  399. selectBox.simulate('click');
  400. // classname
  401. nodeBeijing = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-3`).at(0);
  402. expect(nodeBeijing.hasClass(`${BASE_CLASS_PREFIX}-tree-option-selected`)).toEqual(true);
  403. // render in input box
  404. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select-selection`).getDOMNode().textContent).toEqual('北京');
  405. // change
  406. let nodeAsia = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`).at(0);
  407. // select asia
  408. nodeAsia.simulate('click');
  409. // onSelect & onChange
  410. expect(spyOnSelect.calledWithMatch('yazhou', true, { key: "yazhou" })).toEqual(true);
  411. expect(spyOnChange.calledWithMatch('Yazhou', { key: "yazhou" })).toEqual(true);
  412. selectBox.simulate('click');
  413. // classname
  414. nodeAsia = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`).at(0);
  415. expect(nodeAsia.hasClass(`${BASE_CLASS_PREFIX}-tree-option-selected`)).toEqual(true);
  416. // render in input box
  417. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select-selection`).getDOMNode().textContent).toEqual('亚洲');
  418. });
  419. it('onChange + value not changed', () => {
  420. let spyOnSelect = sinon.spy(() => { });
  421. let spyOnChange = sinon.spy(() => { });
  422. let treeSelect = getTreeSelect({
  423. defaultExpandAll: true,
  424. onSelect: spyOnSelect,
  425. onChange: spyOnChange,
  426. defaultValue: 'Beijing'
  427. });
  428. let nodeBeijing = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-3`).at(0);
  429. // select beijing
  430. nodeBeijing.simulate('click');
  431. // onSelect & onChange
  432. expect(spyOnSelect.calledOnce).toBe(true);
  433. expect(spyOnChange.notCalled).toBe(true);
  434. });
  435. it('onChange + onChangeWithObject', () => {
  436. let spyOnChange = sinon.spy(() => { });
  437. let treeSelect = getTreeSelect({
  438. defaultExpandAll: true,
  439. onChangeWithObject: true,
  440. onChange: spyOnChange,
  441. });
  442. let nodeBeijing = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-3`).at(0);
  443. // select beijing
  444. nodeBeijing.simulate('click');
  445. // onSelect & onChange
  446. expect(spyOnChange.calledOnce).toBe(true);
  447. expect(spyOnChange.calledWithMatch({ key: "beijing" })).toEqual(true);
  448. });
  449. it('treeNodeLabelProp', () => {
  450. // auto expand parent, if node exist means parent is open
  451. let treeSelect = getTreeSelect({
  452. defaultValue: 'Beijing',
  453. treeNodeLabelProp: 'value'
  454. });
  455. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select-selection`).getDOMNode().textContent).toEqual('Beijing');
  456. // select asia
  457. let nodeAsia = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`).at(0);
  458. nodeAsia.simulate('click');
  459. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select-selection`).getDOMNode().textContent).toEqual('Yazhou');
  460. })
  461. it('filterTreeNode = true shows input box', () => {
  462. let treeSelect = getTreeSelect({});
  463. let searchWrapper = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`)
  464. expect(searchWrapper.exists()).toEqual(false);
  465. treeSelect.setProps({
  466. filterTreeNode: true
  467. });
  468. treeSelect.update();
  469. searchWrapper = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`)
  470. expect(searchWrapper.exists()).toEqual(true);
  471. });
  472. it('searchPlaceholder', () => {
  473. let treeSelect = getTreeSelect({
  474. filterTreeNode: true,
  475. searchPlaceholder: 'test',
  476. });
  477. let searchWrapper = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`)
  478. expect(searchWrapper.find('input').instance().getAttribute('placeholder')).toEqual('test');
  479. });
  480. it('onSearch', () => {
  481. let onSearch = value => { };
  482. let spyOnSearch = sinon.spy(onSearch);
  483. let treeSelect = getTreeSelect({
  484. filterTreeNode: true,
  485. onSearch: spyOnSearch,
  486. });
  487. const searchWrapper = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  488. let searchValue = 'semi';
  489. let event = { target: { value: searchValue } };
  490. searchWrapper.find('input').simulate('change', event);
  491. expect(spyOnSearch.calledOnce).toBe(true);
  492. expect(spyOnSearch.calledWithMatch(searchValue)).toBe(true);
  493. });
  494. it('filterTreeNode shows correct result', () => {
  495. let treeSelect1 = getTreeSelect({
  496. filterTreeNode: true,
  497. });
  498. const searchWrapper = treeSelect1.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  499. let searchValue = '北';
  500. let event = { target: { value: searchValue } };
  501. searchWrapper.find('input').simulate('change', event);
  502. expect(treeSelect1.find(`.${BASE_CLASS_PREFIX}-tree-option`).length).toEqual(6);
  503. expect(treeSelect1.find(`.${BASE_CLASS_PREFIX}-tree-option-highlight`).length).toEqual(2);
  504. expect(treeSelect1.find(`.${BASE_CLASS_PREFIX}-tree-option-highlight`).at(0).instance().textContent).toEqual('北');
  505. expect(treeSelect1.find(`.${BASE_CLASS_PREFIX}-tree-option-highlight`).at(1).instance().textContent).toEqual('北');
  506. treeSelect1.unmount();
  507. let treeSelect2 = getTreeSelect({
  508. filterTreeNode: true,
  509. treeNodeFilterProp: 'value',
  510. });
  511. const searchWrapper2 = treeSelect2.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  512. let searchValue2 = 'an';
  513. let event2 = { target: { value: searchValue2 } };
  514. searchWrapper2.find('input').simulate('change', event2);
  515. expect(treeSelect2.find(`.${BASE_CLASS_PREFIX}-tree-option`).length).toEqual(10);
  516. expect(treeSelect2.find(`.${BASE_CLASS_PREFIX}-tree-option-filtered`).length).toEqual(3);
  517. expect(treeSelect2.find(`.${BASE_CLASS_PREFIX}-tree-option-filtered`).at(0).instance().textContent).toEqual('上海');
  518. expect(treeSelect2.find(`.${BASE_CLASS_PREFIX}-tree-option-filtered`).at(1).instance().textContent).toEqual('大阪');
  519. expect(treeSelect2.find(`.${BASE_CLASS_PREFIX}-tree-option-filtered`).at(2).instance().textContent).toEqual('加拿大');
  520. });
  521. it('filterTreeNode + no result', () => {
  522. let treeSelect1 = getTreeSelect({
  523. filterTreeNode: true,
  524. });
  525. const searchWrapper = treeSelect1.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  526. let searchValue = 'Bei';
  527. let event = { target: { value: searchValue } };
  528. searchWrapper.find('input').simulate('change', event);
  529. expect(treeSelect1.find(`.${BASE_CLASS_PREFIX}-tree-option`).length).toEqual(2);
  530. expect(treeSelect1.find(`.${BASE_CLASS_PREFIX}-tree-option-highlight`).length).toEqual(0);
  531. treeSelect1.unmount();
  532. let treeSelect2 = getTreeSelect({
  533. filterTreeNode: true,
  534. treeNodeFilterProp: 'value',
  535. });
  536. const searchWrapper2 = treeSelect2.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  537. let searchValue2 = '北';
  538. let event2 = { target: { value: searchValue2 } };
  539. searchWrapper2.find('input').simulate('change', event2);
  540. expect(treeSelect2.find(`.${BASE_CLASS_PREFIX}-tree-option`).length).toEqual(2);
  541. expect(treeSelect2.find(`.${BASE_CLASS_PREFIX}-tree-option-filtered`).length).toEqual(0);
  542. });
  543. it('async load data', () => {
  544. const nativeEvent = { nativeEvent: { stopImmediatePropagation: () => { } } }
  545. const then = jest.fn(() => Promise.resolve());
  546. const loadData = jest.fn(() => ({ then }));
  547. const data = {
  548. label: '亚洲',
  549. value: 'Asia',
  550. key: 'asia',
  551. };
  552. const treeSelect = getTreeSelect({
  553. loadData,
  554. loadedKeys: ['0-1'],
  555. treeData: [data]
  556. });
  557. const topNodeAsia = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`).at(0);
  558. const expandIcon = topNodeAsia.find(`.${BASE_CLASS_PREFIX}-tree-option-expand-icon`).at(0);
  559. expandIcon.simulate('click', nativeEvent);
  560. expect(loadData).toHaveBeenCalledWith(data);
  561. expect(then).toHaveBeenCalled();
  562. });
  563. it('filterTreeNode + treeNodeFilterProp', () => {
  564. let treeSelect = getTreeSelect({
  565. filterTreeNode: true,
  566. treeNodeFilterProp: 'value',
  567. });
  568. const searchWrapper = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  569. let searchValue = 'Bei';
  570. let event = { target: { value: searchValue } };
  571. searchWrapper.find('input').simulate('change', event);
  572. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option`).length).toEqual(6);
  573. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-filtered`).length).toEqual(2);
  574. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-filtered`).at(0).instance().textContent).toEqual('北京');
  575. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-filtered`).at(1).instance().textContent).toEqual('北美洲');
  576. });
  577. it('filterTreeNode + showFilteredOnly + no result', () => {
  578. let treeSelect = getTreeSelect({
  579. filterTreeNode: true,
  580. showFilteredOnly: true,
  581. });
  582. const searchWrapper = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  583. let searchValue = 'Bei';
  584. let event = { target: { value: searchValue } };
  585. searchWrapper.find('input').simulate('change', event);
  586. let node = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option`);
  587. expect(node.length).toEqual(1);
  588. expect(node.hasClass(`${BASE_CLASS_PREFIX}-tree-option-empty`)).toEqual(true);
  589. });
  590. it('filterTreeNode + showFilteredOnly shows correct result', () => {
  591. let treeSelect = getTreeSelect({
  592. filterTreeNode: true,
  593. showFilteredOnly: true,
  594. });
  595. const searchWrapper = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  596. let searchValue = '北';
  597. let event = { target: { value: searchValue } };
  598. searchWrapper.find('input').simulate('change', event);
  599. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option`).length).toEqual(4);
  600. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-highlight`).length).toEqual(2);
  601. });
  602. it('filterTreeNode as a func', () => {
  603. let treeSelect = getTreeSelect({
  604. filterTreeNode: (inputValue, treeNode) => treeNode === inputValue,
  605. });
  606. const searchWrapper = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  607. searchWrapper.find('input').simulate('change', { target: { value: '北' } });
  608. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-highlight`).length).toEqual(0);
  609. // update
  610. searchWrapper.find('input').simulate('change', { target: { value: '北京' } });
  611. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-highlight`).length).toEqual(1);
  612. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-highlight`).instance().textContent).toEqual('北京');
  613. });
  614. it('controlled: value shows correct', () => {
  615. let treeSelect = getTreeSelect({
  616. value: 'Beijing'
  617. });
  618. let selectedNode = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-selected`);
  619. expect(selectedNode.instance().textContent).toEqual('北京');
  620. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select-selection`).getDOMNode().textContent).toEqual('北京');
  621. treeSelect.unmount();
  622. // array case only select first item
  623. let treeSelect2 = getTreeSelect({
  624. value: ['Riben', 'Beijing']
  625. });
  626. let selectedNode2 = treeSelect2.find(`.${BASE_CLASS_PREFIX}-tree-option-selected`);
  627. expect(selectedNode2.instance().textContent).toEqual('日本');
  628. expect(treeSelect2.find(`.${BASE_CLASS_PREFIX}-tree-select-selection`).getDOMNode().textContent).toEqual('日本');
  629. 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);
  630. });
  631. it('controlled: fire onChange and ui not update', () => {
  632. let spyOnChange = sinon.spy(() => { });
  633. let treeSelect = getTreeSelect({
  634. value: '',
  635. defaultExpandAll: true,
  636. onChange: spyOnChange,
  637. });
  638. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-selected`).exists()).toEqual(false);
  639. let nodeBeijing = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-3`).at(0);
  640. // select beijing
  641. nodeBeijing.simulate('click');
  642. // onSelect & onChange
  643. expect(spyOnChange.calledOnce).toBe(true);
  644. expect(spyOnChange.calledWithMatch("Beijing")).toEqual(true);
  645. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-selected`).exists()).toEqual(false);
  646. });
  647. it('controlled: value + onChangeWithObject', () => {
  648. let spyOnChange = sinon.spy(() => { });
  649. let treeSelect = getTreeSelect({
  650. value: {
  651. label: '北京',
  652. value: 'Beijing',
  653. key: 'beijing',
  654. },
  655. defaultExpandAll: true,
  656. onChange: spyOnChange,
  657. onChangeWithObject: true,
  658. });
  659. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option-selected`).exists()).toEqual(true);
  660. });
  661. it('virtualized: fixed height', () => {
  662. let treeSelect = getTreeSelect({
  663. defaultExpandAll: true,
  664. virtualize: {
  665. itemSize: 28,
  666. height: 84,
  667. },
  668. });
  669. // virtual list
  670. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-virtual-list`).exists()).toEqual(true);
  671. // fewer nodes
  672. let nodes = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option`);
  673. expect(nodes.length).toBeLessThan(10);
  674. });
  675. it('disabled', () => {
  676. let treeSelect = getTreeSelect({
  677. disabled: true,
  678. });
  679. let inputBox = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select-disabled`);
  680. expect(inputBox.exists()).toEqual(true);
  681. expect(treeSelect.state().isOpen).toEqual(false);
  682. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-wrapper`).exists()).toEqual(false);
  683. inputBox.simulate('click');
  684. expect(treeSelect.state().isOpen).toEqual(false);
  685. expect(treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-wrapper`).exists()).toEqual(false);
  686. });
  687. it('renderSelectedItem', () => {
  688. let spyOnSelect = sinon.spy(() => { });
  689. let spyOnChange = sinon.spy(() => { });
  690. let treeSelect = getTreeSelect({
  691. renderSelectedItem: treeNode => treeNode.value,
  692. defaultExpandAll: true,
  693. onSelect: spyOnSelect,
  694. onChange: spyOnChange,
  695. });
  696. const yaZhouKey = 'yazhou';
  697. const yaZhouValue = 'Yazhou';
  698. let nodeYaZhou = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`).at(0);
  699. nodeYaZhou.simulate('click');
  700. // 判断回调,这里其实没有更新,不是很重要
  701. expect(spyOnSelect.calledOnce).toBe(true);
  702. expect(spyOnChange.calledOnce).toBe(true);
  703. expect(spyOnSelect.getCall(0).args[0]).toEqual(yaZhouKey);
  704. expect(spyOnChange.getCall(0).args[0]).toEqual(yaZhouValue);
  705. // 判断已选项的渲染
  706. const innerHTML = document.querySelector('.semi-tree-select-selection span').textContent;
  707. expect(innerHTML).toEqual(yaZhouValue);
  708. });
  709. it('search autofocus', () => {
  710. let treeSelect = getTreeSelect({
  711. filterTreeNode: true,
  712. searchAutoFocus: true,
  713. });
  714. let selectEle = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-select`)
  715. selectEle.simulate('click');
  716. setTimeout(() => {
  717. let searchWrapper = treeSelect.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`)
  718. const searchInput = searchWrapper.find(`input`)
  719. expect(searchInput.matchesElement(document.activeElement)).toEqual(true);
  720. done();
  721. }, 100);
  722. });
  723. })