-
Notifications
You must be signed in to change notification settings - Fork 668
/
Copy pathadd-scoped-slots.js
92 lines (86 loc) · 2.35 KB
/
add-scoped-slots.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
// @flow
import { compileToFunctions } from 'vue-template-compiler'
import { throwError, vueVersion } from 'shared/util'
function isDestructuringSlotScope (slotScope: string): boolean {
return slotScope[0] === '{' && slotScope[slotScope.length - 1] === '}'
}
function getVueTemplateCompilerHelpers (proxy: Object): Object {
const helpers = {}
const names = [
'_c',
'_o',
'_n',
'_s',
'_l',
'_t',
'_q',
'_i',
'_m',
'_f',
'_k',
'_b',
'_v',
'_e',
'_u',
'_g'
]
names.forEach(name => {
helpers[name] = proxy[name]
})
return helpers
}
export function addScopedSlots (
vm: Component,
scopedSlots: { [name: string]: string }
): void {
if (window.navigator.userAgent.match(/PhantomJS/i)) {
throwError(
`the scopedSlots option does not support PhantomJS. ` +
`Please use Puppeteer, or pass a component.`
)
}
if (vueVersion < 2.5) {
throwError(`the scopedSlots option is only supported in ` + `[email protected]+.`)
}
vm.$_vueTestUtils_scopedSlots = {}
vm.$_vueTestUtils_slotScopes = {}
const renderSlot = vm._renderProxy._t
vm._renderProxy._t = function (name, feedback, props, bindObject) {
const scopedSlotFn = vm.$_vueTestUtils_scopedSlots[name]
const slotScope = vm.$_vueTestUtils_slotScopes[name]
if (scopedSlotFn) {
props = { ...bindObject, ...props }
const helpers = getVueTemplateCompilerHelpers(vm._renderProxy)
let proxy = { ...helpers }
if (isDestructuringSlotScope(slotScope)) {
proxy = { ...helpers, ...props }
} else {
proxy[slotScope] = props
}
return scopedSlotFn.call(proxy)
} else {
return renderSlot.call(
vm._renderProxy,
name,
feedback,
props,
bindObject
)
}
}
Object.keys(scopedSlots).forEach(key => {
const template = scopedSlots[key].trim()
if (template.substr(0, 9) === '<template') {
throwError(
`the scopedSlots option does not support a template ` +
`tag as the root element.`
)
}
const domParser = new window.DOMParser()
const _document = domParser.parseFromString(template, 'text/html')
vm.$_vueTestUtils_scopedSlots[key] = compileToFunctions(template).render
vm.$_vueTestUtils_slotScopes[key] = _document.body.firstChild.getAttribute(
'slot-scope'
)
})
}