Testing fabric.js mouse events using Testing Library’s fireEvent

When testing fabric.js you may want to trigger events based on inputs to make sure your components or other interactions work properly.

To do this you may have or create a canvas element and then try to run mouse events on that element. The problem is the events should be triggered on the upper canvas element that fabric.js use for interactions. To properly trigger these events use canvas.upperCanvasEl instead of your canvas element.

const canvasElement = document.createElement("canvas");

// Appending to the body may be necessary for it to exist on the canvas
document.body.appendChild(canvasElement);

const canvas = new fabric.Canvas(canvasElement, { width: 640, height: 480 });

// Now let say we have a component that register events for "mouse:down",
// "mouse:move", and "mouse:down" on the fabricjs canva
render(<LineShape onFinish={jest.fn()} onCancel={jest.fn()} />);

// Use the upper canva element as the target for fireEvent
const upperCanvasEl = canvas.upperCanvasEl;
fireEvent.mouseDown(upperCanvasEl, { clientX: 20, clientY: 20 });
fireEvent.mouseMove(upperCanvasEl, { clientX: 100, clientY: 100 });
fireEvent.mouseUp(upperCanvasEl, { clientX: 120, clientY: 120 });

// then you should see those event fired properly to the canvas

// in this example LineShape adds a line when we do
// "mouse:down" and when "mouse:up" we are done creating the line

const obj = canvas._objects[0];
expect(obj.x1).toBe(20);
expect(obj.y1).toBe(20);
expect(obj.x2).toBe(120);
expect(obj.y2).toBe(120);