Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(designer): Add unit tests for graph container node #6415

Merged
merged 3 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`GraphContainer component > renders with active prop set to false 1`] = `
<div
className="msla-graph-container msla-card-inactive"
/>
`;

exports[`GraphContainer component > renders with default props 1`] = `
<div
className="msla-graph-container"
/>
`;

exports[`GraphContainer component > renders with selected and active props 1`] = `
<div
className="msla-graph-container selected msla-card-inactive"
/>
`;

exports[`GraphContainer component > renders with selected prop 1`] = `
<div
className="msla-graph-container selected"
/>
`;
Original file line number Diff line number Diff line change
@@ -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(<GraphContainer />).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(<GraphContainer selected={true} />).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(<GraphContainer active={false} />).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(<GraphContainer selected={true} active={false} />).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'));
});
});
Original file line number Diff line number Diff line change
@@ -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 }) => <div {...props}>{'DropZone'}</div>) as any,
};
});

vi.mock(import('@xyflow/react'), async (importOriginal) => {
const actual = await importOriginal();
return {
...actual,
Handle: (({ children, ...props }) => <div {...props}>{'Handle reactflow'}</div>) 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(<GraphContainerNode {...defaultProps} />).toJSON();
expect(tree).toMatchSnapshot();
});

it('should render with footer and be a subgrah', () => {
ccastrotrejo marked this conversation as resolved.
Show resolved Hide resolved
(useNodeMetadata as Mock).mockReturnValue({ subgraphType: SUBGRAPH_TYPES.UNTIL_DO });
const tree = renderer.create(<GraphContainerNode {...defaultProps} />).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 is monitoring view', () => {
ccastrotrejo marked this conversation as resolved.
Show resolved Hide resolved
(useMonitoringView as Mock).mockReturnValue(true);
(useRunData as Mock).mockReturnValue({ status: 'Success' });

const tree = renderer.create(<GraphContainerNode {...defaultProps} />).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(<GraphContainerNode {...defaultProps} />).toJSON();

expect(tree).toMatchSnapshot();
});

it('should apply correct styles based on node size', () => {
const tree = renderer.create(<GraphContainerNode {...defaultProps} />).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(<GraphContainerNode {...defaultProps} />).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(<GraphContainerNode {...defaultProps} />).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(<GraphContainerNode {...defaultProps} />).toJSON();
const dropZone = tree.children.find((child) => child.props.className.includes('edge-drop-zone-container'));

expect(dropZone).toBeFalsy();
expect(tree).toMatchSnapshot();
});
});
Loading
Loading