manager.test.ts 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. import { it, expect, beforeEach, describe, vi } from 'vitest';
  2. import { debounce } from 'lodash';
  3. import { interfaces } from 'inversify';
  4. import {
  5. delay,
  6. WorkflowDocument,
  7. WorkflowHoverService,
  8. WorkflowSelectService,
  9. } from '@flowgram.ai/free-layout-core';
  10. import { FlowNodeRenderData } from '@flowgram.ai/document';
  11. import {
  12. EntityManager,
  13. PipelineRegistry,
  14. PipelineRenderer,
  15. PlaygroundConfigEntity,
  16. } from '@flowgram.ai/core';
  17. import { StackingContextManager } from '../src/manager';
  18. import { createWorkflowContainer, workflowJSON } from './utils.mock';
  19. import { IStackingContextManager } from './type.mock';
  20. let container: interfaces.Container;
  21. let document: WorkflowDocument;
  22. let stackingContextManager: IStackingContextManager;
  23. beforeEach(async () => {
  24. container = createWorkflowContainer();
  25. container.bind(StackingContextManager).to(StackingContextManager);
  26. document = container.get<WorkflowDocument>(WorkflowDocument);
  27. stackingContextManager = container.get<StackingContextManager>(
  28. StackingContextManager
  29. ) as unknown as IStackingContextManager;
  30. await document.fromJSON(workflowJSON);
  31. });
  32. describe('StackingContextManager public methods', () => {
  33. it('should create instance', () => {
  34. const stackingContextManager = container.get<StackingContextManager>(StackingContextManager);
  35. expect(stackingContextManager.node).toMatchInlineSnapshot(`
  36. <div
  37. class="gedit-playground-layer gedit-flow-render-layer"
  38. />
  39. `);
  40. expect(stackingContextManager).not.toBeUndefined();
  41. });
  42. it('should execute init', () => {
  43. stackingContextManager.init();
  44. const pipelineRenderer = container.get<PipelineRenderer>(PipelineRenderer);
  45. expect(pipelineRenderer.node).toMatchInlineSnapshot(
  46. `
  47. <div
  48. class="gedit-playground-pipeline"
  49. >
  50. <div
  51. class="gedit-playground-layer gedit-flow-render-layer"
  52. />
  53. </div>
  54. `
  55. );
  56. expect(stackingContextManager.disposers).toHaveLength(4);
  57. });
  58. it('should execute ready', () => {
  59. stackingContextManager.compute = vi.fn();
  60. stackingContextManager.ready();
  61. expect(stackingContextManager.compute).toBeCalled();
  62. });
  63. it('should dispose', () => {
  64. expect(stackingContextManager.disposers).toHaveLength(0);
  65. stackingContextManager.init();
  66. expect(stackingContextManager.disposers).toHaveLength(4);
  67. const mockDispose = { dispose: vi.fn() };
  68. stackingContextManager.disposers.push(mockDispose);
  69. stackingContextManager.dispose();
  70. expect(mockDispose.dispose).toBeCalled();
  71. });
  72. });
  73. describe('StackingContextManager private methods', () => {
  74. it('should compute with debounce', async () => {
  75. const compute = vi.fn();
  76. vi.spyOn(stackingContextManager, 'compute').mockImplementation(debounce(compute, 10));
  77. stackingContextManager.compute();
  78. await delay(1);
  79. stackingContextManager.compute();
  80. await delay(1);
  81. stackingContextManager.compute();
  82. await delay(1);
  83. stackingContextManager.compute();
  84. expect(compute).toBeCalledTimes(0);
  85. await delay(20);
  86. expect(compute).toBeCalledTimes(1);
  87. });
  88. it('should get nodes and lines', async () => {
  89. const nodeIds = stackingContextManager.nodes.map((n) => n.id);
  90. const lineIds = stackingContextManager.lines.map((l) => l.id);
  91. expect(nodeIds).toEqual([
  92. 'root',
  93. 'start_0',
  94. 'condition_0',
  95. 'end_0',
  96. 'loop_0',
  97. 'break_0',
  98. 'variable_0',
  99. ]);
  100. expect(lineIds).toEqual([
  101. 'break_0_-variable_0_',
  102. 'start_0_-condition_0_',
  103. 'condition_0_if-end_0_',
  104. 'condition_0_else-end_0_',
  105. 'loop_0_-end_0_',
  106. 'start_0_-loop_0_',
  107. ]);
  108. });
  109. it('should generate context', async () => {
  110. const hoverService = container.get<WorkflowHoverService>(WorkflowHoverService);
  111. const selectService = container.get<WorkflowSelectService>(WorkflowSelectService);
  112. expect(stackingContextManager.context).toStrictEqual({
  113. hoveredEntity: undefined,
  114. hoveredEntityID: undefined,
  115. selectedEntities: [],
  116. selectedIDs: [],
  117. });
  118. hoverService.updateHoveredKey('start_0');
  119. const breakNode = document.getNode('break_0')!;
  120. const variableNode = document.getNode('variable_0')!;
  121. selectService.selection = [breakNode, variableNode];
  122. expect(stackingContextManager.context.hoveredEntityID).toEqual('start_0');
  123. expect(stackingContextManager.context.selectedIDs).toEqual(['break_0', 'variable_0']);
  124. });
  125. it('should callback compute when onZoom trigger', () => {
  126. const entityManager = container.get<EntityManager>(EntityManager);
  127. const pipelineRegistry = container.get<PipelineRegistry>(PipelineRegistry);
  128. const compute = vi.spyOn(stackingContextManager, 'compute').mockImplementation(() => {});
  129. const playgroundConfig =
  130. entityManager.getEntity<PlaygroundConfigEntity>(PlaygroundConfigEntity)!;
  131. pipelineRegistry.ready();
  132. stackingContextManager.mountListener();
  133. playgroundConfig.updateConfig({
  134. zoom: 1.5,
  135. });
  136. expect(stackingContextManager.node.style.transform).toBe('scale(1.5)');
  137. playgroundConfig.updateConfig({
  138. zoom: 2,
  139. });
  140. expect(stackingContextManager.node.style.transform).toBe('scale(2)');
  141. playgroundConfig.updateConfig({
  142. zoom: 1,
  143. });
  144. expect(stackingContextManager.node.style.transform).toBe('scale(1)');
  145. expect(compute).toBeCalledTimes(3);
  146. });
  147. it('should callback compute when onHover trigger', () => {
  148. const hoverService = container.get<WorkflowHoverService>(WorkflowHoverService);
  149. const compute = vi.spyOn(stackingContextManager, 'compute').mockImplementation(() => {});
  150. stackingContextManager.mountListener();
  151. hoverService.updateHoveredKey('start_0');
  152. hoverService.updateHoveredKey('end_0');
  153. expect(compute).toBeCalledTimes(2);
  154. });
  155. it('should callback compute when onEntityChange trigger', () => {
  156. const entityManager = container.get<EntityManager>(EntityManager);
  157. const compute = vi.spyOn(stackingContextManager, 'compute').mockImplementation(() => {});
  158. const node = document.getNode('start_0')!;
  159. stackingContextManager.mountListener();
  160. entityManager.fireEntityChanged(node);
  161. expect(compute).toBeCalledTimes(1);
  162. });
  163. it('should callback compute when onSelect trigger', () => {
  164. const selectService = container.get<WorkflowSelectService>(WorkflowSelectService);
  165. const compute = vi.spyOn(stackingContextManager, 'compute').mockImplementation(() => {});
  166. stackingContextManager.mountListener();
  167. const breakNode = document.getNode('break_0')!;
  168. const variableNode = document.getNode('variable_0')!;
  169. selectService.selectNode(breakNode);
  170. selectService.selectNode(variableNode);
  171. expect(compute).toBeCalledTimes(2);
  172. });
  173. it('should mount listeners', () => {
  174. const hoverService = container.get<WorkflowHoverService>(WorkflowHoverService);
  175. const selectService = container.get<WorkflowSelectService>(WorkflowSelectService);
  176. const compute = vi.spyOn(stackingContextManager, 'compute').mockImplementation(() => {});
  177. stackingContextManager.mountListener();
  178. // onHover
  179. hoverService.updateHoveredKey('start_0');
  180. hoverService.updateHoveredKey('end_0');
  181. expect(compute).toBeCalledTimes(2);
  182. compute.mockReset();
  183. // select callback
  184. const breakNode = document.getNode('break_0')!;
  185. const variableNode = document.getNode('variable_0')!;
  186. selectService.selectNode(breakNode);
  187. selectService.selectNode(variableNode);
  188. expect(compute).toBeCalledTimes(2);
  189. });
  190. it('should trigger compute', async () => {
  191. stackingContextManager.ready();
  192. await delay(200);
  193. const node = document.getNode('loop_0')!;
  194. const nodeRenderData = node.getData<FlowNodeRenderData>(FlowNodeRenderData);
  195. const element = nodeRenderData.node;
  196. expect(element.style.zIndex).toBe('12');
  197. });
  198. });