@@ -56,29 +56,46 @@ function validateSlots (slots) {
56
56
57
57
//
58
58
59
+ function isSingleElement ( slotValue ) {
60
+ var _slotValue = slotValue . trim ( ) ;
61
+ if ( _slotValue [ 0 ] !== '<' || _slotValue [ _slotValue . length - 1 ] !== '>' ) {
62
+ return false
63
+ }
64
+ var domParser = new window . DOMParser ( ) ;
65
+ var _document = domParser . parseFromString ( slotValue , 'text/html' ) ;
66
+ return _document . body . childElementCount === 1
67
+ }
68
+
69
+ // see https://github.com/vuejs/vue-test-utils/pull/274
70
+ function createVNodes ( vm , slotValue ) {
71
+ var compiledResult = vueTemplateCompiler . compileToFunctions ( ( "<div>" + slotValue + "{{ }}</div>" ) ) ;
72
+ var _staticRenderFns = vm . _renderProxy . $options . staticRenderFns ;
73
+ vm . _renderProxy . $options . staticRenderFns = compiledResult . staticRenderFns ;
74
+ var elem = compiledResult . render . call ( vm . _renderProxy , vm . $createElement ) . children ;
75
+ vm . _renderProxy . $options . staticRenderFns = _staticRenderFns ;
76
+ return elem
77
+ }
78
+
79
+ function validateEnvironment ( ) {
80
+ if ( ! vueTemplateCompiler . compileToFunctions ) {
81
+ throwError ( 'vueTemplateCompiler is undefined, you must pass components explicitly if vue-template-compiler is undefined' ) ;
82
+ }
83
+ if ( typeof window === 'undefined' ) {
84
+ throwError ( 'the slots string option does not support strings in server-test-uitls.' ) ;
85
+ }
86
+ if ( window . navigator . userAgent . match ( / P h a n t o m J S / i) ) {
87
+ throwError ( 'the slots option does not support strings in PhantomJS. Please use Puppeteer, or pass a component.' ) ;
88
+ }
89
+ }
90
+
59
91
function addSlotToVm ( vm , slotName , slotValue ) {
60
92
var elem ;
61
93
if ( typeof slotValue === 'string' ) {
62
- if ( ! vueTemplateCompiler . compileToFunctions ) {
63
- throwError ( 'vueTemplateCompiler is undefined, you must pass components explicitly if vue-template-compiler is undefined' ) ;
64
- }
65
- if ( typeof window === 'undefined' ) {
66
- throwError ( 'the slots string option does not support strings in server-test-uitls.' ) ;
67
- }
68
- if ( window . navigator . userAgent . match ( / P h a n t o m J S / i) ) {
69
- throwError ( 'the slots option does not support strings in PhantomJS. Please use Puppeteer, or pass a component.' ) ;
70
- }
71
- var domParser = new window . DOMParser ( ) ;
72
- var _document = domParser . parseFromString ( slotValue , 'text/html' ) ;
73
- var _slotValue = slotValue . trim ( ) ;
74
- if ( _slotValue [ 0 ] === '<' && _slotValue [ _slotValue . length - 1 ] === '>' && _document . body . childElementCount === 1 ) {
94
+ validateEnvironment ( ) ;
95
+ if ( isSingleElement ( slotValue ) ) {
75
96
elem = vm . $createElement ( vueTemplateCompiler . compileToFunctions ( slotValue ) ) ;
76
97
} else {
77
- var compiledResult = vueTemplateCompiler . compileToFunctions ( ( "<div>" + slotValue + "{{ }}</div>" ) ) ;
78
- var _staticRenderFns = vm . _renderProxy . $options . staticRenderFns ;
79
- vm . _renderProxy . $options . staticRenderFns = compiledResult . staticRenderFns ;
80
- elem = compiledResult . render . call ( vm . _renderProxy , vm . $createElement ) . children ;
81
- vm . _renderProxy . $options . staticRenderFns = _staticRenderFns ;
98
+ elem = createVNodes ( vm , slotValue ) ;
82
99
}
83
100
} else {
84
101
elem = vm . $createElement ( slotValue ) ;
@@ -217,9 +234,15 @@ function compileTemplate (component) {
217
234
}
218
235
} ) ;
219
236
}
237
+
220
238
if ( component . extends ) {
221
239
compileTemplate ( component . extends ) ;
222
240
}
241
+
242
+ if ( component . extendOptions && ! component . options . render ) {
243
+ compileTemplate ( component . options ) ;
244
+ }
245
+
223
246
if ( component . template ) {
224
247
Object . assign ( component , vueTemplateCompiler . compileToFunctions ( component . template ) ) ;
225
248
}
@@ -339,25 +362,6 @@ function createComponentStubs (originalComponents, stubs) {
339
362
return components
340
363
}
341
364
342
- //
343
-
344
- function compileTemplate$1 ( component ) {
345
- if ( component . components ) {
346
- Object . keys ( component . components ) . forEach ( function ( c ) {
347
- var cmp = component . components [ c ] ;
348
- if ( ! cmp . render ) {
349
- compileTemplate$1 ( cmp ) ;
350
- }
351
- } ) ;
352
- }
353
- if ( component . extends ) {
354
- compileTemplate$1 ( component . extends ) ;
355
- }
356
- if ( component . template ) {
357
- Object . assign ( component , vueTemplateCompiler . compileToFunctions ( component . template ) ) ;
358
- }
359
- }
360
-
361
365
function deleteMountingOptions ( options ) {
362
366
delete options . attachToDocument ;
363
367
delete options . mocks ;
@@ -459,7 +463,7 @@ function createInstance (
459
463
}
460
464
461
465
if ( componentNeedsCompiling ( component ) ) {
462
- compileTemplate$1 ( component ) ;
466
+ compileTemplate ( component ) ;
463
467
}
464
468
465
469
addEventLogger ( vue ) ;
@@ -468,12 +472,29 @@ function createInstance (
468
472
469
473
var instanceOptions = Object . assign ( { } , options ) ;
470
474
deleteMountingOptions ( instanceOptions ) ;
475
+ // $FlowIgnore
476
+ var stubComponents = createComponentStubs ( component . components , options . stubs ) ;
477
+
471
478
if ( options . stubs ) {
472
479
instanceOptions . components = Object . assign ( { } , instanceOptions . components ,
473
480
// $FlowIgnore
474
- createComponentStubs ( component . components , options . stubs ) ) ;
481
+ stubComponents ) ;
475
482
}
476
483
484
+ Object . keys ( component . components || { } ) . forEach ( function ( c ) {
485
+ if ( component . components [ c ] . extendOptions &&
486
+ ! instanceOptions . components [ c ] ) {
487
+ if ( options . logModifiedComponents ) {
488
+ warn ( ( "an extended child component " + c + " has been modified to ensure it has the correct instance properties. This means it is not possible to find the component with a component selector. To find the component, you must stub it manually using the mocks mounting option." ) ) ;
489
+ }
490
+ instanceOptions . components [ c ] = vue . extend ( component . components [ c ] ) ;
491
+ }
492
+ } ) ;
493
+
494
+ Object . keys ( stubComponents ) . forEach ( function ( c ) {
495
+ vue . component ( c , stubComponents [ c ] ) ;
496
+ } ) ;
497
+
477
498
var vm = new Constructor ( instanceOptions ) ;
478
499
479
500
addAttrs ( vm , options . attrs ) ;
@@ -526,11 +547,15 @@ function createInstance (
526
547
function getOptions ( key , options , config ) {
527
548
if ( options ||
528
549
( config [ key ] && Object . keys ( config [ key ] ) . length > 0 ) ) {
529
- if ( Array . isArray ( options ) ) {
550
+ if ( options instanceof Function ) {
551
+ return options
552
+ } else if ( Array . isArray ( options ) ) {
530
553
return options . concat ( Object . keys ( config [ key ] || { } ) )
531
- } else {
554
+ } else if ( ! ( config [ key ] instanceof Function ) ) {
532
555
return Object . assign ( { } , config [ key ] ,
533
556
options )
557
+ } else {
558
+ throw new Error ( "Config can't be a Function." )
534
559
}
535
560
}
536
561
}
@@ -540,9 +565,11 @@ function mergeOptions (
540
565
config
541
566
) {
542
567
return Object . assign ( { } , options ,
543
- { stubs : getOptions ( 'stubs' , options . stubs , config ) ,
568
+ { logModifiedComponents : config . logModifiedComponents ,
569
+ stubs : getOptions ( 'stubs' , options . stubs , config ) ,
544
570
mocks : getOptions ( 'mocks' , options . mocks , config ) ,
545
- methods : getOptions ( 'methods' , options . methods , config ) } )
571
+ methods : getOptions ( 'methods' , options . methods , config ) ,
572
+ provide : getOptions ( 'provide' , options . provide , config ) } )
546
573
}
547
574
548
575
var config = testUtils . config
0 commit comments