Skip to content

Commit d2f26e8

Browse files
authored
fix: handle options applied by mixins (#1101)
1 parent c13cac3 commit d2f26e8

File tree

4 files changed

+58
-17
lines changed

4 files changed

+58
-17
lines changed

Diff for: packages/create-instance/create-component-stubs.js

+17-9
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@ function getCoreProperties (componentOptions: Component): Object {
4242
return {
4343
attrs: componentOptions.attrs,
4444
name: componentOptions.name,
45+
props: componentOptions.props,
4546
on: componentOptions.on,
4647
key: componentOptions.key,
4748
ref: componentOptions.ref,
48-
props: componentOptions.props,
4949
domProps: componentOptions.domProps,
5050
class: componentOptions.class,
5151
staticClass: componentOptions.staticClass,
@@ -64,15 +64,22 @@ function createClassString (staticClass, dynamicClass) {
6464
return staticClass || dynamicClass
6565
}
6666

67+
function resolveOptions (component, _Vue) {
68+
if (typeof component === 'function' && !component.cid) {
69+
return {}
70+
}
71+
72+
return typeof component === 'function'
73+
? component.options
74+
: _Vue.extend(component).options
75+
}
76+
6777
export function createStubFromComponent (
6878
originalComponent: Component,
69-
name: string
79+
name: string,
80+
_Vue: Component
7081
): Component {
71-
const componentOptions =
72-
typeof originalComponent === 'function' && originalComponent.cid
73-
? originalComponent.extendOptions
74-
: originalComponent
75-
82+
const componentOptions = resolveOptions(originalComponent, _Vue)
7683
const tagName = `${name || 'anonymous'}-stub`
7784

7885
// ignoreElements does not exist in Vue 2.0.x
@@ -137,7 +144,8 @@ function validateStub (stub) {
137144

138145
export function createStubsFromStubsObject (
139146
originalComponents: Object = {},
140-
stubs: Object
147+
stubs: Object,
148+
_Vue: Component
141149
): Components {
142150
return Object.keys(stubs || {}).reduce((acc, stubName) => {
143151
const stub = stubs[stubName]
@@ -150,7 +158,7 @@ export function createStubsFromStubsObject (
150158

151159
if (stub === true) {
152160
const component = resolveComponent(originalComponents, stubName)
153-
acc[stubName] = createStubFromComponent(component, stubName)
161+
acc[stubName] = createStubFromComponent(component, stubName, _Vue)
154162
return acc
155163
}
156164

Diff for: packages/create-instance/create-instance.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { componentNeedsCompiling, isPlainObject } from 'shared/validators'
1616
import { validateSlots } from './validate-slots'
1717
import createScopedSlots from './create-scoped-slots'
1818
import { createStubsFromStubsObject } from './create-component-stubs'
19-
import { patchRender } from './patch-render'
19+
import { patchCreateElement } from './patch-create-element'
2020

2121
function vueExtendUnsupportedOption (option: string) {
2222
return `options.${option} is not supported for ` +
@@ -60,13 +60,14 @@ export default function createInstance (
6060
const stubComponentsObject = createStubsFromStubsObject(
6161
component.components,
6262
// $FlowIgnore
63-
options.stubs
63+
options.stubs,
64+
_Vue
6465
)
6566

6667
addEventLogger(_Vue)
6768
addMocks(_Vue, options.mocks)
6869
addStubs(_Vue, stubComponentsObject)
69-
patchRender(_Vue, stubComponentsObject, options.shouldProxy)
70+
patchCreateElement(_Vue, stubComponentsObject, options.shouldProxy)
7071

7172
if (
7273
(component.options && component.options.functional) ||

Diff for: packages/create-instance/patch-render.js renamed to packages/create-instance/patch-create-element.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ function extend (component, _Vue) {
2525

2626
function createStubIfNeeded (shouldStub, component, _Vue, el) {
2727
if (shouldStub) {
28-
return createStubFromComponent(component || {}, el)
28+
return createStubFromComponent(component || {}, el, _Vue)
2929
}
3030

3131
if (shouldExtend(component, _Vue)) {
@@ -49,14 +49,14 @@ function isComponentOptions (el) {
4949
return typeof el === 'object' && (el.template || el.render)
5050
}
5151

52-
export function patchRender (_Vue, stubs, stubAllComponents) {
52+
export function patchCreateElement (_Vue, stubs, stubAllComponents) {
5353
// This mixin patches vm.$createElement so that we can stub all components
5454
// before they are rendered in shallow mode. We also need to ensure that
5555
// component constructors were created from the _Vue constructor. If not,
5656
// we must replace them with components created from the _Vue constructor
5757
// before calling the original $createElement. This ensures that components
5858
// have the correct instance properties and stubs when they are rendered.
59-
function patchRenderMixin () {
59+
function patchCreateElementMixin () {
6060
const vm = this
6161

6262
if (
@@ -77,7 +77,7 @@ export function patchRender (_Vue, stubs, stubAllComponents) {
7777

7878
if (isConstructor(el) || isComponentOptions(el)) {
7979
if (stubAllComponents) {
80-
const stub = createStubFromComponent(el, el.name || 'anonymous')
80+
const stub = createStubFromComponent(el, el.name || 'anonymous', _Vue)
8181
return originalCreateElement(stub, ...args)
8282
}
8383
const Constructor = shouldExtend(el, _Vue) ? extend(el, _Vue) : el
@@ -121,6 +121,6 @@ export function patchRender (_Vue, stubs, stubAllComponents) {
121121
}
122122

123123
_Vue.mixin({
124-
[BEFORE_RENDER_LIFECYCLE_HOOK]: patchRenderMixin
124+
[BEFORE_RENDER_LIFECYCLE_HOOK]: patchCreateElementMixin
125125
})
126126
}

Diff for: test/specs/shallow-mount.spec.js

+32
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,38 @@ describeRunIf(process.env.TEST_ENV !== 'node', 'shallowMount', () => {
308308
expect(wrapper.find('p').exists()).to.equal(false)
309309
})
310310

311+
it('stubs components that receive props through mixin', () => {
312+
const addProps = {
313+
props: ['a']
314+
}
315+
316+
const ChildComponent = {
317+
template: '<div />',
318+
mixins: [addProps]
319+
}
320+
321+
const ChildComponentExtended = Vue.extend({
322+
template: '<div />',
323+
mixins: [addProps]
324+
})
325+
326+
const TestComponent = {
327+
template: `
328+
<div>
329+
<child-component a="val" />
330+
<child-component-extended a="val" />
331+
</div>
332+
`,
333+
components: {
334+
ChildComponent,
335+
ChildComponentExtended
336+
}
337+
}
338+
const wrapper = shallowMount(TestComponent)
339+
expect(wrapper.find(ChildComponent).props('a')).to.equal('val')
340+
expect(wrapper.find(ChildComponentExtended).props('a')).to.equal('val')
341+
})
342+
311343
itDoNotRunIf(
312344
vueVersion < 2.3,
313345
'stubs Vue class component children', () => {

0 commit comments

Comments
 (0)