import {act} from '@testing-library/react'; import useFlowStore from '../../../../src/pages/VisProgPage/visualProgrammingUI/VisProgStores.tsx'; import { mockReactFlow } from '../../../setupFlowTests.ts'; beforeAll(() => { mockReactFlow(); }); describe('FlowStore Functionality', () => { describe('Node changes', () => { // currently just using a single function from the ReactFlow library, // so testing would mean we are testing already tested behavior. // if implementation gets modified tests should be added for custom behavior }); describe('Edge changes', () => { // currently just using a single function from the ReactFlow library, // so testing would mean we are testing already tested behavior. // if implementation gets modified tests should be added for custom behavior }) describe('ReactFlow onConnect', () => { test('adds an edge when onConnect is triggered', () => { const {onConnect} = useFlowStore.getState(); act(() => { onConnect({ source: 'A', target: 'B', sourceHandle: null, targetHandle: null, }); }); const updatedEdges = useFlowStore.getState().edges; expect(updatedEdges).toHaveLength(1); expect(updatedEdges[0]).toMatchObject({ source: 'A', target: 'B', }); }); }); describe('ReactFlow onReconnect', () => { test('reconnects an existing edge when onReconnect is triggered', () => { const {onReconnect} = useFlowStore.getState(); const oldEdge = { id: 'xy-edge__A-B', source: 'A', target: 'B' }; const newConnection = { source: 'A', target: 'C', sourceHandle: null, targetHandle: null, }; act(() => { useFlowStore.setState({ edges: [oldEdge] }); onReconnect(oldEdge, newConnection); }); const updatedEdges = useFlowStore.getState().edges; expect(updatedEdges).toHaveLength(1); expect(updatedEdges[0]).toMatchObject({ id: 'xy-edge__A-C', source: 'A', target: 'C', }); }); }); describe('ReactFlow onReconnectStart', () => { test('does correct setup for edge reconnection sequences', () => { const {onReconnectStart} = useFlowStore.getState(); act(() => { onReconnectStart(); }); const updatedState = useFlowStore.getState().edgeReconnectSuccessful; expect(updatedState).toEqual(false); }); }); describe('ReactFlow onReconnectEnd', () => { // prepares the state to have an edge in the edge array beforeEach(() => { useFlowStore.setState({edges: [ { id: 'xy-edge__A-B', source: 'A', target: 'B' } ]} ); }); test('successfully removes edge if no successful reconnect occurred', () => { const {onReconnectEnd} = useFlowStore.getState(); useFlowStore.setState({edgeReconnectSuccessful: false}); act(() => { onReconnectEnd(null, {id: 'xy-edge__A-B'}); }); const updatedState = useFlowStore.getState(); expect(updatedState.edgeReconnectSuccessful).toBe(true); expect(updatedState.edges).toHaveLength(0); }); test('does not remove reconnecting edge if successful reconnect occurred', () => { const {onReconnectEnd} = useFlowStore.getState(); act(() => { onReconnectEnd(null, {id: 'xy-edge__A-B'}); }); const updatedState = useFlowStore.getState(); expect(updatedState.edgeReconnectSuccessful).toBe(true); expect(updatedState.edges).toHaveLength(1); expect(updatedState.edges).toMatchObject([ { id: 'xy-edge__A-B', source: 'A', target: 'B' }] ); }); }); describe('ReactFlow deleteNode', () => { // test deleting A and B, so we make sure the connecting edge gets deleted regardless of test.each([['A','B'],['B','A']])('deletes a node and its connected edges', (nodeId, undeletedNodeId) => { const {deleteNode} = useFlowStore.getState(); useFlowStore.setState({ nodes: [ { id: 'A', type: 'default', position: {x: 0, y: 0}, data: {label: 'A'} }, { id: 'B', type: 'default', position: {x: 0, y: 300}, data: {label: 'A'} }], edges: [ { id: 'xy-edge__A-B', source: 'A', target: 'B' }] }); act(()=> { deleteNode(nodeId); }); const updatedState = useFlowStore.getState(); expect(updatedState.edges).toHaveLength(0); expect(updatedState.nodes).toHaveLength(1); expect(updatedState.nodes[0].id).toBe(undeletedNodeId); }); }); describe('ReactFlow setNodes', () => { test('sets nodes to the provided list of nodes', () => { const {setNodes} = useFlowStore.getState(); act(() => { setNodes([ { id: 'start', type: 'start', position: {x: 0, y: 0}, data: {label: 'start'} }, { id: 'end', type: 'end', position: {x: 0, y: 300}, data: {label: 'End'} } ]); }); const updatedNodes = useFlowStore.getState().nodes; expect(updatedNodes).toHaveLength(2); expect(updatedNodes[0]).toMatchObject({ id: 'start', type: 'start', position: {x: 0, y: 0}, data: {label: 'start'} }); expect(updatedNodes[1]).toMatchObject({ id: 'end', type: 'end', position: {x: 0, y: 300}, data: {label: 'End'} }); }); }); describe('ReactFlow setEdges', () => { test('sets edges to the provided list of edges', () => { const {setEdges} = useFlowStore.getState(); act(() => { setEdges([ { id: 'start-end', source: 'start', target: 'end' } ]); }); const updatedEdges = useFlowStore.getState().edges; expect(updatedEdges).toHaveLength(1); expect(updatedEdges[0]).toMatchObject({ id: 'start-end', source: 'start', target: 'end' }); }); }); });