Skip to content

Commit f510fd2

Browse files
authored
Fix class component find (#419)
1 parent 865c526 commit f510fd2

15 files changed

+181
-153
lines changed

src/lib/find-vue-components.js

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// @flow
22
import {
3-
COMPONENT_SELECTOR,
43
FUNCTIONAL_OPTIONS,
54
VUE_VERSION
65
} from './consts'
@@ -52,15 +51,20 @@ function findAllFunctionalComponentsFromVnode (
5251
}
5352

5453
export function vmCtorMatchesName (vm: Component, name: string): boolean {
55-
return (vm.$vnode && vm.$vnode.componentOptions &&
54+
return !!((vm.$vnode && vm.$vnode.componentOptions &&
5655
vm.$vnode.componentOptions.Ctor.options.name === name) ||
57-
(vm._vnode && vm._vnode.functionalOptions &&
58-
vm._vnode.functionalOptions.name === name) ||
59-
vm.$options && vm.$options.name === name
56+
(vm._vnode &&
57+
vm._vnode.functionalOptions &&
58+
vm._vnode.functionalOptions.name === name) ||
59+
vm.$options && vm.$options.name === name ||
60+
vm.options && vm.options.name === name)
6061
}
6162

6263
export function vmCtorMatchesSelector (component: Component, selector: Object) {
63-
const Ctor = selector._Ctor || selector.options && selector.options._Ctor
64+
const Ctor = selector._Ctor || (selector.options && selector.options._Ctor)
65+
if (!Ctor) {
66+
return false
67+
}
6468
const Ctors = Object.keys(Ctor)
6569
return Ctors.some(c => Ctor[c] === component.__proto__.constructor)
6670
}
@@ -95,15 +99,14 @@ export default function findVueComponents (
9599
node[FUNCTIONAL_OPTIONS].name === selector.name
96100
)
97101
}
102+
const nameSelector = typeof selector === 'function' ? selector.options.name : selector.name
98103
const components = root._isVue
99104
? findAllVueComponentsFromVm(root)
100105
: findAllVueComponentsFromVnode(root)
101106
return components.filter((component) => {
102107
if (!component.$vnode && !component.$options.extends) {
103108
return false
104109
}
105-
return selectorType === COMPONENT_SELECTOR
106-
? vmCtorMatchesSelector(component, selector)
107-
: vmCtorMatchesName(component, selector.name)
110+
return vmCtorMatchesSelector(component, selector) || vmCtorMatchesName(component, nameSelector)
108111
})
109112
}

test/resources/components/component-as-a-class.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<div />
2+
<div><slot /></div>
33
</template>
44

55
<script>

test/resources/test-utils.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,11 @@ export function itSkipIf (predicate, spec, cb) {
4646
it(spec, cb)
4747
}
4848
}
49+
50+
export function itDoNotRunIf (predicate, spec, cb) {
51+
if (predicate) {
52+
() => {}
53+
} else {
54+
it(spec, cb)
55+
}
56+
}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { compileToFunctions } from 'vue-template-compiler'
2-
import { mount } from '~vue-test-utils'
2+
import { describeWithShallowAndMount } from '~resources/test-utils'
33

