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