@@ -296,33 +296,117 @@ describe('Plotly.react transitions:', function() {
296296 } ) ;
297297 }
298298
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 = { } ;
300356 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+ }
319367 } ) ;
320- } else if ( typeof exp [ 2 ] === 'number' ) {
321- expect ( cnt ) . toBe ( exp [ 2 ] , msg ) ;
322- } else {
323- fail ( 'wrong arguments for assertSpies' ) ;
324368 }
325369 } ) ;
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+
326410 resetSpyCounters ( ) ;
327411 }
328412
@@ -362,7 +446,7 @@ describe('Plotly.react transitions:', function() {
362446 } )
363447 . then ( function ( ) {
364448 assertSpies ( 'with *transition* set and changes' , [
365- [ Plots , 'transitionFromReact' , 1 ] ,
449+ [ Plots , 'transitionFromReact' , 1 ]
366450 ] ) ;
367451 } )
368452 . catch ( failTest )
@@ -547,7 +631,7 @@ describe('Plotly.react transitions:', function() {
547631 . then ( function ( ) {
548632 assertSpies ( 'redraw required' , [
549633 [ Plots , 'transitionFromReact' , 1 ] ,
550- [ Registry , 'call' , [ [ 'redraw' , gd ] ] ]
634+ [ Registry , 'call' , [ 'redraw' , gd ] ]
551635 ] ) ;
552636 } )
553637 . catch ( failTest )
@@ -588,7 +672,7 @@ describe('Plotly.react transitions:', function() {
588672 [ Plots , 'transitionFromReact' , 1 ] ,
589673 [ gd . _fullLayout . _basePlotModules [ 0 ] , 'transitionAxes' , 1 ] ,
590674 // 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 ] } ] ] ,
592676 [ gd . _fullLayout . _basePlotModules [ 0 ] , 'plot' , 1 ] ,
593677 ] ) ;
594678 } )
@@ -597,18 +681,16 @@ describe('Plotly.react transitions:', function() {
597681 layout . xaxis . range = [ - 1 , 1 ] ;
598682 return Plotly . react ( gd , data , layout ) ;
599683 } )
684+ . then ( delay ( 20 ) )
600685 . then ( function ( ) {
601686 assertSpies ( 'both trace and layout transitions' , [
602687 [ Plots , 'transitionFromReact' , 1 ] ,
603688 [ 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 ] ]
612694 ] ) ;
613695 } )
614696 . then ( function ( ) {
@@ -621,14 +703,12 @@ describe('Plotly.react transitions:', function() {
621703 . then ( function ( ) {
622704 assertSpies ( 'both trace and layout transitions under *ordering:traces first*' , [
623705 [ 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
630709 [ 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 ] ]
632712 ] ) ;
633713 } )
634714 . catch ( failTest )
@@ -730,13 +810,10 @@ describe('Plotly.react transitions:', function() {
730810 assertSpies ( 'must transition autoranged axes, not the traces' , [
731811 [ Plots , 'transitionFromReact' , 1 ] ,
732812 [ 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 ] ] ,
740817 ] ) ;
741818 assertAxAutorange ( 'axes are now autorange:false' , false ) ;
742819 } )
@@ -748,10 +825,8 @@ describe('Plotly.react transitions:', function() {
748825 assertSpies ( 'transition just traces, as now axis ranges are set' , [
749826 [ Plots , 'transitionFromReact' , 1 ] ,
750827 [ 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' ] ]
755830 ] ) ;
756831 assertAxAutorange ( 'axes are still autorange:false' , false ) ;
757832 } )
@@ -795,36 +870,34 @@ describe('Plotly.react transitions:', function() {
795870 } )
796871 . then ( function ( ) {
797872 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+
798884 [ Plots , 'transitionFromReact' , 1 ] ,
799885 [ 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 ] ]
828901 ] ) ;
829902 assertAxAutorange ( 'y-axis is now autorange:false' , false ) ;
830903 } )
@@ -1002,8 +1075,9 @@ describe('Plotly.react transitions:', function() {
10021075 var msg = 'transition into data2' ;
10031076 assertSpies ( msg , [
10041077 [ 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 ] ,
10071081 [ gd . _fullLayout . _basePlotModules [ 0 ] , 'transitionAxes' , 0 ]
10081082 ] ) ;
10091083
@@ -1015,8 +1089,9 @@ describe('Plotly.react transitions:', function() {
10151089 var msg = 'transition back to data1' ;
10161090 assertSpies ( msg , [
10171091 [ 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 ] ,
10201095 [ gd . _fullLayout . _basePlotModules [ 0 ] , 'transitionAxes' , 0 ]
10211096 ] ) ;
10221097
0 commit comments