4-
describe('mount.attachToDocument', () => {
4+
describeWithShallowAndMount('options.attachToDocument', (mountingMethod) => {
55
it('returns VueWrapper with attachedToDocument set to true when passed attachToDocument in options', () => {
66
const compiled = compileToFunctions('<div><input /></div>')
7-
const wrapper = mount(compiled, { attachToDocument: true })
7+
const wrapper = mountingMethod(compiled, { attachToDocument: true })
88
expect(wrapper.options.attachedToDocument).to.equal(true)
99
})
1010
})
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { compileToFunctions } from 'vue-template-compiler'
2-
import { mount } from '~vue-test-utils'
32
import { attrsSupported } from '~resources/test-utils'
3+
import { describeWithShallowAndMount } from '~resources/test-utils'
44

5-
describe('mount.attrs', () => {
5+
describeWithShallowAndMount('options.attrs', (mountingMethod) => {
66
it('handles inherit attrs', () => {
77
if (!attrsSupported()) return
8-
const wrapper = mount(compileToFunctions('<p :id="anAttr" />'), {
8+
const wrapper = mountingMethod(compileToFunctions('<p :id="anAttr" />'), {
99
attrs: {
1010
anAttr: 'an attribute'
1111
}
@@ -16,7 +16,7 @@ describe('mount.attrs', () => {
1616
})
1717

1818
it('defines attrs as empty object even when not passed', () => {
19-
const wrapper = mount(compileToFunctions('<p />'))
19+
const wrapper = mountingMethod(compileToFunctions('<p />'))
2020
expect(wrapper.vm.$attrs).to.deep.equal({})
2121
})
2222
})

test/specs/mounting-options/context.spec.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import Vue from 'vue'
2-
import { mount } from '~vue-test-utils'
32
import { vueVersion } from '~resources/test-utils'
3+
import { describeWithShallowAndMount } from '~resources/test-utils'
44

5-
describe('context', () => {
5+
describeWithShallowAndMount('options.context', (mountingMethod) => {
66
it('mounts functional component when passed context object', () => {
77
if (vueVersion <= 2.2) {
88
console.log('WARN: no current way to test functional component is component in v2.1.x')
@@ -21,7 +21,7 @@ describe('context', () => {
2121
props: { show: true }
2222
}
2323

24-
const wrapper = mount(Component, { context })
24+
const wrapper = mountingMethod(Component, { context })
2525
expect(wrapper.is(Component)).to.equal(true)
2626
})
2727

@@ -31,7 +31,7 @@ describe('context', () => {
3131
}
3232
const context = {}
3333
const message = '[vue-test-utils]: mount.context can only be used when mounting a functional component'
34-
const fn = () => mount(Component, { context })
34+
const fn = () => mountingMethod(Component, { context })
3535
expect(fn).to.throw().with.property('message', message)
3636
})
3737

@@ -41,7 +41,7 @@ describe('context', () => {
4141
render: h => h('div')
4242
})
4343
const context = {}
44-
const fn = () => mount(Component, { context })
44+
const fn = () => mountingMethod(Component, { context })
4545
expect(fn).not.to.throw()
4646
})
4747

@@ -52,7 +52,7 @@ describe('context', () => {
5252
}
5353
const context = 'string'
5454
const message = '[vue-test-utils]: mount.context must be an object'
55-
const fn = () => mount(Component, { context })
55+
const fn = () => mountingMethod(Component, { context })
5656
expect(fn).to.throw().with.property('message', message)
5757
})
5858

@@ -68,7 +68,7 @@ describe('context', () => {
6868
},
6969
render: (h, { props }) => h('div', props.testProp)
7070
}
71-
const wrapper = mount(Component)
71+
const wrapper = mountingMethod(Component)
7272
expect(wrapper.element.textContent).to.equal(defaultValue)
7373
})
7474

@@ -79,7 +79,7 @@ describe('context', () => {
7979
return h('div', children)
8080
}
8181
}
82-
const wrapper = mount(Component, {
82+
const wrapper = mountingMethod(Component, {
8383
context: {
8484
children: ['render text']
8585
}
@@ -94,7 +94,7 @@ describe('context', () => {
9494
return h('div', children)
9595
}
9696
}
97-
const wrapper = mount(Component, {
97+
const wrapper = mountingMethod(Component, {
9898
context: {
9999
children: [h => h('div', 'render component')]
100100
}
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { compileToFunctions } from 'vue-template-compiler'
2-
import { mount } from '~vue-test-utils'
32
import { listenersSupported } from '~resources/test-utils'
3+
import { describeWithShallowAndMount } from '~resources/test-utils'
44

5-
describe('mount.listeners', () => {
5+
describeWithShallowAndMount('options.listeners', (mountingMethod) => {
66
it('handles inherit listeners', () => {
77
if (!listenersSupported()) return
88
const aListener = () => {}
9-
const wrapper = mount(compileToFunctions('<p :id="aListener" />'), {
9+
const wrapper = mountingMethod(compileToFunctions('<p :id="aListener" />'), {
1010
listeners: {
1111
aListener
1212
}
@@ -18,7 +18,7 @@ describe('mount.listeners', () => {
1818
})
1919

2020
it('defines listeners as empty object even when not passed', () => {
21-
const wrapper = mount(compileToFunctions('<p />'))
21+
const wrapper = mountingMethod(compileToFunctions('<p />'))
2222
expect(wrapper.vm.$listeners).to.deep.equal({})
2323
})
2424
})
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
import Vue from 'vue'
2-
import { mount } from '~vue-test-utils'
32
import Component from '~resources/components/component.vue'
3+
import { describeWithShallowAndMount } from '~resources/test-utils'
44

5-
describe('mount.localVue', () => {
5+
describeWithShallowAndMount('options.localVue', (mountingMethod) => {
66
it('mounts component using passed localVue as base Vue', () => {
77
const localVue = Vue.extend()
88
localVue.version = '2.3'
9-
const wrapper = mount(Component, { localVue: localVue, mocks: { test: true }})
9+
const wrapper = mountingMethod(Component, { localVue: localVue, mocks: { test: true }})
1010
expect(wrapper.vm.test).to.equal(true)
11-
const freshWrapper = mount(Component)
11+
const freshWrapper = mountingMethod(Component)
1212
expect(typeof freshWrapper.vm.test).to.equal('undefined')
1313
})
1414
})
15-

test/specs/mounting-options/mocks.spec.js

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1-
import { mount } from '~vue-test-utils'
21
import { createLocalVue } from '~vue-test-utils'
32
import Component from '~resources/components/component.vue'
43
import ComponentWithVuex from '~resources/components/component-with-vuex.vue'
4+
import {
5+
describeWithShallowAndMount,
6+
itDoNotRunIf
7+
} from '~resources/test-utils'
58

6-
describe('mount.mocks', () => {
9+
describeWithShallowAndMount('options.mocks', (mountingMethod) => {
710
it('adds variables to vm when passed as mocks object', () => {
811
const $store = { store: true }
912
const $route = { path: 'http://test.com' }
10-
const wrapper = mount(Component, {
13+
const wrapper = mountingMethod(Component, {
1114
mocks: {
1215
$store,
1316
$route
@@ -20,7 +23,7 @@ describe('mount.mocks', () => {
2023
it('adds variables to vm when passed as mocks object', () => {
2124
const stub = sinon.stub()
2225
const $reactiveMock = { value: 'value' }
23-
const wrapper = mount({
26+
const wrapper = mountingMethod({
2427
template: `
2528
<div>
2629
{{value}}
@@ -45,23 +48,25 @@ describe('mount.mocks', () => {
4548
expect(wrapper.text()).to.contain('changed value')
4649
})
4750

48-
it('adds variables available to nested vms', () => {
49-
const count = 1
50-
const wrapper = mount({
51-
template: '<div><component-with-vuex /></div>',
52-
components: {
53-
ComponentWithVuex
54-
}
55-
}, {
56-
mocks: { $store: { state: { count, foo: {}}}}
51+
itDoNotRunIf(mountingMethod.name === 'shallow',
52+
'adds variables available to nested vms', () => {
53+
const count = 1
54+
const wrapper = mountingMethod({
55+
template: '<div><component-with-vuex /></div>',
56+
components: {
57+
ComponentWithVuex
58+
}
59+
}, {
60+
mocks: { $store: { state: { count, foo: {}}}}
61+
})
62+
expect(wrapper.text()).contains(count)
5763
})
58-
expect(wrapper.text()).contains(count)
59-
})
6064

61-
it('adds variables available to nested vms using localVue', () => {
65+
itDoNotRunIf(mountingMethod.name === 'shallow',
66+
'adds variables available to nested vms using localVue', () => {
6267
const localVue = createLocalVue()
6368
const count = 1
64-
const wrapper = mount({
69+
const wrapper = mountingMethod({
6570
template: '<div><component-with-vuex /></div>',
6671
components: {
6772
ComponentWithVuex
@@ -75,13 +80,13 @@ describe('mount.mocks', () => {
7580

7681
it('does not affect global vue class when passed as mocks object', () => {
7782
const $store = { store: true }
78-
const wrapper = mount(Component, {
83+
const wrapper = mountingMethod(Component, {
7984
mocks: {
8085
$store
8186
}
8287
})
8388
expect(wrapper.vm.$store).to.equal($store)
84-
const freshWrapper = mount(Component)
89+
const freshWrapper = mountingMethod(Component)
8590
expect(typeof freshWrapper.vm.$store).to.equal('undefined')
8691
})
8792

@@ -92,7 +97,7 @@ describe('mount.mocks', () => {
9297
value: 42
9398
})
9499
const $store = 64
95-
mount(Component, {
100+
mountingMethod(Component, {
96101
localVue,
97102
mocks: {
98103
$store
@@ -110,7 +115,7 @@ describe('mount.mocks', () => {
110115
value: 42
111116
})
112117
const $val = 64
113-
mount(Component, {
118+
mountingMethod(Component, {
114119
localVue,
115120
mocks: {
116121
$val

test/specs/mounting-options/provide.spec.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { mount } from '~vue-test-utils'
22
import ComponentWithInject from '~resources/components/component-with-inject.vue'
33
import { injectSupported } from '~resources/test-utils'
4+
import { describeWithShallowAndMount } from '~resources/test-utils'
45

5-
describe('mount.provide', () => {
6+
describeWithShallowAndMount('options.provide', (mountingMethod) => {
67
it('provides objects which is injected by mounted component', () => {
78
if (!injectSupported()) return
89

@@ -16,7 +17,7 @@ describe('mount.provide', () => {
1617
it('provides function which is injected by mounted component', () => {
1718
if (!injectSupported()) return
1819

19-
const wrapper = mount(ComponentWithInject, {
20+
const wrapper = mountingMethod(ComponentWithInject, {
2021
provide () {
2122
return {
2223
fromMount: 'functionValue'
@@ -30,7 +31,7 @@ describe('mount.provide', () => {
3031
it('supports beforeCreate in component', () => {
3132
if (!injectSupported()) return
3233

33-
const wrapper = mount(ComponentWithInject, {
34+
const wrapper = mountingMethod(ComponentWithInject, {
3435
provide: { fromMount: '_' }
3536
})
3637

0 commit comments

Comments
 (0)