@@ -27,15 +27,17 @@ var capitalize = function (str) { return str.charAt(0).toUpperCase() + str.slice
2727var hyphenateRE = / \B ( [ A - Z ] ) / g;
2828var hyphenate = function ( str ) { return str . replace ( hyphenateRE , '-$1' ) . toLowerCase ( ) ; } ;
2929
30- if ( typeof window === 'undefined' ) {
31- throwError (
32- 'window is undefined, vue-test-utils needs to be run in a browser environment.\n' +
33- 'You can run the tests in node using jsdom + jsdom-global.\n' +
34- 'See https://vue-test-utils.vuejs.org/en/guides/common-tips.html for more details.'
35- ) ;
30+ function warnIfNoWindow ( ) {
31+ if ( typeof window === 'undefined' ) {
32+ throwError (
33+ 'window is undefined, vue-test-utils needs to be run in a browser environment.\n' +
34+ 'You can run the tests in node using jsdom + jsdom-global.\n' +
35+ 'See https://vue-test-utils.vuejs.org/en/guides/common-tips.html for more details.'
36+ ) ;
37+ }
3638}
3739
38- if ( ! Element . prototype . matches ) {
40+ if ( typeof Element !== 'undefined' && ! Element . prototype . matches ) {
3941 Element . prototype . matches =
4042 Element . prototype . matchesSelector ||
4143 Element . prototype . mozMatchesSelector ||
@@ -122,13 +124,11 @@ function componentNeedsCompiling (component) {
122124}
123125
124126function isRefSelector ( refOptionsObject ) {
125- if ( typeof refOptionsObject !== 'object' || ! Object . keys ( refOptionsObject || { } ) . length ) {
127+ if ( typeof refOptionsObject !== 'object' || Object . keys ( refOptionsObject || { } ) . length !== 1 ) {
126128 return false
127129 }
128130
129- return Object
130- . keys ( refOptionsObject )
131- . every ( function ( key ) { return [ 'ref' ] . includes ( key ) && typeof refOptionsObject [ key ] === 'string' ; } )
131+ return typeof refOptionsObject . ref === 'string'
132132}
133133
134134function isNameSelector ( nameOptionsObject ) {
@@ -1457,13 +1457,16 @@ function addSlotToVm (vm, slotName, slotValue) {
14571457 if ( ! vueTemplateCompiler . compileToFunctions ) {
14581458 throwError ( 'vueTemplateCompiler is undefined, you must pass components explicitly if vue-template-compiler is undefined' ) ;
14591459 }
1460+ if ( typeof window === 'undefined' ) {
1461+ throwError ( 'the slots string option does not support strings in server-test-uitls.' ) ;
1462+ }
14601463 if ( window . navigator . userAgent . match ( / P h a n t o m J S / i) ) {
1461- throwError ( 'option. slots does not support strings in PhantomJS. Please use Puppeteer, or pass a component' ) ;
1464+ throwError ( 'the slots option does not support strings in PhantomJS. Please use Puppeteer, or pass a component. ' ) ;
14621465 }
14631466 var domParser = new window . DOMParser ( ) ;
1464- var document = domParser . parseFromString ( slotValue , 'text/html' ) ;
1467+ var _document = domParser . parseFromString ( slotValue , 'text/html' ) ;
14651468 var _slotValue = slotValue . trim ( ) ;
1466- if ( _slotValue [ 0 ] === '<' && _slotValue [ _slotValue . length - 1 ] === '>' && document . body . childElementCount === 1 ) {
1469+ if ( _slotValue [ 0 ] === '<' && _slotValue [ _slotValue . length - 1 ] === '>' && _document . body . childElementCount === 1 ) {
14671470 elem = vm . $createElement ( vueTemplateCompiler . compileToFunctions ( slotValue ) ) ;
14681471 } else {
14691472 var compiledResult = vueTemplateCompiler . compileToFunctions ( ( "<div>" + slotValue + "{{ }}</div>" ) ) ;
@@ -1505,6 +1508,21 @@ function addSlots (vm, slots) {
15051508
15061509//
15071510
1511+ function addScopedSlots ( vm , scopedSlots ) {
1512+ Object . keys ( scopedSlots ) . forEach ( function ( key ) {
1513+ var template = scopedSlots [ key ] . trim ( ) ;
1514+ if ( template . substr ( 0 , 9 ) === '<template' ) {
1515+ throwError ( 'the scopedSlots option does not support a template tag as the root element.' ) ;
1516+ }
1517+ var domParser = new window . DOMParser ( ) ;
1518+ var _document = domParser . parseFromString ( template , 'text/html' ) ;
1519+ vm . $_vueTestUtils_scopedSlots [ key ] = vueTemplateCompiler . compileToFunctions ( template ) . render ;
1520+ vm . $_vueTestUtils_slotScopes [ key ] = _document . body . firstChild . getAttribute ( 'slot-scope' ) ;
1521+ } ) ;
1522+ }
1523+
1524+ //
1525+
15081526function addMocks ( mockedProperties , Vue$$1 ) {
15091527 Object . keys ( mockedProperties ) . forEach ( function ( key ) {
15101528 try {
@@ -1850,6 +1868,19 @@ function createFunctionalComponent (component, mountingOptions) {
18501868
18511869//
18521870
1871+ function isDestructuringSlotScope ( slotScope ) {
1872+ return slotScope [ 0 ] === '{' && slotScope [ slotScope . length - 1 ] === '}'
1873+ }
1874+
1875+ function getVueTemplateCompilerHelpers ( proxy ) {
1876+ var helpers = { } ;
1877+ var names = [ '_c' , '_o' , '_n' , '_s' , '_l' , '_t' , '_q' , '_i' , '_m' , '_f' , '_k' , '_b' , '_v' , '_e' , '_u' , '_g' ] ;
1878+ names . forEach ( function ( name ) {
1879+ helpers [ name ] = proxy [ name ] ;
1880+ } ) ;
1881+ return helpers
1882+ }
1883+
18531884function createInstance (
18541885 component ,
18551886 options ,
@@ -1892,6 +1923,41 @@ function createInstance (
18921923 addAttrs ( vm , options . attrs ) ;
18931924 addListeners ( vm , options . listeners ) ;
18941925
1926+ if ( options . scopedSlots ) {
1927+ if ( window . navigator . userAgent . match ( / P h a n t o m J S / i) ) {
1928+ throwError ( 'the scopedSlots option does not support PhantomJS. Please use Puppeteer, or pass a component.' ) ;
1929+ }
1930+ var vueVersion = Number ( ( ( Vue . version . split ( '.' ) [ 0 ] ) + "." + ( Vue . version . split ( '.' ) [ 1 ] ) ) ) ;
1931+ if ( vueVersion >= 2.5 ) {
1932+ vm . $_vueTestUtils_scopedSlots = { } ;
1933+ vm . $_vueTestUtils_slotScopes = { } ;
1934+ var renderSlot = vm . _renderProxy . _t ;
1935+
1936+ vm . _renderProxy . _t = function ( name , feedback , props , bindObject ) {
1937+ var scopedSlotFn = vm . $_vueTestUtils_scopedSlots [ name ] ;
1938+ var slotScope = vm . $_vueTestUtils_slotScopes [ name ] ;
1939+ if ( scopedSlotFn ) {
1940+ props = Object . assign ( { } , bindObject , props ) ;
1941+ var helpers = getVueTemplateCompilerHelpers ( vm . _renderProxy ) ;
1942+ var proxy = Object . assign ( { } , helpers ) ;
1943+ if ( isDestructuringSlotScope ( slotScope ) ) {
1944+ proxy = Object . assign ( { } , helpers , props ) ;
1945+ } else {
1946+ proxy [ slotScope ] = props ;
1947+ }
1948+ return scopedSlotFn . call ( proxy )
1949+ } else {
1950+ return renderSlot . call ( vm . _renderProxy , name , feedback , props , bindObject )
1951+ }
1952+ } ;
1953+
1954+ // $FlowIgnore
1955+ addScopedSlots ( vm , options . scopedSlots ) ;
1956+ } else {
1957+ throwError ( 'the scopedSlots option is only supported in vue@2.5+.' ) ;
1958+ }
1959+ }
1960+
18951961 if ( options . slots ) {
18961962 addSlots ( vm , options . slots ) ;
18971963 }
@@ -4502,14 +4568,14 @@ function createLocalVue () {
45024568
45034569//
45044570
4505- function getStubs ( optionStubs , config ) {
4506- if ( optionStubs ||
4507- ( config . stubs && Object . keys ( config . stubs ) . length > 0 ) ) {
4508- if ( Array . isArray ( optionStubs ) ) {
4509- return optionStubs . concat ( Object . keys ( config . stubs || { } ) )
4571+ function getOptions ( key , options , config ) {
4572+ if ( options ||
4573+ ( config [ key ] && Object . keys ( config [ key ] ) . length > 0 ) ) {
4574+ if ( Array . isArray ( options ) ) {
4575+ return options . concat ( Object . keys ( config [ key ] || { } ) )
45104576 } else {
4511- return Object . assign ( { } , config . stubs ,
4512- optionStubs )
4577+ return Object . assign ( { } , config [ key ] ,
4578+ options )
45134579 }
45144580 }
45154581}
@@ -4519,7 +4585,9 @@ function mergeOptions (
45194585 config
45204586) {
45214587 return Object . assign ( { } , options ,
4522- { stubs : getStubs ( options . stubs , config ) } )
4588+ { stubs : getOptions ( 'stubs' , options . stubs , config ) ,
4589+ mocks : getOptions ( 'mocks' , options . mocks , config ) ,
4590+ methods : getOptions ( 'methods' , options . methods , config ) } )
45234591}
45244592
45254593//
@@ -4668,7 +4736,9 @@ var config = {
46684736 stubs : {
46694737 transition : TransitionStub ,
46704738 'transition-group' : TransitionGroupStub
4671- }
4739+ } ,
4740+ mocks : { } ,
4741+ methods : { }
46724742}
46734743
46744744//
@@ -4680,6 +4750,7 @@ Vue.config.errorHandler = errorHandler;
46804750function mount ( component , options ) {
46814751 if ( options === void 0 ) options = { } ;
46824752
4753+ warnIfNoWindow ( ) ;
46834754 // Remove cached constructor
46844755 delete component . _Ctor ;
46854756 var vueClass = options . localVue || createLocalVue ( ) ;
0 commit comments