Vue projects can use Jest alongside Vue Test Utils to mount and test components. This lesson covers setup and the core testing patterns specific to Vue's component model.
Mounting Vue Components with Vue Test Utils
@vue/test-utils provides a mount() function that renders a Vue component into a simulated DOM (via jsdom), returning a wrapper object with methods for finding elements, reading text, and simulating interaction — conceptually similar to React Testing Library, but tailored to Vue's reactivity system.
Jest needs a transformer capable of handling .vue single-file components; vue-jest (for Vue 3) or Vite's native test runner Vitest (a common alternative for newer Vue/Vite projects) fills that role.
// Counter.vue
<template>
<button @click="count++">Count: {{ count }}</button>
</template>
<script setup>
import { ref } from 'vue';
const count = ref(0);
</script>
// Counter.test.js
import { mount } from '@vue/test-utils';
import Counter from './Counter.vue';
test('increments the count when clicked', async () => {
const wrapper = mount(Counter);
await wrapper.find('button').trigger('click');
expect(wrapper.text()).toContain('Count: 1');
});
await is required after .trigger() because Vue batches DOM updates asynchronously after reactive state changes.
@vue/vue3-jest transforms .vue files so Jest can parse and run them.
moduleFileExtensions must include 'vue' so Jest resolves imports without an explicit extension.
Vitest is a popular Jest-API-compatible alternative that many Vite-based Vue projects use instead.
Testing Library also offers @testing-library/vue for a more RTL-style query API on Vue components.
Jest + Vue Cheat Sheet
Core Vue Test Utils methods you'll use constantly.
Method
Purpose
mount(Component, options)
Renders a component into a test DOM
wrapper.find(selector)
Finds a single matching element
wrapper.trigger('click')
Simulates a DOM event
wrapper.text()
Gets the rendered text content
wrapper.emitted('event-name')
Checks emitted custom events
mount(Component, { props: {...} })
Passes props into the component
Testing Props and Emitted Events
Passing props into mount() lets you test how a component renders with different inputs, and wrapper.emitted() lets you assert on custom events a component emits, which is Vue's primary mechanism for child-to-parent communication.
test('emits an update event with the new value', async () => {
const wrapper = mount(QuantityInput, { props: { value: 1 } });
await wrapper.find('button.increment').trigger('click');
expect(wrapper.emitted('update:value')).toBeTruthy();
expect(wrapper.emitted('update:value')[0]).toEqual([2]);
});
Awaiting Vue's Reactivity System
Vue batches DOM updates after a reactive value changes, so assertions checking the updated DOM need to happen after an await on the triggering action (or await nextTick()), otherwise the test may check the DOM before Vue has actually re-rendered.
Forgetting to await wrapper.trigger(), checking the DOM before Vue re-renders.
Missing 'vue' in moduleFileExtensions, causing import resolution errors.
Testing a component's internal reactive state directly instead of its rendered output.
Not configuring a .vue file transformer, leading to syntax errors when Jest tries to parse single-file components.
Key Takeaways
Vue Test Utils' mount() renders components into a simulated DOM for testing.
Testing .vue files with Jest requires a dedicated transformer like @vue/vue3-jest.
wrapper.emitted() lets you assert on custom events emitted by a component.
Always await triggered interactions to let Vue's reactivity system update the DOM first.
Pro Tip
If your Vue project uses Vite, consider Vitest instead of Jest — it shares almost the same API (describe, it, expect) but integrates more directly with Vite's build pipeline, avoiding extra transformer configuration.
You now know how to test Vue components with Jest. Next, explore lower-level DOM testing techniques that work with any framework.