1
1
// @flow
2
2
3
3
import { compileToFunctions } from 'vue-template-compiler'
4
+ import { throwError } from 'shared/util'
4
5
import { validateSlots } from './validate-slots'
5
- import { toArray } from 'shared/util'
6
6
7
- function isSingleHTMLTag ( template : string ) {
8
- if ( ! template . startsWith ( '<' ) || ! template . endsWith ( '>' ) ) {
7
+ function isSingleElement ( slotValue : string ) : boolean {
8
+ const _slotValue = slotValue . trim ( )
9
+ if ( _slotValue [ 0 ] !== '<' || _slotValue [ _slotValue . length - 1 ] !== '>' ) {
9
10
return false
10
11
}
11
- const _document = new window . DOMParser ( ) . parseFromString ( template , 'text/html' )
12
+ const domParser = new window . DOMParser ( )
13
+ const _document = domParser . parseFromString ( slotValue , 'text/html' )
12
14
return _document . body . childElementCount === 1
13
15
}
14
16
15
- function createElementFromAdvancedString ( slotValue , vm ) {
17
+ // see https://github.com/vuejs/vue-test-utils/pull/274
18
+ function createVNodes ( vm : Component , slotValue : string ) {
16
19
const compiledResult = compileToFunctions ( `<div>${ slotValue } {{ }}</div>` )
17
20
const _staticRenderFns = vm . _renderProxy . $options . staticRenderFns
18
21
vm . _renderProxy . $options . staticRenderFns = compiledResult . staticRenderFns
@@ -21,23 +24,54 @@ function createElementFromAdvancedString (slotValue, vm) {
21
24
return elem
22
25
}
23
26
24
- function createElement ( slotValue : string | Object , vm ) {
27
+ function validateEnvironment ( ) : void {
28
+ if ( ! compileToFunctions ) {
29
+ throwError ( 'vueTemplateCompiler is undefined, you must pass components explicitly if vue-template-compiler is undefined' )
30
+ }
31
+ if ( typeof window === 'undefined' ) {
32
+ throwError ( 'the slots string option does not support strings in server-test-uitls.' )
33
+ }
34
+ if ( window . navigator . userAgent . match ( / P h a n t o m J S / i) ) {
35
+ throwError ( 'the slots option does not support strings in PhantomJS. Please use Puppeteer, or pass a component.' )
36
+ }
37
+ }
38
+
39
+ function addSlotToVm ( vm : Component , slotName : string , slotValue : SlotValue ) : void {
40
+ let elem
25
41
if ( typeof slotValue === 'string' ) {
26
- slotValue = slotValue . trim ( )
27
- if ( isSingleHTMLTag ( slotValue ) ) {
28
- return vm . $createElement ( compileToFunctions ( slotValue ) )
42
+ validateEnvironment ( )
43
+ if ( isSingleElement ( slotValue ) ) {
44
+ elem = vm . $createElement ( compileToFunctions ( slotValue ) )
29
45
} else {
30
- return createElementFromAdvancedString ( slotValue , vm )
46
+ elem = createVNodes ( vm , slotValue )
31
47
}
32
48
} else {
33
- return vm . $createElement ( slotValue )
49
+ elem = vm . $createElement ( slotValue )
50
+ }
51
+ if ( Array . isArray ( elem ) ) {
52
+ if ( Array . isArray ( vm . $slots [ slotName ] ) ) {
53
+ vm . $slots [ slotName ] = [ ...vm . $slots [ slotName ] , ...elem ]
54
+ } else {
55
+ vm . $slots [ slotName ] = [ ...elem ]
56
+ }
57
+ } else {
58
+ if ( Array . isArray ( vm . $slots [ slotName ] ) ) {
59
+ vm . $slots [ slotName ] . push ( elem )
60
+ } else {
61
+ vm . $slots [ slotName ] = [ elem ]
62
+ }
34
63
}
35
64
}
36
65
37
66
export function addSlots ( vm : Component , slots : Object ) : void {
38
67
validateSlots ( slots )
39
- Object . keys ( slots ) . forEach ( name => {
40
- vm . $slots [ name ] = toArray ( slots [ name ] )
41
- . map ( slotValue => createElement ( slotValue , vm ) )
68
+ Object . keys ( slots ) . forEach ( ( key ) => {
69
+ if ( Array . isArray ( slots [ key ] ) ) {
70
+ slots [ key ] . forEach ( ( slotValue ) => {
71
+ addSlotToVm ( vm , key , slotValue )
72
+ } )
73
+ } else {
74
+ addSlotToVm ( vm , key , slots [ key ] )
75
+ }
42
76
} )
43
77
}
0 commit comments