diff --git a/src/lib/consts.js b/src/lib/consts.js index b2d4f7bb6..f72395951 100644 --- a/src/lib/consts.js +++ b/src/lib/consts.js @@ -1,4 +1,8 @@ +import Vue from 'vue' + export const NAME_SELECTOR = 'NAME_SELECTOR' export const COMPONENT_SELECTOR = 'COMPONENT_SELECTOR' export const REF_SELECTOR = 'REF_SELECTOR' export const DOM_SELECTOR = 'DOM_SELECTOR' +export const VUE_VERSION = Number(`${Vue.version.split('.')[0]}.${Vue.version.split('.')[1]}`) +export const FUNCTIONAL_OPTIONS = VUE_VERSION >= 2.5 ? 'fnOptions' : 'functionalOptions' diff --git a/src/lib/find-vue-components.js b/src/lib/find-vue-components.js index 2bac6f055..4d76edac5 100644 --- a/src/lib/find-vue-components.js +++ b/src/lib/find-vue-components.js @@ -1,7 +1,12 @@ // @flow import { - COMPONENT_SELECTOR + COMPONENT_SELECTOR, + FUNCTIONAL_OPTIONS, + VUE_VERSION } from './consts' +import { + throwError +} from './util' function findAllVueComponentsFromVm ( vm: Component, @@ -35,7 +40,7 @@ function findAllFunctionalComponentsFromVnode ( vnode: Component, components: Array = [] ): Array { - if (vnode.fnOptions) { + if (vnode[FUNCTIONAL_OPTIONS] || vnode.functionalContext) { components.push(vnode) } if (vnode.children) { @@ -61,11 +66,15 @@ export function vmCtorMatchesSelector (component: Component, selector: Object) { } export function vmFunctionalCtorMatchesSelector (component: VNode, Ctor: Object) { - if (!component.fnOptions) { + if (VUE_VERSION < 2.3) { + throwError('find for functional components is not support in Vue < 2.3') + } + + if (!component[FUNCTIONAL_OPTIONS]) { return false } - const Ctors = Object.keys(component.fnOptions._Ctor) - return Ctors.some(c => Ctor[c] === component.fnOptions._Ctor[c]) + const Ctors = Object.keys(component[FUNCTIONAL_OPTIONS]._Ctor) + return Ctors.some(c => Ctor[c] === component[FUNCTIONAL_OPTIONS]._Ctor[c]) } export default function findVueComponents ( @@ -74,10 +83,10 @@ export default function findVueComponents ( selector: Object ): Array { if (selector.functional) { - const components = root._vnode + const nodes = root._vnode ? findAllFunctionalComponentsFromVnode(root._vnode) : findAllFunctionalComponentsFromVnode(root) - return components.filter(component => vmFunctionalCtorMatchesSelector(component, selector._Ctor)) + return nodes.filter(node => vmFunctionalCtorMatchesSelector(node, selector._Ctor)) } const components = root._isVue ? findAllVueComponentsFromVm(root) diff --git a/test/unit/specs/mount/Wrapper/find.spec.js b/test/unit/specs/mount/Wrapper/find.spec.js index 0c4e06df3..e7cf10e53 100644 --- a/test/unit/specs/mount/Wrapper/find.spec.js +++ b/test/unit/specs/mount/Wrapper/find.spec.js @@ -8,7 +8,7 @@ import ComponentWithVFor from '~resources/components/component-with-v-for.vue' import Component from '~resources/components/component.vue' import FunctionalComponent from '~resources/components/functional-component.vue' import ComponentAsAClass from '~resources/components/component-as-a-class.vue' -import { functionalSFCsSupported } from '~resources/test-utils' +import { functionalSFCsSupported, vueVersion } from '~resources/test-utils' describe('find', () => { it('returns a Wrapper matching tag selector passed', () => { @@ -141,6 +141,28 @@ describe('find', () => { expect(wrapper.find(FunctionalComponent).vm).to.equal(undefined) }) + it('returns Wrapper of Vue Component matching functional component with name', () => { + const TestFunctionalComponent = { + render: h => h('div'), + functional: true, + name: 'test-functional-component' + } + const TestComponent = { + template: '
', + components: { + TestFunctionalComponent + } + } + const wrapper = mount(TestComponent) + if (vueVersion < 2.3) { + const message = '[vue-test-utils]: find for functional components is not support in Vue < 2.3' + const fn = () => wrapper.find(TestFunctionalComponent) + expect(fn).to.throw().with.property('message', message) + } else { + expect(wrapper.find(TestFunctionalComponent).exists()).to.equal(true) + } + }) + it('returns correct number of Vue Wrappers when component has a v-for', () => { const items = [{ id: 1 }, { id: 2 }, { id: 3 }] const wrapper = mount(ComponentWithVFor, { propsData: { items }})