@@ -257,13 +257,17 @@ describe('component: proxy', () => {
257
257
expect ( instanceProxy . isDisplayed ) . toBe ( true )
258
258
} )
259
259
260
- test ( 'allow spying on proxy methods' , ( ) => {
260
+
261
+ test ( 'allow jest spying on proxy methods with Object.defineProperty' , ( ) => {
262
+ // #5417
261
263
let instanceProxy : any
262
264
const Comp = {
263
265
render ( ) { } ,
264
266
setup ( ) {
265
267
return {
266
- toggle ( ) { }
268
+ toggle ( ) {
269
+ return 'a'
270
+ }
267
271
}
268
272
} ,
269
273
mounted ( ) {
@@ -275,13 +279,154 @@ describe('component: proxy', () => {
275
279
276
280
app . mount ( nodeOps . createElement ( 'div' ) )
277
281
278
- const spy = jest . spyOn ( instanceProxy , 'toggle' )
282
+ // access 'toggle' to ensure key is cached
283
+ const v1 = instanceProxy . toggle ( )
284
+ expect ( v1 ) . toEqual ( 'a' )
285
+
286
+ // reconfigure "toggle" to be getter based.
287
+ let getCalledTimes = 0
288
+ Object . defineProperty ( instanceProxy , 'toggle' , {
289
+ get ( ) {
290
+ getCalledTimes ++
291
+ return ( ) => 'b'
292
+ }
293
+ } )
279
294
295
+ // getter should not be evaluated on initial definition
296
+ expect ( getCalledTimes ) . toEqual ( 0 )
297
+
298
+ // invoke "toggle" after "defineProperty"
299
+ const v2 = instanceProxy . toggle ( )
300
+ expect ( v2 ) . toEqual ( 'b' )
301
+ expect ( getCalledTimes ) . toEqual ( 1 )
302
+
303
+ // expect toggle getter not to be cached. it can't be
280
304
instanceProxy . toggle ( )
305
+ expect ( getCalledTimes ) . toEqual ( 2 )
281
306
307
+ // attaching jest spy, triggers the getter once, cache it and override the property.
308
+ // also uses Object.defineProperty
309
+ const spy = jest . spyOn ( instanceProxy , 'toggle' )
310
+ expect ( getCalledTimes ) . toEqual ( 3 )
311
+
312
+ // expect getter to not evaluate the jest spy caches its value
313
+ const v3 = instanceProxy . toggle ( )
314
+ expect ( v3 ) . toEqual ( 'b' )
282
315
expect ( spy ) . toHaveBeenCalled ( )
316
+ expect ( getCalledTimes ) . toEqual ( 3 )
317
+ } )
318
+
319
+ test ( 'defineProperty on proxy property with value descriptor' , ( ) => {
320
+ // #5417
321
+ let instanceProxy : any
322
+ const Comp = {
323
+ render ( ) { } ,
324
+ setup ( ) {
325
+ return {
326
+ toggle : 'a'
327
+ }
328
+ } ,
329
+ mounted ( ) {
330
+ instanceProxy = this
331
+ }
332
+ }
333
+
334
+ const app = createApp ( Comp )
335
+
336
+ app . mount ( nodeOps . createElement ( 'div' ) )
337
+
338
+ const v1 = instanceProxy . toggle
339
+ expect ( v1 ) . toEqual ( 'a' )
340
+
341
+ Object . defineProperty ( instanceProxy , 'toggle' , {
342
+ value : 'b'
343
+ } )
344
+ const v2 = instanceProxy . toggle
345
+ expect ( v2 ) . toEqual ( 'b' )
346
+
347
+ // expect null to be a settable value
348
+ Object . defineProperty ( instanceProxy , 'toggle' , {
349
+ value : null
350
+ } )
351
+ const v3 = instanceProxy . toggle
352
+ expect ( v3 ) . toBeNull ( )
353
+ } )
354
+
355
+ test ( 'defineProperty on public instance proxy should work with SETUP,DATA,CONTEXT,PROPS' , ( ) => {
356
+ // #5417
357
+ let instanceProxy : any
358
+ const Comp = {
359
+ props : [ 'fromProp' ] ,
360
+ data ( ) {
361
+ return { name : 'data.name' }
362
+ } ,
363
+ computed : {
364
+ greet ( ) {
365
+ return 'Hi ' + ( this as any ) . name
366
+ }
367
+ } ,
368
+ render ( ) { } ,
369
+ setup ( ) {
370
+ return {
371
+ fromSetup : true
372
+ }
373
+ } ,
374
+ mounted ( ) {
375
+ instanceProxy = this
376
+ }
377
+ }
378
+
379
+ const app = createApp ( Comp , {
380
+ fromProp : true
381
+ } )
382
+
383
+ app . mount ( nodeOps . createElement ( 'div' ) )
384
+ expect ( instanceProxy . greet ) . toEqual ( 'Hi data.name' )
385
+
386
+ // define property on data
387
+ Object . defineProperty ( instanceProxy , 'name' , {
388
+ get ( ) {
389
+ return 'getter.name'
390
+ }
391
+ } )
392
+
393
+ // computed is same still cached
394
+ expect ( instanceProxy . greet ) . toEqual ( 'Hi data.name' )
395
+
396
+ // trigger computed
397
+ instanceProxy . name = ''
398
+
399
+ // expect "greet" to evaluated and use name from context getter
400
+ expect ( instanceProxy . greet ) . toEqual ( 'Hi getter.name' )
401
+
402
+ // defineProperty on computed ( context )
403
+ Object . defineProperty ( instanceProxy , 'greet' , {
404
+ get ( ) {
405
+ return 'Hi greet.getter.computed'
406
+ }
407
+ } )
408
+ expect ( instanceProxy . greet ) . toEqual ( 'Hi greet.getter.computed' )
409
+
410
+ // defineProperty on setupState
411
+ expect ( instanceProxy . fromSetup ) . toBe ( true )
412
+ Object . defineProperty ( instanceProxy , 'fromSetup' , {
413
+ get ( ) {
414
+ return false
415
+ }
416
+ } )
417
+ expect ( instanceProxy . fromSetup ) . toBe ( false )
418
+
419
+ // defineProperty on Props
420
+ expect ( instanceProxy . fromProp ) . toBe ( true )
421
+ Object . defineProperty ( instanceProxy , 'fromProp' , {
422
+ get ( ) {
423
+ return false
424
+ }
425
+ } )
426
+ expect ( instanceProxy . fromProp ) . toBe ( false )
283
427
} )
284
428
429
+
285
430
// #864
286
431
test ( 'should not warn declared but absent props' , ( ) => {
287
432
const Comp = {
0 commit comments