flow-virtual-tree.spec.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /**
  2. * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
  3. * SPDX-License-Identifier: MIT
  4. */
  5. import { beforeEach, describe, expect, it } from 'vitest';
  6. import { FlowVirtualTree } from '../src/flow-virtual-tree';
  7. import NodeInfo = FlowVirtualTree.NodeInfo;
  8. interface Node {
  9. id: string;
  10. }
  11. describe('flow-virtual-tree', () => {
  12. let tree: FlowVirtualTree<Node>;
  13. beforeEach(() => {
  14. tree = new FlowVirtualTree<Node>({
  15. id: 'root',
  16. });
  17. addBase();
  18. });
  19. function addBase(): void {
  20. const noop1 = tree.addChild(tree.root, { id: 'noop1' });
  21. const noop2 = tree.addChild(noop1, { id: 'noop2' });
  22. tree.addChild(tree.root, { id: 'noop1_n' });
  23. tree.addChild(noop2, { id: 'noop3' });
  24. tree.addChild(noop2, { id: 'noop4' });
  25. tree.addChild(noop2, { id: 'noop5' });
  26. }
  27. function get(id: string): Node {
  28. return tree.getById(id)!;
  29. }
  30. function getInfo(id: string): FlowVirtualTree.NodeInfo<Node> {
  31. return tree.getInfo(get(id)!)!;
  32. }
  33. it('get infos', () => {
  34. const infos: Record<string, NodeInfo<Node>> = {};
  35. // tree.traverse()
  36. expect(tree.toString()).toEqual(`root
  37. |-- noop1
  38. |---- noop2
  39. |------ noop3
  40. |------ noop4
  41. |------ noop5
  42. |-- noop1_n`);
  43. expect(tree.size).toEqual(7);
  44. tree.traverse((n) => {
  45. infos[n.id] = {
  46. parent: tree.getParent(n),
  47. pre: tree.getPre(n),
  48. next: tree.getNext(n),
  49. children: tree.getChildren(n),
  50. };
  51. });
  52. expect(infos).toEqual({
  53. root: { children: [{ id: 'noop1' }, { id: 'noop1_n' }] },
  54. noop1: { parent: { id: 'root' }, next: { id: 'noop1_n' }, children: [{ id: 'noop2' }] },
  55. noop2: {
  56. parent: { id: 'noop1' },
  57. children: [{ id: 'noop3' }, { id: 'noop4' }, { id: 'noop5' }],
  58. },
  59. noop3: { parent: { id: 'noop2' }, next: { id: 'noop4' }, children: [] },
  60. noop4: { parent: { id: 'noop2' }, pre: { id: 'noop3' }, next: { id: 'noop5' }, children: [] },
  61. noop5: { parent: { id: 'noop2' }, pre: { id: 'noop4' }, children: [] },
  62. noop1_n: { parent: { id: 'root' }, pre: { id: 'noop1' }, children: [] },
  63. });
  64. });
  65. it('add child from node existed', () => {
  66. tree.addChild(get('root'), get('noop4'));
  67. expect(tree.toString()).toEqual(`root
  68. |-- noop1
  69. |---- noop2
  70. |------ noop3
  71. |------ noop5
  72. |-- noop1_n
  73. |-- noop4`);
  74. expect(getInfo('noop4').pre).toEqual(get('noop1_n'));
  75. expect(getInfo('noop4').parent).toEqual(get('root'));
  76. expect(getInfo('noop3').next).toEqual(get('noop5'));
  77. expect(getInfo('noop5').pre).toEqual(get('noop3'));
  78. });
  79. it('add child same', () => {
  80. tree.addChild(get('root'), get('noop1'));
  81. expect(tree.toString()).toEqual(`root
  82. |-- noop1
  83. |---- noop2
  84. |------ noop3
  85. |------ noop4
  86. |------ noop5
  87. |-- noop1_n`);
  88. });
  89. it('remove child', () => {
  90. tree.remove(get('noop4')!);
  91. expect(tree.toString()).toEqual(`root
  92. |-- noop1
  93. |---- noop2
  94. |------ noop3
  95. |------ noop5
  96. |-- noop1_n`);
  97. expect(tree.size).toEqual(6);
  98. expect(getInfo('noop3').next).toEqual(get('noop5'));
  99. expect(getInfo('noop5').pre).toEqual(get('noop3'));
  100. tree.remove(get('noop3')!);
  101. expect(getInfo('noop5').pre).toBeUndefined();
  102. expect(tree.toString()).toEqual(`root
  103. |-- noop1
  104. |---- noop2
  105. |------ noop5
  106. |-- noop1_n`);
  107. expect(tree.size).toEqual(5);
  108. tree.addChild(get('noop5'), { id: 'left' });
  109. tree.remove(get('noop2')!);
  110. expect(tree.toString()).toEqual(`root
  111. |-- noop1
  112. |-- noop1_n`);
  113. expect(tree.size).toEqual(3);
  114. });
  115. it('clear', () => {
  116. tree.clear();
  117. expect(tree.size).toEqual(0);
  118. });
  119. it('clone', () => {
  120. const clone = tree.clone();
  121. expect(clone.toString()).toEqual(tree.toString());
  122. expect(clone.size).toEqual(tree.size);
  123. });
  124. it('dispose', () => {
  125. let times = 0;
  126. tree.onTreeChange(() => {
  127. times += 1;
  128. });
  129. tree.addChild(tree.root, { id: 'noop1' });
  130. tree.dispose();
  131. tree.addChild(tree.root, { id: 'noop2' });
  132. expect(tree.toString()).toEqual(`root
  133. |-- noop2`);
  134. expect(times).toEqual(1);
  135. });
  136. it('insertAfter', () => {
  137. tree.insertAfter(get('noop2'), { id: 'noop2_next' });
  138. expect(getInfo('noop2').next).toEqual(get('noop2_next'));
  139. expect(getInfo('noop2_next').pre).toEqual(get('noop2'));
  140. expect(getInfo('noop2_next').parent).toEqual(get('noop1'));
  141. expect(tree.toString()).toEqual(`root
  142. |-- noop1
  143. |---- noop2
  144. |------ noop3
  145. |------ noop4
  146. |------ noop5
  147. |---- noop2_next
  148. |-- noop1_n`);
  149. tree.insertAfter(get('noop3'), { id: 'noop3_next' });
  150. expect(tree.toString()).toEqual(`root
  151. |-- noop1
  152. |---- noop2
  153. |------ noop3
  154. |------ noop3_next
  155. |------ noop4
  156. |------ noop5
  157. |---- noop2_next
  158. |-- noop1_n`);
  159. expect(getInfo('noop3').next).toEqual(get('noop3_next'));
  160. expect(getInfo('noop3_next').pre).toEqual(get('noop3'));
  161. expect(getInfo('noop3_next').next).toEqual(get('noop4'));
  162. expect(getInfo('noop3_next').parent).toEqual(get('noop2'));
  163. expect(getInfo('noop4').pre).toEqual(get('noop3_next'));
  164. });
  165. });