Skip to content

Commit

Permalink
test: add workflowcanvas tests
Browse files Browse the repository at this point in the history
  • Loading branch information
alexgrozav committed Aug 28, 2024
1 parent 3ec586c commit 72b2fe6
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 1 deletion.
4 changes: 3 additions & 1 deletion packages/editor-ui/src/__tests__/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
STICKY_NODE_TYPE,
} from '@/constants';
import type { INodeUi, IWorkflowDb } from '@/Interface';
import { CanvasNodeRenderType } from '@/types';

export const mockNode = ({
id = uuid(),
Expand Down Expand Up @@ -94,6 +95,7 @@ export const mockNodes = [
mockNode({ name: 'Chat Trigger', type: CHAT_TRIGGER_NODE_TYPE }),
mockNode({ name: 'Agent', type: AGENT_NODE_TYPE }),
mockNode({ name: 'Sticky', type: STICKY_NODE_TYPE }),
mockNode({ name: CanvasNodeRenderType.AddNodes, type: CanvasNodeRenderType.AddNodes }),
mockNode({ name: 'End', type: NO_OP_NODE_TYPE }),
];

Expand Down Expand Up @@ -180,7 +182,7 @@ export function createTestNode(node: Partial<INode> = {}): INode {
return {
id: uuid(),
name: 'Node',
type: 'n8n-nodes-base.test',
type: 'n8n-nodes-base.set',
typeVersion: 1,
position: [0, 0] as [number, number],
parameters: {},
Expand Down
146 changes: 146 additions & 0 deletions packages/editor-ui/src/components/canvas/WorkflowCanvas.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import { waitFor } from '@testing-library/vue';
import { createPinia, setActivePinia } from 'pinia';
import WorkflowCanvas from '@/components/canvas/WorkflowCanvas.vue';
import { createEventBus } from 'n8n-design-system';
import { createCanvasNodeElement, createCanvasConnection } from '@/__tests__/data';
import type { Workflow } from 'n8n-workflow';
import { createComponentRenderer } from '@/__tests__/render';
import { STICKY_NODE_TYPE } from '@/constants';
import { CanvasNodeRenderType } from '@/types';
import {
createTestNode,
createTestWorkflow,
createTestWorkflowObject,
defaultNodeDescriptions,
} from '@/__tests__/mocks';
import { useNodeTypesStore } from '@/stores/nodeTypes.store';

const renderComponent = createComponentRenderer(WorkflowCanvas, {
props: {
id: 'canvas',
workflow: {
id: '1',
name: 'Test Workflow',
nodes: [],
connections: [],
},
workflowObject: {} as Workflow,
eventBus: createEventBus(),
},
});

beforeEach(() => {
const pinia = createPinia();
setActivePinia(pinia);

const nodeTypesStore = useNodeTypesStore();
nodeTypesStore.setNodeTypes(defaultNodeDescriptions);
});

afterEach(() => {
vi.clearAllMocks();
});

describe('WorkflowCanvas', () => {
it('should initialize with default props', () => {
const { getByTestId } = renderComponent();

expect(getByTestId('canvas')).toBeVisible();
});

it('should render nodes and connections', async () => {
const nodes = [
createCanvasNodeElement({ id: '1', label: 'Node 1' }),
createCanvasNodeElement({ id: '2', label: 'Node 2' }),
];
const connections = [createCanvasConnection(nodes[0], nodes[1])];

const { container } = renderComponent({
props: {
nodes,
connections,
},
});

await waitFor(() => expect(container.querySelectorAll('.vue-flow__node')).toHaveLength(2));

expect(container.querySelector(`[data-id="${nodes[0].id}"]`)).toBeInTheDocument();
expect(container.querySelector(`[data-id="${nodes[1].id}"]`)).toBeInTheDocument();
expect(container.querySelector(`[data-id="${connections[0].id}"]`)).toBeInTheDocument();
});

it('should handle empty nodes and connections gracefully', async () => {
const { container } = renderComponent();

await waitFor(() => expect(container.querySelectorAll('.vue-flow__node')).toHaveLength(0));
expect(container.querySelectorAll('.vue-flow__connection')).toHaveLength(0);
});

it('should render fallback nodes when sticky nodes are present', async () => {
const stickyNodes = [createTestNode({ id: '2', name: 'Sticky Node', type: STICKY_NODE_TYPE })];
const fallbackNodes = [
createTestNode({
id: CanvasNodeRenderType.AddNodes,
type: CanvasNodeRenderType.AddNodes,
name: CanvasNodeRenderType.AddNodes,
}),
];

const workflow = createTestWorkflow({
id: '1',
name: 'Test Workflow',
nodes: [...stickyNodes],
connections: {},
});

const workflowObject = createTestWorkflowObject(workflow);

const { container } = renderComponent({
props: {
workflow,
workflowObject,
fallbackNodes,
},
});

await waitFor(() => expect(container.querySelectorAll('.vue-flow__node')).toHaveLength(2));

expect(container.querySelector(`[data-id="${stickyNodes[0].id}"]`)).toBeInTheDocument();
expect(container.querySelector(`[data-id="${fallbackNodes[0].id}"]`)).toBeInTheDocument();
});

it('should not render fallback nodes when non-sticky nodes are present', async () => {
const nonStickyNodes = [createTestNode({ id: '1', name: 'Non-Sticky Node 1' })];
const stickyNodes = [createTestNode({ id: '2', name: 'Sticky Node', type: STICKY_NODE_TYPE })];
const fallbackNodes = [
createTestNode({
id: CanvasNodeRenderType.AddNodes,
type: CanvasNodeRenderType.AddNodes,
name: CanvasNodeRenderType.AddNodes,
}),
];

const workflow = createTestWorkflow({
id: '1',
name: 'Test Workflow',
nodes: [...nonStickyNodes, ...stickyNodes],
connections: {},
});

const workflowObject = createTestWorkflowObject(workflow);

const { container } = renderComponent({
props: {
workflow,
workflowObject,
fallbackNodes,
},
});

await waitFor(() => expect(container.querySelectorAll('.vue-flow__node')).toHaveLength(2));

expect(container.querySelector(`[data-id="${nonStickyNodes[0].id}"]`)).toBeInTheDocument();
expect(container.querySelector(`[data-id="${stickyNodes[0].id}"]`)).toBeInTheDocument();
expect(container.querySelector(`[data-id="${fallbackNodes[0].id}"]`)).not.toBeInTheDocument();
});
});

0 comments on commit 72b2fe6

Please sign in to comment.