Composition API SFC test issue when using Vue 2.7 or the compat Mode
lisilinhart opened this issue Β· 24 comments
Subject of the issue
Hi,
this issue is created, after another issue was opened here in vue-testing-library : testing-library/vue-testing-library#275
The core of the problem seems to be in @vue/test-utils:
When using the compat mode or the 2.7 build, the unit tests start failing when using the composition api in the SFC syntax.
I tried using the composition api in a SFC synctax from the 2.7 build itself and this behaviour appears:
<script setup>
import { ref, onBeforeMount, defineProps } from 'vue'
defineProps({
msg: {
type: String,
default: ''
},
})
const label = ref('init')
onBeforeMount(() => {
label.value = 'mounted'
})
</script>
<template>
<div>{{ msg }} - {{ label }}</div>
</template>results in this testing html
If we use the regular export default syntax with the composition api, it seems to be still working.
Steps to reproduce
To reproduce the behavior:
Use this minimal reproduction repo: https://github.com/lisilinhart/vue-2.7-sfc-test-bug-repo
Expected behaviour
When mounting the component with the composition API in a sfc syntax, it should render the component correctly like it does for the options api.
Actual behaviour
The asynchronous text is never rendered in the mounted component.
Possible Solution
This problem is not caused by @vue/test-utils but vue-jest.
"jest": {
"transform": {
"^.+.vue$": "vue-jest"
}
}
When you started testing, you actually called jest. vue-jest will transform SFCComponent.vue to:
(function () {})();
var defaultExport = module.exports.__esModule
? module.exports.default
: module.exports;
var __vue__options__ =
typeof defaultExport === "function" ? defaultExport.options : defaultExport;
__vue__options__.render = function render() {
var _vm = this;
var _h = _vm.$createElement;
var _c = _vm._self._c || _h;
return _c("div", [_vm._v(_vm._s(_vm.msg) + " - " + _vm._s(_vm.label))]);
};
__vue__options__.staticRenderFns = [];But with @vue/vue2-jest from vuejs/vue-jest#483 it will be transformed to:
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
const vue_1 = require("vue");
const vue_2 = require("vue");
exports.default = (0, vue_1.defineComponent)({
__name: 'SFCComponent',
props: {
msg: {
type: String,
default: ''
}
},
setup(__props) {
const label = (0, vue_2.ref)('init');
(0, vue_2.onBeforeMount)(() => {
label.value = 'mounted';
});
return {
__sfc: true,
label
};
}
});
//# sourceMappingURL=xxx
var __options__ = typeof exports.default === 'function' ? exports.default.options : exports.default
var render = function render() {
var _vm = this,
_c = _vm._self._c,
_setup = _vm._self._setupProxy
return _c("div", [_vm._v(_vm._s(_vm.msg) + " - " + _vm._s(_setup.label))])
}
var staticRenderFns = []
render._withStripped = true
__options__.render = render
__options__.staticRenderFns = staticRenderFns@admhpr Here is a vue 2.7 unit test example: https://github.com/iMuFeng/vite-vue2-starter
This problem is not caused by
@vue/test-utilsbutvue-jest."jest": { "transform": { "^.+.vue$": "vue-jest" } }When you started testing, you actually called jest.
vue-jestwill transformSFCComponent.vueto:(function () {})(); var defaultExport = module.exports.__esModule ? module.exports.default : module.exports; var __vue__options__ = typeof defaultExport === "function" ? defaultExport.options : defaultExport; __vue__options__.render = function render() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c("div", [_vm._v(_vm._s(_vm.msg) + " - " + _vm._s(_vm.label))]); }; __vue__options__.staticRenderFns = [];But with
@vue/vue2-jestfrom vuejs/vue-jest#483 it will be transformed to:"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const vue_1 = require("vue"); const vue_2 = require("vue"); exports.default = (0, vue_1.defineComponent)({ __name: 'SFCComponent', props: { msg: { type: String, default: '' } }, setup(__props) { const label = (0, vue_2.ref)('init'); (0, vue_2.onBeforeMount)(() => { label.value = 'mounted'; }); return { __sfc: true, label }; } }); //# sourceMappingURL=xxx var __options__ = typeof exports.default === 'function' ? exports.default.options : exports.default var render = function render() { var _vm = this, _c = _vm._self._c, _setup = _vm._self._setupProxy return _c("div", [_vm._v(_vm._s(_vm.msg) + " - " + _vm._s(_setup.label))]) } var staticRenderFns = [] render._withStripped = true __options__.render = render __options__.staticRenderFns = staticRenderFns
I'm using preset: '@vue/cli-plugin-unit-jest',, which I don't think is using "vue-jest"
This problem is not caused by
@vue/test-utilsbutvue-jest."jest": { "transform": { "^.+.vue$": "vue-jest" } }When you started testing, you actually called jest.
vue-jestwill transformSFCComponent.vueto:(function () {})(); var defaultExport = module.exports.__esModule ? module.exports.default : module.exports; var __vue__options__ = typeof defaultExport === "function" ? defaultExport.options : defaultExport; __vue__options__.render = function render() { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c("div", [_vm._v(_vm._s(_vm.msg) + " - " + _vm._s(_vm.label))]); }; __vue__options__.staticRenderFns = [];But with
@vue/vue2-jestfrom vuejs/vue-jest#483 it will be transformed to:"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const vue_1 = require("vue"); const vue_2 = require("vue"); exports.default = (0, vue_1.defineComponent)({ __name: 'SFCComponent', props: { msg: { type: String, default: '' } }, setup(__props) { const label = (0, vue_2.ref)('init'); (0, vue_2.onBeforeMount)(() => { label.value = 'mounted'; }); return { __sfc: true, label }; } }); //# sourceMappingURL=xxx var __options__ = typeof exports.default === 'function' ? exports.default.options : exports.default var render = function render() { var _vm = this, _c = _vm._self._c, _setup = _vm._self._setupProxy return _c("div", [_vm._v(_vm._s(_vm.msg) + " - " + _vm._s(_setup.label))]) } var staticRenderFns = [] render._withStripped = true __options__.render = render __options__.staticRenderFns = staticRenderFnsI'm using
preset: '@vue/cli-plugin-unit-jest',, which I don't think is using"vue-jest"
You can take a look at this line: https://github.com/lisilinhart/vue-2.7-sfc-test-bug-repo/blob/63ed5b486b037b59c690188493af432a7e860284/yarn.lock#L1643
If you have used @vue/cli 5.x version, it should be @vue/vue2-jest https://github.com/vuejs/vue-cli/blob/b154dbd7aca4b4538e6c483b1d4b817499d7b8eb/packages/%40vue/cli-plugin-unit-jest/package.json#L45
Hi @iMuFeng
Check out this test file / repo on the jh/vue-utils-version branch: https://github.com/Weetbix/vue-compat-composition-api-bug-repo/blob/jh/vue-utils-version/test.spec.js
Run yarn test:vue3 to run in vue 3 and notice all tests pass.
Run yarn test:vue-compat to run with the vue compat alias.
All 3 tests fail when using vue in compat mode, and there is no jest-dom dependency, its only using vitest.
Hi @Weetbix
Your testing of Vue 3.x depends on @vue/test-utils@2.x (https://github.com/vuejs/test-utils/), which I think there must be some bug on combat mode.
But for SFC Vue 2.7 which depends on @vue/test-utils@1.x (https://github.com/vuejs/vue-test-utils).
@iMuFeng Ahhhhh I see, sorry for the confusion!
Here is that repo with vue 2.7 and test-utils 1.x: https://github.com/Weetbix/vue-compat-composition-api-bug-repo/tree/jh/vue-utils-v1-vue-27-version
All the tests are passing, so I guess this issue is with vue-jest as you were saying.
Your testing of Vue 3.x depends on @vue/test-utils@2.x (https://github.com/vuejs/test-utils/), which I think there must be some bug on combat mode.
So I will open an issue for vue-compat, vue 3 and test-utils 2.x in that repo π
@iMuFeng cheers for the pointers, I switched over to vitest using your example repo and things started breaking.
The whole back porting of Vue 3 to Vue 2 is making a lot of work for this repo (and old versions of Vue Jest).
I have no bandwidth to work on Vue Test Utils v1/Vue 2/Vue Jest combo right now.
If there's a bug in Vue 3/Vue Test Utils 2 (different repo, as mentioned above) we will actively try to fix/address it.
@lmiller1990 We cannot migrate to Vue 2.7 without testππ
Probably a silly question - but from a workload point of view, would it be easier to just go straight to Vue 3? Is Vue 2.6 -> 2.7 -> 3.x actually just making more work for your team?
Is anyone interested in helping with this? I can't commit to working on this right now, definitely happy to assist if someone else wants to give it a try.
First step would be to fork this repo and add a failing test case.
@kingyue737 this PR is the one you are looking for vuejs/vue-jest#483
Thanks @ebisbe, I'm using vitest and the issue I faced is caused by @vitejs/plugin-vue2 which modifies entry to vue #1982 (comment). vue-test-utils does not need patching.
I am trying to clean up this repo and get a handle on things.
If anyone is interested in helping, I'd like to get some test cases for Vue 2.7, especially with <script setup>.
@lmiller1990 what are you thinking I can help
I think we need a few things. At this point, as a mature piece of software (Vue 2 and VTU v1) we should focus on long term maintenance.
- Issue triage. We've got a ton, we need to find out which are real bugs (eg, "XX doesn't work with Vue 2.7) and just people asking for help (how do I do with ). There's over 150 issues, I'd like to get that under 100.
- Regarding priorities - this means making sure all existing features work with the latest version of Vue 2 (2.7) including
<script setup>. We don't have any tests for that in this library, so I think we probably want to add some, along with some basic smoke tests around all the features (passingpropsshould work,stubs, etc). - After we know things generally work with Vue 2.7, we can focus on fixing other, outstanding bugs.
What do you think?
Not sure about the compat mode issue - Vue 3 and VTU v2 works fine with the Vue 3 compat mode to my knowledge.
I can help with the initial triage as I think I would be more helpful there. Do you want to move the conversation to somewhere else? ( vuejs discord ? )
I think working in public is fine, let me get you added as triage - I think we start by labelling issues so we can prioritize and closing stale/old ones.
@ebisbe done-zo, you should have triage access. I think we probably want to categorize issues, whatever make sense - ideally something like "bug", "Vue 2.7", "composition API" and "needs reproduction".
After that we can go through and try verify any bugs, if we cannot repro, close and move on. 151 issues is daunting, once we trim it down, I think things will be easier. LMK if you need to clarify anything, Discord is fine but in general I prefer work in public, that's what makes OSS great, open collaboration.
@lmiller1990 ok, got it. I'll start with those 4 tags and see if I need anymore.
I mentioned the discord as what we are currently talking is not related to this issue. That's all I was thinking.
Edit: I can't add/edit labels
@ebisbe thanks!
Try now, I elevated your privileges. Please don't push to any of the main branches π
@lmiller1990 all issues tagged. I will start to review old issues as you suggested
Great, thanks!
Sorry I have not been able to help out much. The issue count is already getting much easier to manage. I wouldn't be scared to close out older issue that don't have reproductions - moving forward, I'd say we close all issues w/o a minimal reproduction - this is what we are doing in Test Utils v2, we don't have time to try and reproduce all the issues on our own.
