https://github.com/hwestphal/vue-crash-reproduce
yarnyarn testThe unit tests should pass with no errors.
The unit test fails because the value which is added to the component in the unit test
localVue.mixin({
beforeCreate() {
(this as any).$content = "some value";
},
});
is accessed in the component in
content(): string {
return (this as any).$content.toUpperCase();
}
which makes the test fail with
TypeError: Cannot read property 'toUpperCase' of undefined
at VueComponent.content (/home/prior/repositories/kn/vue-crash-reproduce/src/some-component.vue:13:34)
at Watcher.get (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:3140:25)
at Watcher.evaluate (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:3247:21)
at Proxy.computedGetter (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:3505:17)
at Proxy.render (/home/prior/repositories/kn/vue-crash-reproduce/src/some-component.vue:20:153)
at VueComponent.Vue._render (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:4542:22)
at VueComponent.updateComponent (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:2786:21)
at Watcher.get (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:3140:25)
at new Watcher (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:3129:12)
at mountComponent (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:2793:3)
at VueComponent.Object.<anonymous>.Vue.$mount (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:7997:10)
at init (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:4135:13)
at createComponent (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:5606:9)
at createElm (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:5553:9)
at createChildren (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:5680:9)
at createElm (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:5582:9)
at VueComponent.patch [as __patch__] (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:6089:7)
at VueComponent.Vue._update (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:2658:19)
at VueComponent.updateComponent (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:2786:10)
at Watcher.get (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:3140:25)
at new Watcher (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:3129:12)
at mountComponent (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:2793:3)
at VueComponent.Object.<anonymous>.Vue.$mount (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:7997:10)
at init (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:4135:13)
at createComponent (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:5606:9)
at createElm (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:5553:9)
at VueComponent.patch [as __patch__] (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:6089:7)
at VueComponent.Vue._update (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:2658:19)
at VueComponent.updateComponent (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:2786:10)
at Watcher.get (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:3140:25)
at new Watcher (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:3129:12)
at mountComponent (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:2793:3)
at VueComponent.Object.<anonymous>.Vue.$mount (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/vue/dist/vue.runtime.common.js:7997:10)
at Object.mount (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/@vue/test-utils/dist/vue-test-utils.js:5940:21)
at Object.<anonymous> (/home/prior/repositories/kn/vue-crash-reproduce/src/__tests__/test-parent-component.ts:18:32)
at Object.asyncFn (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/jest-jasmine2/build/jasmine_async.js:82:37)
at resolve (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/jest-jasmine2/build/queue_runner.js:52:12)
at new Promise (<anonymous>)
at mapper (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/jest-jasmine2/build/queue_runner.js:39:19)
at promise.then (/home/prior/repositories/kn/vue-crash-reproduce/node_modules/jest-jasmine2/build/queue_runner.js:73:82)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
However, when deleting the access in the component, the asserts in the test:
expect((wrapper.vm as any).$content).not.toBeUndefined();
expect((wrapper.find(SomeComponent).vm as any).$content).not.toBeUndefined();
pass which leads to the conclusion that after the mount(ParentComponent, { localVue }) the hook is called while it wasn't during the mount.
When removing the Vue.extend(...) around the SomeComponent in src/some-component.vue the error disappears and everything works fine.
This issues was created as vue#8441 was closed immediately after it was opened.
This issue might be related to vue instead. I had a look at whether vue-jest could be related to this issue but it doesn't seem to be.
This issue might be the underlying issue for vuex#1330.
This happens because the component implementation is already extended imported Vue constructor on the user land. Then descendant components won't be extended by localVue.
The current implementation relies on an undocumented API in Vue core which is _base option in component options. https://github.com/vuejs/vue/blob/dev/src/core/vdom/create-component.js#L112-L117
Maybe, we should consider different approach to achieve localVue feature. 🤔
I'm open to suggestions for solving this problem with extended components and localVue
This is especially problematic with class components in typescript as they implicitly extend the components.
I have a PR that would replace all extended components with a new component extended from the localVue constructor (#840).
This isn't an ideal solution, but I can't think of another approach right now.
Awesome. A solution is desperately needed, especially since I found out that mocking the router is not possible without using localVue and hence migrating unit tests away from localVue is sometimes not an option.
Most helpful comment
I have a PR that would replace all extended components with a new component extended from the localVue constructor (#840).
This isn't an ideal solution, but I can't think of another approach right now.