Open riovir opened 7 years ago
This is not a regression, it's a result of the documented breaking change concerning require()
:
Similarly, old CommonJS-style requires will also need to be updated:
// before const Foo = require('./Foo.vue') // after const Foo = require('./Foo.vue').default
The difference when using ?inject
compared to the given example above is that you would not do:
const HelloInjector = require('!!vue-loader?inject!@/components/Hello').default // wrong!
because with ?inject
, the require does return a constructor, not the module exports object.
Instead, We have to get the .default
after we have run the constructor:
const Constructor = Vue.extend(HelloInjector({}).default)
We should fix the docs in this regard, though.
I've applied the suggested fix on the sample repo (also downgraded the inject-loader to 2.0.0): https://github.com/riovir/injected-component-reprod/commit/8db5a94cf722fde144785bc0dff57ad4c1ba2841
Unfortunately the problem persists.
I'll check it out...
Dang, forgot about this one. assigned myself now and will take a look on the weekend hopefully.
Let me know if I can help.
I have the same kind of problem : https://github.com/phoenix741/passprotect-server/blob/update-versions/test/unit/specs/components/user/Login.spec.js
I use es6 import in test (cjs import don't resolve the problem event using .default). When i import vue file without inject, it work, but if i use inject the created mock don't contains the template and i have the warning.
I made a console.log to see the created object :
LOG LOG: Object{name: 'login', mixins: [Object{created: ..., mounted: ..., methods: ...}], data: function data() { ... }, computed: Object{usernameValidation: function usernameValidation() { ... }, passwordValidation: function passwordValidation() { ... }}, methods: Object{submitForm: function submitForm() { ... }}, render: undefined, staticRenderFns: undefined, __file: 'client/components/user/Login.vue'}
ERROR LOG: '[Vue warn]: Failed to mount component: template or render function not defined.
How can i wrote my test ? Is it a bug or it was my mistake ?
Please consult the forum for support.
forum.vuejs.org
I have open a topic on the forum.
The problem come from component-normalizer that get compiledTemplate.render and compiledTemplate.staticRenderFns but we should get the compiledTemplate.default.render and compiledTemplate.default.staticRenderFns because i use ES6
I have made a correction on my computer (directly in node_modules) in component-normalizer :
// render functions if (compiledTemplate) { compiledTemplate = compiledTemplate.default || compiledTemplate options.render = compiledTemplate.render options.staticRenderFns = compiledTemplate.staticRenderFns }
Thanks for investigating this, there seems to be an issue indeed.
Appreciated!
on second thought, would you be so kind and opens proper bug report issue for this?
The current issue is 1) old and 2) originally about a a different problem (improving docs to reflect the changed from v13)
Ok I will create a bug on a new issue, but strangely reinstalling the project in another path with a new node_modules resolve the problem.
I search why to reproduce the problem in a minimal project
@phoenix741 I've reinstalled into another path, but i keep having the same problem. Did you find out why it's working on your side after reinstalling ? (i'm currently using you're proposed solution which makes everything working)
Hi, I reproduce the problem only some times, and think that when i start the app and then test. Test fails. If i start the test without starting the application it work. I have the feeling that the problem is related to a cache (babel cache ? vue cache ?).
Tried applying your suggested fix @LinusBorg to use Vue.extend(Injector({}).default)
. Doesn't seem to have done anything unfortunately and the injected component seems to still have the notorious undefined render
function.
I'm currently running these tests using these versions:
inject-loader@3.0.1
vue-loader@13.3.0
webpack@3.8.1
A horrible fix I've employed to get around this is to import the original component and replace the injected component's render
method with the original's.
import OriginalComponent from '@/Component.vue';
import injector from '!!vue-loader?inject!@/Component.vue';
// require('!!vue-loader?inject!@/Component.vue') also does the same thing
const Component = injector({ ... });
Component.render = OriginalComponent.render;
This is pretty horrendous though and it would be good to not have to do this :disappointed:
I'm having a similar issue with a karma@1.7.1
+ jasmine@2.8.0
+ webpack@2.2.1
+ inject-loader@3.0.1
setup.
Component.vue
:
<template>
<div></div>
</template>
<script>
export default {};
</script>
ComponentTest.js
:
import Component from './Component.vue';
import Injector from './Component.vue?inject';
// ...
beforeEach(() => {
console.log('Component', Component);
console.log('Injector', Injector());
});
The ?inject
is resolved via webpack config:
// ...
{
test: /\.vue$/,
include: includePaths,
oneOf: [
{
resourceQuery: /inject/,
loader: 'vue-loader',
options: {
inject: true,
loaders: {
js: jsLoader
},
},
},
{
loader: 'vue-loader',
options: {
loaders: {
js: jsLoader
},
},
},
],
},
// ...
With vue-loader@13.5.0
:
LOG: 'Component', Object{render: function () { ... }, staticRenderFns: [], _compiled: true, __file: 'tests/pages/Component.vue'}
LOG: 'Injector', Object{render: undefined, staticRenderFns: undefined, _compiled: true, __file: 'tests/Component.vue'}
// or
LOG: 'Component', Object{render: function () { ... }, staticRenderFns: [], _compiled: true, __file: 'tests/Component.vue'}
LOG: 'Injector', Object{render: function () { ... }, staticRenderFns: [], _compiled: true, __file: 'tests/Component.vue'}
With vue-loader@12.2.2
:
LOG: 'Component', Object{render: function (){ ... }, staticRenderFns: [], __file: '/home/user/.../tests/Component.vue'}
LOG: 'Injector', Object{render: function (){ ... }, staticRenderFns: [], __file: '/home/user/.../tests/Component.vue'}
With vue-loader@13.5.0
the props render
and staticRenderFns
are randomly undefined
. First I thought it's a caching issue. But in my case it happens randomly, so maybe a timing issue?
I had the same issue and solved it (for now) by avoiding to import components straight away (as in without using the inject loader) even when I don't have to mock any dependencies.
import Search from './../../../src/components/Search.vue'; // AVOID
import SearchInjector from '!!vue-loader?inject!./../../../src/components/Search.vue'; // IT WORKS
I just had to remove the import Search from './../../../src/components/Search.vue';
and then when I need to test the component without mocking any dependencies I simply do:
const vm = new Vue(SearchInjector());
I took me some time to figure out that was the problem because I wasn't getting the failure in the test where I was doing the mounting (which in fact was passing when ran on its own). I got the failure only when running ALL tests as in some tests I had some component imports without injection and it made the mounting fail also in the other tests (which makes me wonder about tests isolation really).
Here's my working configuration with Karma and Webpack 3: https://github.com/fracasula/inject-loader-test
Can anyone report what the status of this issue is? I'm experiencing this problem as well.
@yyx990803 In https://github.com/vuejs/vue-loader/commit/611fda8c76b5f2c612536eb90ac5694384717659 using the inject-loader
is deprecated. Will there be a replacement?
I had to downgrade to vue-loader@12.2.2 because >v13 has the above issue. how do we inject dependencies from now?
We replaced inject-loader
with babel-plugin-rewire
and could finally upgrade to vue-loader@14.2.1
.
Version
13.0.0
Reproduction link
https://github.com/riovir/injected-component-reprod
Steps to reproduce
Clone - install - test with the given repo, or:
What is expected?
Mock-injected components to behave the same way as their regularly loaded counterparts. Particularly where the render function is concerned.
What is actually happening?
In arbitrary situations (project size seems to be a factor) inject-loaded Vue components fail to mount due to missing render function.