Skip to content

Commit 2f8e0b1

Browse files
committed
fix: stub extended component children in shallow
1 parent 756913a commit 2f8e0b1

File tree

4 files changed

+114
-14
lines changed

4 files changed

+114
-14
lines changed

src/lib/stub-components.js

+31-12
Original file line numberDiff line numberDiff line change
@@ -112,25 +112,44 @@ export function createComponentStubs (originalComponents: Object = {}, stubs: Ob
112112
return components
113113
}
114114

115-
export function createComponentStubsForAll (component: Component): Object {
116-
const components = {}
117-
if (!component.components) {
118-
return components
119-
}
120-
Object.keys(component.components).forEach(c => {
115+
function stubComponents (components: Object, stubbedComponents: Object) {
116+
Object.keys(components).forEach(component => {
121117
// Remove cached constructor
122-
delete component.components[c]._Ctor
123-
if (!component.components[c].name) {
124-
component.components[c].name = c
118+
delete components[component]._Ctor
119+
if (!components[component].name) {
120+
components[component].name = component
125121
}
126-
components[c] = createBlankStub(component.components[c])
122+
stubbedComponents[component] = createBlankStub(components[component])
127123

128124
// ignoreElements does not exist in Vue 2.0.x
129125
if (Vue.config.ignoredElements) {
130-
Vue.config.ignoredElements.push(c)
126+
Vue.config.ignoredElements.push(component)
131127
}
132128
})
133-
return components
129+
}
130+
131+
export function createComponentStubsForAll (component: Component): Object {
132+
const stubbedComponents = {}
133+
134+
if (component.components) {
135+
stubComponents(component.components, stubbedComponents)
136+
}
137+
138+
let extended = component.extends
139+
140+
// Loop through extended component chains to stub all child components
141+
while (extended) {
142+
if (extended.components) {
143+
stubComponents(extended.components, stubbedComponents)
144+
}
145+
extended = extended.extends
146+
}
147+
148+
if (component.extendOptions && component.extendOptions.components) {
149+
stubComponents(component.extendOptions.components, stubbedComponents)
150+
}
151+
152+
return stubbedComponents
134153
}
135154

136155
export function createComponentStubsForGlobals (instance: Component): Object {

src/shallow.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ export default function shallow (
2929

3030
const stubbedComponents = createComponentStubsForAll(component)
3131
const stubbedGlobalComponents = createComponentStubsForGlobals(vue)
32+
3233
return mount(component, {
3334
...options,
3435
components: {
3536
// stubbed components are used instead of original components components
3637
...stubbedGlobalComponents,
37-
...stubbedComponents,
38-
...options
38+
...stubbedComponents
3939
}
4040
})
4141
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<template>
2+
<div>
3+
<a-component />
4+
</div>
5+
</template>
6+
7+
<script>
8+
import Vue from 'vue'
9+
import Component from 'vue-class-component'
10+
import AComponent from './component.vue'
11+
12+
@Component({
13+
components: {
14+
AComponent
15+
}
16+
})
17+
export default class CogPage extends Vue {}
18+
</script>

test/unit/specs/shallow.spec.js

+63
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import ComponentWithChild from '~resources/components/component-with-child.vue'
66
import ComponentWithNestedChildren from '~resources/components/component-with-nested-children.vue'
77
import ComponentWithLifecycleHooks from '~resources/components/component-with-lifecycle-hooks.vue'
88
import ComponentWithoutName from '~resources/components/component-without-name.vue'
9+
import ComponentAsAClassWithChild from '~resources/components/component-as-a-class-with-child.vue'
910
import RecursiveComponent from '~resources/components/recursive-component.vue'
11+
import { vueVersion } from '~resources/test-utils'
1012

1113
describe('shallow', () => {
1214
let info
@@ -75,6 +77,67 @@ describe('shallow', () => {
7577
expect(info.called).to.equal(false)
7678
})
7779

80+
it('stubs extended components', () => {
81+
const ComponentWithPTag = {
82+
template: `<p></p>`
83+
}
84+
const BaseComponent = {
85+
template: `
86+
<div>
87+
<component-with-p-tag />
88+
</div>
89+
`,
90+
components: {
91+
ComponentWithPTag
92+
}
93+
}
94+
95+
const TestComponent = {
96+
extends: BaseComponent
97+
}
98+
99+
const wrapper = shallow(TestComponent)
100+
expect(wrapper.find(ComponentWithPTag).exists()).to.equal(true)
101+
expect(wrapper.find('p').exists()).to.equal(false)
102+
})
103+
104+
it('stubs nested extended components', () => {
105+
const ComponentWithPTag = {
106+
template: `<p></p>`
107+
}
108+
const BaseComponent = {
109+
template: `
110+
<div>
111+
<component-with-p-tag />
112+
</div>
113+
`,
114+
components: {
115+
ComponentWithPTag
116+
}
117+
}
118+
119+
const ExtendedBaseComponent = {
120+
extends: BaseComponent
121+
}
122+
123+
const TestComponent = {
124+
extends: ExtendedBaseComponent
125+
}
126+
127+
const wrapper = shallow(TestComponent)
128+
expect(wrapper.find(ComponentWithPTag).exists()).to.equal(true)
129+
expect(wrapper.find('p').exists()).to.equal(false)
130+
})
131+
132+
it('stubs Vue class component children', () => {
133+
if(vueVersion < 2.3) {
134+
return
135+
}
136+
const wrapper = shallow(ComponentAsAClassWithChild)
137+
expect(wrapper.find(Component).exists()).to.equal(true)
138+
expect(wrapper.findAll('div').length).to.equal(1)
139+
})
140+
78141
it('works correctly with find, contains, findAll, and is on unnamed components', () => {
79142
const TestComponent = {
80143
template: `

0 commit comments

Comments
 (0)