diff --git a/package.json b/package.json index 28d1310c0..8650768fd 100644 --- a/package.json +++ b/package.json @@ -77,12 +77,12 @@ "sinon-chai": "^3.3.0", "typescript": "3", "vee-validate": "^2.1.3", - "vue": "^2.5.22", + "vue": "^2.6.11", "vue-class-component": "^6.1.2", "vue-loader": "^13.6.2", "vue-router": "^3.0.1", - "vue-server-renderer": "^2.5.22", - "vue-template-compiler": "^2.5.22", + "vue-server-renderer": "^2.6.11", + "vue-template-compiler": "^2.6.11", "vuepress": "^0.14.2", "vuepress-theme-vue": "^1.0.3", "vuex": "^3.0.1", diff --git a/packages/create-instance/create-component-stubs.js b/packages/create-instance/create-component-stubs.js index 5b6660761..843a7e471 100644 --- a/packages/create-instance/create-component-stubs.js +++ b/packages/create-instance/create-component-stubs.js @@ -1,7 +1,13 @@ // @flow import Vue from 'vue' -import { throwError, camelize, capitalize, hyphenate } from '../shared/util' +import { + throwError, + camelize, + capitalize, + hyphenate, + keys +} from '../shared/util' import { componentNeedsCompiling, templateContainsComponent, @@ -75,6 +81,25 @@ function resolveOptions(component, _Vue) { return options } +function getScopedSlotRenderFunctions(ctx: any): Array { + // In Vue 2.6+ a new v-slot syntax was introduced + // scopedSlots are now saved in parent._vnode.data.scopedSlots + // We filter out the _normalized and $stable key + if ( + ctx && + ctx.$options && + ctx.$options.parent && + ctx.$options.parent._vnode && + ctx.$options.parent._vnode.data && + ctx.$options.parent._vnode.data.scopedSlots + ) { + const slotKeys: Array = ctx.$options.parent._vnode.data.scopedSlots + return keys(slotKeys).filter(x => x !== '_normalized' && x !== '$stable') + } + + return [] +} + export function createStubFromComponent( originalComponent: Component, name: string, @@ -109,7 +134,12 @@ export function createStubFromComponent( ...this.$props } }, - context ? context.children : this.$options._renderChildren + context + ? context.children + : this.$options._renderChildren || + getScopedSlotRenderFunctions(this).map(x => + this.$options.parent._vnode.data.scopedSlots[x]() + ) ) } } diff --git a/packages/shared/util.js b/packages/shared/util.js index b3b5e5da3..dfa362945 100644 --- a/packages/shared/util.js +++ b/packages/shared/util.js @@ -36,6 +36,10 @@ function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop) } +export function keys(obj: any): Array { + return Object.keys(obj) +} + export function resolveComponent(id: string, components: Object) { if (typeof id !== 'string') { return diff --git a/test/resources/components/component-with-v-slot-syntax.vue b/test/resources/components/component-with-v-slot-syntax.vue new file mode 100644 index 000000000..0e990a4cb --- /dev/null +++ b/test/resources/components/component-with-v-slot-syntax.vue @@ -0,0 +1,17 @@ + + + diff --git a/test/resources/components/component-with-v-slot.vue b/test/resources/components/component-with-v-slot.vue new file mode 100644 index 000000000..fa6165b77 --- /dev/null +++ b/test/resources/components/component-with-v-slot.vue @@ -0,0 +1,11 @@ + + + diff --git a/test/specs/shallow-mount.spec.js b/test/specs/shallow-mount.spec.js index da422f3a3..7b7bf15e0 100644 --- a/test/specs/shallow-mount.spec.js +++ b/test/specs/shallow-mount.spec.js @@ -7,6 +7,8 @@ import ComponentWithNestedChildren from '~resources/components/component-with-ne import ComponentWithLifecycleHooks from '~resources/components/component-with-lifecycle-hooks.vue' import ComponentWithoutName from '~resources/components/component-without-name.vue' import ComponentAsAClassWithChild from '~resources/components/component-as-a-class-with-child.vue' +import ComponentWithVSlotSyntax from '~resources/components/component-with-v-slot-syntax.vue' +import ComponentWithVSlot from '~resources/components/component-with-v-slot.vue' import RecursiveComponent from '~resources/components/recursive-component.vue' import { vueVersion } from '~resources/utils' import { describeRunIf, itDoNotRunIf } from 'conditional-specs' @@ -96,6 +98,42 @@ describeRunIf(process.env.TEST_ENV !== 'node', 'shallowMount', () => { ) }) + it('renders SFC with named slots with v-slot syntax', () => { + const wrapper = shallowMount(ComponentWithVSlotSyntax) + + expect(wrapper.find(ComponentWithVSlot).exists()).to.equal(true) + expect(wrapper.find('.new-example').exists()).to.equal(true) + expect(wrapper.html()).to.equal( + '\n' + + '

