From bc736fb6431e54ba5a9cf7908044e5c71234facc Mon Sep 17 00:00:00 2001 From: Edd Yerburgh Date: Sun, 17 Jun 2018 15:37:43 +0100 Subject: [PATCH] fix: stub child components (#723) --- packages/create-instance/create-instance.js | 22 +++++---- .../server-test-utils/src/renderToString.js | 8 +++- packages/test-utils/src/create-local-vue.js | 8 ++-- packages/test-utils/src/mount.js | 3 +- test/specs/mount.spec.js | 11 ++--- test/specs/mounting-options/localVue.spec.js | 8 ++++ test/specs/mounting-options/stubs.spec.js | 46 +++++++++++++++++++ test/specs/shallow-mount.spec.js | 15 +++--- 8 files changed, 89 insertions(+), 32 deletions(-) diff --git a/packages/create-instance/create-instance.js b/packages/create-instance/create-instance.js index 8b693a7e0..b96872853 100644 --- a/packages/create-instance/create-instance.js +++ b/packages/create-instance/create-instance.js @@ -59,7 +59,14 @@ export default function createInstance ( ...stubComponents } } - + _Vue.mixin({ + created () { + Object.assign( + this.$options.components, + stubComponents + ) + } + }) Object.keys(component.components || {}).forEach(c => { if ( component.components[c].extendOptions && @@ -79,14 +86,13 @@ export default function createInstance ( } }) - Object.keys(stubComponents).forEach(c => { - _Vue.component(c, stubComponents[c]) - }) + if (component.options) { + component.options._base = _Vue + } - const Constructor = - vueVersion < 2.3 && typeof component === 'function' - ? component.extend(instanceOptions) - : _Vue.extend(component).extend(instanceOptions) + const Constructor = vueVersion < 2.3 && typeof component === 'function' + ? component.extend(instanceOptions) + : _Vue.extend(component).extend(instanceOptions) Object.keys(instanceOptions.components || {}).forEach(key => { Constructor.component(key, instanceOptions.components[key]) diff --git a/packages/server-test-utils/src/renderToString.js b/packages/server-test-utils/src/renderToString.js index e4c7c0d4b..cfdd8ab7e 100644 --- a/packages/server-test-utils/src/renderToString.js +++ b/packages/server-test-utils/src/renderToString.js @@ -28,8 +28,12 @@ export default function renderToString ( if (options.attachToDocument) { throwError(`you cannot use attachToDocument with ` + `renderToString`) } - const vueClass = options.localVue || testUtils.createLocalVue() - const vm = createInstance(component, mergeOptions(options, config), vueClass) + const vueConstructor = testUtils.createLocalVue(options.localVue) + const vm = createInstance( + component, + mergeOptions(options, config), + vueConstructor + ) let renderedString = '' // $FlowIgnore diff --git a/packages/test-utils/src/create-local-vue.js b/packages/test-utils/src/create-local-vue.js index 80b655a90..2a0979c71 100644 --- a/packages/test-utils/src/create-local-vue.js +++ b/packages/test-utils/src/create-local-vue.js @@ -4,13 +4,13 @@ import Vue from 'vue' import cloneDeep from 'lodash/cloneDeep' import errorHandler from './error-handler' -function createLocalVue (): Component { - const instance = Vue.extend() +function createLocalVue (_Vue: Component = Vue): Component { + const instance = _Vue.extend() // clone global APIs - Object.keys(Vue).forEach(key => { + Object.keys(_Vue).forEach(key => { if (!instance.hasOwnProperty(key)) { - const original = Vue[key] + const original = _Vue[key] instance[key] = typeof original === 'object' ? cloneDeep(original) : original } diff --git a/packages/test-utils/src/mount.js b/packages/test-utils/src/mount.js index 5372c0f0f..1c1b98f60 100644 --- a/packages/test-utils/src/mount.js +++ b/packages/test-utils/src/mount.js @@ -28,8 +28,7 @@ export default function mount ( // Remove cached constructor delete component._Ctor - - const vueConstructor = options.localVue || createLocalVue() + const vueConstructor = createLocalVue(options.localVue) const elm = options.attachToDocument ? createElement() : undefined diff --git a/test/specs/mount.spec.js b/test/specs/mount.spec.js index a13100388..906dfc26b 100644 --- a/test/specs/mount.spec.js +++ b/test/specs/mount.spec.js @@ -58,20 +58,15 @@ describeRunIf(process.env.TEST_ENV !== 'node', 'mount', () => { } }) - it('returns new VueWrapper with mounted Vue instance initialized with Vue.extend with props, if passed as propsData', () => { - const prop1 = { test: 'TEST' } + it('handles propsData for extended components', () => { + const prop1 = 'test' const TestComponent = Vue.extend(ComponentWithProps) const wrapper = mount(TestComponent, { propsData: { prop1 } }) - expect(wrapper.vm).to.be.an('object') - if (wrapper.vm.$props) { - expect(wrapper.vm.$props.prop1).to.equal(prop1) - } else { - expect(wrapper.vm.$options.propsData.prop1).to.equal(prop1) - } + expect(wrapper.text()).to.contain(prop1) }) it('handles uncompiled extended Vue component', () => { diff --git a/test/specs/mounting-options/localVue.spec.js b/test/specs/mounting-options/localVue.spec.js index 9fbf2bb26..2f51b8e20 100644 --- a/test/specs/mounting-options/localVue.spec.js +++ b/test/specs/mounting-options/localVue.spec.js @@ -69,4 +69,12 @@ describeWithMountingMethods('options.localVue', mountingMethod => { expect(HTML).to.contain('2') } }) + + it('does not add created mixin to localVue', () => { + const localVue = createLocalVue() + mountingMethod({ render: () => {} }, { + localVue + }) + expect(localVue.options.created).to.equal(undefined) + }) }) diff --git a/test/specs/mounting-options/stubs.spec.js b/test/specs/mounting-options/stubs.spec.js index fe89333f1..9fde1810a 100644 --- a/test/specs/mounting-options/stubs.spec.js +++ b/test/specs/mounting-options/stubs.spec.js @@ -128,6 +128,52 @@ describeWithMountingMethods('options.stub', mountingMethod => { expect(HTML).to.contain('') }) + itDoNotRunIf( + mountingMethod.name === 'shallowMount', + 'stubs nested components', () => { + const GrandchildComponent = { + template: '' + } + const ChildComponent = { + template: '', + components: { GrandchildComponent } + } + const TestComponent = { + template: '', + components: { ChildComponent } + } + const wrapper = mountingMethod(TestComponent, { + stubs: ['grandchild-component'] + }) + const HTML = mountingMethod.name === 'renderToString' + ? wrapper + : wrapper.html() + expect(HTML).not.to.contain('') + }) + + itDoNotRunIf( + mountingMethod.name === 'shallowMount', + 'stubs nested components on extended components', () => { + const GrandchildComponent = { + template: '' + } + const ChildComponent = { + template: '', + components: { GrandchildComponent } + } + const TestComponent = { + template: '
', + components: { ChildComponent } + } + const wrapper = mountingMethod(Vue.extend(TestComponent), { + stubs: ['grandchild-component'] + }) + const HTML = mountingMethod.name === 'renderToString' + ? wrapper + : wrapper.html() + expect(HTML).not.to.contain('') + }) + it('stubs components with dummy when passed a boolean', () => { const ComponentWithGlobalComponent = { render: h => h('div', [h('registered-component')]) diff --git a/test/specs/shallow-mount.spec.js b/test/specs/shallow-mount.spec.js index 41f75b41b..6522a85e6 100644 --- a/test/specs/shallow-mount.spec.js +++ b/test/specs/shallow-mount.spec.js @@ -171,14 +171,13 @@ describeRunIf(process.env.TEST_ENV !== 'node', 'shallowMount', () => { expect(wrapper.find('p').exists()).to.equal(false) }) - it('stubs Vue class component children', () => { - if (vueVersion < 2.3) { - return - } - const wrapper = shallowMount(ComponentAsAClassWithChild) - expect(wrapper.find(Component).exists()).to.equal(true) - expect(wrapper.findAll('div').length).to.equal(1) - }) + itDoNotRunIf( + vueVersion < 2.3, + 'stubs Vue class component children', () => { + const wrapper = shallowMount(ComponentAsAClassWithChild) + expect(wrapper.find(Component).exists()).to.equal(true) + expect(wrapper.findAll('div').length).to.equal(1) + }) it('works correctly with find, contains, findAll, and is on unnamed components', () => { const TestComponent = {