From c8b98b128662adbb0a41673f5c6ae67a88b46e13 Mon Sep 17 00:00:00 2001 From: eddyerburgh Date: Fri, 15 Jun 2018 19:41:30 +0100 Subject: [PATCH 1/3] fix: stub child components --- packages/create-instance/create-instance.js | 20 ++++++++++-------- packages/test-utils/src/create-local-vue.js | 8 +++---- packages/test-utils/src/mount.js | 3 +-- test/specs/mounting-options/stubs.spec.js | 23 +++++++++++++++++++++ 4 files changed, 39 insertions(+), 15 deletions(-) diff --git a/packages/create-instance/create-instance.js b/packages/create-instance/create-instance.js index fc8c7b19c..77b30d6c8 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,9 @@ export default function createInstance ( } }) - Object.keys(stubComponents).forEach(c => { - _Vue.component(c, stubComponents[c]) - }) - - 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/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/mounting-options/stubs.spec.js b/test/specs/mounting-options/stubs.spec.js index fe89333f1..cda0d4c29 100644 --- a/test/specs/mounting-options/stubs.spec.js +++ b/test/specs/mounting-options/stubs.spec.js @@ -128,6 +128,29 @@ 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('') + }) + it('stubs components with dummy when passed a boolean', () => { const ComponentWithGlobalComponent = { render: h => h('div', [h('registered-component')]) From a08d7eed81eb0ed78d33a6b55f2c7121e0cc93de Mon Sep 17 00:00:00 2001 From: eddyerburgh Date: Sun, 17 Jun 2018 13:40:14 +0100 Subject: [PATCH 2/3] fix: add support for extended class components --- packages/create-instance/create-instance.js | 4 ++++ test/specs/mount.spec.js | 11 +++------- test/specs/mounting-options/stubs.spec.js | 24 +++++++++++++++++++++ test/specs/shallow-mount.spec.js | 15 ++++++------- 4 files changed, 38 insertions(+), 16 deletions(-) diff --git a/packages/create-instance/create-instance.js b/packages/create-instance/create-instance.js index 77b30d6c8..a7d435cc3 100644 --- a/packages/create-instance/create-instance.js +++ b/packages/create-instance/create-instance.js @@ -86,6 +86,10 @@ export default function createInstance ( } }) + if (component.options) { + component.options._base = _Vue + } + const Constructor = vueVersion < 2.3 && typeof component === 'function' ? component.extend(instanceOptions) : _Vue.extend(component).extend(instanceOptions) diff --git a/test/specs/mount.spec.js b/test/specs/mount.spec.js index 7f5b3f427..f95777752 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/stubs.spec.js b/test/specs/mounting-options/stubs.spec.js index cda0d4c29..fd9b7fe20 100644 --- a/test/specs/mounting-options/stubs.spec.js +++ b/test/specs/mounting-options/stubs.spec.js @@ -151,6 +151,30 @@ describeWithMountingMethods('options.stub', mountingMethod => { 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'] + }) + console.log(wrapper.html()) + 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 = { From 176b02ce8d07e35d3093c96e0e843b9e9ff914d8 Mon Sep 17 00:00:00 2001 From: eddyerburgh Date: Sun, 17 Jun 2018 14:36:39 +0100 Subject: [PATCH 3/3] fix: clone localVue in renderToString --- packages/server-test-utils/src/renderToString.js | 8 ++++++-- test/specs/mounting-options/localVue.spec.js | 8 ++++++++ test/specs/mounting-options/stubs.spec.js | 1 - 3 files changed, 14 insertions(+), 3 deletions(-) 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/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 fd9b7fe20..9fde1810a 100644 --- a/test/specs/mounting-options/stubs.spec.js +++ b/test/specs/mounting-options/stubs.spec.js @@ -168,7 +168,6 @@ describeWithMountingMethods('options.stub', mountingMethod => { const wrapper = mountingMethod(Vue.extend(TestComponent), { stubs: ['grandchild-component'] }) - console.log(wrapper.html()) const HTML = mountingMethod.name === 'renderToString' ? wrapper : wrapper.html()