I'm running into problems when testing a component that uses the react-flow package. In the actual implementation, the selected elements get passed to my onSelectionChange
handler perfectly, but when testing it through react-testing-library, the elements are always empty. This is what its currently console logging when running the test Selection changed { nodes: [], edges: [] }
.
Is there any way to get around this problem?
Here is my code:
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import ReactFlow from 'reactflow';
import { mockReactFlow } from '../../setupTests';
function MyComponent() {
const onSelectionChange = (elements: any) => {
console.log('Selection changed', elements);
};
const nodes = [
{ id: 'node-1', type: 'default', data: { label: 'Node 1' }, position: { x: 0, y: 0 } },
{ id: 'node-2', type: 'default', data: { label: 'Node 2' }, position: { x: 200, y: 0 } },
];
return <ReactFlow nodes={nodes} onSelectionChange={onSelectionChange} />;
}
describe('ReactFlow', () => {
beforeEach(() => {
mockReactFlow()
})
test('should trigger onSelectionChange event', async () => {
render(<MyComponent />);
const node = await screen.findByText('Node 1');
fireEvent.click(node);
});
});
You may be wondering what mockReactFlow
does. That was a recommendation by the react-flow documentation itself to help test react-flow components. Here is that implementation straight from the documentation:
export const mockReactFlow = () => {
if (init) return
init = true
global.ResizeObserver = ResizeObserver
global.DOMMatrixReadOnly = DOMMatrixReadOnly
Object.defineProperties(global.HTMLElement.prototype, {
offsetHeight: {
get() {
return parseFloat(this.style.height) || 1
},
},
offsetWidth: {
get() {
return parseFloat(this.style.width) || 1
},
},
})
;(global.SVGElement as any).prototype.getBBox = () => ({
x: 0,
y: 0,
width: 0,
height: 0,
})
}