Only include visible series in range selector (#785)
[dygraphs.git] / auto_tests / tests / range_selector.js
index a145d7a..1bba353 100644 (file)
@@ -4,16 +4,31 @@
  * @fileoverview Regression tests for range selector.
  * @author paul.eric.felix@gmail.com (Paul Felix)
  */
-var RangeSelectorTestCase = TestCase("range-selector");
 
-RangeSelectorTestCase.prototype.setUp = function() {
-  document.body.innerHTML = "<div id='graph'></div>";
-};
+import Dygraph from '../../src/dygraph';
+import * as utils from '../../src/dygraph-utils';
+import RangeSelectorPlugin from '../../src/plugins/range-selector';
 
-RangeSelectorTestCase.prototype.tearDown = function() {
-};
+import Util from './Util';
+import DygraphOps from './DygraphOps';
+import CanvasAssertions from './CanvasAssertions';
+import Proxy from './Proxy';
+
+describe("range-selector", function() {
+
+cleanupAfterEach();
+
+var restoreConsole;
+var logs = {};
+beforeEach(function() {
+  restoreConsole = Util.captureConsole(logs);
+});
+
+afterEach(function() {
+  restoreConsole();
+});
 
-RangeSelectorTestCase.prototype.testRangeSelector = function() {
+it('testRangeSelector', function() {
   var opts = {
     width: 480,
     height: 320,
@@ -33,10 +48,10 @@ RangeSelectorTestCase.prototype.testRangeSelector = function() {
              ];
   var graph = document.getElementById("graph");
   var g = new Dygraph(graph, data, opts);
-  this.assertGraphExistence(g, graph);
-};
+  assertGraphExistence(g, graph);
+});
 
-RangeSelectorTestCase.prototype.testRangeSelectorWithErrorBars = function() {
+it('testRangeSelectorWithErrorBars', function() {
   var opts = {
     width: 480,
     height: 320,
@@ -57,10 +72,10 @@ RangeSelectorTestCase.prototype.testRangeSelectorWithErrorBars = function() {
              ];
   var graph = document.getElementById("graph");
   var g = new Dygraph(graph, data, opts);
-  this.assertGraphExistence(g, graph);
-};
+  assertGraphExistence(g, graph);
+});
 
-RangeSelectorTestCase.prototype.testRangeSelectorWithCustomBars = function() {
+it('testRangeSelectorWithCustomBars', function() {
   var opts = {
     width: 480,
     height: 320,
@@ -81,10 +96,10 @@ RangeSelectorTestCase.prototype.testRangeSelectorWithCustomBars = function() {
              ];
   var graph = document.getElementById("graph");
   var g = new Dygraph(graph, data, opts);
-  this.assertGraphExistence(g, graph);
-};
+  assertGraphExistence(g, graph);
+});
 
-RangeSelectorTestCase.prototype.testRangeSelectorWithLogScale = function() {
+it('testRangeSelectorWithLogScale', function() {
   var opts = {
     width: 480,
     height: 320,
@@ -105,16 +120,17 @@ RangeSelectorTestCase.prototype.testRangeSelectorWithLogScale = function() {
              ];
   var graph = document.getElementById("graph");
   var g = new Dygraph(graph, data, opts);
-  this.assertGraphExistence(g, graph);
-};
+  assertGraphExistence(g, graph);
+});
 
-RangeSelectorTestCase.prototype.testRangeSelectorOptions = function() {
+it('testRangeSelectorOptions', function() {
   var opts = {
     width: 480,
     height: 320,
     showRangeSelector: true,
     rangeSelectorHeight: 30,
     rangeSelectorPlotFillColor: 'lightyellow',
+    rangeSelectorPlotFillGradientColor: 'rgba(200, 200, 42, 10)',
     labels: ['X', 'Y']
   };
   var data = [
@@ -130,13 +146,21 @@ RangeSelectorTestCase.prototype.testRangeSelectorOptions = function() {
              ];
   var graph = document.getElementById("graph");
   var g = new Dygraph(graph, data, opts);
-  this.assertGraphExistence(g, graph);
-};
+  assertGraphExistence(g, graph);
+});
 
-RangeSelectorTestCase.prototype.testRangeSelectorEnablingAfterCreation = function() {
+it('testAdditionalRangeSelectorOptions', function() {
   var opts = {
     width: 480,
     height: 320,
+    showRangeSelector: true,
+    rangeSelectorHeight: 30,
+    rangeSelectorBackgroundStrokeColor: 'blue',
+    rangeSelectorBackgroundLineWidth: 3,
+    rangeSelectorPlotLineWidth: 0.5,
+    rangeSelectorForegroundStrokeColor: 'red',
+    rangeSelectorForegroundLineWidth: 2,
+    rangeSelectorAlpha: 0.8,
     labels: ['X', 'Y']
   };
   var data = [
@@ -152,12 +176,39 @@ RangeSelectorTestCase.prototype.testRangeSelectorEnablingAfterCreation = functio
              ];
   var graph = document.getElementById("graph");
   var g = new Dygraph(graph, data, opts);
+  assertGraphExistence(g, graph);
+});
+
+it('testRangeSelectorEnablingAfterCreation', function() {
+  var opts = {
+    width: 480,
+    height: 320,
+    labels: ['X', 'Y']
+  };
+  var data = [
+               [1, 10],
+               [2, 15],
+               [3, 10],
+               [4, 15],
+               [5, 10],
+               [6, 15],
+               [7, 10],
+               [8, 15],
+               [9, 10]
+             ];
+  var graph = document.getElementById("graph");
+  var g = new Dygraph(graph, data, opts);
+  var initialChartHeight = g.getArea().h;
   g.updateOptions({showRangeSelector: true});
-  this.assertGraphExistence(g, graph);
-};
+  assertGraphExistence(g, graph);
+  assert(g.getArea().h < initialChartHeight);  // range selector shown
+
+  g.updateOptions({showRangeSelector: false});
+  assert.equal(g.getArea().h, initialChartHeight);  // range selector hidden
+});
 
 // The animatedZooms option does not work with the range selector. Make sure it gets turned off.
-RangeSelectorTestCase.prototype.testRangeSelectorWithAnimatedZoomsOption = function() {
+it('testRangeSelectorWithAnimatedZoomsOption', function() {
   var opts = {
     width: 480,
     height: 320,
@@ -178,11 +229,15 @@ RangeSelectorTestCase.prototype.testRangeSelectorWithAnimatedZoomsOption = funct
              ];
   var graph = document.getElementById("graph");
   var g = new Dygraph(graph, data, opts);
-  this.assertGraphExistence(g, graph);
-  assertFalse(g.getOption('animatedZooms'));
-};
+  assertGraphExistence(g, graph);
+  assert.isFalse(g.getOption('animatedZooms'));
+  assert.deepEqual(logs, {
+    log: [], error: [],
+    warn: ["Animated zooms and range selector are not compatible; disabling animatedZooms."]
+  });
+});
 
-RangeSelectorTestCase.prototype.testRangeSelectorWithAnimatedZoomsOption2 = function() {
+it('testRangeSelectorWithAnimatedZoomsOption2', function() {
   var opts = {
     width: 480,
     height: 320,
@@ -203,11 +258,15 @@ RangeSelectorTestCase.prototype.testRangeSelectorWithAnimatedZoomsOption2 = func
   var graph = document.getElementById("graph");
   var g = new Dygraph(graph, data, opts);
   g.updateOptions({showRangeSelector: true});
-  this.assertGraphExistence(g, graph);
-  assertFalse(g.getOption('animatedZooms'));
-};
+  assertGraphExistence(g, graph);
+  assert.isFalse(g.getOption('animatedZooms'));
+  assert.deepEqual(logs, {
+    log: [], error: [],
+    warn: ["Animated zooms and range selector are not compatible; disabling animatedZooms."]
+  });
+});
 
-RangeSelectorTestCase.prototype.testRangeSelectorInteraction = function() {
+it('testRangeSelectorInteraction', function() {
   var opts = {
     width: 480,
     height: 320,
@@ -227,7 +286,7 @@ RangeSelectorTestCase.prototype.testRangeSelectorInteraction = function() {
              ];
   var graph = document.getElementById("graph");
   var g = new Dygraph(graph, data, opts);
-  this.assertGraphExistence(g, graph);
+  assertGraphExistence(g, graph);
   var zoomhandles = graph.getElementsByClassName('dygraph-rangesel-zoomhandle');
 
   // Move left zoomhandle in
@@ -257,8 +316,8 @@ RangeSelectorTestCase.prototype.testRangeSelectorInteraction = function() {
   zoomhandles[0].dispatchEvent(mouseUpEvent);
 
   var newXRange = g.xAxisRange().slice();
-  assert('left zoomhandle should have moved: '+newXRange[0]+'>'+xRange[0], newXRange[0] > xRange[0]);
-  assertEquals('right zoomhandle should not have moved', xRange[1], newXRange[1]);
+  assert(newXRange[0] > xRange[0], 'left zoomhandle should have moved: '+newXRange[0]+'>'+xRange[0]);
+  assert.equal(xRange[1], newXRange[1], 'right zoomhandle should not have moved');
 
   // Move right zoomhandle in
   xRange = newXRange;
@@ -287,8 +346,8 @@ RangeSelectorTestCase.prototype.testRangeSelectorInteraction = function() {
   zoomhandles[1].dispatchEvent(mouseUpEvent);
 
   var newXRange = g.xAxisRange().slice();
-  assert('right zoomhandle should have moved: '+newXRange[1]+'<'+xRange[1], newXRange[1] < xRange[1]);
-  assertEquals('left zoomhandle should not have moved', xRange[0], newXRange[0]);
+  assert(newXRange[1] < xRange[1], 'right zoomhandle should have moved: '+newXRange[1]+'<'+xRange[1]);
+  assert.equal(xRange[0], newXRange[0], 'left zoomhandle should not have moved');
 
   // Pan left
   xRange = newXRange;
@@ -322,12 +381,12 @@ RangeSelectorTestCase.prototype.testRangeSelectorInteraction = function() {
   fgcanvas.dispatchEvent(mouseUpEvent);
 
   var newXRange = g.xAxisRange().slice();
-  assert(newXRange[0]+'<'+xRange[0], newXRange[0] < xRange[0]);
-  assert(newXRange[1]+'<'+xRange[1], newXRange[1] < xRange[1]);
-};
+  assert(newXRange[0] < xRange[0], newXRange[0]+'<'+xRange[0]);
+  assert(newXRange[1] < xRange[1], newXRange[1]+'<'+xRange[1]);
+});
 
 
-RangeSelectorTestCase.prototype.testRangeSelectorPositionIfXAxisNotDrawn = function() {
+it('testRangeSelectorPositionIfXAxisNotDrawn', function() {
   var opts = {
     width: 480,
     height: 100,
@@ -343,22 +402,21 @@ RangeSelectorTestCase.prototype.testRangeSelectorPositionIfXAxisNotDrawn = funct
              ];
   var graph = document.getElementById("graph");
   var g = new Dygraph(graph, data, opts);
-  
+
   //assert, that the range selector is at top position 70 since the 30px of the
   // xAxis shouldn't be reserved since it isn't drawn.
-  this.assertGraphExistence(g, graph);
+  assertGraphExistence(g, graph);
   var bgcanvas = graph.getElementsByClassName('dygraph-rangesel-bgcanvas')[0];
-  assertEquals("Range selector is not at the expected position.","70px", bgcanvas.style.top);
+  assert.equal("70px", bgcanvas.style.top, "Range selector is not at the expected position.");
   var fgcanvas = graph.getElementsByClassName('dygraph-rangesel-fgcanvas')[0];
-  assertEquals("Range selector is not at the expected position.","70px", fgcanvas.style.top);
-};
+  assert.equal("70px", fgcanvas.style.top, "Range selector is not at the expected position.");
+});
 
-RangeSelectorTestCase.prototype.testMiniPlotDrawn = function() {
+it('testMiniPlotDrawn', function() {
   // Install Proxy to track canvas calls.
-  var origFunc = Dygraph.getContext;
+  var origFunc = utils.getContext;
   var miniHtx;
-  Dygraph.getContext = function(canvas) {
-    console.log(canvas.className);
+  utils.getContext = function(canvas) {
     if (canvas.className != 'dygraph-rangesel-bgcanvas') {
       return origFunc(canvas);
     }
@@ -385,14 +443,14 @@ RangeSelectorTestCase.prototype.testMiniPlotDrawn = function() {
   var g = new Dygraph(graph, data, opts);
 
   // TODO(danvk): more precise tests.
-  assertNotNull(miniHtx);
-  assertTrue(0 < CanvasAssertions.numLinesDrawn(miniHtx, '#ff0000'));
+  assert.isNotNull(miniHtx);
+  assert.isTrue(0 < CanvasAssertions.numLinesDrawn(miniHtx, '#ff0000'));
 
-  Dygraph.getContext = origFunc;
-};
+  utils.getContext = origFunc;
+});
 
 // Tests data computation for the mini plot with a single series.
-RangeSelectorTestCase.prototype.testSingleCombinedSeries = function() {
+it('testSingleCombinedSeries', function() {
   var opts = {
     showRangeSelector: true,
     labels: ['X', 'Y1']
@@ -405,11 +463,11 @@ RangeSelectorTestCase.prototype.testSingleCombinedSeries = function() {
   var graph = document.getElementById("graph");
   var g = new Dygraph(graph, data, opts);
 
-  var rangeSelector = g.getPluginInstance_(Dygraph.Plugins.RangeSelector);
-  assertNotNull(rangeSelector);
+  var rangeSelector = g.getPluginInstance_(RangeSelectorPlugin);
+  assert.isNotNull(rangeSelector);
 
   var combinedSeries = rangeSelector.computeCombinedSeriesAndLimits_();
-  assertEquals({
+  assert.deepEqual({
     yMin: 1 - 7 * 0.25,  // 25% padding
     yMax: 8 + 7 * 0.25,
     data: [
@@ -418,11 +476,11 @@ RangeSelectorTestCase.prototype.testSingleCombinedSeries = function() {
       [10, 8]
     ]
   }, combinedSeries);
-};
+});
 
 
 // Tests that multiple series are averaged for the miniplot.
-RangeSelectorTestCase.prototype.testCombinedSeries = function() {
+it('testCombinedSeries', function() {
   var opts = {
     showRangeSelector: true,
     labels: ['X', 'Y1', 'Y2']
@@ -435,11 +493,11 @@ RangeSelectorTestCase.prototype.testCombinedSeries = function() {
   var graph = document.getElementById("graph");
   var g = new Dygraph(graph, data, opts);
 
-  var rangeSelector = g.getPluginInstance_(Dygraph.Plugins.RangeSelector);
-  assertNotNull(rangeSelector);
+  var rangeSelector = g.getPluginInstance_(RangeSelectorPlugin);
+  assert.isNotNull(rangeSelector);
 
   var combinedSeries = rangeSelector.computeCombinedSeriesAndLimits_();
-  assertEquals({
+  assert.deepEqual({
     yMin: 2 - 6 * 0.25,  // 25% padding on combined series range.
     yMax: 8 + 6 * 0.25,
     data: [
@@ -448,10 +506,10 @@ RangeSelectorTestCase.prototype.testCombinedSeries = function() {
       [10, 8]
     ]
   }, combinedSeries);
-};
+});
 
 // Tests selection of a specific series to average for the mini plot.
-RangeSelectorTestCase.prototype.testSelectedCombinedSeries = function() {
+it('testSelectedCombinedSeries', function() {
   var opts = {
     showRangeSelector: true,
     labels: ['X', 'Y1', 'Y2', 'Y3', 'Y4'],
@@ -468,11 +526,11 @@ RangeSelectorTestCase.prototype.testSelectedCombinedSeries = function() {
   var graph = document.getElementById("graph");
   var g = new Dygraph(graph, data, opts);
 
-  var rangeSelector = g.getPluginInstance_(Dygraph.Plugins.RangeSelector);
-  assertNotNull(rangeSelector);
+  var rangeSelector = g.getPluginInstance_(RangeSelectorPlugin);
+  assert.isNotNull(rangeSelector);
 
   var combinedSeries = rangeSelector.computeCombinedSeriesAndLimits_();
-  assertEquals({
+  assert.deepEqual({
     yMin: 4 - 5 * 0.25,  // 25% padding on combined series range.
     yMax: 9 + 5 * 0.25,
     data: [
@@ -481,10 +539,10 @@ RangeSelectorTestCase.prototype.testSelectedCombinedSeries = function() {
       [10, 5]
     ]
   }, combinedSeries);
-};
+});
 
 // Tests data computation for the mini plot with a single error bar series.
-RangeSelectorTestCase.prototype.testSingleCombinedSeriesCustomBars = function() {
+it('testSingleCombinedSeriesCustomBars', function() {
   var opts = {
     customBars: true,
     showRangeSelector: true,
@@ -498,11 +556,11 @@ RangeSelectorTestCase.prototype.testSingleCombinedSeriesCustomBars = function()
   var graph = document.getElementById("graph");
   var g = new Dygraph(graph, data, opts);
 
-  var rangeSelector = g.getPluginInstance_(Dygraph.Plugins.RangeSelector);
-  assertNotNull(rangeSelector);
+  var rangeSelector = g.getPluginInstance_(RangeSelectorPlugin);
+  assert.isNotNull(rangeSelector);
 
   var combinedSeries = rangeSelector.computeCombinedSeriesAndLimits_();
-  assertEquals({
+  assert.deepEqual({
     yMin: 1 - 7 * 0.25,  // 25% padding
     yMax: 8 + 7 * 0.25,
     data: [
@@ -511,9 +569,9 @@ RangeSelectorTestCase.prototype.testSingleCombinedSeriesCustomBars = function()
       [10, 8]
     ]
   }, combinedSeries);
-};
+});
 
-RangeSelectorTestCase.prototype.testSingleCombinedSeriesErrorBars = function() {
+it('testSingleCombinedSeriesErrorBars', function() {
   var opts = {
     errorBars: true,
     showRangeSelector: true,
@@ -527,11 +585,11 @@ RangeSelectorTestCase.prototype.testSingleCombinedSeriesErrorBars = function() {
   var graph = document.getElementById("graph");
   var g = new Dygraph(graph, data, opts);
 
-  var rangeSelector = g.getPluginInstance_(Dygraph.Plugins.RangeSelector);
-  assertNotNull(rangeSelector);
+  var rangeSelector = g.getPluginInstance_(RangeSelectorPlugin);
+  assert.isNotNull(rangeSelector);
 
   var combinedSeries = rangeSelector.computeCombinedSeriesAndLimits_();
-  assertEquals({
+  assert.deepEqual({
     yMin: 1 - 7 * 0.25,  // 25% padding
     yMax: 8 + 7 * 0.25,
     data: [
@@ -540,10 +598,10 @@ RangeSelectorTestCase.prototype.testSingleCombinedSeriesErrorBars = function() {
       [10, 8]
     ]
   }, combinedSeries);
-};
+});
 
 // Tests data computation for the mini plot with two custom bar series.
-RangeSelectorTestCase.prototype.testTwoCombinedSeriesCustomBars = function() {
+it('testTwoCombinedSeriesCustomBars', function() {
   var opts = {
     customBars: true,
     showRangeSelector: true,
@@ -557,11 +615,11 @@ RangeSelectorTestCase.prototype.testTwoCombinedSeriesCustomBars = function() {
   var graph = document.getElementById("graph");
   var g = new Dygraph(graph, data, opts);
 
-  var rangeSelector = g.getPluginInstance_(Dygraph.Plugins.RangeSelector);
-  assertNotNull(rangeSelector);
+  var rangeSelector = g.getPluginInstance_(RangeSelectorPlugin);
+  assert.isNotNull(rangeSelector);
 
   var combinedSeries = rangeSelector.computeCombinedSeriesAndLimits_();
-  assertEquals({
+  assert.deepEqual({
     yMin: 3 - 7 * 0.25,  // 25% padding
     yMax: 10 + 7 * 0.25,
     data: [
@@ -570,15 +628,84 @@ RangeSelectorTestCase.prototype.testTwoCombinedSeriesCustomBars = function() {
       [10, 10]
     ]
   }, combinedSeries);
-};
+});
+
+it('testHiddenSeriesExcludedFromMiniplot', function() {
+  var opts = {
+    showRangeSelector: true,
+    labels: ['X', 'Y1', 'Y2'],
+    visibility: [true, false]
+  };
+  var data = [
+      [0, 1, 3],  // average = 2
+      [5, 4, 6],  // average = 5
+      [10, 7, 9]  // average = 8
+    ];
+  var graph = document.getElementById("graph");
+  var g = new Dygraph(graph, data, opts);
+
+  var rangeSelector = g.getPluginInstance_(RangeSelectorPlugin);
+  assert.isNotNull(rangeSelector);
+
+  // Invisible series (e.g. Y2) are not included in the combined series.
+  var combinedSeries = rangeSelector.computeCombinedSeriesAndLimits_();
+  assert.deepEqual({
+    yMin: 1 - 6 * 0.25,  // 25% padding on single series range.
+    yMax: 7 + 6 * 0.25,
+    data: [
+      [0, 1],
+      [5, 4],
+      [10, 7]
+    ]
+  }, combinedSeries);
 
+  // If Y2 is explicitly marked to be included in the range selector,
+  // then it will be (even if it's not visible). Since we've started being
+  // explicit about marking series for inclusion, this means that Y1 is no
+  // longer included.
+  g.updateOptions({
+    series: {
+      Y2: { showInRangeSelector: true },
+    }
+  });
+  combinedSeries = rangeSelector.computeCombinedSeriesAndLimits_();
+  assert.deepEqual({
+    yMin: 3 - 6 * 0.25,  // 25% padding on combined series range.
+    yMax: 9 + 6 * 0.25,
+    data: [
+      [0, 3],
+      [5, 6],
+      [10, 9]
+    ]
+  }, combinedSeries);
+
+  // If we explicitly mark Y1, too, then it also gets included.
+  g.updateOptions({
+    series: {
+      Y1: { showInRangeSelector: true },
+      Y2: { showInRangeSelector: true },
+    }
+  });
+  combinedSeries = rangeSelector.computeCombinedSeriesAndLimits_();
+  assert.deepEqual({
+    yMin: 2 - 6 * 0.25,  // 25% padding on combined series range.
+    yMax: 8 + 6 * 0.25,
+    data: [
+      [0, 2],
+      [5, 5],
+      [10, 8]
+    ]
+  }, combinedSeries);
+});
 
-RangeSelectorTestCase.prototype.assertGraphExistence = function(g, graph) {
-  assertNotNull(g);
+var assertGraphExistence = function(g, graph) {
+  assert.isNotNull(g);
   var zoomhandles = graph.getElementsByClassName('dygraph-rangesel-zoomhandle');
-  assertEquals(2, zoomhandles.length);
+  assert.equal(2, zoomhandles.length);
   var bgcanvas = graph.getElementsByClassName('dygraph-rangesel-bgcanvas');
-  assertEquals(1, bgcanvas.length);
+  assert.equal(1, bgcanvas.length);
   var fgcanvas = graph.getElementsByClassName('dygraph-rangesel-fgcanvas');
-  assertEquals(1, fgcanvas.length);
-}
+  assert.equal(1, fgcanvas.length);
+};
+
+});