Skip to content
This repository has been archived by the owner on Nov 11, 2022. It is now read-only.
/ vue-test-utils-compat Public archive

Compatibility layer for @vue/test-utils v2.x and v1.x

License

Notifications You must be signed in to change notification settings

xanf/vue-test-utils-compat

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

vue-test-utils-compat npm badge

Upgrade your Vue components first, deal with tests later


A migration tool to help you with migration from Vue 2 to Vue3

Vue 3 introduced migration build to help teams with gradual migration. vue-test-utils-next is playing well with migration build, but there are many differences between v1 vue-test-utils and v2.

This package provides a compatibility layer, which allows you to run old v1 test suites on vue-test-utils v2 and Vue 3

Table of Contents

⏩ Quickstart

npm install --save-dev vue-test-utils-compat

Vue 3:

const VueTestUtils = require('vue@/test-utils');
const { h } = require('vue');
const {
  installCompat as installVTUCompat,
  fullCompatConfig
} = require('vue-test-utils-compat');

installVTUCompat(VueTestUtils, fullCompatConfig, h)

Vue 3 migration build (in Vue 2 mode):

const VueTestUtils = require("vue@/test-utils");
const Vue = require("vue");
let compatH;
Vue.createApp({
  compatConfig: {
    MODE: 3,
    RENDER_FUNCTION: "suppress-warning",
  },
  render(h) {
    compatH = h;
  },
}).mount(document.createElement("div"));
installVTUCompat(VueTestUtils, fullCompatConfig, compatH);

✔️ Upgrade workflow

This upgrade workflow is demonstrated in bootstrap-vue migration to Vue 3.

  1. Before you start make sure you are using latest version of @vue/test-utils v1 in your project and fix all deprecations reported
  2. Follow Vue3 migration build upgrade workflow to set up Vue build infrastructure [example commit]
  3. Make sure your test infrastructure uses @vue/compat as vue alias. Example (using jest - jest.config.js):
module.exports = {
  // ...
  moduleNameMapper: {
    "^vue$": "@vue/compat",
  },
  // ...
};

Hint: it might be a good idea to set up your environment to use Vue 2 or Vue 3 conditionally. It greatly simplifies the migration process.

