@@ -2592,6 +2592,9 @@ function getCoreProperties (component) {
2592
2592
}
2593
2593
}
2594
2594
function createStubFromString ( templateString , originalComponent ) {
2595
+ if ( ! vueTemplateCompiler . compileToFunctions ) {
2596
+ throwError ( 'vueTemplateCompiler is undefined, you must pass components explicitly if vue-template-compiler is undefined' ) ;
2597
+ }
2595
2598
return Object . assign ( { } , getCoreProperties ( originalComponent ) ,
2596
2599
vueTemplateCompiler . compileToFunctions ( templateString ) )
2597
2600
}
@@ -2634,6 +2637,9 @@ function stubComponents (component, stubs) {
2634
2637
}
2635
2638
} else {
2636
2639
if ( typeof stubs [ stub ] === 'string' ) {
2640
+ if ( ! vueTemplateCompiler . compileToFunctions ) {
2641
+ throwError ( 'vueTemplateCompiler is undefined, you must pass components explicitly if vue-template-compiler is undefined' ) ;
2642
+ }
2637
2643
component . components [ stub ] = Object . assign ( { } , vueTemplateCompiler . compileToFunctions ( stubs [ stub ] ) ) ;
2638
2644
stubLifeCycleEvents ( component . components [ stub ] ) ;
2639
2645
} else {
@@ -2817,11 +2823,22 @@ WrapperArray.prototype.contains = function contains (selector) {
2817
2823
2818
2824
return this . wrappers . every ( function ( wrapper ) { return wrapper . contains ( selector ) ; } )
2819
2825
} ;
2820
-
2821
2826
WrapperArray . prototype . exists = function exists ( ) {
2822
2827
return this . wrappers . length > 0
2823
2828
} ;
2824
2829
2830
+ WrapperArray . prototype . emitted = function emitted ( ) {
2831
+ this . throwErrorIfWrappersIsEmpty ( 'emitted' ) ;
2832
+
2833
+ throwError ( 'emitted must be called on a single wrapper, use at(i) to access a wrapper' ) ;
2834
+ } ;
2835
+
2836
+ WrapperArray . prototype . emittedByOrder = function emittedByOrder ( ) {
2837
+ this . throwErrorIfWrappersIsEmpty ( 'emittedByOrder' ) ;
2838
+
2839
+ throwError ( 'emittedByOrder must be called on a single wrapper, use at(i) to access a wrapper' ) ;
2840
+ } ;
2841
+
2825
2842
WrapperArray . prototype . hasAttribute = function hasAttribute ( attribute , value ) {
2826
2843
this . throwErrorIfWrappersIsEmpty ( 'hasAttribute' ) ;
2827
2844
@@ -2943,6 +2960,14 @@ ErrorWrapper.prototype.contains = function contains () {
2943
2960
throwError ( ( "find did not return " + ( this . selector ) + ", cannot call contains() on empty Wrapper" ) ) ;
2944
2961
} ;
2945
2962
2963
+ ErrorWrapper . prototype . emitted = function emitted ( ) {
2964
+ throwError ( ( "find did not return " + ( this . selector ) + ", cannot call emitted() on empty Wrapper" ) ) ;
2965
+ } ;
2966
+
2967
+ ErrorWrapper . prototype . emittedByOrder = function emittedByOrder ( ) {
2968
+ throwError ( ( "find did not return " + ( this . selector ) + ", cannot call emittedByOrder() on empty Wrapper" ) ) ;
2969
+ } ;
2970
+
2946
2971
ErrorWrapper . prototype . exists = function exists ( ) {
2947
2972
return false
2948
2973
} ;
@@ -3048,6 +3073,26 @@ Wrapper.prototype.contains = function contains (selector) {
3048
3073
return false
3049
3074
} ;
3050
3075
3076
+ /**
3077
+ * Returns an object containing custom events emitted by the Wrapper vm
3078
+ */
3079
+ Wrapper . prototype . emitted = function emitted ( ) {
3080
+ if ( ! this . _emitted && ! this . vm ) {
3081
+ throwError ( 'wrapper.emitted() can only be called on a Vue instance' ) ;
3082
+ }
3083
+ return this . _emitted
3084
+ } ;
3085
+
3086
+ /**
3087
+ * Returns an Array containing custom events emitted by the Wrapper vm
3088
+ */
3089
+ Wrapper . prototype . emittedByOrder = function emittedByOrder ( ) {
3090
+ if ( ! this . _emittedByOrder && ! this . vm ) {
3091
+ throwError ( 'wrapper.emittedByOrder() can only be called on a Vue instance' ) ;
3092
+ }
3093
+ return this . _emittedByOrder
3094
+ } ;
3095
+
3051
3096
/**
3052
3097
* Utility to check wrapper exists. Returns true as Wrapper always exists
3053
3098
*/
@@ -3067,7 +3112,7 @@ Wrapper.prototype.hasAttribute = function hasAttribute (attribute, value) {
3067
3112
throwError ( 'wrapper.hasAttribute() must be passed value as a string' ) ;
3068
3113
}
3069
3114
3070
- return this . element && this . element . getAttribute ( attribute ) === value
3115
+ return ! ! ( this . element && this . element . getAttribute ( attribute ) === value )
3071
3116
} ;
3072
3117
3073
3118
/**
@@ -3078,7 +3123,7 @@ Wrapper.prototype.hasClass = function hasClass (className) {
3078
3123
throwError ( 'wrapper.hasClass() must be passed a string' ) ;
3079
3124
}
3080
3125
3081
- return this . element . className . split ( ' ' ) . indexOf ( className ) !== - 1
3126
+ return ! ! ( this . element && this . element . classList . contains ( className ) )
3082
3127
} ;
3083
3128
3084
3129
/**
@@ -3133,7 +3178,7 @@ Wrapper.prototype.hasStyle = function hasStyle (style, value) {
3133
3178
3134
3179
var elStyle = window . getComputedStyle ( this . element ) [ style ] ;
3135
3180
var mockNodeStyle = window . getComputedStyle ( mockNode ) [ style ] ;
3136
- return elStyle === mockNodeStyle
3181
+ return ! ! ( elStyle && mockNodeStyle && elStyle === mockNodeStyle )
3137
3182
} ;
3138
3183
3139
3184
/**
@@ -3219,7 +3264,10 @@ Wrapper.prototype.is = function is (selector) {
3219
3264
}
3220
3265
return vmCtorMatchesName ( this . vm , selector . name )
3221
3266
}
3222
- return this . element . getAttribute && this . element . matches ( selector )
3267
+
3268
+ return ! ! ( this . element &&
3269
+ this . element . getAttribute &&
3270
+ this . element . matches ( selector ) )
3223
3271
} ;
3224
3272
3225
3273
/**
@@ -3317,6 +3365,10 @@ Wrapper.prototype.setProps = function setProps (data) {
3317
3365
* Return text of wrapper element
3318
3366
*/
3319
3367
Wrapper . prototype . text = function text ( ) {
3368
+ if ( ! this . element ) {
3369
+ throwError ( 'cannot call wrapper.text() on a wrapper without an element' ) ;
3370
+ }
3371
+
3320
3372
return this . element . textContent
3321
3373
} ;
3322
3374
@@ -3330,6 +3382,10 @@ Wrapper.prototype.trigger = function trigger (type, options) {
3330
3382
throwError ( 'wrapper.trigger() must be passed a string' ) ;
3331
3383
}
3332
3384
3385
+ if ( ! this . element ) {
3386
+ throwError ( 'cannot call wrapper.trigger() on a wrapper without an element' ) ;
3387
+ }
3388
+
3333
3389
var modifiers = {
3334
3390
enter : 13 ,
3335
3391
tab : 9 ,
@@ -3367,6 +3423,18 @@ Wrapper.prototype.trigger = function trigger (type, options) {
3367
3423
this . update ( ) ;
3368
3424
} ;
3369
3425
3426
+ function logEvents ( vm , emitted , emittedByOrder ) {
3427
+ var emit = vm . $emit ;
3428
+ vm . $emit = function ( name ) {
3429
+ var args = [ ] , len = arguments . length - 1 ;
3430
+ while ( len -- > 0 ) args [ len ] = arguments [ len + 1 ] ;
3431
+
3432
+ ( emitted [ name ] || ( emitted [ name ] = [ ] ) ) . push ( args ) ;
3433
+ emittedByOrder . push ( { name : name , args : args } ) ;
3434
+ return emit . call . apply ( emit , [ vm , name ] . concat ( args ) )
3435
+ } ;
3436
+ }
3437
+
3370
3438
//
3371
3439
3372
3440
function update ( ) {
@@ -3385,6 +3453,10 @@ var VueWrapper = (function (Wrapper$$1) {
3385
3453
3386
3454
this . vm = vm ;
3387
3455
this . isVueComponent = true ;
3456
+ this . _emitted = Object . create ( null ) ;
3457
+ this . _emittedByOrder = [ ] ;
3458
+
3459
+ logEvents ( vm , this . _emitted , this . _emittedByOrder ) ;
3388
3460
}
3389
3461
3390
3462
if ( Wrapper$$1 ) VueWrapper . __proto__ = Wrapper$$1 ;
@@ -3403,12 +3475,18 @@ function isValidSlot (slot) {
3403
3475
function addSlotToVm ( vm , slotName , slotValue ) {
3404
3476
if ( Array . isArray ( vm . $slots [ slotName ] ) ) {
3405
3477
if ( typeof slotValue === 'string' ) {
3478
+ if ( ! vueTemplateCompiler . compileToFunctions ) {
3479
+ throwError ( 'vueTemplateCompiler is undefined, you must pass components explicitly if vue-template-compiler is undefined' ) ;
3480
+ }
3406
3481
vm . $slots [ slotName ] . push ( vm . $createElement ( vueTemplateCompiler . compileToFunctions ( slotValue ) ) ) ;
3407
3482
} else {
3408
3483
vm . $slots [ slotName ] . push ( vm . $createElement ( slotValue ) ) ;
3409
3484
}
3410
3485
} else {
3411
3486
if ( typeof slotValue === 'string' ) {
3487
+ if ( ! vueTemplateCompiler . compileToFunctions ) {
3488
+ throwError ( 'vueTemplateCompiler is undefined, you must pass components explicitly if vue-template-compiler is undefined' ) ;
3489
+ }
3412
3490
vm . $slots [ slotName ] = [ vm . $createElement ( vueTemplateCompiler . compileToFunctions ( slotValue ) ) ] ;
3413
3491
} else {
3414
3492
vm . $slots [ slotName ] = [ vm . $createElement ( slotValue ) ] ; // eslint-disable-line no-param-reassign
@@ -3434,14 +3512,30 @@ function addSlots (vm, slots) {
3434
3512
3435
3513
//
3436
3514
3437
- function createInterceptPlugin ( interceptedProperties ) {
3438
- return {
3439
- install : function ( Vue$$1 ) {
3440
- Object . keys ( interceptedProperties ) . forEach ( function ( key ) {
3441
- Vue$$1 . prototype [ key ] = interceptedProperties [ key ] ;
3442
- } ) ;
3443
- }
3515
+ function addMocks ( mockedProperties , Vue$$1 ) {
3516
+ Object . keys ( mockedProperties ) . forEach ( function ( key ) {
3517
+ Vue$$1 . prototype [ key ] = mockedProperties [ key ] ;
3518
+ } ) ;
3519
+ }
3520
+
3521
+ function addAttrs ( vm , attrs ) {
3522
+ Vue . config . silent = true ;
3523
+ if ( attrs ) {
3524
+ vm . $attrs = attrs ;
3525
+ } else {
3526
+ vm . $attrs = { } ;
3527
+ }
3528
+ Vue . config . silent = false ;
3529
+ }
3530
+
3531
+ function addListeners ( vm , listeners ) {
3532
+ Vue . config . silent = true ;
3533
+ if ( listeners ) {
3534
+ vm . $listeners = listeners ;
3535
+ } else {
3536
+ vm . $listeners = { } ;
3444
3537
}
3538
+ Vue . config . silent = false ;
3445
3539
}
3446
3540
3447
3541
function addProvide ( component , options ) {
@@ -3460,6 +3554,12 @@ function addProvide (component, options) {
3460
3554
3461
3555
//
3462
3556
3557
+ function compileTemplate ( component ) {
3558
+ Object . assign ( component , vueTemplateCompiler . compileToFunctions ( component . template ) ) ;
3559
+ }
3560
+
3561
+ //
3562
+
3463
3563
function createConstructor ( component , options ) {
3464
3564
var vue = options . localVue || Vue ;
3465
3565
@@ -3487,17 +3587,21 @@ function createConstructor (component, options) {
3487
3587
stubComponents ( component , options . stubs ) ;
3488
3588
}
3489
3589
3590
+ if ( ! component . render && component . template && ! component . functional ) {
3591
+ compileTemplate ( component ) ;
3592
+ }
3593
+
3490
3594
var Constructor = vue . extend ( component ) ;
3491
3595
3492
- if ( options . intercept ) {
3493
- // creates a plugin that adds properties, and then install on local Constructor
3494
- // this does not affect the base Vue class
3495
- var interceptPlugin = createInterceptPlugin ( options . intercept ) ;
3496
- Constructor . use ( interceptPlugin ) ;
3596
+ if ( options . mocks ) {
3597
+ addMocks ( options . mocks , Constructor ) ;
3497
3598
}
3498
3599
3499
3600
var vm = new Constructor ( options ) ;
3500
3601
3602
+ addAttrs ( vm , options . attrs ) ;
3603
+ addListeners ( vm , options . listeners ) ;
3604
+
3501
3605
if ( options . slots ) {
3502
3606
addSlots ( vm , options . slots ) ;
3503
3607
}
@@ -3541,7 +3645,11 @@ function mount (component, options) {
3541
3645
if ( options === void 0 ) options = { } ;
3542
3646
3543
3647
if ( ! window ) {
3544
- throwError ( 'window is undefined, vue-test-utils needs to be run in a browser environment.\n You can run the tests in node using JSDOM' ) ;
3648
+ throwError (
3649
+ 'window is undefined, vue-test-utils needs to be run in a browser environment.\n' +
3650
+ 'You can run the tests in node using jsdom + jsdom-global.\n' +
3651
+ 'See https://vue-test-utils.vuejs.org/en/guides/general-tips.html for more details.'
3652
+ ) ;
3545
3653
}
3546
3654
3547
3655
var componentToMount = options . clone === false ? component : cloneDeep_1 ( component ) ;
@@ -3580,15 +3688,35 @@ function shallow (component, options) {
3580
3688
3581
3689
function createLocalVue ( ) {
3582
3690
var instance = Vue . extend ( ) ;
3583
- instance . version = Vue . version ;
3584
- instance . _installedPlugins = [ ] ;
3691
+
3692
+ // clone global APIs
3693
+ Object . keys ( Vue ) . forEach ( function ( key ) {
3694
+ if ( ! instance . hasOwnProperty ( key ) ) {
3695
+ var original = Vue [ key ] ;
3696
+ instance [ key ] = typeof original === 'object'
3697
+ ? cloneDeep_1 ( original )
3698
+ : original ;
3699
+ }
3700
+ } ) ;
3701
+
3702
+ // config is not enumerable
3585
3703
instance . config = cloneDeep_1 ( Vue . config ) ;
3586
- instance . util = cloneDeep_1 ( Vue . util ) ;
3587
- instance . _use = instance . use ;
3704
+
3705
+ // option merge strategies need to be exposed by reference
3706
+ // so that merge strats registered by plguins can work properly
3707
+ instance . config . optionMergeStrategies = Vue . config . optionMergeStrategies ;
3708
+
3709
+ // make sure all extends are based on this instance.
3710
+ // this is important so that global components registered by plugins,
3711
+ // e.g. router-link are created using the correct base constructor
3712
+ instance . options . _base = instance ;
3713
+
3714
+ // compat for vue-router < 2.7.1 where it does not allow multiple installs
3715
+ var use = instance . use ;
3588
3716
instance . use = function ( plugin ) {
3589
3717
plugin . installed = false ;
3590
3718
plugin . install . installed = false ;
3591
- instance . _use ( plugin ) ;
3719
+ use . call ( instance , plugin ) ;
3592
3720
} ;
3593
3721
return instance
3594
3722
}
0 commit comments