new slot syntax

\n' + + '
' + ) + }) + + it('renders named slots with v-slot syntax', () => { + const localVue = createLocalVue() + localVue.component('Foo', { + template: '
' + }) + const TestComponent = { + template: ` + + + + ` + } + const wrapper = shallowMount(TestComponent, { + localVue + }) + expect(wrapper.find({ name: 'Foo' }).exists()).to.equal(true) + expect(wrapper.find('.new-example').exists()).to.equal(true) + expect(wrapper.html()).to.equal( + '\n' + '

text

\n' + '
' + ) + }) + it('renders no children if none supplied', () => { const TestComponent = { template: '', diff --git a/yarn.lock b/yarn.lock index 55f6f7ddb..72a9549c0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6290,7 +6290,7 @@ lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" -lodash.template@^4.0.2, lodash.template@^4.4.0: +lodash.template@^4.0.2, lodash.template@^4.4.0, lodash.template@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== @@ -8787,6 +8787,11 @@ serialize-javascript@^1.4.0: version "1.5.0" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.5.0.tgz#1aa336162c88a890ddad5384baebc93a655161fe" +serialize-javascript@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" + integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ== + set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" @@ -10092,18 +10097,18 @@ vue-server-renderer@^2.5.16: serialize-javascript "^1.3.0" source-map "0.5.6" -vue-server-renderer@^2.5.22: - version "2.5.22" - resolved "https://registry.yarnpkg.com/vue-server-renderer/-/vue-server-renderer-2.5.22.tgz#f119efef289c865adc22fda0ae7595299bedbdcf" - integrity sha512-PQ0PubA6b2MyZud/gepWeiUuDFSbRfa6h1qYINcbwXRr4Z3yLTHprEQuFnWikdkTkZpeLFYUqZrDxPbDcJ71mA== +vue-server-renderer@^2.6.11: + version "2.6.11" + resolved "https://registry.yarnpkg.com/vue-server-renderer/-/vue-server-renderer-2.6.11.tgz#be8c9abc6aacc309828a755c021a05fc474b4bc3" + integrity sha512-V3faFJHr2KYfdSIalL+JjinZSHYUhlrvJ9pzCIjjwSh77+pkrsXpK4PucdPcng57+N77pd1LrKqwbqjQdktU1A== dependencies: chalk "^1.1.3" hash-sum "^1.0.2" he "^1.1.0" - lodash.template "^4.4.0" + lodash.template "^4.5.0" lodash.uniq "^4.5.0" resolve "^1.2.0" - serialize-javascript "^1.3.0" + serialize-javascript "^2.1.2" source-map "0.5.6" vue-style-loader@^3.0.0: @@ -10127,10 +10132,10 @@ vue-template-compiler@^2.5.16: de-indent "^1.0.2" he "^1.1.0" -vue-template-compiler@^2.5.22: - version "2.5.22" - resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.5.22.tgz#c3d3c02c65f1908205c4fbd3b0ef579e51239955" - integrity sha512-1VTw/NPTUeHNiwhkq6NkFzO7gYLjFCueBN0FX8NEiQIemd5EUMQ5hxrF7O0zCPo5tae+U9S/scETPea+hIz8Eg== +vue-template-compiler@^2.6.11: + version "2.6.11" + resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.6.11.tgz#c04704ef8f498b153130018993e56309d4698080" + integrity sha512-KIq15bvQDrcCjpGjrAhx4mUlyyHfdmTaoNfeoATHLAiWB+MU3cx4lOzMwrnUh9cCxy0Lt1T11hAFY6TQgroUAA== dependencies: de-indent "^1.0.2" he "^1.1.0" @@ -10143,10 +10148,10 @@ vue@^2.5.16: version "2.5.16" resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.16.tgz#07edb75e8412aaeed871ebafa99f4672584a0085" -vue@^2.5.22: - version "2.5.22" - resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.22.tgz#3bf88041af08b8539c37b268b70ca79245e9cc30" - integrity sha512-pxY3ZHlXNJMFQbkjEgGVMaMMkSV1ONpz+4qB55kZuJzyJOhn6MSy/YZdzhdnumegNzVTL/Dn3Pp4UrVBYt1j/g== +vue@^2.6.11: + version "2.6.11" + resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.11.tgz#76594d877d4b12234406e84e35275c6d514125c5" + integrity sha512-VfPwgcGABbGAue9+sfrD4PuwFar7gPb1yl1UK1MwXoQPAw0BKSqWfoYCT/ThFrdEVWoI51dBuyCoiNU9bZDZxQ== vuepress-html-webpack-plugin@^3.2.0: version "3.2.0"