forked from vuejs/vue-test-utils
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpatch-render.js
126 lines (103 loc) · 3.62 KB
/
patch-render.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import { createStubFromComponent } from './create-component-stubs'
import { resolveComponent } from 'shared/util'
import { isReservedTag } from 'shared/validators'
import {
BEFORE_RENDER_LIFECYCLE_HOOK,
CREATE_ELEMENT_ALIAS
} from 'shared/consts'
const isWhitelisted = (el, whitelist) => resolveComponent(el, whitelist)
const isAlreadyStubbed = (el, stubs) => stubs.has(el)
const isDynamicComponent = cmp => typeof cmp === 'function' && !cmp.cid
function shouldExtend (component, _Vue) {
return (
(typeof component === 'function' && !isDynamicComponent(component)) ||
(component && component.extends)
)
}
function extend (component, _Vue) {
const stub = _Vue.extend(component.options)
stub.options.$_vueTestUtils_original = component
return stub
}
function createStubIfNeeded (shouldStub, component, _Vue, el) {
if (shouldStub) {
return createStubFromComponent(component || {}, el)
}
if (shouldExtend(component, _Vue)) {
return extend(component, _Vue)
}
}
function shouldNotBeStubbed (el, whitelist, modifiedComponents) {
return (
(typeof el === 'string' && isReservedTag(el)) ||
isWhitelisted(el, whitelist) ||
isAlreadyStubbed(el, modifiedComponents)
)
}
function isConstructor (el) {
return typeof el === 'function'
}
function isComponentOptions (el) {
return typeof el === 'object' && (el.template || el.render)
}
export function patchRender (_Vue, stubs, stubAllComponents) {
// This mixin patches vm.$createElement so that we can stub all components
// before they are rendered in shallow mode. We also need to ensure that
// component constructors were created from the _Vue constructor. If not,
// we must replace them with components created from the _Vue constructor
// before calling the original $createElement. This ensures that components
// have the correct instance properties and stubs when they are rendered.
function patchRenderMixin () {
const vm = this
if (
vm.$options.$_doNotStubChildren ||
vm.$options._isFunctionalContainer
) {
return
}
const modifiedComponents = new Set()
const originalCreateElement = vm.$createElement
const originalComponents = vm.$options.components
const createElement = (el, ...args) => {
if (shouldNotBeStubbed(el, stubs, modifiedComponents)) {
return originalCreateElement(el, ...args)
}
if (isConstructor(el) || isComponentOptions(el)) {
if (stubAllComponents) {
const stub = createStubFromComponent(el, el.name || 'anonymous')
return originalCreateElement(stub, ...args)
}
const Constructor = shouldExtend(el, _Vue) ? extend(el, _Vue) : el
return originalCreateElement(Constructor, ...args)
}
if (typeof el === 'string') {
let original = resolveComponent(el, originalComponents)
if (!original) {
return originalCreateElement(el, ...args)
}
if (
original.options &&
original.options.$_vueTestUtils_original
) {
original = original.options.$_vueTestUtils_original
}
if (isDynamicComponent(original)) {
return originalCreateElement(el, ...args)
}
const stub = createStubIfNeeded(stubAllComponents, original, _Vue, el)
if (stub) {
Object.assign(vm.$options.components, {
[el]: stub
})
modifiedComponents.add(el)
}
}
return originalCreateElement(el, ...args)
}
vm[CREATE_ELEMENT_ALIAS] = createElement
vm.$createElement = createElement
}
_Vue.mixin({
[BEFORE_RENDER_LIFECYCLE_HOOK]: patchRenderMixin
})
}