11// @flow
22
33import { compileToFunctions } from 'vue-template-compiler'
4+ import { throwError } from 'shared/util'
45import { validateSlots } from './validate-slots'
5- import { toArray } from 'shared/util'
66
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 ] !== '>' ) {
910 return false
1011 }
11- const _document = new window . DOMParser ( ) . parseFromString ( template , 'text/html' )
12+ const domParser = new window . DOMParser ( )
13+ const _document = domParser . parseFromString ( slotValue , 'text/html' )
1214 return _document . body . childElementCount === 1
1315}
1416
15- function createElementFromAdvancedString ( slotValue , vm ) {
17+ // see https://github.com/vuejs/vue-test-utils/pull/274
18+ function createVNodes ( vm : Component , slotValue : string ) {
1619 const compiledResult = compileToFunctions ( `<div>${ slotValue } {{ }}</div>` )
1720 const _staticRenderFns = vm . _renderProxy . $options . staticRenderFns
1821 vm . _renderProxy . $options . staticRenderFns = compiledResult . staticRenderFns
@@ -21,23 +24,54 @@ function createElementFromAdvancedString (slotValue, vm) {
2124 return elem
2225}
2326
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
2541 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 ) )
2945 } else {
30- return createElementFromAdvancedString ( slotValue , vm )
46+ elem = createVNodes ( vm , slotValue )
3147 }
3248 } 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+ }
3463 }
3564}
3665
3766export function addSlots ( vm : Component , slots : Object ) : void {
3867 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+ }
4276 } )
4377}
0 commit comments