11var Plotly = require ( '@lib/index' ) ;
2+ var d3 = require ( 'd3' ) ;
23
34var Plots = require ( '@src/plots/plots' ) ;
45var Lib = require ( '@src/lib' ) ;
@@ -7,10 +8,12 @@ var tinycolor = require('tinycolor2');
78
89var handleTickValueDefaults = require ( '@src/plots/cartesian/tick_value_defaults' ) ;
910var Axes = require ( '@src/plots/cartesian/axes' ) ;
11+ var Fx = require ( '@src/components/fx' ) ;
1012
1113var createGraphDiv = require ( '../assets/create_graph_div' ) ;
1214var destroyGraphDiv = require ( '../assets/destroy_graph_div' ) ;
1315var failTest = require ( '../assets/fail_test' ) ;
16+ var selectButton = require ( '../assets/modebar_button' ) ;
1417
1518
1619describe ( 'Test axes' , function ( ) {
@@ -2481,3 +2484,301 @@ describe('Test axes', function() {
24812484 } ) ;
24822485 } ) ;
24832486} ) ;
2487+
2488+ function getZoomInButton ( gd ) {
2489+ return selectButton ( gd . _fullLayout . _modeBar , 'zoomIn2d' ) ;
2490+ }
2491+
2492+ function getZoomOutButton ( gd ) {
2493+ return selectButton ( gd . _fullLayout . _modeBar , 'zoomOut2d' ) ;
2494+ }
2495+
2496+ function getFormatter ( format ) {
2497+ return d3 . time . format . utc ( format ) ;
2498+ }
2499+
2500+ describe ( 'Test Axes.getTickformat' , function ( ) {
2501+ 'use strict' ;
2502+
2503+ it ( 'get proper tickformatstop for linear axis' , function ( ) {
2504+ var lineartickformatstops = [
2505+ {
2506+ dtickrange : [ null , 1 ] ,
2507+ value : '.f2' ,
2508+ } ,
2509+ {
2510+ dtickrange : [ 1 , 100 ] ,
2511+ value : '.f1' ,
2512+ } ,
2513+ {
2514+ dtickrange : [ 100 , null ] ,
2515+ value : 'g' ,
2516+ }
2517+ ] ;
2518+ expect ( Axes . getTickFormat ( {
2519+ type : 'linear' ,
2520+ tickformatstops : lineartickformatstops ,
2521+ dtick : 0.1
2522+ } ) ) . toEqual ( lineartickformatstops [ 0 ] . value ) ;
2523+
2524+ expect ( Axes . getTickFormat ( {
2525+ type : 'linear' ,
2526+ tickformatstops : lineartickformatstops ,
2527+ dtick : 1
2528+ } ) ) . toEqual ( lineartickformatstops [ 0 ] . value ) ;
2529+
2530+ expect ( Axes . getTickFormat ( {
2531+ type : 'linear' ,
2532+ tickformatstops : lineartickformatstops ,
2533+ dtick : 99
2534+ } ) ) . toEqual ( lineartickformatstops [ 1 ] . value ) ;
2535+ expect ( Axes . getTickFormat ( {
2536+ type : 'linear' ,
2537+ tickformatstops : lineartickformatstops ,
2538+ dtick : 99999
2539+ } ) ) . toEqual ( lineartickformatstops [ 2 ] . value ) ;
2540+ } ) ;
2541+
2542+ it ( 'get proper tickformatstop for date axis' , function ( ) {
2543+ var MILLISECOND = 1 ;
2544+ var SECOND = MILLISECOND * 1000 ;
2545+ var MINUTE = SECOND * 60 ;
2546+ var HOUR = MINUTE * 60 ;
2547+ var DAY = HOUR * 24 ;
2548+ var WEEK = DAY * 7 ;
2549+ var MONTH = 'M1' ; // or YEAR / 12;
2550+ var YEAR = 'M12' ; // or 365.25 * DAY;
2551+ var datetickformatstops = [
2552+ {
2553+ dtickrange : [ null , SECOND ] ,
2554+ value : '%H:%M:%S.%L ms' // millisecond
2555+ } ,
2556+ {
2557+ dtickrange : [ SECOND , MINUTE ] ,
2558+ value : '%H:%M:%S s' // second
2559+ } ,
2560+ {
2561+ dtickrange : [ MINUTE , HOUR ] ,
2562+ value : '%H:%M m' // minute
2563+ } ,
2564+ {
2565+ dtickrange : [ HOUR , DAY ] ,
2566+ value : '%H:%M h' // hour
2567+ } ,
2568+ {
2569+ dtickrange : [ DAY , WEEK ] ,
2570+ value : '%e. %b d' // day
2571+ } ,
2572+ {
2573+ dtickrange : [ WEEK , MONTH ] ,
2574+ value : '%e. %b w' // week
2575+ } ,
2576+ {
2577+ dtickrange : [ MONTH , YEAR ] ,
2578+ value : '%b \'%y M' // month
2579+ } ,
2580+ {
2581+ dtickrange : [ YEAR , null ] ,
2582+ value : '%Y Y' // year
2583+ }
2584+ ] ;
2585+ expect ( Axes . getTickFormat ( {
2586+ type : 'date' ,
2587+ tickformatstops : datetickformatstops ,
2588+ dtick : 100
2589+ } ) ) . toEqual ( datetickformatstops [ 0 ] . value ) ; // millisecond
2590+
2591+ expect ( Axes . getTickFormat ( {
2592+ type : 'date' ,
2593+ tickformatstops : datetickformatstops ,
2594+ dtick : 1000
2595+ } ) ) . toEqual ( datetickformatstops [ 0 ] . value ) ; // millisecond
2596+
2597+ expect ( Axes . getTickFormat ( {
2598+ type : 'date' ,
2599+ tickformatstops : datetickformatstops ,
2600+ dtick : 1000 * 60 * 60 * 3 // three hours
2601+ } ) ) . toEqual ( datetickformatstops [ 3 ] . value ) ; // hour
2602+
2603+ expect ( Axes . getTickFormat ( {
2604+ type : 'date' ,
2605+ tickformatstops : datetickformatstops ,
2606+ dtick : 1000 * 60 * 60 * 24 * 7 * 2 // two weeks
2607+ } ) ) . toEqual ( datetickformatstops [ 5 ] . value ) ; // week
2608+
2609+ expect ( Axes . getTickFormat ( {
2610+ type : 'date' ,
2611+ tickformatstops : datetickformatstops ,
2612+ dtick : 'M1'
2613+ } ) ) . toEqual ( datetickformatstops [ 5 ] . value ) ; // week
2614+
2615+ expect ( Axes . getTickFormat ( {
2616+ type : 'date' ,
2617+ tickformatstops : datetickformatstops ,
2618+ dtick : 'M5'
2619+ } ) ) . toEqual ( datetickformatstops [ 6 ] . value ) ; // month
2620+
2621+ expect ( Axes . getTickFormat ( {
2622+ type : 'date' ,
2623+ tickformatstops : datetickformatstops ,
2624+ dtick : 'M24'
2625+ } ) ) . toEqual ( datetickformatstops [ 7 ] . value ) ; // year
2626+ } ) ;
2627+
2628+ it ( 'get proper tickformatstop for log axis' , function ( ) {
2629+ var logtickformatstops = [
2630+ {
2631+ dtickrange : [ null , 'L0.01' ] ,
2632+ value : '.f3' ,
2633+ } ,
2634+ {
2635+ dtickrange : [ 'L0.01' , 'L1' ] ,
2636+ value : '.f2' ,
2637+ } ,
2638+ {
2639+ dtickrange : [ 'D1' , 'D2' ] ,
2640+ value : '.f1' ,
2641+ } ,
2642+ {
2643+ dtickrange : [ 1 , null ] ,
2644+ value : 'g'
2645+ }
2646+ ] ;
2647+ expect ( Axes . getTickFormat ( {
2648+ type : 'log' ,
2649+ tickformatstops : logtickformatstops ,
2650+ dtick : 'L0.0001'
2651+ } ) ) . toEqual ( logtickformatstops [ 0 ] . value ) ;
2652+
2653+ expect ( Axes . getTickFormat ( {
2654+ type : 'log' ,
2655+ tickformatstops : logtickformatstops ,
2656+ dtick : 'L0.1'
2657+ } ) ) . toEqual ( logtickformatstops [ 1 ] . value ) ;
2658+
2659+ expect ( Axes . getTickFormat ( {
2660+ type : 'log' ,
2661+ tickformatstops : logtickformatstops ,
2662+ dtick : 'L2'
2663+ } ) ) . toEqual ( undefined ) ;
2664+ expect ( Axes . getTickFormat ( {
2665+ type : 'log' ,
2666+ tickformatstops : logtickformatstops ,
2667+ dtick : 'D2'
2668+ } ) ) . toEqual ( logtickformatstops [ 2 ] . value ) ;
2669+ expect ( Axes . getTickFormat ( {
2670+ type : 'log' ,
2671+ tickformatstops : logtickformatstops ,
2672+ dtick : 1
2673+ } ) ) . toEqual ( logtickformatstops [ 3 ] . value ) ;
2674+ } ) ;
2675+ } ) ;
2676+
2677+ describe ( 'Test tickformatstops:' , function ( ) {
2678+ 'use strict' ;
2679+
2680+ var mock = require ( '@mocks/tickformatstops.json' ) ;
2681+
2682+ var mockCopy , gd ;
2683+
2684+ beforeEach ( function ( ) {
2685+ gd = createGraphDiv ( ) ;
2686+ mockCopy = Lib . extendDeep ( { } , mock ) ;
2687+ } ) ;
2688+
2689+ afterEach ( destroyGraphDiv ) ;
2690+
2691+ it ( 'handles zooming-in until milliseconds zoom level' , function ( done ) {
2692+ var promise = Plotly . plot ( gd , mockCopy . data , mockCopy . layout ) ;
2693+
2694+ var testCount = 0 ;
2695+
2696+ var zoomIn = function ( ) {
2697+ promise = promise . then ( function ( ) {
2698+ getZoomInButton ( gd ) . click ( ) ;
2699+ var xLabels = Axes . calcTicks ( gd . _fullLayout . xaxis ) ;
2700+ var formatter = getFormatter ( Axes . getTickFormat ( gd . _fullLayout . xaxis ) ) ;
2701+ var expectedLabels = xLabels . map ( function ( d ) { return formatter ( new Date ( d . x ) ) ; } ) ;
2702+ var actualLabels = xLabels . map ( function ( d ) { return d . text ; } ) ;
2703+ expect ( expectedLabels ) . toEqual ( actualLabels ) ;
2704+ testCount ++ ;
2705+
2706+ if ( gd . _fullLayout . xaxis . dtick > 1 ) {
2707+ zoomIn ( ) ;
2708+ } else {
2709+ // make sure we tested as many levels as we thought we would
2710+ expect ( testCount ) . toBe ( 32 ) ;
2711+ done ( ) ;
2712+ }
2713+ } ) ;
2714+ } ;
2715+ zoomIn ( ) ;
2716+ } ) ;
2717+
2718+ it ( 'handles zooming-out until years zoom level' , function ( done ) {
2719+ var promise = Plotly . plot ( gd , mockCopy . data , mockCopy . layout ) ;
2720+
2721+ var testCount = 0 ;
2722+
2723+ var zoomOut = function ( ) {
2724+ promise = promise . then ( function ( ) {
2725+ getZoomOutButton ( gd ) . click ( ) ;
2726+ var xLabels = Axes . calcTicks ( gd . _fullLayout . xaxis ) ;
2727+ var formatter = getFormatter ( Axes . getTickFormat ( gd . _fullLayout . xaxis ) ) ;
2728+ var expectedLabels = xLabels . map ( function ( d ) { return formatter ( new Date ( d . x ) ) ; } ) ;
2729+ var actualLabels = xLabels . map ( function ( d ) { return d . text ; } ) ;
2730+ expect ( expectedLabels ) . toEqual ( actualLabels ) ;
2731+ testCount ++ ;
2732+
2733+ if ( typeof gd . _fullLayout . xaxis . dtick === 'number' ||
2734+ typeof gd . _fullLayout . xaxis . dtick === 'string' && parseInt ( gd . _fullLayout . xaxis . dtick . replace ( / \D / g, '' ) ) < 48 ) {
2735+ zoomOut ( ) ;
2736+ } else {
2737+ // make sure we tested as many levels as we thought we would
2738+ expect ( testCount ) . toBe ( 5 ) ;
2739+ done ( ) ;
2740+ }
2741+ } ) ;
2742+ } ;
2743+ zoomOut ( ) ;
2744+ } ) ;
2745+
2746+ it ( 'responds to hover' , function ( done ) {
2747+ var evt = { xpx : 270 , ypx : 10 } ;
2748+
2749+ Plotly . plot ( gd , mockCopy . data , mockCopy . layout ) . then ( function ( ) {
2750+ Fx . hover ( gd , evt , 'xy' ) ;
2751+
2752+ var hoverTrace = gd . _hoverdata [ 0 ] ;
2753+ var formatter = getFormatter ( Axes . getTickFormat ( gd . _fullLayout . xaxis ) ) ;
2754+
2755+ expect ( hoverTrace . curveNumber ) . toEqual ( 0 ) ;
2756+ expect ( hoverTrace . pointNumber ) . toEqual ( 3 ) ;
2757+ expect ( hoverTrace . x ) . toEqual ( '2005-04-01' ) ;
2758+ expect ( hoverTrace . y ) . toEqual ( 0 ) ;
2759+
2760+ expect ( d3 . selectAll ( 'g.axistext' ) . size ( ) ) . toEqual ( 1 ) ;
2761+ expect ( d3 . selectAll ( 'g.hovertext' ) . size ( ) ) . toEqual ( 1 ) ;
2762+ expect ( d3 . selectAll ( 'g.axistext' ) . select ( 'text' ) . html ( ) ) . toEqual ( formatter ( new Date ( hoverTrace . x ) ) ) ;
2763+ expect ( d3 . selectAll ( 'g.hovertext' ) . select ( 'text' ) . html ( ) ) . toEqual ( '0' ) ;
2764+ } )
2765+ . catch ( failTest )
2766+ . then ( done ) ;
2767+ } ) ;
2768+
2769+ it ( 'doesn\'t fail on bad input' , function ( done ) {
2770+ var promise = Plotly . plot ( gd , mockCopy . data , mockCopy . layout ) ;
2771+
2772+ [ 1 , { a : 1 , b : 2 } , 'boo' ] . forEach ( function ( v ) {
2773+ promise = promise . then ( function ( ) {
2774+ return Plotly . relayout ( gd , { 'xaxis.tickformatstops' : v } ) ;
2775+ } ) . then ( function ( ) {
2776+ expect ( gd . _fullLayout . xaxis . tickformatstops ) . toEqual ( [ ] ) ;
2777+ } ) ;
2778+ } ) ;
2779+
2780+ promise
2781+ . catch ( failTest )
2782+ . then ( done ) ;
2783+ } ) ;
2784+ } ) ;
0 commit comments