Merge pull request #210 from klausw-g/range-pad-2
[dygraphs.git] / auto_tests / tests / range_tests.js
1 // Copyright (c) 2011 Google, Inc.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 // THE SOFTWARE.
20
21
22 /**
23 * @fileoverview Test valueRange and dateWindow changes.
24 *
25 * @author konigsberg@google.com (Robert Konigsberg)
26 */
27 var ZERO_TO_FIFTY = [[ 10, 0 ] , [ 20, 50 ]];
28 var ZERO_TO_FIFTY_STEPS = function() {
29 var a = [];
30 var x = 10;
31 var y = 0;
32 var step = 0;
33 for (step = 0; step <= 50; step++) {
34 a.push([x + (step * .2), y + step]);
35 }
36 return a;
37 } ();
38 var FIVE_TO_ONE_THOUSAND = [
39 [ 1, 10 ], [ 2, 20 ], [ 3, 30 ], [ 4, 40 ] , [ 5, 50 ],
40 [ 6, 60 ], [ 7, 70 ], [ 8, 80 ], [ 9, 90 ] , [ 10, 1000 ]];
41
42 var RangeTestCase = TestCase("range-tests");
43
44 RangeTestCase.prototype.setUp = function() {
45 document.body.innerHTML = "<div id='graph'></div>";
46 };
47
48 RangeTestCase.prototype.createGraph = function(opts, data, expectRangeX, expectRangeY) {
49 if (data === undefined) data = ZERO_TO_FIFTY_STEPS;
50 if (expectRangeX === undefined) expectRangeX = [10, 20];
51 if (expectRangeY === undefined) expectRangeY = [0, 55];
52 var graph = document.getElementById("graph");
53 var g = new Dygraph(graph, data, opts);
54
55 assertEqualsDelta(expectRangeX, g.xAxisRange(), 0.01);
56 assertEqualsDelta(expectRangeY, g.yAxisRange(0), 0.01);
57
58 return g;
59 };
60
61 /**
62 * Test that changes to valueRange and dateWindow are reflected
63 * appropriately.
64 */
65 RangeTestCase.prototype.testRangeSetOperations = function() {
66 var g = this.createGraph({valueRange : [ 0, 55 ]});
67
68 g.updateOptions({ dateWindow : [ 12, 18 ] });
69 assertEquals([12, 18], g.xAxisRange());
70 assertEquals([0, 55], g.yAxisRange(0));
71
72 g.updateOptions({ valueRange : [ 10, 40 ] });
73 assertEquals([12, 18], g.xAxisRange());
74 assertEquals([10, 40], g.yAxisRange(0));
75
76 g.updateOptions({ valueRange: [10, NaN] });
77 assertEquals([12, 18], g.xAxisRange());
78 assertEquals([10, 44.2], g.yAxisRange(0));
79
80 g.updateOptions({ valueRange: [10, 40] });
81 assertEquals([12, 18], g.xAxisRange());
82 assertEquals([10, 40], g.yAxisRange(0));
83
84 g.updateOptions({ valueRange: [10, null] });
85 assertEquals([12, 18], g.xAxisRange());
86 assertEquals([10, 44.2], g.yAxisRange(0));
87
88 g.updateOptions({ valueRange: [10, 40] });
89 assertEquals([12, 18], g.xAxisRange());
90 assertEquals([10, 40], g.yAxisRange(0));
91
92 g.updateOptions({ valueRange: [10, undefined] });
93 assertEquals([12, 18], g.xAxisRange());
94 assertEquals([10, 44.2], g.yAxisRange(0));
95
96 g.updateOptions({ valueRange: [10, 40] });
97 assertEquals([12, 18], g.xAxisRange());
98 assertEquals([10, 40], g.yAxisRange(0));
99
100 g.updateOptions({ });
101 assertEquals([12, 18], g.xAxisRange());
102 assertEquals([10, 40], g.yAxisRange(0));
103
104 g.updateOptions({valueRange : null, axes: {y:{valueRange : [15, 20]}}});
105 assertEquals([12, 18], g.xAxisRange());
106 assertEquals([15, 20], g.yAxisRange(0));
107
108 g.updateOptions({ dateWindow : null, valueRange : null, axes: null });
109 assertEquals([10, 20], g.xAxisRange());
110 assertEquals([0, 55], g.yAxisRange(0));
111 };
112
113 /**
114 * Verify that when zoomed in by mouse operations, an empty call to
115 * updateOptions doesn't change the displayed ranges.
116 */
117 RangeTestCase.prototype.zoom = function(g, xRange, yRange) {
118 var originalXRange = g.xAxisRange();
119 var originalYRange = g.yAxisRange(0);
120
121 DygraphOps.dispatchMouseDown(g, xRange[0], yRange[0]);
122 DygraphOps.dispatchMouseMove(g, xRange[1], yRange[0]); // this is really necessary.
123 DygraphOps.dispatchMouseUp(g, xRange[1], yRange[0]);
124
125 assertEqualsDelta(xRange, g.xAxisRange(), 0.2);
126 // assertEqualsDelta(originalYRange, g.yAxisRange(0), 0.2); // Not true, it's something in the middle.
127
128 var midX = (xRange[1] - xRange[0]) / 2;
129 DygraphOps.dispatchMouseDown(g, midX, yRange[0]);
130 DygraphOps.dispatchMouseMove(g, midX, yRange[1]); // this is really necessary.
131 DygraphOps.dispatchMouseUp(g, midX, yRange[1]);
132
133 assertEqualsDelta(xRange, g.xAxisRange(), 0.2);
134 assertEqualsDelta(yRange, g.yAxisRange(0), 0.2);
135 }
136
137
138 /**
139 * Verify that when zoomed in by mouse operations, an empty call to
140 * updateOptions doesn't change the displayed ranges.
141 */
142 RangeTestCase.prototype.testEmptyUpdateOptions_doesntUnzoom = function() {
143 var g = this.createGraph();
144 this.zoom(g, [ 11, 18 ], [ 35, 40 ]);
145
146 assertEqualsDelta([11, 18], g.xAxisRange(), 0.1);
147 assertEqualsDelta([35, 40], g.yAxisRange(0), 0.2);
148
149 g.updateOptions({});
150
151 assertEqualsDelta([11, 18], g.xAxisRange(), 0.1);
152 assertEqualsDelta([35, 40], g.yAxisRange(0), 0.2);
153 }
154
155 /**
156 * Verify that when zoomed in by mouse operations, a call to
157 * updateOptions({ dateWindow : null, valueRange : null }) fully
158 * unzooms.
159 */
160 RangeTestCase.prototype.testRestoreOriginalRanges_viaUpdateOptions = function() {
161 var g = this.createGraph();
162 this.zoom(g, [ 11, 18 ], [ 35, 40 ]);
163
164 g.updateOptions({ dateWindow : null, valueRange : null });
165
166 assertEquals([0, 55], g.yAxisRange(0));
167 assertEquals([10, 20], g.xAxisRange());
168 }
169
170 /**
171 * Verify that log scale axis range is properly specified.
172 */
173 RangeTestCase.prototype.testLogScaleExcludesZero = function() {
174 var g = new Dygraph("graph", FIVE_TO_ONE_THOUSAND, { logscale : true });
175 assertEquals([10, 1099], g.yAxisRange(0));
176
177 g.updateOptions({ logscale : false });
178 assertEquals([0, 1099], g.yAxisRange(0));
179 }
180
181 /**
182 * Verify that includeZero range is properly specified.
183 */
184 RangeTestCase.prototype.testIncludeZeroIncludesZero = function() {
185 var g = new Dygraph("graph", [[0, 500], [500, 1000]], { includeZero : true });
186 assertEquals([0, 1100], g.yAxisRange(0));
187
188 g.updateOptions({ includeZero : false });
189 assertEquals([450, 1050], g.yAxisRange(0));
190 }
191
192
193 /**
194 * Verify that includeZero range is properly specified per axis.
195 */
196 RangeTestCase.prototype.testIncludeZeroPerAxis = function() {
197 var g = new Dygraph("graph",
198 'X,A,B\n'+
199 '0,50,50\n'+
200 '50,110,110\n',
201 {
202 drawPoints: true,
203 pointSize:5,
204 series:{
205 A: {
206 axis: 'y',
207 pointSize: 10
208 },
209 B: {
210 axis: 'y2'
211 }
212 },
213 axes: {
214 'y2': { includeZero: true }
215 }
216 });
217
218
219 assertEquals([44, 116], g.yAxisRange(0));
220 assertEquals([0, 121], g.yAxisRange(1));
221
222 g.updateOptions({
223 axes: {
224 'y2': { includeZero: false }
225 }
226 });
227
228 assertEquals([44, 116], g.yAxisRange(1));
229 }
230
231
232 /**
233 * Verify that includeZero range is properly specified per axis with old axis options.
234 */
235 RangeTestCase.prototype.testIncludeZeroPerAxisOld = function() {
236 var g = new Dygraph("graph",
237 'X,A,B\n' +
238 '0,50,50\n' +
239 '50,110,110\n',
240 {
241 drawPoints: true,
242 pointSize: 5,
243
244 A: {
245 pointSize: 10
246 },
247 B: {
248 axis: {}
249 },
250 axes: {
251 'y': { includeZero: true },
252 'y2': { includeZero: false }
253 }
254 });
255
256 assertEquals([0, 121], g.yAxisRange(0));
257 assertEquals([44, 116], g.yAxisRange(1));
258
259 g.updateOptions({
260 axes: {
261 'y': { includeZero: false },
262 'y2': { includeZero: true }
263 }
264 });
265
266 assertEquals([44, 116], g.yAxisRange(0));
267 assertEquals([0, 121], g.yAxisRange(1));
268 }
269
270 /**
271 * Verify that very large Y ranges don't break things.
272 */
273 RangeTestCase.prototype.testHugeRange = function() {
274 var g = new Dygraph("graph", [[0, -1e120], [1, 1e230]], { includeZero : true });
275 assertEqualsDelta(1, -1e229 / g.yAxisRange(0)[0], 0.001);
276 assertEqualsDelta(1, 1.1e230 / g.yAxisRange(0)[1], 0.001);
277 }
278
279 /**
280 * Verify old-style avoidMinZero option.
281 */
282 RangeTestCase.prototype.testAvoidMinZero = function() {
283 var g = this.createGraph({
284 avoidMinZero: true,
285 }, ZERO_TO_FIFTY_STEPS, [10, 20], [-5, 55]);
286 };
287
288 /**
289 * Verify ranges with user-specified padding, implicit avoidMinZero.
290 */
291 RangeTestCase.prototype.testPaddingAuto = function() {
292 var g = this.createGraph({
293 xRangePad: 42,
294 yRangePad: 30
295 }, ZERO_TO_FIFTY_STEPS, [9, 21], [-5, 55]);
296 };
297
298 /**
299 * Verify auto range with drawAxesAtZero.
300 */
301 RangeTestCase.prototype.testPaddingAutoAxisAtZero = function() {
302 var g = this.createGraph({
303 drawAxesAtZero: true,
304 }, ZERO_TO_FIFTY_STEPS, [10, 20], [0, 55]);
305 };
306
307 /**
308 * Verify user-specified range with padding and drawAxesAtZero options.
309 * Try explicit range matching the auto range, should have identical results.
310 */
311 RangeTestCase.prototype.testPaddingRange1 = function() {
312 var g = this.createGraph({
313 valueRange: [0, 50],
314 xRangePad: 42,
315 yRangePad: 30,
316 drawAxesAtZero: true
317 }, ZERO_TO_FIFTY_STEPS, [9, 21], [-5, 55]);
318 };
319
320 /**
321 * Verify user-specified range with padding and drawAxesAtZero options.
322 * User-supplied range differs from the auto range.
323 */
324 RangeTestCase.prototype.testPaddingRange2 = function() {
325 var g = this.createGraph({
326 valueRange: [10, 60],
327 xRangePad: 42,
328 yRangePad: 30,
329 drawAxesAtZero: true,
330 }, ZERO_TO_FIFTY_STEPS, [9, 21], [5, 65]);
331 };
332
333 /**
334 * Verify drawAxesAtZero and includeZero.
335 */
336 RangeTestCase.prototype.testPaddingYAtZero = function() {
337 var g = this.createGraph({
338 includeZero: true,
339 xRangePad: 42,
340 yRangePad: 30,
341 drawAxesAtZero: true,
342 }, [
343 [-10, 10],
344 [10, 20],
345 [30, 50]
346 ], [-14, 34], [-5, 55]);
347 };
348
349 /**
350 * Verify logscale, compat mode.
351 */
352 RangeTestCase.prototype.testLogscaleCompat = function() {
353 var g = this.createGraph({
354 logscale: true
355 },
356 [[-10, 10], [10, 10], [30, 1000]],
357 [-10, 30], [10, 1099]);
358 };
359
360 /**
361 * Verify logscale, new mode.
362 */
363 RangeTestCase.prototype.testLogscalePad = function() {
364 var g = this.createGraph({
365 logscale: true,
366 yRangePad: 30
367 },
368 [[-10, 10], [10, 10], [30, 1000]],
369 [-10, 30], [5.01691, 1993.25801]);
370 };
371
372 /**
373 * Verify scrolling all-zero region, traditional.
374 */
375 RangeTestCase.prototype.testZeroScroll = function() {
376 g = new Dygraph(
377 document.getElementById("graph"),
378 "X,Y\n" +
379 "1,0\n" +
380 "8,0\n" +
381 "9,0.1\n",
382 {
383 drawAxesAtZero: true,
384 animatedZooms: true,
385 avoidMinZero: true
386 });
387 };
388
389 /**
390 * Verify scrolling all-zero region, new-style.
391 */
392 RangeTestCase.prototype.testZeroScroll2 = function() {
393 g = new Dygraph(
394 document.getElementById("graph"),
395 "X,Y\n" +
396 "1,0\n" +
397 "8,0\n" +
398 "9,0.1\n",
399 {
400 animatedZooms: true,
401 drawAxesAtZero: true,
402 xRangePad: 4,
403 yRangePad: 4
404 });
405 };