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