diff --git a/packages/create-instance/create-component-stubs.js b/packages/create-instance/create-component-stubs.js index ededc3b1e..33470ae76 100644 --- a/packages/create-instance/create-component-stubs.js +++ b/packages/create-instance/create-component-stubs.js @@ -42,10 +42,10 @@ function getCoreProperties (componentOptions: Component): Object { return { attrs: componentOptions.attrs, name: componentOptions.name, + props: componentOptions.props, on: componentOptions.on, key: componentOptions.key, ref: componentOptions.ref, - props: componentOptions.props, domProps: componentOptions.domProps, class: componentOptions.class, staticClass: componentOptions.staticClass, @@ -64,15 +64,22 @@ function createClassString (staticClass, dynamicClass) { return staticClass || dynamicClass } +function resolveOptions (component, _Vue) { + if (typeof component === 'function' && !component.cid) { + return {} + } + + return typeof component === 'function' + ? component.options + : _Vue.extend(component).options +} + export function createStubFromComponent ( originalComponent: Component, - name: string + name: string, + _Vue: Component ): Component { - const componentOptions = - typeof originalComponent === 'function' && originalComponent.cid - ? originalComponent.extendOptions - : originalComponent - + const componentOptions = resolveOptions(originalComponent, _Vue) const tagName = `${name || 'anonymous'}-stub` // ignoreElements does not exist in Vue 2.0.x @@ -137,7 +144,8 @@ function validateStub (stub) { export function createStubsFromStubsObject ( originalComponents: Object = {}, - stubs: Object + stubs: Object, + _Vue: Component ): Components { return Object.keys(stubs || {}).reduce((acc, stubName) => { const stub = stubs[stubName] @@ -150,7 +158,7 @@ export function createStubsFromStubsObject ( if (stub === true) { const component = resolveComponent(originalComponents, stubName) - acc[stubName] = createStubFromComponent(component, stubName) + acc[stubName] = createStubFromComponent(component, stubName, _Vue) return acc } diff --git a/packages/create-instance/create-instance.js b/packages/create-instance/create-instance.js index 182f36097..6e1cdd458 100644 --- a/packages/create-instance/create-instance.js +++ b/packages/create-instance/create-instance.js @@ -16,7 +16,7 @@ import { componentNeedsCompiling, isPlainObject } from 'shared/validators' import { validateSlots } from './validate-slots' import createScopedSlots from './create-scoped-slots' import { createStubsFromStubsObject } from './create-component-stubs' -import { patchRender } from './patch-render' +import { patchCreateElement } from './patch-create-element' function vueExtendUnsupportedOption (option: string) { return `options.${option} is not supported for ` + @@ -60,13 +60,14 @@ export default function createInstance ( const stubComponentsObject = createStubsFromStubsObject( component.components, // $FlowIgnore - options.stubs + options.stubs, + _Vue ) addEventLogger(_Vue) addMocks(_Vue, options.mocks) addStubs(_Vue, stubComponentsObject) - patchRender(_Vue, stubComponentsObject, options.shouldProxy) + patchCreateElement(_Vue, stubComponentsObject, options.shouldProxy) if ( (component.options && component.options.functional) || diff --git a/packages/create-instance/patch-render.js b/packages/create-instance/patch-create-element.js similarity index 93% rename from packages/create-instance/patch-render.js rename to packages/create-instance/patch-create-element.js index 598f434e2..272d47772 100644 --- a/packages/create-instance/patch-render.js +++ b/packages/create-instance/patch-create-element.js @@ -25,7 +25,7 @@ function extend (component, _Vue) { function createStubIfNeeded (shouldStub, component, _Vue, el) { if (shouldStub) { - return createStubFromComponent(component || {}, el) + return createStubFromComponent(component || {}, el, _Vue) } if (shouldExtend(component, _Vue)) { @@ -49,14 +49,14 @@ function isComponentOptions (el) { return typeof el === 'object' && (el.template || el.render) } -export function patchRender (_Vue, stubs, stubAllComponents) { +export function patchCreateElement (_Vue, stubs, stubAllComponents) { // This mixin patches vm.$createElement so that we can stub all components // before they are rendered in shallow mode. We also need to ensure that // component constructors were created from the _Vue constructor. If not, // we must replace them with components created from the _Vue constructor // before calling the original $createElement. This ensures that components // have the correct instance properties and stubs when they are rendered. - function patchRenderMixin () { + function patchCreateElementMixin () { const vm = this if ( @@ -77,7 +77,7 @@ export function patchRender (_Vue, stubs, stubAllComponents) { if (isConstructor(el) || isComponentOptions(el)) { if (stubAllComponents) { - const stub = createStubFromComponent(el, el.name || 'anonymous') + const stub = createStubFromComponent(el, el.name || 'anonymous', _Vue) return originalCreateElement(stub, ...args) } const Constructor = shouldExtend(el, _Vue) ? extend(el, _Vue) : el @@ -121,6 +121,6 @@ export function patchRender (_Vue, stubs, stubAllComponents) { } _Vue.mixin({ - [BEFORE_RENDER_LIFECYCLE_HOOK]: patchRenderMixin + [BEFORE_RENDER_LIFECYCLE_HOOK]: patchCreateElementMixin }) } diff --git a/test/specs/shallow-mount.spec.js b/test/specs/shallow-mount.spec.js index 7dd91b877..dedcc69ef 100644 --- a/test/specs/shallow-mount.spec.js +++ b/test/specs/shallow-mount.spec.js @@ -308,6 +308,38 @@ describeRunIf(process.env.TEST_ENV !== 'node', 'shallowMount', () => { expect(wrapper.find('p').exists()).to.equal(false) }) + it('stubs components that receive props through mixin', () => { + const addProps = { + props: ['a'] + } + + const ChildComponent = { + template: '
', + mixins: [addProps] + } + + const ChildComponentExtended = Vue.extend({ + template: '
', + mixins: [addProps] + }) + + const TestComponent = { + template: ` +
+ + +
+ `, + components: { + ChildComponent, + ChildComponentExtended + } + } + const wrapper = shallowMount(TestComponent) + expect(wrapper.find(ChildComponent).props('a')).to.equal('val') + expect(wrapper.find(ChildComponentExtended).props('a')).to.equal('val') + }) + itDoNotRunIf( vueVersion < 2.3, 'stubs Vue class component children', () => {