Vue Test Utils Compatibility Layer
vue-test-utils-compat provides a critical compatibility layer for migrating existing Vue 2 test suites written with `@vue/test-utils` v1 to run seamlessly on `@vue/test-utils` v2 and Vue 3. This package, currently at version 0.0.15, is designed to ease the transition burden by allowing developers to upgrade their Vue components to Vue 3 first, and then address test migrations, leveraging Vue 3's migration build. It achieves this by providing numerous compatibility flags that can be configured to mimic v1 behavior, addressing differences in mounting options, wrapper APIs, and event handling. Its release cadence is tied to the needs of the Vue 2 to Vue 3 migration process. A key differentiator is its extensive configuration options, allowing granular control over which v1 behaviors are re-enabled, facilitating a gradual and less disruptive migration path.
Common errors
-
TypeError: Cannot read properties of undefined (reading 'config')
cause The `@vue/test-utils` instance passed to `installCompat` is undefined or incorrect.fixEnsure `@vue/test-utils` is correctly installed and imported, and that `installCompat` receives the actual `VueTestUtils` object (e.g., `import * as VueTestUtils from '@vue/test-utils'`). -
Error: [vue-compat] h is not defined
cause The `h` (render function) argument was not provided or was incorrect during `installCompat`.fixPass the `h` function imported from 'vue' (for Vue 3) or correctly retrieved from a Vue 3 migration build instance to `installCompat`. -
TypeError: wrapper.find(...).text is not a function
cause This error often indicates that `wrapper.find` is returning a `WrapperArray` or a component wrapper instead of a DOM wrapper, and `text()` is called on an unexpected type, or the element was not found.fixEnsure you are targeting a DOM element (`wrapper.find('p')`) and not a component (`wrapper.findComponent(MyComponent)`) when expecting DOM-specific methods like `text()`. Also verify the selector correctly matches an element present in the rendered output.
Warnings
- breaking Before applying `vue-test-utils-compat`, ensure all deprecations from `@vue/test-utils` v1 are addressed and fixed in your existing test suite. This ensures the baseline v1 tests are stable before introducing the compatibility layer.
- gotcha The `h` function (render function) is a required argument for `installCompat`. If using the Vue 3 migration build (Vue 2 mode), you must correctly retrieve the `h` function from a mounted Vue application instance, which can be non-trivial.
- breaking Many `@vue/test-utils` v1 APIs, such as direct access to `wrapper.vm`, `wrapper.attributes()`, and event handling (`wrapper.trigger`), behave differently or are removed in v2. The compatibility layer attempts to bridge these gaps, but subtle differences or edge cases may still exist.
- gotcha The compatibility layer introduces some overhead and potential for unexpected behavior due to the translation of v1 APIs to v2. It is an interim solution, and tests should ideally be refactored to native `@vue/test-utils` v2 APIs over time.
Install
-
npm install vue-test-utils-compat -
yarn add vue-test-utils-compat -
pnpm add vue-test-utils-compat
Imports
- installCompat
const { installCompat } = require('vue-test-utils-compat')import { installCompat } from 'vue-test-utils-compat' - fullCompatConfig
const fullCompatConfig = require('vue-test-utils-compat').fullCompatConfigimport { fullCompatConfig } from 'vue-test-utils-compat' - installCompat (CommonJS)
const { installCompat } = require('vue-test-utils-compat')
Quickstart
import { h } from 'vue';
import * as VueTestUtils from '@vue/test-utils';
import { installCompat, fullCompatConfig } from 'vue-test-utils-compat';
// Assuming Vue 3 without migration build
// If using 'vue/compat', the 'h' function might need to be retrieved from a mounted app instance.
installCompat(VueTestUtils, fullCompatConfig, h);
// Example test using the compat layer
describe('MyComponent with VTU v1 compat', () => {
const MyComponent = {
template: '<div><p>{{ message }}</p><button @click="increment">Click me</button></div>',
data: () => ({ message: 'Hello', count: 0 }),
methods: { increment() { this.count++; } }
};
it('renders the message', () => {
const wrapper = VueTestUtils.mount(MyComponent);
expect(wrapper.find('p').text()).toBe('Hello');
});
it('increments count on button click (v1 style)', async () => {
const wrapper = VueTestUtils.mount(MyComponent);
await wrapper.find('button').trigger('click');
// In v1, wrapper.vm would directly expose the component instance
// With compat, this attempts to bridge that gap.
expect(wrapper.vm.count).toBe(1);
});
});