Several teams with Vue 2 codebases have been asking about how to migrate those tests to the current version of Vue (v3) and Vue Test Utils (v4).
Both @Jdforrester-WMF and @SimoneThisDot have been working on this (in Abstract Wikipedia and Structured Data MediaSearch, respectively), and I know that @Jdlrobson has also been looking into this.
The Design System Team should aggregate the lessons learned by various folks working on this issue and publish on-wiki documentation that we can point others to in the future.
We can post draft guidelines here for discussion until things are ready for publication on MediaWiki.
Draft Guidelines for Vue 3 Test suite migration
Useful references:
- Vue 3 migration guide: https://v3-migration.vuejs.org/
- Vue Test Utils migration guide: https://test-utils.vuejs.org/migration/
Example Migration patches
Software Dependencies
Vue
All Vue 2 apps which rely on the MediaWiki-provided copy of Vue are currently in the following situation: at runtime, they are using Vue 3.2 in compatibility mode, but all CLI testing is still relying on Vue 2 from NPM. The first step in migrating such a test suite is to use the correct version of Vue during testing.
Updates should be made in the following places:
packages.json: update Vue in devDependencies:
"vue": "3.2.23", "@vue/compat": "3.2.23"
The test suite must then be configured to use Vue in compat mode.
Jest Config (jest.config.js): Configure the moduleNameMapper option:
moduleNameMapper: { "^vue$": "@vue/compat" },
Jest Setup (jest.setup.js): Provide any necessary configuration to the compatibility build here (see https://v3-migration.vuejs.org/migration-build.html#global-config for more details)
const Vue = require( 'vue' ); Vue.configureCompat({ // Add any necessary global config options here MODE: 3 } );
Other Test dependencies
In addition to Vue 3 and @vue/compat, the following dependencies should be updated in package.json devDependencies (source).
- @vue/test-utils: Update to v2 (latest version is v 2.0.0-rc.17 at the time of writing)
- @vue/compiler-sfc: This should match the Vue version, so 3.2.23 following the above
- @vue/vue3-jest: The Vue Jest transformer (will be needed if you are using Jest). The version you need depends on the version of Jest you are using. If using Jest 26 and below, use vue-jest@5. If using Jest 27+, use @vue/vue3-jest. More details here: https://github.com/vuejs/vue-jest.
- jest: You need to upgrade Jest to v27 if using @vue/vue3-jest.
- @babel/preset-env may also need to be upgraded (MediaSearch is using ^7.16.11).
Jest Configuration
In addition to instructing Jest to use @vue/compat via the moduleNameMapper, the following settings should be specified in jest.config.js:
The transform property should point to whatever version of vue-jest is being used:
transform: { ".*\\.(vue)$": "<rootDir>/node_modules/@vue/vue3-jest" },
Finally, the testEnvironment should be set to jsdom.
Component files
Exports vs Module.exports
In order to guarantee consistent behavior both in the browser (where ResourceLoader's CommonJS implementation is used) and in Node.js, we recommend doing the following in all .vue files:
// The following need to be changed to all .vue files module.exports = exports = { // component code here... }
See https://nodejs.org/docs/latest/api/modules.html#exports-shortcut for some information about why this is needed.
Plugins
TBD: Document changes to plugin API
Composition API
If you were previously using the Composition API plugin, this can be removed; all of the helpers you would use inside of setup() can now be require()-ed from Vue itself.
Emits option
In Vue 3, components can now declare what events they emit via an emits option. Doing this for all events a component can emit is strongly recommended. Without doing so, it is possible that component events whose names match those of native DOM events (like click) will get emitted twice, which could reasonably cause your tests to fail. More information here: https://v3-migration.vuejs.org/breaking-changes/emits-option.html. Relatedly, the .native event modifier has been removed.
TLDR; Add an emits option for all components which emit events: https://vuejs.org/api/options-state.html#emits
Attribute Coercion Behavior
In Vue 2, binding an attribute to a false-y value caused it to be removed from the rendered markup. In Vue 3, the attribute will show up with a value of attr="false" unless null or undefined is bound. More info: https://v3-migration.vuejs.org/breaking-changes/attribute-coercion.html
$children instance property removed
It is no longer possible to access the $children of a component instance. More info: https://v3-migration.vuejs.org/breaking-changes/children.html
Complete list of breaking changes
A complete description of breaking changes can be found here: https://v3-migration.vuejs.org/breaking-changes/. In most cases, it is possible to set a compatConfig flag on a per-component basis to keep the Vue 2 behavior until you are able to refactor the code in question; see the Vue 3 migration guide for more information about this.
Test suite changes
Some changes to your tests will also be necessary as part of the Vue Test Utils v1 -> v2 migration. In particular, propsData is now props, and createLocalVue no longer exists. Plugins and mocks can be added using the "global" property instead.
If you were only using createLocalVue to add the MediaWiki i18n plugin, you can now mock this globally in your jest.setup.js file. See: https://gerrit.wikimedia.org/r/c/mediawiki/extensions/WikiLambda/+/768139
// jest.setup.js // Mock i18n for all tests var vueTestUtils = require( '@vue/test-utils' ); vueTestUtils.config.global.mocks = { $i18n: jest.fn( function ( str ) { return str; } ) };
A full list of breaking changes in Vue Test Utils can be seen here: https://test-utils.vuejs.org/migration/#changes
Related in-progress test suite migrations
- T302137: Vector test suite migration
- T297722: MediaSearch test suite migration
- T302134: MachineVision test suite migration
- T302135: NearbyPages test suite migration
- T302136: QuickSurvey's test suite migration
- T302130: WikiLambda test suite migration
- Wikibase migration?
- Top-level task or all Vue test suite migration: T302129