Testing
There are plenty of ways to test a Vue application. For a Vue Flow app we recommend Cypress or Playwright : Vue Flow measures nodes in order to render edges, and that relies on real DOM elements, which a headless browser provides.
Using Cypress or Playwright
No extra setup is needed. See the getting-started guides for Cypress and Playwright .
Using Vitest
Vitest runs in a simulated DOM (jsdom or happy-dom) that doesn’t implement
the layout APIs Vue Flow relies on, so you need to shim them. Add this helper and call
mockVueFlow() in a setup file (or a beforeEach):
// A jsdom/happy-dom-friendly stand-in for the ResizeObserver and DOMMatrixReadOnly APIs
// Vue Flow uses to measure nodes and read the viewport transform.
class ResizeObserver {
callback: globalThis.ResizeObserverCallback;
constructor(callback: globalThis.ResizeObserverCallback) {
this.callback = callback;
}
observe(target: Element) {
setTimeout(() => {
this.callback([{ target } as globalThis.ResizeObserverEntry], this);
}, 0);
}
unobserve() {}
disconnect() {}
}
class DOMMatrixReadOnly {
m22: number;
constructor(transform: string) {
const scale = transform?.match(/scale\(([1-9.])\)/)?.[1];
this.m22 = scale !== undefined ? +scale : 1;
}
}
let init = false;
export function mockVueFlow() {
if (init) {
return;
}
init = true;
global.ResizeObserver = ResizeObserver as unknown as typeof globalThis.ResizeObserver;
global.DOMMatrixReadOnly = DOMMatrixReadOnly as unknown as typeof globalThis.DOMMatrixReadOnly;
Object.defineProperties(global.HTMLElement.prototype, {
offsetHeight: {
get() {
return Number.parseFloat(this.style.height) || 1;
},
},
offsetWidth: {
get() {
return Number.parseFloat(this.style.width) || 1;
},
},
});
(global.SVGElement.prototype as unknown as { getBBox: () => DOMRect }).getBBox = () =>
({ x: 0, y: 0, width: 0, height: 0 }) as DOMRect;
}Register it as a Vitest setup file:
import vue from '@vitejs/plugin-vue';
import { defineConfig } from 'vitest/config';
export default defineConfig({
plugins: [vue()],
test: {
environment: 'jsdom',
setupFiles: ['./mockVueFlow.ts'],
},
});Testing edges
Edges only render once their nodes have been measured, so mount inside a sized container and
wait for them with vi.waitFor:
import { mount } from '@vue/test-utils';
import { VueFlow } from '@xyflow/vue';
import { expect, test, vi } from 'vitest';
import { mockVueFlow } from './mockVueFlow';
mockVueFlow();
test('renders edges', async () => {
const wrapper = mount(VueFlow, {
attrs: { style: 'width: 800px; height: 600px' },
props: { nodes, edges },
});
await vi.waitFor(() => {
expect(wrapper.findAll('.vue-flow__edge').length).toBeGreaterThan(0);
});
});To test mouse events inside a custom node with Vitest, disable dragging and panning so
d3-drag — which needs a real browser — stays out of the way:
<VueFlow :nodes-draggable="false" :pan-on-drag="false" v-bind="rest" />