flow-operation-base-service.test.ts 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /**
  2. * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
  3. * SPDX-License-Identifier: MIT
  4. */
  5. import { beforeEach, describe, expect, it, vi } from 'vitest';
  6. import { baseMockAddNode, baseMockAddBranch } from '../flow.mock';
  7. import { createDocumentContainer } from '../flow-document-container.mock';
  8. import { FlowOperationBaseService, FlowDocument, OperationType, OnNodeMoveEvent } from '../../src';
  9. describe('flow-operation-base-service', () => {
  10. let container = createDocumentContainer();
  11. let document: FlowDocument;
  12. let flowOperationService: FlowOperationBaseService;
  13. beforeEach(() => {
  14. container = createDocumentContainer();
  15. document = container.get(FlowDocument);
  16. document.fromJSON(baseMockAddNode);
  17. flowOperationService = container.get<FlowOperationBaseService>(FlowOperationBaseService);
  18. });
  19. it('addFromNode deleteFromNode', () => {
  20. const json = document.toJSON();
  21. const value = {
  22. fromId: 'start_0',
  23. data: {
  24. id: 'test',
  25. type: 'noop',
  26. },
  27. };
  28. flowOperationService.apply({
  29. type: OperationType.addFromNode,
  30. value,
  31. });
  32. expect(document.toJSON()).matchSnapshot();
  33. flowOperationService.apply({
  34. type: OperationType.deleteFromNode,
  35. value,
  36. });
  37. expect(document.toJSON()).matchSnapshot();
  38. expect(document.toJSON()).toEqual(json);
  39. });
  40. it('addBlock deleteBlock', () => {
  41. const json = document.toJSON();
  42. const value = {
  43. targetId: 'dynamicSplit_0',
  44. blockData: {
  45. id: 'test',
  46. },
  47. };
  48. flowOperationService.apply({
  49. type: OperationType.addBlock,
  50. value,
  51. });
  52. expect(document.toJSON()).matchSnapshot();
  53. flowOperationService.apply({
  54. type: OperationType.deleteBlock,
  55. value,
  56. });
  57. expect(document.toJSON()).matchSnapshot();
  58. expect(document.toJSON()).toEqual(json);
  59. });
  60. it('addBlock deleteBlock by index', () => {
  61. const json = document.toJSON();
  62. const value = {
  63. targetId: 'dynamicSplit_0',
  64. blockData: {
  65. id: 'test',
  66. },
  67. index: 1,
  68. };
  69. flowOperationService.apply({
  70. type: OperationType.addBlock,
  71. value,
  72. });
  73. expect(document.toJSON()).matchSnapshot();
  74. flowOperationService.apply({
  75. type: OperationType.deleteBlock,
  76. value,
  77. });
  78. expect(document.toJSON()).matchSnapshot();
  79. expect(document.toJSON()).toEqual(json);
  80. });
  81. it('moveNodes', () => {
  82. const value = {
  83. fromId: 'block_1',
  84. toId: 'start_0',
  85. nodeIds: ['noop_0'],
  86. };
  87. flowOperationService.apply({
  88. type: OperationType.moveNodes,
  89. value,
  90. });
  91. expect(document.toJSON()).matchSnapshot();
  92. flowOperationService.apply({
  93. type: OperationType.moveNodes,
  94. value: {
  95. ...value,
  96. fromId: 'start_0',
  97. toId: 'block_1',
  98. },
  99. });
  100. expect(document.toJSON()).matchSnapshot();
  101. // expect(document.toJSON()).toEqual(json);
  102. });
  103. it('moveBlock', () => {
  104. document.fromJSON(baseMockAddBranch);
  105. const json = document.toJSON();
  106. flowOperationService.apply({
  107. type: OperationType.moveBlock,
  108. value: {
  109. nodeId: 'block_0',
  110. fromParentId: '$inlineBlocks$dynamicSplit_0',
  111. fromIndex: 0,
  112. toParentId: '$inlineBlocks$dynamicSplit_0',
  113. toIndex: 1,
  114. },
  115. });
  116. expect(document.toJSON()).matchSnapshot();
  117. flowOperationService.apply({
  118. type: OperationType.moveBlock,
  119. value: {
  120. nodeId: 'block_0',
  121. fromParentId: '$inlineBlocks$dynamicSplit_0',
  122. fromIndex: 1,
  123. toParentId: '$inlineBlocks$dynamicSplit_0',
  124. toIndex: 0,
  125. },
  126. });
  127. expect(document.toJSON()).matchSnapshot();
  128. expect(document.toJSON()).toEqual(json);
  129. });
  130. it('dragNodes', () => {
  131. document.fromJSON(baseMockAddBranch);
  132. flowOperationService.dragNodes({
  133. dropNode: document.getNode('block_1')!,
  134. nodes: [document.getNode('block_0')!],
  135. });
  136. expect(document.toJSON()).matchSnapshot();
  137. flowOperationService.dragNodes({
  138. dropNode: document.getNode('block_1')!,
  139. nodes: [document.getNode('block_2')!],
  140. });
  141. expect(document.toJSON()).matchSnapshot();
  142. });
  143. it('moveChildNodes', () => {
  144. document.fromJSON(baseMockAddBranch);
  145. const json = document.toJSON();
  146. flowOperationService.apply({
  147. type: OperationType.moveChildNodes,
  148. value: {
  149. nodeIds: ['block_0', 'block_1'],
  150. fromParentId: '$inlineBlocks$dynamicSplit_0',
  151. fromIndex: 0,
  152. toParentId: '$inlineBlocks$dynamicSplit_0',
  153. toIndex: 1,
  154. },
  155. });
  156. expect(document.toJSON()).matchSnapshot();
  157. flowOperationService.apply({
  158. type: OperationType.moveChildNodes,
  159. value: {
  160. nodeIds: ['block_0', 'block_1'],
  161. fromParentId: '$inlineBlocks$dynamicSplit_0',
  162. fromIndex: 1,
  163. toParentId: '$inlineBlocks$dynamicSplit_0',
  164. toIndex: 0,
  165. },
  166. });
  167. expect(document.toJSON()).matchSnapshot();
  168. expect(document.toJSON()).toEqual(json);
  169. });
  170. it('addNodes deleteNodes', () => {
  171. const json = document.toJSON();
  172. const value = {
  173. fromId: 'start_0',
  174. nodes: [
  175. {
  176. id: 'test1',
  177. type: 'noop',
  178. },
  179. {
  180. id: 'test2',
  181. type: 'noop',
  182. },
  183. ],
  184. };
  185. flowOperationService.apply({
  186. type: OperationType.addNodes,
  187. value,
  188. });
  189. expect(document.toJSON()).matchSnapshot();
  190. flowOperationService.apply({
  191. type: OperationType.deleteNodes,
  192. value,
  193. });
  194. expect(document.toJSON()).matchSnapshot();
  195. expect(document.toJSON()).toEqual(json);
  196. });
  197. it('addChildNode deleteChildNode', () => {
  198. const json = document.toJSON();
  199. const value = {
  200. parentId: 'noop_0',
  201. data: {
  202. id: 'test-node',
  203. },
  204. index: 0,
  205. };
  206. flowOperationService.apply({
  207. type: OperationType.addChildNode,
  208. value,
  209. });
  210. expect(document.getNode('noop_0')?.children.map((c) => c.toJSON())).matchSnapshot();
  211. flowOperationService.apply({
  212. type: OperationType.deleteChildNode,
  213. value,
  214. });
  215. expect(document.getNode('noop_0')?.children.map((c) => c.toJSON())).matchSnapshot();
  216. expect(document.toJSON()).toEqual(json);
  217. });
  218. it('addNode', () => {
  219. const fn = vi.fn();
  220. flowOperationService.onNodeAdd(fn);
  221. const child = flowOperationService.addNode(
  222. {
  223. id: 'test',
  224. type: 'test',
  225. },
  226. {
  227. parent: 'root',
  228. index: 1,
  229. hidden: true,
  230. }
  231. );
  232. expect(child.id).toEqual('test');
  233. expect(child.pre?.id).toEqual('start_0');
  234. expect(child.next?.id).toEqual('dynamicSplit_0');
  235. expect(child.hidden).toEqual(true);
  236. expect(fn).toBeCalledTimes(1);
  237. });
  238. it('moveNode should fire event', () => {
  239. let event: OnNodeMoveEvent;
  240. flowOperationService.onNodeMove((e) => {
  241. event = e;
  242. expect(event.node.id === 'noop_0');
  243. expect(event.fromIndex === 1);
  244. expect(event.toParent.id === 'block_0');
  245. expect(event.toIndex === 1);
  246. });
  247. flowOperationService.moveNode('noop_0', { parent: 'block_0' });
  248. });
  249. });