Fork off Karma file for in-browser debug
[dygraphs.git] / auto_tests / tests / range_selector.js
CommitLineData
ccd9d7c2
PF
1// Copyright 2011 Google Inc. All Rights Reserved.
2
3/**
4 * @fileoverview Regression tests for range selector.
5 * @author paul.eric.felix@gmail.com (Paul Felix)
6 */
89fdcedb 7describe("range-selector", function() {
ccd9d7c2 8
1b7afc93
DV
9var restoreConsole;
10var logs = {};
89fdcedb 11beforeEach(function() {
ccd9d7c2 12 document.body.innerHTML = "<div id='graph'></div>";
1b7afc93 13 restoreConsole = Util.captureConsole(logs);
89fdcedb 14});
ccd9d7c2 15
89fdcedb 16afterEach(function() {
1b7afc93 17 restoreConsole();
89fdcedb 18});
ccd9d7c2 19
89fdcedb 20it('testRangeSelector', function() {
ccd9d7c2
PF
21 var opts = {
22 width: 480,
23 height: 320,
b1a96215
DV
24 showRangeSelector: true,
25 labels: ['X', 'Y']
ccd9d7c2
PF
26 };
27 var data = [
28 [1, 10],
29 [2, 15],
30 [3, 10],
31 [4, 15],
32 [5, 10],
33 [6, 15],
34 [7, 10],
35 [8, 15],
36 [9, 10]
37 ];
38 var graph = document.getElementById("graph");
39 var g = new Dygraph(graph, data, opts);
319d0361 40 assertGraphExistence(g, graph);
89fdcedb 41});
ccd9d7c2 42
89fdcedb 43it('testRangeSelectorWithErrorBars', function() {
ccd9d7c2
PF
44 var opts = {
45 width: 480,
46 height: 320,
47 errorBars: true,
b1a96215
DV
48 showRangeSelector: true,
49 labels: ['X', 'Y']
ccd9d7c2
PF
50 };
51 var data = [
52 [1, [10, 10]],
53 [2, [15, 10]],
54 [3, [10, 10]],
55 [4, [15, 10]],
56 [5, [10, 10]],
57 [6, [15, 20]],
58 [7, [10, 20]],
59 [8, [15, 20]],
60 [9, [10, 20]]
61 ];
62 var graph = document.getElementById("graph");
63 var g = new Dygraph(graph, data, opts);
319d0361 64 assertGraphExistence(g, graph);
89fdcedb 65});
ccd9d7c2 66
89fdcedb 67it('testRangeSelectorWithCustomBars', function() {
ccd9d7c2
PF
68 var opts = {
69 width: 480,
70 height: 320,
71 customBars: true,
b1a96215
DV
72 showRangeSelector: true,
73 labels: ['X', 'Y']
ccd9d7c2
PF
74 };
75 var data = [
76 [1, [10, 10, 100]],
77 [2, [15, 20, 110]],
78 [3, [10, 30, 100]],
79 [4, [15, 40, 110]],
80 [5, [10, 120, 100]],
81 [6, [15, 50, 110]],
82 [7, [10, 70, 100]],
83 [8, [15, 90, 110]],
84 [9, [10, 50, 100]]
85 ];
86 var graph = document.getElementById("graph");
87 var g = new Dygraph(graph, data, opts);
319d0361 88 assertGraphExistence(g, graph);
89fdcedb 89});
ccd9d7c2 90
89fdcedb 91it('testRangeSelectorWithLogScale', function() {
ccd9d7c2
PF
92 var opts = {
93 width: 480,
94 height: 320,
95 logscale: true,
b1a96215
DV
96 showRangeSelector: true,
97 labels: ['X', 'Y']
ccd9d7c2
PF
98 };
99 var data = [
100 [1, 10],
101 [2, 15],
102 [3, 10],
103 [4, 15],
104 [5, 10],
105 [6, 15],
106 [7, 10],
107 [8, 15],
108 [9, 10]
109 ];
110 var graph = document.getElementById("graph");
111 var g = new Dygraph(graph, data, opts);
319d0361 112 assertGraphExistence(g, graph);
89fdcedb 113});
ccd9d7c2 114
89fdcedb 115it('testRangeSelectorOptions', function() {
ccd9d7c2
PF
116 var opts = {
117 width: 480,
118 height: 320,
119 showRangeSelector: true,
120 rangeSelectorHeight: 30,
121 rangeSelectorPlotFillColor: 'lightyellow',
79cb28dd 122 rangeSelectorPlotFillGradientColor: 'rgba(200, 200, 42, 10)',
b1a96215 123 labels: ['X', 'Y']
ccd9d7c2
PF
124 };
125 var data = [
126 [1, 10],
127 [2, 15],
128 [3, 10],
129 [4, 15],
130 [5, 10],
131 [6, 15],
132 [7, 10],
133 [8, 15],
134 [9, 10]
135 ];
136 var graph = document.getElementById("graph");
137 var g = new Dygraph(graph, data, opts);
319d0361 138 assertGraphExistence(g, graph);
89fdcedb 139});
ccd9d7c2 140
89fdcedb 141it('testAdditionalRangeSelectorOptions', function() {
b77d7a56 142 var opts = {
143 width: 480,
144 height: 320,
145 showRangeSelector: true,
146 rangeSelectorHeight: 30,
fb24d32c 147 rangeSelectorBackgroundStrokeColor: 'blue',
148 rangeSelectorBackgroundLineWidth: 3,
b77d7a56 149 rangeSelectorPlotLineWidth: 0.5,
fb24d32c 150 rangeSelectorForegroundStrokeColor: 'red',
151 rangeSelectorForegroundLineWidth: 2,
b77d7a56 152 rangeSelectorAlpha: 0.8,
153 labels: ['X', 'Y']
154 };
155 var data = [
156 [1, 10],
157 [2, 15],
158 [3, 10],
159 [4, 15],
160 [5, 10],
161 [6, 15],
162 [7, 10],
163 [8, 15],
164 [9, 10]
165 ];
166 var graph = document.getElementById("graph");
167 var g = new Dygraph(graph, data, opts);
319d0361 168 assertGraphExistence(g, graph);
89fdcedb 169});
b77d7a56 170
89fdcedb 171it('testRangeSelectorEnablingAfterCreation', function() {
ceb821aa
PF
172 var opts = {
173 width: 480,
b1a96215
DV
174 height: 320,
175 labels: ['X', 'Y']
ceb821aa
PF
176 };
177 var data = [
178 [1, 10],
179 [2, 15],
180 [3, 10],
181 [4, 15],
182 [5, 10],
183 [6, 15],
184 [7, 10],
185 [8, 15],
186 [9, 10]
187 ];
188 var graph = document.getElementById("graph");
189 var g = new Dygraph(graph, data, opts);
44310217 190 var initialChartHeight = g.getArea().h;
ceb821aa 191 g.updateOptions({showRangeSelector: true});
319d0361 192 assertGraphExistence(g, graph);
44310217
DV
193 assert(g.getArea().h < initialChartHeight); // range selector shown
194
195 g.updateOptions({showRangeSelector: false});
196 assert.equal(g.getArea().h, initialChartHeight); // range selector hidden
89fdcedb 197});
ceb821aa
PF
198
199// The animatedZooms option does not work with the range selector. Make sure it gets turned off.
89fdcedb 200it('testRangeSelectorWithAnimatedZoomsOption', function() {
ceb821aa
PF
201 var opts = {
202 width: 480,
203 height: 320,
204 showRangeSelector: true,
b1a96215
DV
205 animatedZooms: true,
206 labels: ['X', 'Y']
ceb821aa
PF
207 };
208 var data = [
209 [1, 10],
210 [2, 15],
211 [3, 10],
212 [4, 15],
213 [5, 10],
214 [6, 15],
215 [7, 10],
216 [8, 15],
217 [9, 10]
218 ];
219 var graph = document.getElementById("graph");
220 var g = new Dygraph(graph, data, opts);
319d0361 221 assertGraphExistence(g, graph);
89fdcedb 222 assert.isFalse(g.getOption('animatedZooms'));
1b7afc93
DV
223 assert.deepEqual(logs, {
224 log: [], error: [],
225 warn: ["Animated zooms and range selector are not compatible; disabling animatedZooms."]
226 });
89fdcedb 227});
ceb821aa 228
89fdcedb 229it('testRangeSelectorWithAnimatedZoomsOption2', function() {
ceb821aa
PF
230 var opts = {
231 width: 480,
232 height: 320,
b1a96215
DV
233 animatedZooms: true,
234 labels: ['X', 'Y']
ceb821aa
PF
235 };
236 var data = [
237 [1, 10],
238 [2, 15],
239 [3, 10],
240 [4, 15],
241 [5, 10],
242 [6, 15],
243 [7, 10],
244 [8, 15],
245 [9, 10]
246 ];
247 var graph = document.getElementById("graph");
248 var g = new Dygraph(graph, data, opts);
249 g.updateOptions({showRangeSelector: true});
319d0361 250 assertGraphExistence(g, graph);
89fdcedb 251 assert.isFalse(g.getOption('animatedZooms'));
1b7afc93
DV
252 assert.deepEqual(logs, {
253 log: [], error: [],
254 warn: ["Animated zooms and range selector are not compatible; disabling animatedZooms."]
255 });
89fdcedb 256});
ceb821aa 257
89fdcedb 258it('testRangeSelectorInteraction', function() {
2871344a
PF
259 var opts = {
260 width: 480,
261 height: 320,
b1a96215
DV
262 showRangeSelector: true,
263 labels: ['X', 'Y']
2871344a
PF
264 };
265 var data = [
266 [1, 10],
267 [2, 15],
268 [3, 10],
269 [4, 15],
270 [5, 10],
271 [6, 15],
272 [7, 10],
273 [8, 15],
274 [9, 10]
275 ];
276 var graph = document.getElementById("graph");
277 var g = new Dygraph(graph, data, opts);
319d0361 278 assertGraphExistence(g, graph);
2871344a
PF
279 var zoomhandles = graph.getElementsByClassName('dygraph-rangesel-zoomhandle');
280
281 // Move left zoomhandle in
282 var xRange = g.xAxisRange().slice();
283
284 var mouseDownEvent = DygraphOps.createEvent({
285 type : 'dragstart',
286 detail: 1,
287 clientX : 0,
288 clientY : 0
289 });
290 zoomhandles[0].dispatchEvent(mouseDownEvent);
291
292 var mouseMoveEvent = DygraphOps.createEvent({
293 type : 'mousemove',
294 clientX : 20,
295 clientY : 20
296 });
297 zoomhandles[0].dispatchEvent(mouseMoveEvent);
298
299 var mouseUpEvent = DygraphOps.createEvent({
300 type : 'mouseup',
301 detail: 1,
302 clientX : 20,
303 clientY : 20
304 });
305 zoomhandles[0].dispatchEvent(mouseUpEvent);
306
307 var newXRange = g.xAxisRange().slice();
fecbcf34 308 assert(newXRange[0] > xRange[0], 'left zoomhandle should have moved: '+newXRange[0]+'>'+xRange[0]);
dc910fce 309 assert.equal(xRange[1], newXRange[1], 'right zoomhandle should not have moved');
2871344a
PF
310
311 // Move right zoomhandle in
312 xRange = newXRange;
313
314 mouseDownEvent = DygraphOps.createEvent({
315 type : 'dragstart',
316 detail: 1,
317 clientX : 100,
318 clientY : 100
319 });
320 zoomhandles[1].dispatchEvent(mouseDownEvent);
321
322 mouseMoveEvent = DygraphOps.createEvent({
323 type : 'mousemove',
324 clientX : 80,
325 clientY : 80
326 });
327 zoomhandles[1].dispatchEvent(mouseMoveEvent);
328
329 mouseUpEvent = DygraphOps.createEvent({
330 type : 'mouseup',
331 detail: 1,
332 clientX : 80,
333 clientY : 80
334 });
335 zoomhandles[1].dispatchEvent(mouseUpEvent);
336
337 var newXRange = g.xAxisRange().slice();
dc910fce
DV
338 assert(newXRange[1] < xRange[1], 'right zoomhandle should have moved: '+newXRange[1]+'<'+xRange[1]);
339 assert.equal(xRange[0], newXRange[0], 'left zoomhandle should not have moved');
2871344a
PF
340
341 // Pan left
342 xRange = newXRange;
343 var fgcanvas = graph.getElementsByClassName('dygraph-rangesel-fgcanvas')[0];
344 var x = parseInt(zoomhandles[0].style.left) + 20;
345 var y = parseInt(zoomhandles[0].style.top);
346
347 mouseDownEvent = DygraphOps.createEvent({
348 type : 'mousedown',
349 detail: 1,
350 clientX : x,
351 clientY : y
352 });
353 fgcanvas.dispatchEvent(mouseDownEvent);
354
355 x -= 10;
356
357 mouseMoveEvent = DygraphOps.createEvent({
358 type : 'mousemove',
359 clientX : x,
360 clientY : y
361 });
362 fgcanvas.dispatchEvent(mouseMoveEvent);
363
364 mouseUpEvent = DygraphOps.createEvent({
365 type : 'mouseup',
366 detail: 1,
367 clientX : x,
368 clientY : y
369 });
370 fgcanvas.dispatchEvent(mouseUpEvent);
371
372 var newXRange = g.xAxisRange().slice();
fecbcf34
DV
373 assert(newXRange[0] < xRange[0], newXRange[0]+'<'+xRange[0]);
374 assert(newXRange[1] < xRange[1], newXRange[1]+'<'+xRange[1]);
89fdcedb 375});
2871344a 376
3718778b 377
89fdcedb 378it('testRangeSelectorPositionIfXAxisNotDrawn', function() {
3718778b
DE
379 var opts = {
380 width: 480,
381 height: 100,
382 xAxisHeight: 30,
bfb3e0a4 383 axes : { x : { drawAxis: false }},
3718778b 384 showRangeSelector: true,
b1a96215
DV
385 rangeSelectorHeight: 30,
386 labels: ['X', 'Y']
3718778b
DE
387 };
388 var data = [
389 [0, 1],
390 [10, 1]
391 ];
392 var graph = document.getElementById("graph");
393 var g = new Dygraph(graph, data, opts);
b77d7a56 394
3718778b 395 //assert, that the range selector is at top position 70 since the 30px of the
55cf43c3 396 // xAxis shouldn't be reserved since it isn't drawn.
319d0361 397 assertGraphExistence(g, graph);
3718778b 398 var bgcanvas = graph.getElementsByClassName('dygraph-rangesel-bgcanvas')[0];
dc910fce 399 assert.equal("70px", bgcanvas.style.top, "Range selector is not at the expected position.");
3718778b 400 var fgcanvas = graph.getElementsByClassName('dygraph-rangesel-fgcanvas')[0];
dc910fce 401 assert.equal("70px", fgcanvas.style.top, "Range selector is not at the expected position.");
89fdcedb 402});
3718778b 403
89fdcedb 404it('testMiniPlotDrawn', function() {
b1a96215
DV
405 // Install Proxy to track canvas calls.
406 var origFunc = Dygraph.getContext;
407 var miniHtx;
408 Dygraph.getContext = function(canvas) {
409 if (canvas.className != 'dygraph-rangesel-bgcanvas') {
410 return origFunc(canvas);
411 }
412 miniHtx = new Proxy(origFunc(canvas));
413 return miniHtx;
414 };
415
416 var opts = {
417 width: 480,
418 height: 100,
419 xAxisHeight: 30,
bfb3e0a4 420 axes : { x : { drawAxis: false }},
b1a96215
DV
421 showRangeSelector: true,
422 rangeSelectorHeight: 30,
423 rangeSelectorPlotStrokeColor: '#ff0000',
424 labels: ['X', 'Y']
425 };
426 var data = [
427 [0, 1],
428 [5, 4],
429 [10, 8]
430 ];
431 var graph = document.getElementById("graph");
432 var g = new Dygraph(graph, data, opts);
433
434 // TODO(danvk): more precise tests.
89fdcedb
DV
435 assert.isNotNull(miniHtx);
436 assert.isTrue(0 < CanvasAssertions.numLinesDrawn(miniHtx, '#ff0000'));
b1a96215
DV
437
438 Dygraph.getContext = origFunc;
89fdcedb 439});
b1a96215
DV
440
441// Tests data computation for the mini plot with a single series.
89fdcedb 442it('testSingleCombinedSeries', function() {
b1a96215
DV
443 var opts = {
444 showRangeSelector: true,
445 labels: ['X', 'Y1']
446 };
447 var data = [
448 [0, 1],
449 [5, 4],
450 [10, 8]
451 ];
452 var graph = document.getElementById("graph");
453 var g = new Dygraph(graph, data, opts);
454
455 var rangeSelector = g.getPluginInstance_(Dygraph.Plugins.RangeSelector);
89fdcedb 456 assert.isNotNull(rangeSelector);
b1a96215
DV
457
458 var combinedSeries = rangeSelector.computeCombinedSeriesAndLimits_();
89fdcedb 459 assert.deepEqual({
b1a96215
DV
460 yMin: 1 - 7 * 0.25, // 25% padding
461 yMax: 8 + 7 * 0.25,
462 data: [
463 [0, 1],
464 [5, 4],
465 [10, 8]
466 ]
467 }, combinedSeries);
89fdcedb 468});
b1a96215
DV
469
470
471// Tests that multiple series are averaged for the miniplot.
89fdcedb 472it('testCombinedSeries', function() {
b1a96215
DV
473 var opts = {
474 showRangeSelector: true,
475 labels: ['X', 'Y1', 'Y2']
476 };
477 var data = [
478 [0, 1, 3], // average = 2
479 [5, 4, 6], // average = 5
480 [10, 7, 9] // average = 8
481 ];
482 var graph = document.getElementById("graph");
483 var g = new Dygraph(graph, data, opts);
484
485 var rangeSelector = g.getPluginInstance_(Dygraph.Plugins.RangeSelector);
89fdcedb 486 assert.isNotNull(rangeSelector);
b1a96215
DV
487
488 var combinedSeries = rangeSelector.computeCombinedSeriesAndLimits_();
89fdcedb 489 assert.deepEqual({
b1a96215
DV
490 yMin: 2 - 6 * 0.25, // 25% padding on combined series range.
491 yMax: 8 + 6 * 0.25,
492 data: [
493 [0, 2],
494 [5, 5],
495 [10, 8]
496 ]
497 }, combinedSeries);
89fdcedb 498});
b1a96215 499
1085dbce 500// Tests selection of a specific series to average for the mini plot.
89fdcedb 501it('testSelectedCombinedSeries', function() {
1085dbce
PP
502 var opts = {
503 showRangeSelector: true,
0a0885d1
DV
504 labels: ['X', 'Y1', 'Y2', 'Y3', 'Y4'],
505 series: {
506 'Y1': { showInRangeSelector: true },
507 'Y3': { showInRangeSelector: true }
508 }
1085dbce
PP
509 };
510 var data = [
511 [0, 5, 8, 13, 21], // average (first and third) = 9
512 [5, 1, 3, 7, 14], // average (first and third) = 4
513 [10, 0, 19, 10, 6] // average (first and third) = 5
514 ];
515 var graph = document.getElementById("graph");
516 var g = new Dygraph(graph, data, opts);
517
518 var rangeSelector = g.getPluginInstance_(Dygraph.Plugins.RangeSelector);
89fdcedb 519 assert.isNotNull(rangeSelector);
1085dbce
PP
520
521 var combinedSeries = rangeSelector.computeCombinedSeriesAndLimits_();
89fdcedb 522 assert.deepEqual({
1085dbce
PP
523 yMin: 4 - 5 * 0.25, // 25% padding on combined series range.
524 yMax: 9 + 5 * 0.25,
525 data: [
526 [0, 9],
527 [5, 4],
528 [10, 5]
529 ]
530 }, combinedSeries);
89fdcedb 531});
1085dbce 532
b1a96215 533// Tests data computation for the mini plot with a single error bar series.
89fdcedb 534it('testSingleCombinedSeriesCustomBars', function() {
b1a96215
DV
535 var opts = {
536 customBars: true,
537 showRangeSelector: true,
538 labels: ['X', 'Y1']
539 };
540 var data = [
541 [0, [0, 1, 2]], // [low, value, high]
542 [5, [1, 4, 5]],
543 [10, [7, 8, 9]]
544 ];
545 var graph = document.getElementById("graph");
546 var g = new Dygraph(graph, data, opts);
547
548 var rangeSelector = g.getPluginInstance_(Dygraph.Plugins.RangeSelector);
89fdcedb 549 assert.isNotNull(rangeSelector);
b1a96215
DV
550
551 var combinedSeries = rangeSelector.computeCombinedSeriesAndLimits_();
89fdcedb 552 assert.deepEqual({
b1a96215
DV
553 yMin: 1 - 7 * 0.25, // 25% padding
554 yMax: 8 + 7 * 0.25,
555 data: [
556 [0, 1],
557 [5, 4],
558 [10, 8]
559 ]
560 }, combinedSeries);
89fdcedb 561});
b1a96215 562
89fdcedb 563it('testSingleCombinedSeriesErrorBars', function() {
b1a96215
DV
564 var opts = {
565 errorBars: true,
566 showRangeSelector: true,
567 labels: ['X', 'Y1']
568 };
569 var data = [
570 [0, [1, 1]], // [value, standard deviation]
571 [5, [4, 2]],
572 [10, [8, 1]]
573 ];
574 var graph = document.getElementById("graph");
575 var g = new Dygraph(graph, data, opts);
576
577 var rangeSelector = g.getPluginInstance_(Dygraph.Plugins.RangeSelector);
89fdcedb 578 assert.isNotNull(rangeSelector);
b1a96215
DV
579
580 var combinedSeries = rangeSelector.computeCombinedSeriesAndLimits_();
89fdcedb 581 assert.deepEqual({
b1a96215
DV
582 yMin: 1 - 7 * 0.25, // 25% padding
583 yMax: 8 + 7 * 0.25,
584 data: [
585 [0, 1],
586 [5, 4],
587 [10, 8]
588 ]
589 }, combinedSeries);
89fdcedb 590});
b1a96215
DV
591
592// Tests data computation for the mini plot with two custom bar series.
89fdcedb 593it('testTwoCombinedSeriesCustomBars', function() {
b1a96215
DV
594 var opts = {
595 customBars: true,
596 showRangeSelector: true,
597 labels: ['X', 'Y1', 'Y2']
598 };
599 var data = [
600 [0, [0, 1, 2], [4, 5, 6]], // [low, value, high], avg_val = 3
601 [5, [1, 4, 5], [5, 8, 9]], // avg_val = 6
602 [10, [7, 8, 9], [11, 12, 13]] // avg_val = 10
603 ];
604 var graph = document.getElementById("graph");
605 var g = new Dygraph(graph, data, opts);
606
607 var rangeSelector = g.getPluginInstance_(Dygraph.Plugins.RangeSelector);
89fdcedb 608 assert.isNotNull(rangeSelector);
b1a96215
DV
609
610 var combinedSeries = rangeSelector.computeCombinedSeriesAndLimits_();
89fdcedb 611 assert.deepEqual({
b1a96215
DV
612 yMin: 3 - 7 * 0.25, // 25% padding
613 yMax: 10 + 7 * 0.25,
614 data: [
615 [0, 3],
616 [5, 6],
617 [10, 10]
618 ]
619 }, combinedSeries);
89fdcedb 620});
b1a96215
DV
621
622
319d0361 623var assertGraphExistence = function(g, graph) {
89fdcedb 624 assert.isNotNull(g);
88c4a47e 625 var zoomhandles = graph.getElementsByClassName('dygraph-rangesel-zoomhandle');
89fdcedb 626 assert.equal(2, zoomhandles.length);
88c4a47e 627 var bgcanvas = graph.getElementsByClassName('dygraph-rangesel-bgcanvas');
89fdcedb 628 assert.equal(1, bgcanvas.length);
88c4a47e 629 var fgcanvas = graph.getElementsByClassName('dygraph-rangesel-fgcanvas');
89fdcedb 630 assert.equal(1, fgcanvas.length);
319d0361 631};
89fdcedb
DV
632
633});