diff --git a/libs/designer-ui/src/lib/card/graphContainer/__test__/__snapshots__/graphContainer.spec.tsx.snap b/libs/designer-ui/src/lib/card/graphContainer/__test__/__snapshots__/graphContainer.spec.tsx.snap new file mode 100644 index 00000000000..06545049f95 --- /dev/null +++ b/libs/designer-ui/src/lib/card/graphContainer/__test__/__snapshots__/graphContainer.spec.tsx.snap @@ -0,0 +1,25 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`GraphContainer component > renders with active prop set to false 1`] = ` +
+`; + +exports[`GraphContainer component > renders with default props 1`] = ` +
+`; + +exports[`GraphContainer component > renders with selected and active props 1`] = ` +
+`; + +exports[`GraphContainer component > renders with selected prop 1`] = ` +
+`; diff --git a/libs/designer-ui/src/lib/card/graphContainer/__test__/graphContainer.spec.tsx b/libs/designer-ui/src/lib/card/graphContainer/__test__/graphContainer.spec.tsx new file mode 100644 index 00000000000..eca4dba7adb --- /dev/null +++ b/libs/designer-ui/src/lib/card/graphContainer/__test__/graphContainer.spec.tsx @@ -0,0 +1,38 @@ +import { describe, it, expect } from 'vitest'; +import renderer from 'react-test-renderer'; +import { GraphContainer } from '../index'; +import React from 'react'; + +describe('GraphContainer component', () => { + it('renders with default props', () => { + const container = renderer.create().toJSON(); + expect(container).toMatchSnapshot(); + expect(container).toHaveProperty('props.className', expect.stringContaining('msla-graph-container')); + expect(container).not.toHaveProperty('props.className', expect.stringContaining('selected')); + expect(container).not.toHaveProperty('props.className', expect.stringContaining('msla-card-inactive')); + }); + + it('renders with selected prop', () => { + const container = renderer.create().toJSON(); + expect(container).toMatchSnapshot(); + expect(container).toHaveProperty('props.className', expect.stringContaining('msla-graph-container')); + expect(container).toHaveProperty('props.className', expect.stringContaining('selected')); + expect(container).not.toHaveProperty('props.className', expect.stringContaining('msla-card-inactive')); + }); + + it('renders with active prop set to false', () => { + const container = renderer.create().toJSON(); + expect(container).toMatchSnapshot(); + expect(container).toHaveProperty('props.className', expect.stringContaining('msla-graph-container')); + expect(container).not.toHaveProperty('props.className', expect.stringContaining('selected')); + expect(container).toHaveProperty('props.className', expect.stringContaining('msla-card-inactive')); + }); + + it('renders with selected and active props', () => { + const container = renderer.create().toJSON(); + expect(container).toMatchSnapshot(); + expect(container).toHaveProperty('props.className', expect.stringContaining('msla-graph-container')); + expect(container).toHaveProperty('props.className', expect.stringContaining('selected')); + expect(container).toHaveProperty('props.className', expect.stringContaining('msla-card-inactive')); + }); +}); diff --git a/libs/designer/src/lib/ui/CustomNodes/__test__/GraphContainerNode.spec.tsx b/libs/designer/src/lib/ui/CustomNodes/__test__/GraphContainerNode.spec.tsx new file mode 100644 index 00000000000..5c5c1f7168b --- /dev/null +++ b/libs/designer/src/lib/ui/CustomNodes/__test__/GraphContainerNode.spec.tsx @@ -0,0 +1,137 @@ +import React from 'react'; +import renderer from 'react-test-renderer'; +import GraphContainerNode from '../GraphContainerNode'; +import { vi, beforeEach, describe, Mock, it, expect } from 'vitest'; +import { useMonitoringView, useReadOnly } from '../../../core/state/designerOptions/designerOptionsSelectors'; +import { useIsNodeSelectedInOperationPanel } from '../../../core/state/panel/panelSelectors'; +import { useNodeMetadata } from '../../../core'; +import { useActionMetadata, useIsLeafNode, useParentRunId, useRunData } from '../../../core/state/workflow/workflowSelectors'; +import { useNodeSize, useNodeLeafIndex, SUBGRAPH_TYPES } from '@microsoft/logic-apps-shared'; +import { NodeProps } from '@xyflow/react'; + +vi.mock('../../../core/state/designerOptions/designerOptionsSelectors', () => ({ + useReadOnly: vi.fn(), + useMonitoringView: vi.fn(), +})); + +vi.mock('../../../core/state/panel/panelSelectors', () => ({ + useIsNodeSelectedInOperationPanel: vi.fn(), +})); + +vi.mock('../../../core/state/workflow/workflowSelectors', () => ({ + useActionMetadata: vi.fn(), + useNodeMetadata: vi.fn(), + useIsLeafNode: vi.fn(), + useParentRunId: vi.fn(), + useRunData: vi.fn(), +})); + +vi.mock(import('@microsoft/logic-apps-shared'), async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + useNodeSize: vi.fn(), + useNodeLeafIndex: vi.fn(), + }; +}); + +vi.mock(import('../../connections/dropzone'), async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + DropZone: (({ children, ...props }) =>
{'DropZone'}
) as any, + }; +}); + +vi.mock(import('@xyflow/react'), async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + Handle: (({ children, ...props }) =>
{'Handle reactflow'}
) as any, + }; +}); + +describe('GraphContainerNode', () => { + const defaultProps = { + id: 'mockId', + } as NodeProps; + + beforeEach(() => { + (useReadOnly as Mock).mockReturnValue(false); + (useIsNodeSelectedInOperationPanel as Mock).mockReturnValue(false); + (useActionMetadata as Mock).mockReturnValue({}); + (useNodeMetadata as Mock).mockReturnValue({}); + (useIsLeafNode as Mock).mockReturnValue(false); + (useMonitoringView as Mock).mockReturnValue(false); + (useParentRunId as Mock).mockReturnValue(null); + (useRunData as Mock).mockReturnValue({}); + (useNodeSize as Mock).mockReturnValue({ width: 100, height: 100 }); + (useNodeLeafIndex as Mock).mockReturnValue(0); + }); + + it('should render without crashing', () => { + const tree = renderer.create().toJSON(); + expect(tree).toMatchSnapshot(); + }); + + it('should render with footer and be a subgraph', () => { + (useNodeMetadata as Mock).mockReturnValue({ subgraphType: SUBGRAPH_TYPES.UNTIL_DO }); + const tree = renderer.create().toJSON(); + expect(tree.props.className).includes('has-footer'); + expect(tree.props.className).includes('is-subgraph'); + + expect(tree).toMatchSnapshot(); + }); + + it('should render graph container as normal when in monitoring view', () => { + (useMonitoringView as Mock).mockReturnValue(true); + (useRunData as Mock).mockReturnValue({ status: 'Success' }); + + const tree = renderer.create().toJSON(); + + expect(tree).toMatchSnapshot(); + }); + + it('should render graph container as inactive when is monitoring view', () => { + (useMonitoringView as Mock).mockReturnValue(true); + (useRunData as Mock).mockReturnValue({}); + + const tree = renderer.create().toJSON(); + + expect(tree).toMatchSnapshot(); + }); + + it('should apply correct styles based on node size', () => { + const tree = renderer.create().toJSON(); + expect(tree?.props.style).toEqual({ width: 100, height: 100 }); + expect(tree).toMatchSnapshot(); + }); + + it('should render the top and bottom handles', () => { + const tree = renderer.create().toJSON(); + const topHandle = tree.children.find((child) => child.props.className.includes('node-handle top')); + const bottomHandle = tree.children.find((child) => child.props.className.includes('node-handle bottom')); + expect(topHandle).toBeTruthy(); + expect(bottomHandle).toBeTruthy(); + expect(tree).toMatchSnapshot(); + }); + + it('should render DropZone when showLeafComponents is true', () => { + (useIsLeafNode as Mock).mockReturnValue(true); + (useActionMetadata as Mock).mockReturnValue({ type: 'someType' }); + + const tree = renderer.create().toJSON(); + + expect(tree.length).toBe(2); + expect(tree[1].props.className).toBe('edge-drop-zone-container'); + expect(tree).toMatchSnapshot(); + }); + + it('should not render DropZone when showLeafComponents is false', () => { + const tree = renderer.create().toJSON(); + const dropZone = tree.children.find((child) => child.props.className.includes('edge-drop-zone-container')); + + expect(dropZone).toBeFalsy(); + expect(tree).toMatchSnapshot(); + }); +}); diff --git a/libs/designer/src/lib/ui/CustomNodes/__test__/__snapshots__/GraphContainerNode.spec.tsx.snap b/libs/designer/src/lib/ui/CustomNodes/__test__/__snapshots__/GraphContainerNode.spec.tsx.snap new file mode 100644 index 00000000000..2edb954989c --- /dev/null +++ b/libs/designer/src/lib/ui/CustomNodes/__test__/__snapshots__/GraphContainerNode.spec.tsx.snap @@ -0,0 +1,271 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`GraphContainerNode > should apply correct styles based on node size 1`] = ` +
+
+ Handle reactflow +
+
+
+ Handle reactflow +
+
+`; + +exports[`GraphContainerNode > should not render DropZone when showLeafComponents is false 1`] = ` +
+
+ Handle reactflow +
+
+
+ Handle reactflow +
+
+`; + +exports[`GraphContainerNode > should render DropZone when showLeafComponents is true 1`] = ` +[ +
+
+ Handle reactflow +
+
+
+ Handle reactflow +
+
, +
+
+ DropZone +
+
, +] +`; + +exports[`GraphContainerNode > should render graph container as inactive when is monitoring view 1`] = ` +
+
+ Handle reactflow +
+
+
+ Handle reactflow +
+
+`; + +exports[`GraphContainerNode > should render graph container as normal when in monitoring view 1`] = ` +
+
+ Handle reactflow +
+
+
+ Handle reactflow +
+
+`; + +exports[`GraphContainerNode > should render the top and bottom handles 1`] = ` +
+
+ Handle reactflow +
+
+
+ Handle reactflow +
+
+`; + +exports[`GraphContainerNode > should render with footer and be a subgraph 1`] = ` +
+
+ Handle reactflow +
+
+
+ Handle reactflow +
+
+`; + +exports[`GraphContainerNode > should render without crashing 1`] = ` +
+
+ Handle reactflow +
+
+
+ Handle reactflow +
+
+`;