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