diff --git a/packages/create-instance/create-instance.js b/packages/create-instance/create-instance.js index a8c0ac00d..669249157 100644 --- a/packages/create-instance/create-instance.js +++ b/packages/create-instance/create-instance.js @@ -39,6 +39,13 @@ function createChildren(vm, h, { slots, context }) { ) } +function getValuesFromCallableOption(optionValue) { + if (typeof optionValue === 'function') { + return optionValue.call(this) + } + return optionValue +} + export default function createInstance( component: Component, options: NormalizedOptions, @@ -99,8 +106,14 @@ export default function createInstance( const parentComponentOptions = options.parentComponent || {} - parentComponentOptions.provide = options.provide - parentComponentOptions._provided = options.provide + const originalParentComponentProvide = parentComponentOptions.provide + parentComponentOptions.provide = function() { + return { + ...getValuesFromCallableOption.call(this, originalParentComponentProvide), + ...getValuesFromCallableOption.call(this, options.provide) + } + } + parentComponentOptions.$_doNotStubChildren = true parentComponentOptions._isFunctionalContainer = componentOptions.functional parentComponentOptions.render = function(h) { diff --git a/test/specs/mounting-options/methods.spec.js b/test/specs/mounting-options/methods.spec.js index 98ff48bbf..3e000361b 100644 --- a/test/specs/mounting-options/methods.spec.js +++ b/test/specs/mounting-options/methods.spec.js @@ -2,6 +2,17 @@ import { config } from '@vue/test-utils' import { describeWithShallowAndMount } from '~resources/utils' describeWithShallowAndMount('options.methods', mountingMethod => { + let configMethodsSave + + beforeEach(() => { + configMethodsSave = config.methods + config.methods = {} + }) + + afterEach(() => { + config.methods = configMethodsSave + }) + it('prioritize mounting options over config', () => { config.methods['val'] = () => 'methodFromConfig' diff --git a/test/specs/mounting-options/provide.spec.js b/test/specs/mounting-options/provide.spec.js index 7339af7f2..904958611 100644 --- a/test/specs/mounting-options/provide.spec.js +++ b/test/specs/mounting-options/provide.spec.js @@ -32,6 +32,86 @@ describeWithShallowAndMount('options.provide', mountingMethod => { } ) + itDoNotRunIf( + !injectSupported, + 'respects provide fooues from parentComponent', + () => { + const parentComponent = { + provide: { + foo: 'from parent' + } + } + + const child = { + inject: ['foo', 'foo2'], + template: '
' + } + + const wrapper = mountingMethod(child, { + parentComponent, + provide: { + foo2: 'from config' + } + }) + + expect(wrapper.vm.foo).to.equal('from parent') + expect(wrapper.vm.foo2).to.equal('from config') + } + ) + + itDoNotRunIf( + !injectSupported, + 'respects provide function from parentComponent', + () => { + const parentComponent = { + provide() { + return { foo: 'from parent' } + } + } + + const child = { + inject: ['foo', 'foo2'], + template: '' + } + + const wrapper = mountingMethod(child, { + parentComponent, + provide: { + foo2: 'from config' + } + }) + + expect(wrapper.vm.foo).to.equal('from parent') + expect(wrapper.vm.foo2).to.equal('from config') + } + ) + + itDoNotRunIf( + !injectSupported, + 'prioritize mounting options over parentComponent provide', + () => { + const parentComponent = { + provide() { + return { foo: 'from parent' } + } + } + + const child = { + inject: ['foo'], + template: '' + } + + const wrapper = mountingMethod(child, { + parentComponent, + provide: { + foo: 'from config' + } + }) + + expect(wrapper.vm.foo).to.equal('from config') + } + ) + itDoNotRunIf( !injectSupported, 'provides function which is injected by mounted component',