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/
#### 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`:
```lang=json
"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:
```lang=js
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)
```lang=js
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` ([[ https://gerrit.wikimedia.org/r/c/mediawiki/extensions/MediaSearch/+/757422/2/package.json | 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:
```lang=js
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:
```lang=js
// 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 remove
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:
```lang=js
//Before
const localVue = VueTestUtils.createLocalVue();
localVue.use( i18n );
// After
VueTestUtils.config.global.plugins = [ i18n ];
```
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