a1982884efede33cd8446dfcda9eae0fec786a85
[dygraphs.git] / auto_tests / tests / axis_labels.js
1 /**
2 * @fileoverview Test cases for how axis labels are chosen and formatted.
3 *
4 * @author dan@dygraphs.com (Dan Vanderkam)
5 */
6 var AxisLabelsTestCase = TestCase("axis-labels");
7
8 AxisLabelsTestCase.prototype.setUp = function() {
9 document.body.innerHTML = "<div id='graph'></div>";
10 };
11
12 AxisLabelsTestCase.prototype.tearDown = function() {
13 };
14
15
16 AxisLabelsTestCase.prototype.kCloseFloat = 1.0e-10;
17
18 AxisLabelsTestCase.prototype.testMinusOneToOne = function() {
19 var opts = {
20 width: 480,
21 height: 320
22 };
23 var data = "X,Y\n" +
24 "0,-1\n" +
25 "1,0\n" +
26 "2,1\n" +
27 "3,0\n"
28 ;
29
30 var graph = document.getElementById("graph");
31 var g = new Dygraph(graph, data, opts);
32
33 // TODO(danvk): would ['-1.0','-0.5','0.0','0.5','1.0'] be better?
34 assertEquals(['-1','-0.5','0','0.5','1'], Util.getYLabels());
35
36 // Go up to 2
37 data += "4,2\n";
38 g.updateOptions({file: data});
39 assertEquals(['-1','-0.5','0','0.5','1','1.5','2'], Util.getYLabels());
40
41 // Now 10
42 data += "5,10\n";
43 g.updateOptions({file: data});
44 assertEquals(['-2','0','2','4','6','8','10'], Util.getYLabels());
45
46 // Now 100
47 data += "6,100\n";
48 g.updateOptions({file: data});
49 assertEquals(['0','20','40','60','80','100'], Util.getYLabels());
50
51 g.setSelection(0);
52 assertEquals('0: Y:-1', Util.getLegend());
53 };
54
55 AxisLabelsTestCase.prototype.testSmallRangeNearZero = function() {
56 var opts = {
57 drawAxesAtZero: true,
58 width: 480,
59 height: 320
60 };
61 var data = "X,Y\n" +
62 "0,-1\n" +
63 "1,0\n" +
64 "2,1\n" +
65 "3,0\n"
66 ;
67 opts.valueRange = [-0.1, 0.1];
68
69 var graph = document.getElementById("graph");
70 var g = new Dygraph(graph, data, opts);
71 assertEqualsDelta([-0.1, -0.08, -0.06, -0.04, -0.02, 0, 0.02, 0.04, 0.06, 0.08],
72 Util.makeNumbers(Util.getYLabels()), this.kCloseFloat);
73
74 opts.valueRange = [-0.05, 0.05];
75 g.updateOptions(opts);
76 assertEquals([-0.05, -0.04, -0.03, -0.02, -0.01, 0, 0.01, 0.02, 0.03, 0.04],
77 Util.makeNumbers(Util.getYLabels()));
78
79 opts.valueRange = [-0.01, 0.01];
80 g.updateOptions(opts);
81 assertEquals([-0.01, -8.00e-3, -6.00e-3, -4.00e-3, -2.00e-3, 0, 2.00e-3, 4.00e-3, 6.00e-3, 8.00e-3],
82 Util.makeNumbers(Util.getYLabels()));
83
84 g.setSelection(1);
85 assertEquals('1: Y:0', Util.getLegend());
86 };
87
88 AxisLabelsTestCase.prototype.testSmallRangeAwayFromZero = function() {
89 var opts = {
90 width: 480,
91 height: 320
92 };
93 var data = "X,Y\n" +
94 "0,-1\n" +
95 "1,0\n" +
96 "2,1\n" +
97 "3,0\n"
98 ;
99 var graph = document.getElementById("graph");
100
101 opts.valueRange = [9.9, 10.1];
102 var g = new Dygraph(graph, data, opts);
103 assertEquals(["9.9","9.92","9.94","9.96","9.98","10","10.02","10.04","10.06","10.08"], Util.getYLabels());
104
105 opts.valueRange = [9.99, 10.01];
106 g.updateOptions(opts);
107 // TODO(danvk): this is bad
108 assertEquals(["9.99","9.99","9.99","10","10","10","10","10","10.01","10.01"], Util.getYLabels());
109
110 opts.valueRange = [9.999, 10.001];
111 g.updateOptions(opts);
112 // TODO(danvk): this is even worse!
113 assertEquals(["10","10","10","10","10","10","10","10","10","10"], Util.getYLabels());
114
115 g.setSelection(1);
116 assertEquals('1: Y:0', Util.getLegend());
117 };
118
119 AxisLabelsTestCase.prototype.testXAxisTimeLabelFormatter = function() {
120 var opts = {
121 width: 480,
122 height: 320
123 };
124 var data = [[5.0,0],[5.1,1],[5.2,2],[5.3,3],[5.4,4],[5.5,5],[5.6,6],[5.7,7],[5.8,8],[5.9,9]];
125 var graph = document.getElementById("graph");
126 var g = new Dygraph(graph, data, opts);
127 g.updateOptions({
128 axes : {
129 x : {
130 axisLabelFormatter : function (totalMinutes) {
131 var hours = Math.floor( totalMinutes / 60);
132 var minutes = Math.floor((totalMinutes - (hours * 60)));
133 var seconds = Math.round((totalMinutes * 60) - (hours * 3600) - (minutes * 60));
134
135 if (hours < 10) hours = "0" + hours;
136 if (minutes < 10) minutes = "0" + minutes;
137 if (seconds < 10) seconds = "0" + seconds;
138
139 return hours + ':' + minutes + ':' + seconds;
140 }
141 }
142 }
143 });
144
145 assertEquals(["00:05:00","00:05:12","00:05:24","00:05:36","00:05:48"], Util.getXLabels());
146
147 // The legend does not use the axisLabelFormatter:
148 g.setSelection(1);
149 assertEquals('5.1: Y1:1', Util.getLegend());
150 };
151
152 AxisLabelsTestCase.prototype.testAxisLabelFormatter = function () {
153 var opts = {
154 width: 480,
155 height: 320,
156 axes : {
157 x : {
158 axisLabelFormatter : function(x, granularity, opts, dg) {
159 assertEquals('number', typeof(x));
160 assertEquals('number', typeof(granularity));
161 assertEquals('function', typeof(opts));
162 assertEquals('[Dygraph graph]', dg.toString());
163 return 'x' + x;
164 }
165 },
166 y : {
167 axisLabelFormatter : function(y, granularity, opts, dg) {
168 assertEquals('number', typeof(y));
169 assertEquals('number', typeof(granularity));
170 assertEquals('function', typeof(opts));
171 assertEquals('[Dygraph graph]', dg.toString());
172 return 'y' + y;
173 }
174 }
175 },
176 labels: ['x', 'y']
177 };
178 var data = [];
179 for (var i = 0; i < 10; i++) {
180 data.push([i, 2 * i]);
181 }
182 var graph = document.getElementById("graph");
183 var g = new Dygraph(graph, data, opts);
184
185 assertEquals(['x0','x2','x4','x6','x8'], Util.getXLabels());
186 assertEquals(['y0','y2','y4','y6','y8','y10','y12','y14','y16','y18'], Util.getYLabels());
187
188 g.setSelection(2);
189 assertEquals("2: y:4", Util.getLegend());
190 };
191
192 AxisLabelsTestCase.prototype.testDateAxisLabelFormatter = function () {
193 var opts = {
194 width: 480,
195 height: 320,
196 axes : {
197 x : {
198 axisLabelFormatter : function(x, granularity, opts, dg) {
199 assertTrue(Dygraph.isDateLike(x));
200 assertEquals('number', typeof(granularity));
201 assertEquals('function', typeof(opts));
202 assertEquals('[Dygraph graph]', dg.toString());
203 return 'x' + x.strftime('%Y/%m/%d');
204 }
205 },
206 y : {
207 axisLabelFormatter : function(y, granularity, opts, dg) {
208 assertEquals('number', typeof(y));
209 assertEquals('number', typeof(granularity));
210 assertEquals('function', typeof(opts));
211 assertEquals('[Dygraph graph]', dg.toString());
212 return 'y' + y;
213 }
214 }
215 },
216 labels: ['x', 'y']
217 };
218 var data = [];
219 for (var i = 1; i < 10; i++) {
220 data.push([new Date("2011/01/0" + i), 2 * i]);
221 }
222 var graph = document.getElementById("graph");
223 var g = new Dygraph(graph, data, opts);
224
225 assertEquals(["x2011/01/01", "x2011/01/02", "x2011/01/03", "x2011/01/04", "x2011/01/05", "x2011/01/06", "x2011/01/07", "x2011/01/08", "x2011/01/09"], Util.getXLabels());
226 assertEquals(['y2','y4','y6','y8','y10','y12','y14','y16','y18'], Util.getYLabels());
227
228 g.setSelection(0);
229 assertEquals("2011/01/01: y:2", Util.getLegend());
230 };
231
232 // This test verifies that when a valueFormatter is set (but not an
233 // axisLabelFormatter), then the valueFormatter is used to format the axis
234 // labels.
235 AxisLabelsTestCase.prototype.testValueFormatter = function () {
236 var opts = {
237 width: 480,
238 height: 320,
239 axes : {
240 x : {
241 valueFormatter: function(x, opts, series_name, dg) {
242 assertEquals('number', typeof(x));
243 assertEquals('function', typeof(opts));
244 assertEquals('string', typeof(series_name));
245 assertEquals('[Dygraph graph]', dg.toString());
246 return 'x' + x;
247 }
248 },
249 y : {
250 valueFormatter: function(y, opts, series_name, dg) {
251 assertEquals('number', typeof(y));
252 assertEquals('function', typeof(opts));
253 assertEquals('string', typeof(series_name));
254 assertEquals('[Dygraph graph]', dg.toString());
255 return 'y' + y;
256 }
257 }
258 },
259 labels: ['x', 'y']
260 };
261 var data = [];
262 for (var i = 0; i < 10; i++) {
263 data.push([i, 2 * i]);
264 }
265 var graph = document.getElementById("graph");
266 var g = new Dygraph(graph, data, opts);
267
268 // the valueFormatter options do not affect the ticks.
269 assertEquals(['0','2','4','6','8'], Util.getXLabels());
270 assertEquals(['0','2','4','6','8','10','12','14','16','18'],
271 Util.getYLabels());
272
273 // they do affect the legend, however.
274 g.setSelection(2);
275 assertEquals("x2: y:y4", Util.getLegend());
276 };
277
278 AxisLabelsTestCase.prototype.testDateValueFormatter = function () {
279 var opts = {
280 width: 480,
281 height: 320,
282 axes : {
283 x : {
284 valueFormatter: function(x, opts, series_name, dg) {
285 assertEquals('number', typeof(x));
286 assertEquals('function', typeof(opts));
287 assertEquals('string', typeof(series_name));
288 assertEquals('[Dygraph graph]', dg.toString());
289 return 'x' + new Date(x).strftime('%Y/%m/%d');
290 }
291 },
292 y : {
293 valueFormatter: function(y, opts, series_name, dg) {
294 assertEquals('number', typeof(y));
295 assertEquals('function', typeof(opts));
296 assertEquals('string', typeof(series_name));
297 assertEquals('[Dygraph graph]', dg.toString());
298 return 'y' + y;
299 }
300 }
301 },
302 labels: ['x', 'y']
303 };
304
305 var data = [];
306 for (var i = 1; i < 10; i++) {
307 data.push([new Date("2011/01/0" + i), 2 * i]);
308 }
309 var graph = document.getElementById("graph");
310 var g = new Dygraph(graph, data, opts);
311
312 // valueFormatters do not affect ticks.
313 assertEquals(['01Jan','02Jan','03Jan','04Jan','05Jan','06Jan','07Jan','08Jan','09Jan'], Util.getXLabels());
314 assertEquals(['2','4','6','8','10','12','14','16','18'], Util.getYLabels());
315
316 // the valueFormatter options also affect the legend.
317 g.setSelection(2);
318 assertEquals('x2011/01/03: y:y6', Util.getLegend());
319 };
320
321 // This test verifies that when both a valueFormatter and an axisLabelFormatter
322 // are specified, the axisLabelFormatter takes precedence.
323 AxisLabelsTestCase.prototype.testAxisLabelFormatterPrecedence = function () {
324 var opts = {
325 width: 480,
326 height: 320,
327 axes : {
328 x : {
329 valueFormatter: function(x) {
330 return 'xvf' + x;
331 },
332 axisLabelFormatter: function(x, granularity) {
333 return 'x' + x;
334 }
335 },
336 y : {
337 valueFormatter: function(y) {
338 return 'yvf' + y;
339 },
340 axisLabelFormatter: function(y) {
341 return 'y' + y;
342 }
343 }
344 },
345 labels: ['x', 'y']
346 };
347 var data = [];
348 for (var i = 0; i < 10; i++) {
349 data.push([i, 2 * i]);
350 }
351 var graph = document.getElementById("graph");
352 var g = new Dygraph(graph, data, opts);
353
354 assertEquals(['x0','x2','x4','x6','x8'], Util.getXLabels());
355 assertEquals(['y0','y2','y4','y6','y8','y10','y12','y14','y16','y18'], Util.getYLabels());
356
357 g.setSelection(9);
358 assertEquals("xvf9: y:yvf18", Util.getLegend());
359 };
360
361 // This is the same as the previous test, except that options are added
362 // one-by-one.
363 AxisLabelsTestCase.prototype.testAxisLabelFormatterIncremental = function () {
364 var opts = {
365 width: 480,
366 height: 320,
367 labels: ['x', 'y']
368 };
369 var data = [];
370 for (var i = 0; i < 10; i++) {
371 data.push([i, 2 * i]);
372 }
373 var graph = document.getElementById("graph");
374 var g = new Dygraph(graph, data, opts);
375 g.updateOptions({
376 axes : {
377 x : {
378 valueFormatter: function(x) {
379 return 'xvf' + x;
380 }
381 }
382 }
383 });
384 g.updateOptions({
385 axes : {
386 y : {
387 valueFormatter: function(y) {
388 return 'yvf' + y;
389 }
390 }
391 }
392 });
393 g.updateOptions({
394 axes : {
395 x : {
396 axisLabelFormatter: function(x, granularity) {
397 return 'x' + x;
398 }
399 }
400 }
401 });
402 g.updateOptions({
403 axes : {
404 y : {
405 axisLabelFormatter: function(y) {
406 return 'y' + y;
407 }
408 }
409 }
410 });
411
412 assertEquals(["x0","x2","x4","x6","x8"], Util.getXLabels());
413 assertEquals(['y0','y2','y4','y6','y8','y10','y12','y14','y16','y18'], Util.getYLabels());
414
415 g.setSelection(9);
416 assertEquals("xvf9: y:yvf18", Util.getLegend());
417 };
418
419 AxisLabelsTestCase.prototype.testGlobalFormatters = function() {
420 var opts = {
421 width: 480,
422 height: 320,
423 labels: ['x', 'y'],
424 valueFormatter: function(x) {
425 return 'vf' + x;
426 },
427 axisLabelFormatter: function(x) {
428 return 'alf' + x;
429 }
430 };
431 var data = [];
432 for (var i = 0; i < 10; i++) {
433 data.push([i, 2 * i]);
434 }
435 var graph = document.getElementById("graph");
436 var g = new Dygraph(graph, data, opts);
437
438 assertEquals(['alf0','alf2','alf4','alf6','alf8'], Util.getXLabels());
439 assertEquals(['alf0','alf2','alf4','alf6','alf8','alf10','alf12','alf14','alf16','alf18'], Util.getYLabels());
440
441 g.setSelection(9);
442 assertEquals("vf9: y:vf18", Util.getLegend());
443 };
444
445 AxisLabelsTestCase.prototype.testSeriesOrder = function() {
446 var opts = {
447 width: 480,
448 height: 320
449 };
450 var data = "x,00,01,10,11\n" +
451 "0,101,201,301,401\n" +
452 "1,102,202,302,402\n" +
453 "2,103,203,303,403\n" +
454 "3,104,204,304,404\n"
455 ;
456
457 var graph = document.getElementById("graph");
458 var g = new Dygraph(graph, data, opts);
459
460 g.setSelection(2);
461 assertEquals('2: 00:103 01:203 10:303 11:403', Util.getLegend());
462
463 // Sanity checks for indexFromSetName
464 assertEquals(0, g.indexFromSetName("x"));
465 assertEquals(1, g.indexFromSetName("00"));
466 assertEquals(null, g.indexFromSetName("abcde"));
467
468 // Verify that we get the label list back in the right order
469 assertEquals(["x", "00", "01", "10", "11"], g.getLabels());
470 };
471
472 AxisLabelsTestCase.prototype.testLabelKMB = function() {
473 var data = [];
474 data.push([0,0]);
475 data.push([1,2000]);
476 data.push([2,1000]);
477
478 var g = new Dygraph(
479 document.getElementById("graph"),
480 data,
481 {
482 labels: [ 'X', 'bar' ],
483 axes : {
484 y: {
485 labelsKMB: true
486 }
487 }
488 }
489 );
490
491 assertEquals(["0", "500", "1K", "1.5K", "2K"], Util.getYLabels());
492 };
493
494 AxisLabelsTestCase.prototype.testLabelKMG2 = function() {
495 var data = [];
496 data.push([0,0]);
497 data.push([1,2000]);
498 data.push([2,1000]);
499
500 var g = new Dygraph(
501 document.getElementById("graph"),
502 data,
503 {
504 labels: [ 'X', 'bar' ],
505 axes : {
506 y: {
507 labelsKMG2: true
508 }
509 }
510 }
511 );
512
513 assertEquals(
514 ["0","256","512","768","1k","1.25k","1.5k","1.75k","2k"],
515 Util.getYLabels());
516 };
517
518 // Same sa testLabelKMG2 but specifies the option at the
519 // top of the option dictionary.
520 AxisLabelsTestCase.prototype.testLabelKMG2_top = function() {
521 var data = [];
522 data.push([0,0]);
523 data.push([1,2000]);
524 data.push([2,1000]);
525
526 var g = new Dygraph(
527 document.getElementById("graph"),
528 data,
529 {
530 labels: [ 'X', 'bar' ],
531 labelsKMG2: true
532 }
533 );
534
535 assertEquals(
536 ["0","256","512","768","1k","1.25k","1.5k","1.75k","2k"],
537 Util.getYLabels());
538 };
539
540 /**
541 * Verify that log scale axis range is properly specified.
542 */
543 AxisLabelsTestCase.prototype.testLogScale = function() {
544 var g = new Dygraph("graph", [[0, 5], [1, 1000]], { logscale : true });
545 var nonEmptyLabels = Util.getYLabels().filter(function(x) { return x.length > 0; });
546 assertEquals(["6","10","30","60","100","300","600","1000"], nonEmptyLabels);
547
548 g.updateOptions({ logscale : false });
549 assertEquals(['0','200','400','600','800','1000'], Util.getYLabels());
550 }
551
552 /**
553 * Verify that include zero range is properly specified.
554 */
555 AxisLabelsTestCase.prototype.testIncludeZero = function() {
556 var g = new Dygraph("graph", [[0, 500], [1, 1000]], { includeZero : true });
557 assertEquals(['0','200','400','600','800','1000'], Util.getYLabels());
558
559 g.updateOptions({ includeZero : false });
560 assertEquals(['500','600','700','800','900','1000'], Util.getYLabels());
561 }