Skip to content

Commit b73c4d1

Browse files
committed
feat(plugins): Add createStubs plugin hook
1 parent 77994a0 commit b73c4d1

File tree

3 files changed

+118
-6
lines changed

3 files changed

+118
-6
lines changed

src/config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { GlobalMountOptions } from './types'
22
import { VueWrapper } from './vueWrapper'
33
import { DOMWrapper } from './domWrapper'
4+
import { CustomCreateStub } from './stubs'
45

56
export interface GlobalConfigOptions {
67
global: Required<GlobalMountOptions>
78
plugins: {
89
VueWrapper: Pluggable<VueWrapper>
910
DOMWrapper: Pluggable<DOMWrapper<Node>>
11+
createStubs?: CustomCreateStub
1012
}
1113
renderStubDefaultSlot: boolean
1214
}

src/stubs.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ import {
2020
getComponentName,
2121
getComponentRegisteredName
2222
} from './utils/componentName'
23+
import { config } from './config'
24+
25+
export type CustomCreateStub = (params: {
26+
name: string
27+
component: ConcreteComponent
28+
}) => ConcreteComponent
2329

2430
interface StubOptions {
2531
name: string
@@ -259,11 +265,16 @@ export function stubComponents(
259265
}
260266

261267
const newStub = createStubOnce(type, () =>
262-
createStub({
263-
name: stubName,
264-
type,
265-
renderStubDefaultSlot
266-
})
268+
config.plugins.createStubs
269+
? config.plugins.createStubs({
270+
name: stubName,
271+
component: type
272+
})
273+
: createStub({
274+
name: stubName,
275+
type,
276+
renderStubDefaultSlot
277+
})
267278
)
268279
registerStub({ source: type, stub: newStub })
269280
return [newStub, props, children, patchFlag, dynamicProps]

tests/features/plugins.spec.ts

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ComponentPublicInstance } from 'vue'
1+
import { ComponentPublicInstance, h } from 'vue'
22

33
import { mount, config, VueWrapper } from '../../src'
44

@@ -92,3 +92,102 @@ describe('Plugin#install', () => {
9292
)
9393
})
9494
})
95+
96+
describe('createStubs', () => {
97+
const Child1 = {
98+
name: 'child1',
99+
render: () => h('div', 'real child 1')
100+
}
101+
const Child2 = {
102+
name: 'child2',
103+
render: () => h('div', 'real child 2')
104+
}
105+
106+
const Parent = {
107+
render: () => h('div', [
108+
h(Child1),
109+
h(Child1),
110+
h(Child2)
111+
])
112+
}
113+
114+
const customCreateStub = jest.fn(({ name }) => h(`${name}-custom-stub`))
115+
beforeAll(() => {
116+
config.plugins.createStubs = customCreateStub
117+
})
118+
119+
afterAll(() => {
120+
config.plugins.createStubs = undefined
121+
})
122+
123+
beforeEach(() => {
124+
customCreateStub.mockClear()
125+
})
126+
127+
it('should be called for every stub once', () => {
128+
const wrapper = mount(Parent, {
129+
shallow: true
130+
})
131+
132+
expect(wrapper.html()).toBe('<div>\n' +
133+
' <child1-custom-stub></child1-custom-stub>\n' +
134+
' <child1-custom-stub></child1-custom-stub>\n' +
135+
' <child2-custom-stub></child2-custom-stub>\n' +
136+
'</div>')
137+
138+
expect(customCreateStub).toHaveBeenCalledTimes(2)
139+
expect(customCreateStub).toHaveBeenCalledWith({ name: 'child1', component: Child1 })
140+
expect(customCreateStub).toHaveBeenCalledWith({ name: 'child2', component: Child2 })
141+
})
142+
143+
it('should be called only for stubbed components', () => {
144+
const wrapper = mount(Parent, {
145+
global: {
146+
stubs: {
147+
child2: true
148+
}
149+
}
150+
})
151+
152+
expect(wrapper.html()).toBe('<div>\n' +
153+
' <div>real child 1</div>\n' +
154+
' <div>real child 1</div>\n' +
155+
' <child2-custom-stub></child2-custom-stub>\n' +
156+
'</div>')
157+
158+
expect(customCreateStub).toHaveBeenCalledTimes(1)
159+
expect(customCreateStub).toHaveBeenCalledWith({ name: 'child2', component: Child2 })
160+
})
161+
162+
it('should not be called for no stubs', () => {
163+
const wrapper = mount(Parent)
164+
165+
expect(wrapper.html()).toBe('<div>\n' +
166+
' <div>real child 1</div>\n' +
167+
' <div>real child 1</div>\n' +
168+
' <div>real child 2</div>\n' +
169+
'</div>')
170+
171+
expect(customCreateStub).not.toHaveBeenCalled()
172+
})
173+
174+
it('should not be called for manual stubs', () => {
175+
const wrapper = mount(Parent, {
176+
shallow: true,
177+
global: {
178+
stubs: {
179+
child2: () => h('div', 'Child 2 stub')
180+
}
181+
}
182+
})
183+
184+
expect(wrapper.html()).toBe('<div>\n' +
185+
' <child1-custom-stub></child1-custom-stub>\n' +
186+
' <child1-custom-stub></child1-custom-stub>\n' +
187+
' <div>Child 2 stub</div>\n' +
188+
'</div>')
189+
190+
expect(customCreateStub).toHaveBeenCalledTimes(1)
191+
expect(customCreateStub).toHaveBeenCalledWith({ name: 'child1', component: Child1 })
192+
})
193+
})

0 commit comments

Comments
 (0)