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