@@ -296,33 +296,117 @@ describe('Plotly.react transitions:', function() {
296
296
} ) ;
297
297
}
298
298
299
- function assertSpies ( msg , exps ) {
299
+ /**
300
+ * assertSpies
301
+ *
302
+ * @param {string } _msg : base message string
303
+ * @param {array of arrays } _exps : expectations
304
+ *
305
+ * assertSpies('test', [
306
+ * [<spied-on {object}>, <method name {string}>, `value`].
307
+ * [<spied-on {object}>, <method name {string}>, <args {array}>].
308
+ * ....
309
+ * [<spied-on {object}>, <method name {string}>, <0 or 1 {number}>]
310
+ * ]);
311
+ *
312
+ * - expectations items must be placed in the order in which they are invoked
313
+ * - to test that a certain spy didn't get called use `0` as value
314
+ * - to test that a certain spy did get called w/o checking its args use `1` as value
315
+ */
316
+ function assertSpies ( _msg , _exps ) {
317
+ var msg = function ( i , exp , extra ) {
318
+ return [ _msg , 'Item #' + i , '@method ' + exp [ 1 ] , ( extra || '' ) ] . join ( ' | ' ) ;
319
+ } ;
320
+
321
+ // check `_exps` structure and if "did (not) get called"
322
+ var failEarly = false ;
323
+ _exps . forEach ( function ( exp , i ) {
324
+ var spy = exp [ 0 ] ;
325
+ var methodName = exp [ 1 ] ;
326
+ var val = exp [ 2 ] ;
327
+ var calls = spy [ methodName ] . calls ;
328
+ var didGetCalled = calls . count ( ) > 0 ;
329
+ var expectingACall ;
330
+
331
+ if ( Array . isArray ( val ) ) {
332
+ expectingACall = true ;
333
+ } else if ( val === 0 || val === 1 ) {
334
+ expectingACall = Boolean ( val ) ;
335
+ } else {
336
+ fail ( _msg + '- Wrong arguments for assertSpies' ) ;
337
+ }
338
+
339
+ expect ( didGetCalled ) . toBe ( expectingACall , msg ( i , exp , 'did (not) get called' ) ) ;
340
+ failEarly = didGetCalled !== expectingACall ;
341
+ } ) ;
342
+
343
+ if ( failEarly ) {
344
+ return fail ( _msg + '- Wrong calls, assertSpies early fail' ) ;
345
+ }
346
+
347
+ // filter out `exps` items with `value=0`
348
+ var exps = _exps . filter ( function ( exp ) {
349
+ var val = exp [ 2 ] ;
350
+ return val !== 0 ;
351
+ } ) ;
352
+
353
+ // find list of spies to assert (N.B. dedupe using `invocationOrder`)
354
+ var actuals = [ ] ;
355
+ var seen = { } ;
300
356
exps . forEach ( function ( exp ) {
301
- var calls = exp [ 0 ] [ exp [ 1 ] ] . calls ;
302
- var cnt = calls . count ( ) ;
303
-
304
- if ( Array . isArray ( exp [ 2 ] ) ) {
305
- expect ( cnt ) . toBe ( exp [ 2 ] . length , msg ) ;
306
-
307
- var allArgs = calls . allArgs ( ) ;
308
- allArgs . forEach ( function ( args , i ) {
309
- args . forEach ( function ( a , j ) {
310
- var e = exp [ 2 ] [ i ] [ j ] ;
311
- if ( Lib . isPlainObject ( a ) || Array . isArray ( a ) ) {
312
- expect ( a ) . toEqual ( e , msg ) ;
313
- } else if ( typeof a === 'function' ) {
314
- expect ( 'function' ) . toBe ( e , msg ) ;
315
- } else {
316
- expect ( a ) . toBe ( e , msg ) ;
317
- }
318
- } ) ;
357
+ var spy = exp [ 0 ] ;
358
+ var methodName = exp [ 1 ] ;
359
+ var calls = spy [ methodName ] . calls ;
360
+ if ( calls . count ( ) ) {
361
+ calls . all ( ) . forEach ( function ( c ) {
362
+ var k = c . invocationOrder ;
363
+ if ( ! seen [ k ] ) {
364
+ actuals . push ( [ spy , methodName , c . args , k ] ) ;
365
+ seen [ k ] = 1 ;
366
+ }
319
367
} ) ;
320
- } else if ( typeof exp [ 2 ] === 'number' ) {
321
- expect ( cnt ) . toBe ( exp [ 2 ] , msg ) ;
322
- } else {
323
- fail ( 'wrong arguments for assertSpies' ) ;
324
368
}
325
369
} ) ;
370
+ actuals . sort ( function ( a , b ) { return a [ 3 ] - b [ 3 ] ; } ) ;
371
+
372
+ // sanity check
373
+ if ( actuals . length !== exps . length ) {
374
+ return fail ( _msg + '- Something went wrong when building "actual" callData list' ) ;
375
+ }
376
+
377
+ for ( var i = 0 ; i < exps . length ; i ++ ) {
378
+ var exp = exps [ i ] ;
379
+ var actual = actuals [ i ] ;
380
+ var val = exp [ 2 ] ;
381
+ var args = actual [ 2 ] ;
382
+
383
+ if ( actual [ 0 ] !== exp [ 0 ] || actual [ 1 ] !== exp [ 1 ] ) {
384
+ fail ( _msg + '- Item #' + i + ' with method "' + exp [ 1 ] + '" is out-of-order' ) ;
385
+ continue ;
386
+ }
387
+
388
+ if ( Array . isArray ( val ) ) {
389
+ // assert function arguments
390
+ expect ( args . length ) . toBe ( val . length , msg ( i , exp , '# of args' ) ) ;
391
+
392
+ for ( var j = 0 ; j < args . length ; j ++ ) {
393
+ var arg = args [ j ] ;
394
+ var e = val [ j ] ;
395
+ var msgj = msg ( i , exp , 'arg #' + j ) ;
396
+
397
+ if ( Lib . isPlainObject ( arg ) ) {
398
+ expect ( arg ) . withContext ( msgj + ' (obj check)' ) . toEqual ( e ) ;
399
+ } else if ( Array . isArray ( arg ) ) {
400
+ expect ( arg ) . withContext ( msgj + ' (arr check)' ) . toEqual ( e ) ;
401
+ } else if ( typeof arg === 'function' ) {
402
+ expect ( 'function' ) . toBe ( e , msgj + ' (fn check)' ) ;
403
+ } else {
404
+ expect ( arg ) . toBe ( e , msgj ) ;
405
+ }
406
+ }
407
+ }
408
+ }
409
+
326
410
resetSpyCounters ( ) ;
327
411
}
328
412
@@ -362,7 +446,7 @@ describe('Plotly.react transitions:', function() {
362
446
} )
363
447
. then ( function ( ) {
364
448
assertSpies ( 'with *transition* set and changes' , [
365
- [ Plots , 'transitionFromReact' , 1 ] ,
449
+ [ Plots , 'transitionFromReact' , 1 ]
366
450
] ) ;
367
451
} )
368
452
. catch ( failTest )
@@ -547,7 +631,7 @@ describe('Plotly.react transitions:', function() {
547
631
. then ( function ( ) {
548
632
assertSpies ( 'redraw required' , [
549
633
[ Plots , 'transitionFromReact' , 1 ] ,
550
- [ Registry , 'call' , [ [ 'redraw' , gd ] ] ]
634
+ [ Registry , 'call' , [ 'redraw' , gd ] ]
551
635
] ) ;
552
636
} )
553
637
. catch ( failTest )
@@ -588,7 +672,7 @@ describe('Plotly.react transitions:', function() {
588
672
[ Plots , 'transitionFromReact' , 1 ] ,
589
673
[ gd . _fullLayout . _basePlotModules [ 0 ] , 'transitionAxes' , 1 ] ,
590
674
// one _module.plot call from the relayout at end of axis transition
591
- [ Registry , 'call' , [ [ 'relayout' , gd , { 'xaxis.range' : [ - 2 , 2 ] } ] ] ] ,
675
+ [ Registry , 'call' , [ 'relayout' , gd , { 'xaxis.range' : [ - 2 , 2 ] } ] ] ,
592
676
[ gd . _fullLayout . _basePlotModules [ 0 ] , 'plot' , 1 ] ,
593
677
] ) ;
594
678
} )
@@ -597,18 +681,16 @@ describe('Plotly.react transitions:', function() {
597
681
layout . xaxis . range = [ - 1 , 1 ] ;
598
682
return Plotly . react ( gd , data , layout ) ;
599
683
} )
684
+ . then ( delay ( 20 ) )
600
685
. then ( function ( ) {
601
686
assertSpies ( 'both trace and layout transitions' , [
602
687
[ Plots , 'transitionFromReact' , 1 ] ,
603
688
[ gd . _fullLayout . _basePlotModules [ 0 ] , 'transitionAxes' , 1 ] ,
604
- [ Registry , 'call' , [ [ 'relayout' , gd , { 'xaxis.range' : [ - 1 , 1 ] } ] ] ] ,
605
- [ gd . _fullLayout . _basePlotModules [ 0 ] , 'plot' , [
606
- // one instantaneous transition options to halt
607
- // other trace transitions (if any)
608
- [ gd , null , { duration : 0 , easing : 'cubic-in-out' , ordering : 'layout first' } , 'function' ] ,
609
- // one _module.plot call from the relayout at end of axis transition
610
- [ gd ]
611
- ] ] ,
689
+ // one instantaneous transition options to halt other trace transitions (if any)
690
+ [ gd . _fullLayout . _basePlotModules [ 0 ] , 'plot' , [ gd , null , { duration : 0 , easing : 'cubic-in-out' , ordering : 'layout first' } , 'function' ] ] ,
691
+ // one _module.plot call from the relayout at end of axis transition
692
+ [ Registry , 'call' , [ 'relayout' , gd , { 'xaxis.range' : [ - 1 , 1 ] } ] ] ,
693
+ [ gd . _fullLayout . _basePlotModules [ 0 ] , 'plot' , [ gd ] ]
612
694
] ) ;
613
695
} )
614
696
. then ( function ( ) {
@@ -621,14 +703,12 @@ describe('Plotly.react transitions:', function() {
621
703
. then ( function ( ) {
622
704
assertSpies ( 'both trace and layout transitions under *ordering:traces first*' , [
623
705
[ Plots , 'transitionFromReact' , 1 ] ,
624
- [ gd . _fullLayout . _basePlotModules [ 0 ] , 'plot' , [
625
- // one smooth transition
626
- [ gd , [ 0 ] , { duration : 10 , easing : 'cubic-in-out' , ordering : 'traces first' } , 'function' ] ,
627
- // one by relayout call at the end of instantaneous axis transition
628
- [ gd ]
629
- ] ] ,
706
+ // one smooth transition
707
+ [ gd . _fullLayout . _basePlotModules [ 0 ] , 'plot' , [ gd , [ 0 ] , { duration : 10 , easing : 'cubic-in-out' , ordering : 'traces first' } , 'function' ] ] ,
708
+ // one by relayout call at the end of instantaneous axis transition
630
709
[ gd . _fullLayout . _basePlotModules [ 0 ] , 'transitionAxes' , 1 ] ,
631
- [ Registry , 'call' , [ [ 'relayout' , gd , { 'xaxis.range' : [ - 2 , 2 ] } ] ] ]
710
+ [ Registry , 'call' , [ 'relayout' , gd , { 'xaxis.range' : [ - 2 , 2 ] } ] ] ,
711
+ [ gd . _fullLayout . _basePlotModules [ 0 ] , 'plot' , [ gd ] ]
632
712
] ) ;
633
713
} )
634
714
. catch ( failTest )
@@ -730,13 +810,10 @@ describe('Plotly.react transitions:', function() {
730
810
assertSpies ( 'must transition autoranged axes, not the traces' , [
731
811
[ Plots , 'transitionFromReact' , 1 ] ,
732
812
[ gd . _fullLayout . _basePlotModules [ 0 ] , 'transitionAxes' , 1 ] ,
733
- [ gd . _fullLayout . _basePlotModules [ 0 ] , 'plot' , [
734
- // one instantaneous transition options to halt
735
- // other trace transitions (if any)
736
- [ gd , null , { duration : 0 , easing : 'cubic-in-out' , ordering : 'layout first' } , 'function' ] ,
737
- // one _module.plot call from the relayout at end of axis transition
738
- [ gd ]
739
- ] ] ,
813
+ // one instantaneous transition options to halt other trace transitions (if any)
814
+ [ gd . _fullLayout . _basePlotModules [ 0 ] , 'plot' , [ gd , null , { duration : 0 , easing : 'cubic-in-out' , ordering : 'layout first' } , 'function' ] ] ,
815
+ // one _module.plot call from the relayout at end of axis transition
816
+ [ gd . _fullLayout . _basePlotModules [ 0 ] , 'plot' , [ gd ] ] ,
740
817
] ) ;
741
818
assertAxAutorange ( 'axes are now autorange:false' , false ) ;
742
819
} )
@@ -748,10 +825,8 @@ describe('Plotly.react transitions:', function() {
748
825
assertSpies ( 'transition just traces, as now axis ranges are set' , [
749
826
[ Plots , 'transitionFromReact' , 1 ] ,
750
827
[ gd . _fullLayout . _basePlotModules [ 0 ] , 'transitionAxes' , 0 ] ,
751
- [ gd . _fullLayout . _basePlotModules [ 0 ] , 'plot' , [
752
- // called from Plots.transitionFromReact
753
- [ gd , [ 0 ] , { duration : 10 , easing : 'cubic-in-out' , ordering : 'layout first' } , 'function' ] ,
754
- ] ] ,
828
+ // called from Plots.transitionFromReact
829
+ [ gd . _fullLayout . _basePlotModules [ 0 ] , 'plot' , [ gd , [ 0 ] , { duration : 10 , easing : 'cubic-in-out' , ordering : 'layout first' } , 'function' ] ]
755
830
] ) ;
756
831
assertAxAutorange ( 'axes are still autorange:false' , false ) ;
757
832
} )
@@ -795,36 +870,34 @@ describe('Plotly.react transitions:', function() {
795
870
} )
796
871
. then ( function ( ) {
797
872
assertSpies ( 'both trace and layout transitions' , [
873
+ // xaxis call to _storeDirectGUIEdit from doAutoRange
874
+ [ Registry , 'call' , [ '_storeDirectGUIEdit' , gd . layout , gd . _fullLayout . _preGUI , {
875
+ 'xaxis.range' : [ - 0.12852664576802508 , 2.128526645768025 ] ,
876
+ 'xaxis.autorange' : true
877
+ } ] ] ,
878
+ // yaxis call to _storeDirectGUIEdit from doAutoRange
879
+ [ Registry , 'call' , [ '_storeDirectGUIEdit' , gd . layout , gd . _fullLayout . _preGUI , {
880
+ 'yaxis.range' : [ 9.26751592356688 , 20.73248407643312 ] ,
881
+ 'yaxis.autorange' : true
882
+ } ] ] ,
883
+
798
884
[ Plots , 'transitionFromReact' , 1 ] ,
799
885
[ gd . _fullLayout . _basePlotModules [ 0 ] , 'transitionAxes' , 1 ] ,
800
- [ Registry , 'call' , [
801
- // xaxis call to _storeDirectGUIEdit from doAutoRange
802
- [ '_storeDirectGUIEdit' , gd . layout , gd . _fullLayout . _preGUI , {
803
- 'xaxis.range' : [ - 0.12852664576802508 , 2.128526645768025 ] ,
804
- 'xaxis.autorange' : true
805
- } ] ,
806
- // yaxis call to _storeDirectGUIEdit from doAutoRange
807
- [ '_storeDirectGUIEdit' , gd . layout , gd . _fullLayout . _preGUI , {
808
- 'yaxis.range' : [ 9.26751592356688 , 20.73248407643312 ] ,
809
- 'yaxis.autorange' : true
810
- } ] ,
811
- [ 'relayout' , gd , {
812
- 'yaxis.range' : [ 9.26751592356688 , 20.73248407643312 ]
813
- } ] ,
814
- // xaxis call #2 to _storeDirectGUIEdit from doAutoRange,
815
- // as this axis is still autorange:true
816
- [ '_storeDirectGUIEdit' , gd . layout , gd . _fullLayout . _preGUI , {
817
- 'xaxis.range' : [ - 0.12852664576802508 , 2.128526645768025 ] ,
818
- 'xaxis.autorange' : true
819
- } ] ,
820
- ] ] ,
821
- [ gd . _fullLayout . _basePlotModules [ 0 ] , 'plot' , [
822
- // one instantaneous transition options to halt
823
- // other trace transitions (if any)
824
- [ gd , null , { duration : 0 , easing : 'cubic-in-out' , ordering : 'layout first' } , 'function' ] ,
825
- // one _module.plot call from the relayout at end of axis transition
826
- [ gd ]
827
- ] ]
886
+
887
+ // one instantaneous transition options to halt other trace transitions (if any)
888
+ [ gd . _fullLayout . _basePlotModules [ 0 ] , 'plot' , [ gd , null , { duration : 0 , easing : 'cubic-in-out' , ordering : 'layout first' } , 'function' ] ] ,
889
+
890
+ // one _module.plot call from the relayout at end of axis transition
891
+ [ Registry , 'call' , [ 'relayout' , gd , {
892
+ 'yaxis.range' : [ 9.26751592356688 , 20.73248407643312 ]
893
+ } ] ] ,
894
+ // xaxis call #2 to _storeDirectGUIEdit from doAutoRange,
895
+ // as this axis is still autorange:true
896
+ [ Registry , 'call' , [ '_storeDirectGUIEdit' , gd . layout , gd . _fullLayout . _preGUI , {
897
+ 'xaxis.range' : [ - 0.12852664576802508 , 2.128526645768025 ] ,
898
+ 'xaxis.autorange' : true
899
+ } ] ] ,
900
+ [ gd . _fullLayout . _basePlotModules [ 0 ] , 'plot' , [ gd ] ]
828
901
] ) ;
829
902
assertAxAutorange ( 'y-axis is now autorange:false' , false ) ;
830
903
} )
@@ -1002,8 +1075,9 @@ describe('Plotly.react transitions:', function() {
1002
1075
var msg = 'transition into data2' ;
1003
1076
assertSpies ( msg , [
1004
1077
[ Plots , 'transitionFromReact' , 1 ] ,
1005
- [ gd . _fullLayout . _basePlotModules [ 0 ] , 'plot' , 2 ] ,
1006
- [ Registry , 'call' , 1 ] ,
1078
+ [ gd . _fullLayout . _basePlotModules [ 0 ] , 'plot' , 1 ] ,
1079
+ [ Registry , 'call' , [ 'redraw' , gd ] ] ,
1080
+ [ gd . _fullLayout . _basePlotModules [ 0 ] , 'plot' , 1 ] ,
1007
1081
[ gd . _fullLayout . _basePlotModules [ 0 ] , 'transitionAxes' , 0 ]
1008
1082
] ) ;
1009
1083
@@ -1015,8 +1089,9 @@ describe('Plotly.react transitions:', function() {
1015
1089
var msg = 'transition back to data1' ;
1016
1090
assertSpies ( msg , [
1017
1091
[ Plots , 'transitionFromReact' , 1 ] ,
1018
- [ Registry , 'call' , 1 ] ,
1019
- [ gd . _fullLayout . _basePlotModules [ 0 ] , 'plot' , 2 ] ,
1092
+ [ gd . _fullLayout . _basePlotModules [ 0 ] , 'plot' , 1 ] ,
1093
+ [ Registry , 'call' , [ 'redraw' , gd ] ] ,
1094
+ [ gd . _fullLayout . _basePlotModules [ 0 ] , 'plot' , 1 ] ,
1020
1095
[ gd . _fullLayout . _basePlotModules [ 0 ] , 'transitionAxes' , 0 ]
1021
1096
] ) ;
1022
1097
0 commit comments