Skip to Content

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):

mockVueFlow.ts
// 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:

vitest.config.ts
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:

flow.test.ts
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" />
Last updated on