flow-document.test.ts 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. import { beforeEach, describe, expect, it } from 'vitest';
  2. import { type FlowDocumentJSON, type FlowNodeJSON } from '../src/typings';
  3. import { FlowDocument } from '../src';
  4. import { baseMock, baseMockAddBranch, baseMockAddNode, baseMockNodeEnd } from './flow.mock';
  5. import { createDocumentContainer } from './flow-document-container.mock';
  6. describe('flow-document', () => {
  7. let container = createDocumentContainer();
  8. let document: FlowDocument;
  9. beforeEach(() => {
  10. container = createDocumentContainer();
  11. container.get(FlowDocument).fromJSON(baseMockAddNode);
  12. document = container.get<FlowDocument>(FlowDocument);
  13. });
  14. it('fromJSON', () => {
  15. document = container.get<FlowDocument>(FlowDocument);
  16. expect(document.root.childrenLength).toEqual(3);
  17. expect(document.root.children[0].parent).toEqual(document.root);
  18. expect(document.getNode('$blockOrderIcon$block_0')!.originParent).toEqual(
  19. document.getNode('dynamicSplit_0')
  20. );
  21. expect(document.getNode('$blockOrderIcon$block_0')!.parent).toEqual(
  22. document.getNode('block_0')
  23. );
  24. expect(document.toString()).toEqual(`root
  25. |-- start_0
  26. |-- dynamicSplit_0
  27. |---- $blockIcon$dynamicSplit_0
  28. |---- $inlineBlocks$dynamicSplit_0
  29. |------ block_0
  30. |-------- $blockOrderIcon$block_0
  31. |------ block_1
  32. |-------- $blockOrderIcon$block_1
  33. |-------- noop_0
  34. |-- end_0`);
  35. });
  36. it('fromJSON is equal toJSON', () => {
  37. function normalizeNode(node: FlowNodeJSON): FlowNodeJSON {
  38. return {
  39. ...node,
  40. type: node.type || 'block',
  41. blocks: node.blocks?.map((b) => normalizeNode(b)),
  42. };
  43. }
  44. function jsonEqual(from: FlowDocumentJSON, to: FlowDocumentJSON) {
  45. const nodes = to.nodes.map((node) => normalizeNode(node));
  46. expect(from.nodes).toEqual(nodes);
  47. }
  48. document.fromJSON(baseMock);
  49. jsonEqual(document.toJSON(), baseMock);
  50. document.fromJSON(baseMockAddNode);
  51. jsonEqual(document.toJSON(), baseMockAddNode);
  52. document.fromJSON(baseMockAddBranch);
  53. jsonEqual(document.toJSON(), baseMockAddBranch);
  54. // eslint-disable-next-line guard-for-in
  55. // for (const key in dataList) {
  56. // const json = (dataList as any)[key]
  57. // document.fromJSON(json)
  58. // jsonEqual(document.toJSON(), json)
  59. // }
  60. });
  61. it('fromJSON with cache', () => {
  62. // Step1: 导入初始结构
  63. document.fromJSON(baseMock);
  64. const originNodes = document.getAllNodes().slice();
  65. expect(document.size).toEqual(10);
  66. // Step2: 同一个数据,结构未变化,数据未变化
  67. document.fromJSON(baseMock);
  68. expect(document.size).toEqual(10);
  69. const nodes2 = document.getAllNodes().slice();
  70. expect(originNodes).toEqual(nodes2);
  71. // Step3: 添加一个节点,结构产生变化
  72. document.fromJSON(baseMockAddNode);
  73. expect(document.size).toEqual(11);
  74. const nodes3 = document.getAllNodes().slice();
  75. // 新添加的节点会放在最后边,前面所有的 instance 都不变
  76. expect(nodes3.slice(0, -1)).toEqual(originNodes);
  77. // Step4: 添加一个块
  78. document.fromJSON(baseMockAddBranch);
  79. expect(document.size).toEqual(13); // 会添加两个节点
  80. const nodes4 = document.getAllNodes().slice();
  81. expect(nodes4.slice(0, -3)).toEqual(originNodes);
  82. // Step5: 跑最初始的数据,结构变化,节点被删除了两个
  83. document.fromJSON(baseMock);
  84. expect(document.size).toEqual(10);
  85. const nodes5 = document.getAllNodes().slice();
  86. expect(nodes5).toEqual(originNodes);
  87. });
  88. // it('remove node from JSON', () => {
  89. // document.fromJSON(dataList['split-nested']);
  90. // expect(document.size).toBeGreaterThan(40);
  91. // document.fromJSON(dataList.empty);
  92. // expect(document.size).toEqual(3);
  93. // });
  94. it('add base node', () => {
  95. document.addFromNode('start_0', { id: 'new_noop', type: 'noop' });
  96. expect(document.toString()).toEqual(`root
  97. |-- start_0
  98. |-- new_noop
  99. |-- dynamicSplit_0
  100. |---- $blockIcon$dynamicSplit_0
  101. |---- $inlineBlocks$dynamicSplit_0
  102. |------ block_0
  103. |-------- $blockOrderIcon$block_0
  104. |------ block_1
  105. |-------- $blockOrderIcon$block_1
  106. |-------- noop_0
  107. |-- end_0`);
  108. expect(document.size).toEqual(12);
  109. });
  110. it('add split node', () => {
  111. document.addFromNode('dynamicSplit_0', {
  112. id: 'new_split',
  113. type: 'dynamicSplit',
  114. blocks: [{ id: 'b1' }, { id: 'b2' }],
  115. });
  116. expect(document.toString()).toEqual(`root
  117. |-- start_0
  118. |-- dynamicSplit_0
  119. |---- $blockIcon$dynamicSplit_0
  120. |---- $inlineBlocks$dynamicSplit_0
  121. |------ block_0
  122. |-------- $blockOrderIcon$block_0
  123. |------ block_1
  124. |-------- $blockOrderIcon$block_1
  125. |-------- noop_0
  126. |-- new_split
  127. |---- $blockIcon$new_split
  128. |---- $inlineBlocks$new_split
  129. |------ b1
  130. |-------- $blockOrderIcon$b1
  131. |------ b2
  132. |-------- $blockOrderIcon$b2
  133. |-- end_0`);
  134. expect(document.size).toEqual(18);
  135. document.addFromNode('block_1', {
  136. id: 'new_split2',
  137. type: 'dynamicSplit',
  138. blocks: [{ id: 'nb1' }, { id: 'nb2' }],
  139. });
  140. expect(document.toString()).toMatchSnapshot();
  141. expect(document.size).toEqual(25);
  142. });
  143. it('removeNode', () => {
  144. document.removeNode('dynamicSplit_0');
  145. expect(document.toString()).toEqual(`root
  146. |-- start_0
  147. |-- end_0`);
  148. expect(document.size).toEqual(3);
  149. });
  150. it('removeLeafBlock', () => {
  151. document.removeNode('noop_0');
  152. expect(document.toString()).toEqual(`root
  153. |-- start_0
  154. |-- dynamicSplit_0
  155. |---- $blockIcon$dynamicSplit_0
  156. |---- $inlineBlocks$dynamicSplit_0
  157. |------ block_0
  158. |-------- $blockOrderIcon$block_0
  159. |------ block_1
  160. |-------- $blockOrderIcon$block_1
  161. |-- end_0`);
  162. });
  163. it('removeBlockFistChild', () => {
  164. document = container.get<FlowDocument>(FlowDocument);
  165. document.removeNode('$blockOrderIcon$block_1');
  166. expect(document.toString()).toEqual(`root
  167. |-- start_0
  168. |-- dynamicSplit_0
  169. |---- $blockIcon$dynamicSplit_0
  170. |---- $inlineBlocks$dynamicSplit_0
  171. |------ block_0
  172. |-------- $blockOrderIcon$block_0
  173. |------ block_1
  174. |-------- noop_0
  175. |-- end_0`);
  176. });
  177. it('removeBlockWithChild', () => {
  178. document.removeNode('block_1');
  179. expect(document.toString()).toEqual(`root
  180. |-- start_0
  181. |-- dynamicSplit_0
  182. |---- $blockIcon$dynamicSplit_0
  183. |---- $inlineBlocks$dynamicSplit_0
  184. |------ block_0
  185. |-------- $blockOrderIcon$block_0
  186. |-- end_0`);
  187. });
  188. it('flow node type changed', () => {
  189. document.fromJSON({
  190. nodes: [
  191. {
  192. id: 'start_0',
  193. type: 'start',
  194. blocks: [],
  195. },
  196. {
  197. id: 'dynamicSplit_0',
  198. type: 'noop', // Change node type to noop
  199. },
  200. {
  201. id: 'end_0',
  202. type: 'dynamicSplit', // Change node type to dynamicSplit
  203. blocks: [{ id: 'block_0' }, { id: 'block_1' }],
  204. },
  205. ],
  206. });
  207. expect(document.toString()).toEqual(`root
  208. |-- start_0
  209. |-- dynamicSplit_0
  210. |-- end_0
  211. |---- $blockIcon$end_0
  212. |---- $inlineBlocks$end_0
  213. |------ block_0
  214. |-------- $blockOrderIcon$block_0
  215. |------ block_1
  216. |-------- $blockOrderIcon$block_1`);
  217. expect(document.size).toEqual(10);
  218. });
  219. /**
  220. * 分支移动
  221. */
  222. it('flow node move', () => {
  223. document.fromJSON({
  224. nodes: [
  225. {
  226. id: 'start_0',
  227. type: 'start',
  228. blocks: [],
  229. },
  230. {
  231. id: 'end_0',
  232. type: 'end',
  233. blocks: [],
  234. },
  235. {
  236. id: 'dynamicSplit_0',
  237. type: 'dynamicSplit',
  238. blocks: [{ id: 'block_1' }, { id: 'block_0' }], // swap blocks order
  239. },
  240. ],
  241. });
  242. expect(document.toString()).toEqual(`root
  243. |-- start_0
  244. |-- end_0
  245. |-- dynamicSplit_0
  246. |---- $blockIcon$dynamicSplit_0
  247. |---- $inlineBlocks$dynamicSplit_0
  248. |------ block_1
  249. |-------- $blockOrderIcon$block_1
  250. |------ block_0
  251. |-------- $blockOrderIcon$block_0`);
  252. });
  253. /**
  254. * 节点结束判断
  255. */
  256. it('flow is node end', () => {
  257. document.fromJSON(baseMockNodeEnd);
  258. expect(document.getNode('dynamicSplit_0')?.isNodeEnd).toBeTruthy();
  259. expect(document.getNode('block_0')?.isNodeEnd).toBeTruthy();
  260. expect(document.getNode('noop_0')?.isNodeEnd).toBeTruthy();
  261. });
  262. it('node registry add cache', () => {
  263. const registry1 = document.getNodeRegistry('start');
  264. const registry2 = document.getNodeRegistry('start');
  265. expect(registry1 === registry2).toBeTruthy();
  266. expect(
  267. document.getNode('block_0')!.getNodeRegistry() ===
  268. document.getNode('block_1')!.getNodeRegistry()
  269. ).toBeTruthy();
  270. expect(
  271. document.getNode('block_0')!.getNodeMeta() === document.getNode('block_1')!.getNodeMeta()
  272. ).toBeTruthy();
  273. });
  274. });