tree.test.js 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842
  1. import { Tree, Icon } from '../../index';
  2. import { BASE_CLASS_PREFIX } from '../../../semi-foundation/base/constants';
  3. import { IconMapPin } from '@douyinfe/semi-icons';
  4. const treeChildren = [
  5. {
  6. label: '北京',
  7. value: 'Beijing',
  8. key: 'beijing',
  9. },
  10. {
  11. label: '上海',
  12. value: 'Shanghai',
  13. key: 'shanghai',
  14. },
  15. ];
  16. const treeData = [
  17. {
  18. label: '亚洲',
  19. value: 'Yazhou',
  20. key: 'yazhou',
  21. children: [
  22. {
  23. label: '中国',
  24. value: 'Zhongguo',
  25. key: 'zhongguo',
  26. children: treeChildren,
  27. },
  28. {
  29. label: '日本',
  30. value: 'Riben',
  31. key: 'riben',
  32. children: [
  33. {
  34. label: '东京',
  35. value: 'Dongjing',
  36. key: 'dongjing'
  37. },
  38. {
  39. label: '大阪',
  40. value: 'Daban',
  41. key: 'daban'
  42. }
  43. ]
  44. },
  45. ],
  46. },
  47. {
  48. label: '北美洲',
  49. value: 'Beimeizhou',
  50. key: 'beimeizhou',
  51. children: [
  52. {
  53. label: '美国',
  54. value: 'Meiguo',
  55. key: 'meiguo'
  56. },
  57. {
  58. label: '加拿大',
  59. value: 'Jianada',
  60. key: 'jianada'
  61. }
  62. ]
  63. },
  64. ];
  65. const treeData2 = [
  66. {
  67. label: '亚洲',
  68. value: 'Asia',
  69. key: '0',
  70. children: [
  71. {
  72. label: '中国',
  73. value: 'China',
  74. key: '0-0',
  75. children: [
  76. {
  77. label: '北京',
  78. value: 'Beijing',
  79. key: '0-0-0',
  80. },
  81. {
  82. label: '上海',
  83. value: 'Shanghai',
  84. key: '0-0-1',
  85. },
  86. ],
  87. },
  88. ],
  89. },
  90. {
  91. label: '北美洲',
  92. value: 'North America',
  93. key: '1',
  94. }
  95. ];
  96. const dragNodeData = {"label":"亚洲","value":"Yazhou","key":"yazhou","children":[{"label":"中国","value":"Zhongguo","key":"zhongguo","children":[{"label":"北京","value":"Beijing","key":"beijing"},{"label":"上海","value":"Shanghai","key":"shanghai"}]},{"label":"日本","value":"Riben","key":"riben","children":[{"label":"东京","value":"Dongjing","key":"dongjing"},{"label":"大阪","value":"Daban","key":"daban"}]}],"expanded":false,"pos":"0-0"}
  97. const dropNodeData = {"label":"北美洲","value":"Beimeizhou","key":"beimeizhou","children":[{"label":"美国","value":"Meiguo","key":"meiguo"},{"label":"加拿大","value":"Jianada","key":"jianada"}],"expanded":false,"pos":"0-1"}
  98. function getTree(props) {
  99. props = { treeData: treeData, ...props }
  100. return mount(
  101. <Tree
  102. {...props}
  103. motion={true}
  104. />,
  105. {
  106. attachTo: document.getElementById('container')
  107. }
  108. );
  109. }
  110. describe('Tree', () => {
  111. beforeEach(() => {
  112. // Avoid `attachTo: document.body` Warning
  113. const div = document.createElement('div');
  114. div.setAttribute('id', 'container');
  115. document.body.appendChild(div);
  116. });
  117. afterEach(() => {
  118. const div = document.getElementById('container');
  119. if (div) {
  120. document.body.removeChild(div);
  121. }
  122. document.body.innerHTML = '';
  123. });
  124. it('className / style', () => {
  125. let props = {
  126. className: 'test',
  127. style: { height: 420 },
  128. };
  129. let tree = getTree(props);
  130. expect(tree.hasClass('test')).toEqual(true);
  131. expect(tree.find('div.test')).toHaveStyle('height', 420);
  132. });
  133. it('blockNode', () => {
  134. let tree = getTree({
  135. defaultValue: 'Beijing'
  136. });
  137. expect(tree.find(`.${BASE_CLASS_PREFIX}-tree-option-list-block`).exists()).toEqual(true);
  138. tree.setProps({ blockNode: false });
  139. expect(tree.find(`.${BASE_CLASS_PREFIX}-tree-option-list-block`).exists()).toEqual(false);
  140. });
  141. it('empty data', () => {
  142. let tree = getTree({
  143. treeData: []
  144. });
  145. let node = tree.find(`.${BASE_CLASS_PREFIX}-tree-option`);
  146. expect(node.length).toEqual(1);
  147. expect(node.hasClass(`${BASE_CLASS_PREFIX}-tree-option-empty`)).toEqual(true);
  148. });
  149. it('defaultValue', () => {
  150. // auto expand parent, if node exist means parent is open
  151. let tree = getTree({
  152. defaultValue: 'Beijing'
  153. });
  154. let selectedNode = tree.find(`.${BASE_CLASS_PREFIX}-tree-option-selected`);
  155. expect(selectedNode.instance().textContent).toEqual('北京');
  156. tree.unmount();
  157. // array case only select first item
  158. let tree2 = getTree({
  159. defaultValue: ['Riben', 'Beijing']
  160. });
  161. let selectedNode2 = tree2.find(`.${BASE_CLASS_PREFIX}-tree-option-selected`);
  162. expect(selectedNode2.instance().textContent).toEqual('日本');
  163. 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);
  164. })
  165. it('defaultExpandedKeys', () => {
  166. // auto expand parent
  167. let tree = getTree({
  168. defaultExpandedKeys: ['zhongguo', 'beimeizhou']
  169. });
  170. // yazhou beimeizhou
  171. let topNode = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`);
  172. expect(topNode.at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(false);
  173. expect(topNode.at(1).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(false);
  174. // zhongguo riben
  175. let children = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-2`);
  176. expect(children.at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(false);
  177. expect(children.at(1).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(true);
  178. })
  179. it('defaultExpandAll', () => {
  180. let tree = getTree({
  181. defaultExpandAll: true
  182. });
  183. let nodes = tree.find(`.${BASE_CLASS_PREFIX}-tree-option`);
  184. let collapsed = tree.find(`.${BASE_CLASS_PREFIX}-tree-option-collapsed`);
  185. expect(nodes.length).toEqual(10);
  186. expect(collapsed.length).toEqual(0);
  187. tree.setProps({ treeData: treeData2});
  188. tree.update();
  189. const nodes2 = tree.find(`.${BASE_CLASS_PREFIX}-tree-option`);
  190. const collapsed2 = tree.find(`.${BASE_CLASS_PREFIX}-tree-option-collapsed`);
  191. expect(nodes2.length).toEqual(2);
  192. expect(collapsed2.length).toEqual(2);
  193. })
  194. it('expandAll', () => {
  195. const tree = getTree({
  196. expandAll: true
  197. });
  198. const nodes = tree.find(`.${BASE_CLASS_PREFIX}-tree-option`);
  199. const collapsed = tree.find(`.${BASE_CLASS_PREFIX}-tree-option-collapsed`);
  200. expect(nodes.length).toEqual(10);
  201. expect(collapsed.length).toEqual(0);
  202. tree.setProps({ treeData: treeData2});
  203. tree.update();
  204. const nodes2 = tree.find(`.${BASE_CLASS_PREFIX}-tree-option`);
  205. const collapsed2 = tree.find(`.${BASE_CLASS_PREFIX}-tree-option-collapsed`);
  206. expect(nodes2.length).toEqual(5);
  207. expect(collapsed2.length).toEqual(0);
  208. })
  209. it('directory mode', () => {
  210. let props = {
  211. defaultExpandedKeys: ['beimeizhou'],
  212. directory: true,
  213. };
  214. let tree = getTree(props);
  215. let topNode = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`);
  216. expect(topNode.at(1).find(`.${BASE_CLASS_PREFIX}-icon-folder_open`).exists()).toEqual(true);
  217. expect(topNode.at(0).find(`.${BASE_CLASS_PREFIX}-icon-folder`).exists()).toEqual(true);
  218. expect(tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-2`).at(0).find(`.${BASE_CLASS_PREFIX}-icon-file`).exists()).toEqual(true);
  219. });
  220. it('custom icon', () => {
  221. let props = {
  222. defaultExpandAll: true,
  223. icon: (<IconMapPin />)
  224. };
  225. let tree = getTree(props);
  226. expect(tree.find(`.${BASE_CLASS_PREFIX}-icon-map_pin`).length).toEqual(10);
  227. });
  228. it('if expandedKeys values work', () => {
  229. // auto expand parent
  230. let tree = getTree({
  231. expandedKeys: ['beimeizhou']
  232. });
  233. // yazhou beimeizhou
  234. let topNode = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`);
  235. expect(topNode.at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(true);
  236. expect(topNode.at(1).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(false);
  237. tree.setProps({ expandedKeys: ['yazhou', 'zhongguo', 'beimeizhou'] });
  238. tree.update();
  239. // zhongguo riben
  240. let children = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-2`);
  241. expect(children.at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(false);
  242. expect(children.at(1).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(true);
  243. });
  244. it('expandedKeys + autoExpandParent', () => {
  245. // auto expand parent is always true when mounted
  246. let tree = getTree({
  247. expandedKeys: ['beimeizhou']
  248. });
  249. // yazhou beimeizhou
  250. let topNode = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`);
  251. expect(topNode.at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(true);
  252. expect(topNode.at(1).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(false);
  253. tree.setProps({ expandedKeys: ['riben'] });
  254. tree.update();
  255. topNode = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`);
  256. expect(topNode.at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(true);
  257. expect(topNode.at(1).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(true);
  258. // autoExpandParent
  259. tree.setProps({ autoExpandParent: true });
  260. tree.update();
  261. topNode = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`);
  262. expect(topNode.at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(false);
  263. expect(topNode.at(1).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(true);
  264. });
  265. it('if expand behavior works / onExpand', () => {
  266. const nativeEvent = { nativeEvent: { stopImmediatePropagation: () => { } } }
  267. let spyOnExpand = sinon.spy(() => { });
  268. let tree = getTree({
  269. onExpand: spyOnExpand,
  270. });
  271. // yazhou
  272. let topNodeAsia = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`).at(0);
  273. let expandIcon = topNodeAsia.find(`.${BASE_CLASS_PREFIX}-tree-option-expand-icon`).at(0);
  274. // expand yazhou
  275. expandIcon.simulate('click', nativeEvent);
  276. expect(spyOnExpand.calledOnce).toBe(true);
  277. expect(spyOnExpand.calledWithMatch(["yazhou"], { expanded: true, node: { key: 'yazhou' } })).toEqual(true);
  278. // yazhou beimeizhou
  279. let topNode = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`);
  280. expect(topNode.at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(false);
  281. expect(topNode.at(1).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(true);
  282. // collapse yazhou
  283. expandIcon.simulate('click', nativeEvent);
  284. expect(spyOnExpand.calledWithMatch([], { expanded: false, node: { key: 'yazhou' } })).toEqual(true);
  285. topNode = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`);
  286. expect(topNode.at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(true);
  287. });
  288. it('if expandedKeys controlled work / onExpand', () => {
  289. const nativeEvent = { nativeEvent: { stopImmediatePropagation: () => { } } }
  290. let spyOnExpand = sinon.spy(() => { });
  291. let tree = getTree({
  292. expandedKeys: ['beimeizhou'],
  293. onExpand: spyOnExpand,
  294. });
  295. // yazhou
  296. let topNodeAsia = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`).at(0);
  297. let expandIcon = topNodeAsia.find(`.${BASE_CLASS_PREFIX}-tree-option-expand-icon`).at(0);
  298. // expand yazhou
  299. expandIcon.simulate('click', nativeEvent);
  300. expect(spyOnExpand.calledWithMatch(["beimeizhou", "yazhou"], { expanded: true, node: { key: 'yazhou' } })).toEqual(true);
  301. // zhongguo riben
  302. let topNode = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`);
  303. expect(topNode.at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(true);
  304. });
  305. it('select item / onSelect / onChange', () => {
  306. let spyOnSelect = sinon.spy(() => { });
  307. let spyOnChange = sinon.spy(() => { });
  308. let tree = getTree({
  309. defaultExpandAll: true,
  310. onSelect: spyOnSelect,
  311. onChange: spyOnChange,
  312. });
  313. let nodeBeijing = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-3`).at(0);
  314. // select beijing
  315. nodeBeijing.simulate('click');
  316. // onSelect & onChange
  317. expect(spyOnSelect.calledOnce).toBe(true);
  318. expect(spyOnChange.calledOnce).toBe(true);
  319. expect(spyOnSelect.calledWithMatch('beijing', true, { key: "beijing" })).toEqual(true);
  320. expect(spyOnChange.calledWithMatch('Beijing')).toEqual(true);
  321. // classname
  322. nodeBeijing = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-3`).at(0);
  323. expect(nodeBeijing.hasClass(`${BASE_CLASS_PREFIX}-tree-option-selected`)).toEqual(true);
  324. // change
  325. let nodeAsia = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`).at(0);
  326. // select asia
  327. nodeAsia.simulate('click');
  328. // onSelect & onChange
  329. expect(spyOnSelect.calledWithMatch('yazhou', true, { key: "yazhou" })).toEqual(true);
  330. expect(spyOnChange.calledWithMatch('Yazhou')).toEqual(true);
  331. // classname
  332. nodeAsia = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`).at(0);
  333. expect(nodeAsia.hasClass(`${BASE_CLASS_PREFIX}-tree-option-selected`)).toEqual(true);
  334. });
  335. it('onChange + onChangeWithObject', () => {
  336. let spyOnChange = sinon.spy(() => { });
  337. let tree = getTree({
  338. defaultExpandAll: true,
  339. onChangeWithObject: true,
  340. onChange: spyOnChange,
  341. });
  342. let nodeBeijing = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-3`).at(0);
  343. // select beijing
  344. nodeBeijing.simulate('click');
  345. // onSelect & onChange
  346. expect(spyOnChange.calledOnce).toBe(true);
  347. expect(spyOnChange.calledWithMatch({ key: "beijing" })).toEqual(true);
  348. });
  349. it('filterTreeNode = true shows input box', () => {
  350. let tree = getTree({});
  351. let searchWrapper = tree.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`)
  352. expect(searchWrapper.exists()).toEqual(false);
  353. tree.setProps({ filterTreeNode: true });
  354. tree.update();
  355. searchWrapper = tree.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`)
  356. expect(searchWrapper.exists()).toEqual(true);
  357. });
  358. it('onSearch', () => {
  359. let onSearch = value => { };
  360. let spyOnSearch = sinon.spy(onSearch);
  361. let tree = getTree({
  362. filterTreeNode: true,
  363. onSearch: spyOnSearch,
  364. });
  365. const searchWrapper = tree.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  366. let searchValue = 'semi';
  367. let event = { target: { value: searchValue } };
  368. searchWrapper.find('input').simulate('change', event);
  369. expect(spyOnSearch.calledOnce).toBe(true);
  370. expect(spyOnSearch.calledWithMatch(searchValue)).toBe(true);
  371. });
  372. it('emptyContent', () => {
  373. let onSearch = value => { };
  374. let spyOnSearch = sinon.spy(onSearch);
  375. let tree = getTree({
  376. filterTreeNode: true,
  377. onSearch: spyOnSearch,
  378. emptyContent: 'diy empty',
  379. showFilteredOnly: true,
  380. });
  381. const searchWrapper = tree.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  382. let searchValue = 'asd';
  383. let event = { target: { value: searchValue } };
  384. searchWrapper.find('input').simulate('change', event);
  385. expect(tree.find(`.${BASE_CLASS_PREFIX}-tree-option-label-empty`).getDOMNode().textContent).toEqual('diy empty');
  386. });
  387. it('searchClassName / searchPlaceholder / searchStyle', () => {
  388. let tree = getTree({
  389. filterTreeNode: true,
  390. searchClassName: 'search',
  391. searchPlaceholder: 'placeholder',
  392. searchStyle: { padding: 16 },
  393. showClear: true,
  394. });
  395. const searchWrapper = tree.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`)
  396. expect(searchWrapper.hasClass('search')).toEqual(true);
  397. expect(searchWrapper).toHaveStyle('padding', 16);
  398. expect(searchWrapper.find('input').instance().getAttribute('placeholder')).toEqual('placeholder');
  399. });
  400. it('filterTreeNode shows correct result', () => {
  401. let tree1 = getTree({
  402. filterTreeNode: true,
  403. });
  404. const searchWrapper = tree1.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  405. let searchValue = '北';
  406. let event = { target: { value: searchValue } };
  407. searchWrapper.find('input').simulate('change', event);
  408. expect(tree1.find(`.${BASE_CLASS_PREFIX}-tree-option`).length).toEqual(6);
  409. expect(tree1.find(`.${BASE_CLASS_PREFIX}-tree-option-highlight`).length).toEqual(2);
  410. expect(tree1.find(`.${BASE_CLASS_PREFIX}-tree-option-highlight`).at(0).instance().textContent).toEqual('北');
  411. expect(tree1.find(`.${BASE_CLASS_PREFIX}-tree-option-highlight`).at(1).instance().textContent).toEqual('北');
  412. tree1.unmount();
  413. let tree2 = getTree({
  414. filterTreeNode: true,
  415. treeNodeFilterProp: 'value',
  416. });
  417. const searchWrapper2 = tree2.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  418. let searchValue2 = 'an';
  419. let event2 = { target: { value: searchValue2 } };
  420. searchWrapper2.find('input').simulate('change', event2);
  421. expect(tree2.find(`.${BASE_CLASS_PREFIX}-tree-option`).length).toEqual(10);
  422. expect(tree2.find(`.${BASE_CLASS_PREFIX}-tree-option-filtered`).length).toEqual(3);
  423. expect(tree2.find(`.${BASE_CLASS_PREFIX}-tree-option-filtered`).at(0).instance().textContent).toEqual('上海');
  424. expect(tree2.find(`.${BASE_CLASS_PREFIX}-tree-option-filtered`).at(1).instance().textContent).toEqual('大阪');
  425. expect(tree2.find(`.${BASE_CLASS_PREFIX}-tree-option-filtered`).at(2).instance().textContent).toEqual('加拿大');
  426. });
  427. it('filterTreeNode + no result', () => {
  428. let tree1 = getTree({
  429. filterTreeNode: true,
  430. });
  431. const searchWrapper = tree1.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  432. let searchValue = 'Bei';
  433. let event = { target: { value: searchValue } };
  434. searchWrapper.find('input').simulate('change', event);
  435. expect(tree1.find(`.${BASE_CLASS_PREFIX}-tree-option`).length).toEqual(2);
  436. expect(tree1.find(`.${BASE_CLASS_PREFIX}-tree-option-highlight`).length).toEqual(0);
  437. tree1.unmount();
  438. let tree2 = getTree({
  439. filterTreeNode: true,
  440. treeNodeFilterProp: 'value',
  441. });
  442. const searchWrapper2 = tree2.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  443. let searchValue2 = '北京';
  444. let event2 = { target: { value: searchValue2 } };
  445. searchWrapper2.find('input').simulate('change', event2);
  446. expect(tree2.find(`.${BASE_CLASS_PREFIX}-tree-option`).length).toEqual(2);
  447. expect(tree2.find(`.${BASE_CLASS_PREFIX}-tree-option-filtered`).length).toEqual(0);
  448. });
  449. it('filterTreeNode + showFilteredOnly + no result', () => {
  450. let tree = getTree({
  451. filterTreeNode: true,
  452. showFilteredOnly: true,
  453. });
  454. const searchWrapper = tree.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  455. let searchValue = 'Bei';
  456. let event = { target: { value: searchValue } };
  457. searchWrapper.find('input').simulate('change', event);
  458. let node = tree.find(`.${BASE_CLASS_PREFIX}-tree-option`);
  459. expect(node.length).toEqual(1);
  460. expect(node.hasClass(`${BASE_CLASS_PREFIX}-tree-option-empty`)).toEqual(true);
  461. });
  462. it('filterTreeNode + showFilteredOnly shows correct result', () => {
  463. let tree = getTree({
  464. filterTreeNode: true,
  465. showFilteredOnly: true,
  466. });
  467. const searchWrapper = tree.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  468. let searchValue = '北';
  469. let event = { target: { value: searchValue } };
  470. searchWrapper.find('input').simulate('change', event);
  471. expect(tree.find(`.${BASE_CLASS_PREFIX}-tree-option`).length).toEqual(4);
  472. expect(tree.find(`.${BASE_CLASS_PREFIX}-tree-option-highlight`).length).toEqual(2);
  473. });
  474. it('filterTreeNode as a func', () => {
  475. let tree = getTree({
  476. filterTreeNode: (inputValue, treeNode) => treeNode === inputValue,
  477. });
  478. const searchWrapper = tree.find(`.${BASE_CLASS_PREFIX}-tree-search-wrapper`);
  479. searchWrapper.find('input').simulate('change', { target: { value: '北' } });
  480. expect(tree.find(`.${BASE_CLASS_PREFIX}-tree-option-highlight`).length).toEqual(0);
  481. // update
  482. searchWrapper.find('input').simulate('change', { target: { value: '北京' } });
  483. expect(tree.find(`.${BASE_CLASS_PREFIX}-tree-option-highlight`).length).toEqual(1);
  484. expect(tree.find(`.${BASE_CLASS_PREFIX}-tree-option-highlight`).instance().textContent).toEqual('北京');
  485. });
  486. it('controlled: value shows correct', () => {
  487. let tree = getTree({
  488. value: 'Beijing'
  489. });
  490. let selectedNode = tree.find(`.${BASE_CLASS_PREFIX}-tree-option-selected`);
  491. expect(selectedNode.instance().textContent).toEqual('北京');
  492. tree.unmount();
  493. // array case only select first item
  494. let tree2 = getTree({
  495. value: ['Riben', 'Beijing']
  496. });
  497. let selectedNode2 = tree2.find(`.${BASE_CLASS_PREFIX}-tree-option-selected`);
  498. expect(selectedNode2.instance().textContent).toEqual('日本');
  499. 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);
  500. });
  501. it('controlled: fire onChange and ui not update', () => {
  502. let spyOnChange = sinon.spy(() => { });
  503. let tree = getTree({
  504. value: '',
  505. defaultExpandAll: true,
  506. onChange: spyOnChange,
  507. });
  508. expect(tree.find(`.${BASE_CLASS_PREFIX}-tree-option-selected`).exists()).toEqual(false);
  509. let nodeBeijing = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-3`).at(0);
  510. // select beijing
  511. nodeBeijing.simulate('click');
  512. // onSelect & onChange
  513. expect(spyOnChange.calledOnce).toBe(true);
  514. expect(spyOnChange.calledWithMatch("Beijing")).toEqual(true);
  515. expect(tree.find(`.${BASE_CLASS_PREFIX}-tree-option-selected`).exists()).toEqual(false);
  516. });
  517. it('controlled: value + onChangeWithObject', () => {
  518. let spyOnChange = sinon.spy(() => { });
  519. let tree = getTree({
  520. value: {
  521. label: '北京',
  522. value: 'Beijing',
  523. key: 'beijing',
  524. },
  525. defaultExpandAll: true,
  526. onChange: spyOnChange,
  527. onChangeWithObject: true,
  528. });
  529. expect(tree.find(`.${BASE_CLASS_PREFIX}-tree-option-selected`).exists()).toEqual(true);
  530. });
  531. it('virtualized: fixed height', () => {
  532. let tree = getTree({
  533. defaultExpandAll: true,
  534. virtualize: {
  535. itemSize: 28,
  536. height: 84,
  537. },
  538. });
  539. // virtual list
  540. debugger
  541. expect(tree.find(`.${BASE_CLASS_PREFIX}-tree-virtual-list`).exists()).toEqual(true);
  542. // fewer nodes
  543. let nodes = tree.find(`.${BASE_CLASS_PREFIX}-tree-option`);
  544. expect(nodes.length).toBeLessThan(10);
  545. });
  546. it('disabled', () => {
  547. let spyOnChange = sinon.spy(() => { });
  548. let tree = getTree({
  549. defaultExpandAll: true,
  550. disabled: true,
  551. onChange: spyOnChange,
  552. });
  553. let nodes = tree.find(`.${BASE_CLASS_PREFIX}-tree-option-disabled`);
  554. expect(nodes.length).toEqual(10);
  555. // cannot select
  556. let nodeBeijing = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-3`).at(0);
  557. nodeBeijing.simulate('click');
  558. expect(spyOnChange.notCalled).toBe(true);
  559. expect(tree.find(`.${BASE_CLASS_PREFIX}-tree-option-selected`).exists()).toEqual(false);
  560. });
  561. it('treedata in json format', () => {
  562. let spyOnChange = sinon.spy(() => { });
  563. let tree = mount(
  564. <Tree
  565. defaultExpandAll={true}
  566. onChange={spyOnChange}
  567. treeDataSimpleJson={{
  568. "Node1": {
  569. "Child1": '0-0-1',
  570. "Child2": '0-0-2',
  571. },
  572. "Node2": "0-1"
  573. }}
  574. />,
  575. {
  576. attachTo: document.getElementById('container')
  577. }
  578. );
  579. let nodes = tree.find(`.${BASE_CLASS_PREFIX}-tree-option`);
  580. expect(nodes.length).toEqual(4);
  581. // select
  582. let child1 = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-2`).at(0);
  583. child1.simulate('click');
  584. expect(spyOnChange.calledOnce).toBe(true);
  585. expect(spyOnChange.calledWithMatch({
  586. "Node1": {
  587. "Child1": '0-0-1',
  588. },
  589. })).toEqual(true);
  590. expect(tree.find(`.${BASE_CLASS_PREFIX}-tree-option-selected`).exists()).toEqual(true);
  591. });
  592. it('onContextMenu', () => {
  593. const nativeEvent = { nativeEvent: { stopImmediatePropagation: () => { } } }
  594. let spyOnContextMenu = sinon.spy(() => { });
  595. let tree = getTree({
  596. onContextMenu: spyOnContextMenu,
  597. });
  598. let event = {};
  599. // yazhou
  600. let topNodeAsia = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`).at(0);
  601. // right click on yazhou
  602. topNodeAsia.simulate('contextmenu', nativeEvent);
  603. expect(spyOnContextMenu.calledWithMatch(event, { key: 'yazhou' })).toEqual(true);
  604. // should not select item
  605. expect(topNodeAsia.hasClass(`${BASE_CLASS_PREFIX}-tree-option-selected`)).toEqual(false);
  606. expect(tree.state().selectedKeys.length).toEqual(0);
  607. });
  608. it('onDoubleClick', () => {
  609. const nativeEvent = { nativeEvent: { stopImmediatePropagation: () => { } } }
  610. let spyOnDoubleClick = sinon.spy(() => { });
  611. let tree = getTree({
  612. onDoubleClick: spyOnDoubleClick,
  613. });
  614. let event = {};
  615. // yazhou
  616. let topNodeAsia = tree.find('.semi-tree-option.semi-tree-option-level-1').at(0);
  617. // double click on yazhou
  618. topNodeAsia.simulate('doubleClick', nativeEvent);
  619. expect(spyOnDoubleClick.calledWithMatch(event, { key: 'yazhou' })).toEqual(true);
  620. // should not select item
  621. expect(topNodeAsia.hasClass(`${BASE_CLASS_PREFIX}-tree-option-selected`)).toEqual(false);
  622. expect(tree.state().selectedKeys.length).toEqual(0);
  623. });
  624. it('expandAction = false / default behavior', () => {
  625. const nativeEvent = { nativeEvent: { stopImmediatePropagation: () => { } } }
  626. let spyOnExpand = sinon.spy(() => { });
  627. let tree = getTree({
  628. onExpand: spyOnExpand,
  629. });
  630. // yazhou
  631. let topNodeAsia = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`).at(0);
  632. // expand yazhou
  633. topNodeAsia.simulate('click', nativeEvent);
  634. expect(spyOnExpand.notCalled).toBe(true);
  635. expect(tree.state().expandedKeys.size).toEqual(0);
  636. });
  637. it('expandAction = click', () => {
  638. const nativeEvent = { nativeEvent: { stopImmediatePropagation: () => { } } }
  639. let spyOnExpand = sinon.spy(() => { });
  640. let tree = getTree({
  641. onExpand: spyOnExpand,
  642. expandAction: 'click',
  643. });
  644. // yazhou
  645. let topNodeAsia = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`).at(0);
  646. // expand yazhou
  647. topNodeAsia.simulate('click', nativeEvent);
  648. expect(spyOnExpand.calledOnce).toBe(true);
  649. expect(spyOnExpand.calledWithMatch(["yazhou"], { expanded: true, node: { key: 'yazhou' } })).toEqual(true);
  650. // yazhou beimeizhou
  651. let topNode = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`);
  652. expect(topNode.at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(false);
  653. expect(topNode.at(1).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(true);
  654. // collapse yazhou
  655. topNodeAsia.simulate('click', nativeEvent);
  656. expect(spyOnExpand.calledWithMatch([], { expanded: false, node: { key: 'yazhou' } })).toEqual(true);
  657. topNode = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`);
  658. expect(topNode.at(0).hasClass(`${BASE_CLASS_PREFIX}-tree-option-collapsed`)).toEqual(true);
  659. });
  660. it('expandAction = doubleClick', () => {
  661. const nativeEvent = { nativeEvent: { stopImmediatePropagation: () => { } } }
  662. let spyOnExpand = sinon.spy(() => { });
  663. let tree = getTree({
  664. onExpand: spyOnExpand,
  665. expandAction: 'doubleClick',
  666. });
  667. // yazhou
  668. let topNodeAsia = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`).at(0);
  669. // expand yazhou
  670. topNodeAsia.simulate('click', nativeEvent);
  671. expect(spyOnExpand.calledOnce).toBe(false);
  672. topNodeAsia.simulate('doubleClick', nativeEvent);
  673. expect(spyOnExpand.calledOnce).toBe(true);
  674. expect(spyOnExpand.calledWithMatch(["yazhou"], { expanded: true, node: { key: 'yazhou' } })).toEqual(true);
  675. // yazhou beimeizhou
  676. expect(tree.state().expandedKeys).toEqual(new Set(["yazhou"]));
  677. expect(tree.state().selectedKeys).toEqual(["yazhou"]);
  678. });
  679. it('async load data', () => {
  680. const nativeEvent = { nativeEvent: { stopImmediatePropagation: () => { } } }
  681. const then = jest.fn(() => Promise.resolve());
  682. const loadData = jest.fn(() => ({ then }));
  683. const data = {
  684. label: '亚洲',
  685. value: 'Asia',
  686. key: 'asia',
  687. };
  688. let tree = getTree({
  689. loadData,
  690. treeData: [data]
  691. });
  692. let topNodeAsia = tree.find(`.${BASE_CLASS_PREFIX}-tree-option.${BASE_CLASS_PREFIX}-tree-option-level-1`).at(0);
  693. let expandIcon = topNodeAsia.find(`.${BASE_CLASS_PREFIX}-tree-option-expand-icon`).at(0);
  694. // expand yazhou
  695. expandIcon.simulate('click', nativeEvent);
  696. expect(loadData).toHaveBeenCalledWith(data);
  697. expect(then).toHaveBeenCalled();
  698. });
  699. it('DND - dragStart event', () => {
  700. const spyOnDragStart = sinon.spy(() => { });
  701. let tree = getTree({
  702. draggable: true,
  703. onDragStart: spyOnDragStart
  704. });
  705. let dragNode = tree.find('.semi-tree-option.semi-tree-option-level-1').at(0);
  706. dragNode.simulate('dragStart');
  707. expect(spyOnDragStart.calledOnce).toBe(true);
  708. expect(spyOnDragStart.calledWithMatch({node: dragNodeData})).toEqual(true);
  709. });
  710. it('DND - dragEnter event', (done) => {
  711. const spyOnDragEnter = sinon.spy(() => { });
  712. let tree = getTree({
  713. draggable: true,
  714. // autoExpandWhenDragEnter: false,
  715. onDragEnter: spyOnDragEnter
  716. });
  717. let dragNode = tree.find('.semi-tree-option.semi-tree-option-level-1').at(0);
  718. dragNode.simulate('dragStart');
  719. dragNode.simulate('dragEnter');
  720. // not trigger on self
  721. expect(spyOnDragEnter.notCalled).toBe(true);
  722. let dropNode = tree.find('.semi-tree-option.semi-tree-option-level-1').at(1);
  723. dropNode.simulate('dragEnter');
  724. setTimeout(() => {
  725. expect(spyOnDragEnter.calledOnce).toBe(true);
  726. expect(spyOnDragEnter.calledWithMatch({node: dropNodeData, expandedKeys: ['beimeizhou']})).toEqual(true);
  727. done();
  728. }, 500);
  729. });
  730. it('DND - dragOver event', () => {
  731. const spyOnDragOver = sinon.spy(() => { });
  732. let tree = getTree({
  733. draggable: true,
  734. onDragOver: spyOnDragOver
  735. });
  736. let dropNode = tree.find('.semi-tree-option.semi-tree-option-level-1').at(1);
  737. dropNode.simulate('dragOver');
  738. expect(spyOnDragOver.calledOnce).toBe(true);
  739. expect(spyOnDragOver.calledWithMatch({node: dropNodeData})).toEqual(true);
  740. });
  741. it('DND - dragLeave event', () => {
  742. const spyOnDragLeave = sinon.spy(() => { });
  743. let tree = getTree({
  744. draggable: true,
  745. onDragLeave: spyOnDragLeave
  746. });
  747. let dropNode = tree.find('.semi-tree-option.semi-tree-option-level-1').at(1);
  748. dropNode.simulate('dragLeave');
  749. expect(spyOnDragLeave.calledOnce).toBe(true);
  750. expect(spyOnDragLeave.calledWithMatch({node: dropNodeData})).toEqual(true);
  751. });
  752. it('DND - drop event', () => {
  753. const spyOnDrop = sinon.spy(() => { });
  754. let tree = getTree({
  755. draggable: true,
  756. onDrop: spyOnDrop
  757. });
  758. let dragNode = tree.find('.semi-tree-option.semi-tree-option-level-1').at(0);
  759. dragNode.simulate('dragStart');
  760. let dropNode = tree.find('.semi-tree-option.semi-tree-option-level-1').at(1);
  761. dropNode.simulate('drop');
  762. expect(spyOnDrop.calledOnce).toBe(true);
  763. expect(spyOnDrop.calledWithMatch({
  764. dragNode: dragNodeData,
  765. dragNodesKeys: ["yazhou","zhongguo","beijing","shanghai","riben","dongjing","daban"],
  766. dropPosition: 1
  767. })).toEqual(true);
  768. });
  769. it('DND - dragEnd event', () => {
  770. const spyOnDragEnd = sinon.spy(() => { });
  771. let tree = getTree({
  772. draggable: true,
  773. onDragEnd: spyOnDragEnd
  774. });
  775. let dragNode = tree.find('.semi-tree-option.semi-tree-option-level-1').at(0);
  776. dragNode.simulate('dragEnd');
  777. expect(spyOnDragEnd.calledOnce).toBe(true);
  778. expect(spyOnDragEnd.calledWithMatch({node: dragNodeData})).toEqual(true);
  779. });
  780. })