[example commit]

  1. Install vue-test-utils-compat. Please take a note that your test environment might reset modules between files (jest do this), so make sure to do this in the proper place (we're using setupFilesAfterEnv in jest):
const compatH = new Vue({}).$createElement;
installVTUCompat(VTU, fullCompatConfig, compatH);
  1. Run your tests and fix failing ones. Typical failures usually include:

    • using private Vue API (like __vue__) [example commit]
    • wrong usage of find vs. findComponent [example commit]
    • snapshots (they might differ between Vue 2 and Vue 3)
  2. At this point, you (theoretically) have a green suite and can start working on upgrading your code to Vue 3

  3. Replace fullCompatConfig from step 3 with the detailed list of compat flags. You can copy-paste the full list of flags below or take a look at the source code to figure all flags:

const compatConfig = {
  EXPORT_CREATE_LOCAL_VUE: true,
  EXPORT_CREATE_WRAPPER: true,

  GLOBAL_STUBS: true,

  MOUNT_ARGS_CONTEXT_ATTRS: true,
  MOUNT_ARGS_CONTEXT_CHILDREN: true,
  MOUNT_ARGS_CONTEXT_CLASS: true,
  MOUNT_ARGS_CONTEXT_ON: true,
  MOUNT_ARGS_CONTEXT_PROPS: true,
  MOUNT_ARGS_LISTENERS: true,
  MOUNT_ARGS_MOCKS: true,
  MOUNT_ARGS_PROVIDE: true,
  MOUNT_ARGS_SCOPED_SLOTS: true,
  MOUNT_ARGS_SCOPED_SLOTS_THIS: true,
  MOUNT_ARGS_STUBS: true,

  WRAPPER_ATTRIBUTES_DISABLED: true,
  WRAPPER_ATTRIBUTES_VALUE: true,
  WRAPPER_DESTROY: true,
  WRAPPER_DO_NOT_INCLUDE_NATIVE_EVENTS_IN_EMITTED: true,
  WRAPPER_FIND_ALL: true,
};
  1. 🔁 Turn off one compatibility flag. Fix failing tests. Repeat.
  2. As soon as you turn off the last compatibility flag - throw away and uninstall this package. You are awesome! 🎉

🌐 Global API

  • installCompat(VueTestUtilsModule, compatConfig, vueH)
    • VueTestUtilsModule - module, which will be patched
    • compatConfig: Record<string, boolean> - list of compatibility flags
    • vueH - function which will be used to create Vue VNodes. Required only if MOUNT_ARGS_SCOPED_SLOTS_THIS compatibility flag is used, could be omitted otherwise
  • compatFlags - object with all available compatibility
  • fullCompatConfig - config object with all compatibility flags enabled

🏁 Compatibility flags

Tests cover all compatibility flags. If the flag description is unclear, check the relevant test in tests folder.

EXPORT_CREATE_LOCAL_VUE

Adds createLocalVue to @vue/test-utils module and support for { localVue } mount option.

⚠️ localVue provides .extend, which is no-op operation. It is sufficient for most of the code but might require special handling

➡️ Migration strategy: available in @vue/test-utils v2 docs

EXPORT_CREATE_WRAPPER

Adds createWrapper to @vue/test-utils module

➡️ Migration strategy: replace createWrapper with new DOMWrapper(), new VueWrapper() which are available as exports in @vue/test-utils v2

MOUNT_ARGS_COMPONENTS (added in v0.0.3)

Enable support for components field in mount args of @vue/test-utils

➡️ Migration strategy: Move components mount arg to global.components

MOUNT_ARGS_CONTEXT_*

Flags:

  • MOUNT_ARGS_CONTEXT_ATTRS
  • MOUNT_ARGS_CONTEXT_CHILDREN
  • MOUNT_ARGS_CONTEXT_CLASS
  • MOUNT_ARGS_CONTEXT_ON
  • MOUNT_ARGS_CONTEXT_PROPS

Enable support for context field in mount args of @vue/test-utils (used to test functional components)

⚠️ MOUNT_ARGS_CONTEXT_CHILDREN converts context.children to the default slot of the component. It is not a complete implementation of old context.children behavior but should be sufficient for most cases.

➡️ Migration strategy: rewrite your mount args as follows:

  • context.props, context.attrs, and context.class go directly to props
  • children are replaced with slots.default
  • context.on become corresponding props: (clickonClick, etc.)

MOUNT_ARGS_DIRECTIVES (added in v0.0.3)

Enable support for components field in mount args of @vue/test-utils

➡️ Migration strategy: Move directives mount arg to global.directives

MOUNT_ARGS_LISTENERS

Allow passing { listeners } field in mount arguments

➡️ Migration strategy: replace listeners with props: (clickonClick, etc.)

MOUNT_ARGS_MOCKS

Enable passing mocks to the component from mount arguments

➡️ Migration strategy: move mocks mount arg to global.mocks

MOUNT_ARGS_PROVIDE

Allow passing relevant provide to the component

⚠️ @vue/test-utils v2 does not support passing provide as function. It means that your provide() function might be invoked earlier than you think

➡️ Migration strategy: move provide mount arg to global.provide. If your provide is a function - replace it with an object.

MOUNT_ARGS_SCOPED_SLOTS

Enable scopedSlots support in mount args

➡️ Migration strategy: merge scopedSlots mount arg to slots. If your scoped slot is using raw string - wrap it with <template #default="props">${your string here}</template>

MOUNT_ARGS_SCOPED_SLOTS_THIS

Allows scopedSlots declared as functions to receive this which contains $createElement and $set

⚠️⚠️⚠️ Requires MOUNT_ARGS_SCOPED_SLOTS to be enabled and third argument (vueH ) a for installCompat call

⚠️$createElement provided by this flag is not context-aware and will not be able to render components as a string. Refer to Vue docs for details

➡️ Migration strategy: ❌ rewrite such slots in your tests

MOUNT_ARGS_STUBS

Enable stubs to be passed to mount arguments

➡️ Migration strategy: move stubs mount arg to global.stubs

WRAPPER_ATTRIBUTES_DISABLED

Adds special handling when retrieving the disabled attribute on wrapper. Previously Vue always normalized such values (Vue 3 migration guide has more details on this)

➡️ Migration strategy: update your .attributes("disabled") assertions to relevant values

WRAPPER_ATTRIBUTES_VALUE

Adds special handling when retrieving the value attribute on wrapper. Previously Vue always set value as DOM node attribute, which is no more the case

➡️ Migration strategy: ❌ rewrite your value retrieval in another way

WRAPPER_DESTROY

Enables wrapper.destroy calls and enableAutoDestroy calls

➡️ Migration strategy: replace all wrapper.destroy calls with wrapper.unmount and enableAutoDestroy with `enableAutoUnmount

WRAPPER_DO_NOT_INCLUDE_NATIVE_EVENTS_IN_EMITTED

Makes sure that native events will not be captured in .emitted()

➡️ Migration strategy: rewrite your event-related assertions to take into account that native events are also captured, or (preferred) use emits option on your components

WRAPPER_DO_NOT_INCLUDE_HOOK_EVENTS_IN_EMITTED (added in v0.0.3)

Makes sure that hook: events (which happen when using @vue/compat) will not be captured in .emitted()

➡️ Migration strategy: rewrite your event-related assertions to take into account that such events are also captured, or just upgrade to Vue 3 build without compat

WRAPPER_FIND_ALL

Implements old behavior of .findAll / .findAllComponents when results were wrapped with special object with .wrappers field and various methods (.at, .filter, .trigger, etc.)

➡️ Migration strategy: rewrite your tests, assuming that .findAll and .findAllComponents return a simple array instead

WRAPPER_FIND_BY_CSS_SELECTOR_RETURNS_COMPONENTS (added in v0.0.2)

Implements old behavior of .find / .findAll when results will be Vue components if they matches. So potentially, you can receive mixed array of DOM/Vue wrappers when using .findAll with this compat flag

➡️ Migration strategy: replace .find with .findComponent and .findAll with .findAllComponents where appropriate. Please take a note that if your tests rely on having a mixed array of DOM/Vue wrappers - you need to rewrite them

WRAPPER_FIND_COMPONENT_BY_REF_RETURNS_DOM (added in v0.0.3)

Implements old behavior when using .findComponent with ref will return DOM wrapper if ref is pointing to one.

➡️ Migration strategy: replace .findComponent with .find by ref (when vuejs/test-utils#1110 will be merged)

WRAPPER_SET_VALUE_DOES_NOT_TRIGGER_CHANGE (added in v0.0.3)

Implements old behavior when using .trigger on DOM Wrapper did not trigger change event, so you should trigger it manually (important for lazy v-models)

➡️ Migration strategy: rewrite relevant tests

WRAPPER_VUE_SET_VALUE_USES_DOM (added in v0.0.3)

Implements old VTU v1 behavior when using .setValue on Vue component actually used same logic, as setting value on DOM node (checking element type of Vue component, etc.)

➡️ Migration strategy: fix your components to use new setValue (which respects v-model) or rewrite relevant tests

Known issues

This package monkey-patches @vue/test-utils package. Depending on your setup this might not work (for example you are using real imports). In that case you can create a mutable wrapper around VTU and replace all your imports from @vue/test-utils to this helper module:

import * as VueTestUtils from '@vue/test-utils';
import { h } from 'vue';
import { installCompat, fullCompatConfig } from `@vue/test-utils/compat`

const PatchedVTU = { ...VueTestUtils };
installCompat(PatchedVTU, fullCompatConfig, h);
export PatchedVTU;

About

Compatibility layer for @vue/test-utils v2.x and v1.x

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published