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