diff --git a/packages/create-instance/create-instance.js b/packages/create-instance/create-instance.js index 7b2a8f761..a3b23fdf6 100644 --- a/packages/create-instance/create-instance.js +++ b/packages/create-instance/create-instance.js @@ -4,6 +4,7 @@ import { createSlotVNodes } from './create-slot-vnodes' import addMocks from './add-mocks' import { addEventLogger } from './log-events' import { addStubs } from './add-stubs' +import { patchRender } from './patch-render' import { throwError, vueVersion } from 'shared/util' import { compileTemplate, @@ -60,6 +61,7 @@ export default function createInstance ( addEventLogger(_Vue) addMocks(options.mocks, _Vue) addStubs(component, options.stubs, _Vue, options.shouldProxy) + patchRender(_Vue) if ( (component.options && component.options.functional) || @@ -104,11 +106,12 @@ export default function createInstance ( component.options._base = _Vue } + const componentOptions = typeof component === 'function' + ? component.options + : component // extend component from _Vue to add properties and mixins // extend does not work correctly for sub class components in Vue < 2.2 - const Constructor = typeof component === 'function' - ? _Vue.extend(component.options).extend(instanceOptions) - : _Vue.extend(component).extend(instanceOptions) + const Constructor = _Vue.extend(componentOptions).extend(instanceOptions) // used to identify extended component using constructor Constructor.options.$_vueTestUtils_original = component diff --git a/packages/create-instance/patch-render.js b/packages/create-instance/patch-render.js new file mode 100644 index 000000000..e0a69ada6 --- /dev/null +++ b/packages/create-instance/patch-render.js @@ -0,0 +1,20 @@ +import { addHook } from './add-hook' + +// This is used to extend component constructors +// used directly in a render function +// see https://github.com/vuejs/vue-test-utils/issues/994 +export function patchRender (_Vue) { + addHook(_Vue.options, 'beforeCreate', function () { + const createElementSave = this.$createElement + this.$createElement = function (el, ...args) { + if ( + typeof el === 'function' && + el.super !== _Vue && + !el.options.$_vueTestUtils_original + ) { + el = _Vue.extend(el.options) + } + return createElementSave(el, ...args) + } + }) +} diff --git a/test/specs/mounting-options/localVue.spec.js b/test/specs/mounting-options/localVue.spec.js index ab2b343c5..bc92cdf37 100644 --- a/test/specs/mounting-options/localVue.spec.js +++ b/test/specs/mounting-options/localVue.spec.js @@ -155,6 +155,23 @@ describeWithMountingMethods('options.localVue', mountingMethod => { }) }) + it('is applied to inline constructor functions', () => { + const ChildComponent = Vue.extend({ + render (h) { + h('p', this.$route.params) + } + }) + const TestComponent = { + render: h => h(ChildComponent) + } + const localVue = createLocalVue() + localVue.prototype.$route = {} + const wrapper = mountingMethod(TestComponent, { + localVue + }) + expect(wrapper.findAll(ChildComponent).length).to.equal(1) + }) + itRunIf( vueVersion < 2.3, 'throws an error if used with an extended component in Vue 2.3', () => {