Commit | Line | Data |
---|---|---|
5469113b | 1 | /** |
1c6b239c | 2 | * @fileoverview Test cases for the callbacks. |
3 | * | |
4 | * @author uemit.seren@gmail.com (Ümit Seren) | |
5 | */ | |
6 | ||
7 | var CallbackTestCase = TestCase("callback"); | |
8 | ||
9 | CallbackTestCase.prototype.setUp = function() { | |
857a6931 KW |
10 | document.body.innerHTML = "<div id='graph'></div><div id='selection'></div>"; |
11 | this.styleSheet = document.createElement("style"); | |
12 | this.styleSheet.type = "text/css"; | |
13 | document.getElementsByTagName("head")[0].appendChild(this.styleSheet); | |
1c6b239c | 14 | }; |
15 | ||
16 | CallbackTestCase.prototype.tearDown = function() { | |
17 | }; | |
475f7420 KW |
18 | |
19 | var data = "X,a\,b,c\n" + | |
1c6b239c | 20 | "10,-1,1,2\n" + |
21 | "11,0,3,1\n" + | |
22 | "12,1,4,2\n" + | |
23 | "13,0,2,3\n"; | |
857a6931 | 24 | |
475f7420 KW |
25 | |
26 | /** | |
27 | * This tests that when the function idxToRow_ returns the proper row and the onHiglightCallback | |
28 | * is properly called when the first series is hidden (setVisibility = false) | |
29 | * | |
30 | */ | |
31 | CallbackTestCase.prototype.testHighlightCallbackIsCalled = function() { | |
32 | var h_row; | |
33 | var h_pts; | |
34 | ||
35 | var highlightCallback = function(e, x, pts, row) { | |
36 | h_row = row; | |
37 | h_pts = pts; | |
38 | }; | |
39 | ||
40 | var graph = document.getElementById("graph"); | |
41 | var g = new Dygraph(graph, data, | |
42 | { | |
43 | width: 100, | |
44 | height: 100, | |
45 | visibility: [false, true, true], | |
46 | highlightCallback: highlightCallback | |
47 | }); | |
48 | ||
49 | DygraphOps.dispatchMouseMove(g, 13, 10); | |
50 | ||
51 | //check correct row is returned | |
52 | assertEquals(3, h_row); | |
53 | //check there are only two points (because first series is hidden) | |
54 | assertEquals(2, h_pts.length); | |
55 | }; | |
56 | ||
a8332379 RK |
57 | |
58 | /** | |
59 | * Test that drawPointCallback isn't called when drawPoints is false | |
60 | */ | |
61 | CallbackTestCase.prototype.testDrawPointCallback_disabled = function() { | |
62 | var called = false; | |
63 | ||
72c12eda | 64 | var callback = function() { |
a8332379 | 65 | called = true; |
5469113b | 66 | }; |
a8332379 RK |
67 | |
68 | var graph = document.getElementById("graph"); | |
69 | var g = new Dygraph(graph, data, { | |
70 | drawPointCallback : callback, | |
71 | }); | |
72 | ||
73 | assertFalse(called); | |
74 | }; | |
75 | ||
76 | /** | |
77 | * Test that drawPointCallback is called when drawPoints is true | |
78 | */ | |
79 | CallbackTestCase.prototype.testDrawPointCallback_enabled = function() { | |
80 | var called = false; | |
81 | ||
72c12eda | 82 | var callback = function() { |
a8332379 | 83 | called = true; |
5469113b | 84 | }; |
a8332379 RK |
85 | |
86 | var graph = document.getElementById("graph"); | |
87 | var g = new Dygraph(graph, data, { | |
88 | drawPoints : true, | |
89 | drawPointCallback : callback | |
90 | }); | |
91 | ||
92 | assertTrue(called); | |
93 | }; | |
72c12eda RK |
94 | |
95 | /** | |
96 | * Test that drawPointCallback is called when drawPoints is true | |
97 | */ | |
98 | CallbackTestCase.prototype.testDrawPointCallback_pointSize = function() { | |
99 | var pointSize = 0; | |
100 | var count = 0; | |
101 | ||
102 | var callback = function(g, seriesName, canvasContext, cx, cy, color, pointSizeParam) { | |
103 | pointSize = pointSizeParam; | |
104 | count++; | |
5469113b | 105 | }; |
72c12eda RK |
106 | |
107 | var graph = document.getElementById("graph"); | |
108 | var g = new Dygraph(graph, data, { | |
109 | drawPoints : true, | |
110 | drawPointCallback : callback | |
111 | }); | |
112 | ||
113 | assertEquals(1.5, pointSize); | |
114 | assertEquals(12, count); // one call per data point. | |
115 | ||
116 | var g = new Dygraph(graph, data, { | |
117 | drawPoints : true, | |
118 | drawPointCallback : callback, | |
119 | pointSize : 8 | |
120 | }); | |
121 | ||
122 | assertEquals(8, pointSize); | |
123 | }; | |
124 | ||
125 | /** | |
41273327 KW |
126 | * Test that drawPointCallback is called for isolated points when |
127 | * drawPoints is false, and also for gap points if that's enabled. | |
128 | */ | |
129 | CallbackTestCase.prototype.testDrawPointCallback_isolated = function() { | |
130 | var xvalues = []; | |
131 | ||
132 | var g; | |
133 | var callback = function(g, seriesName, canvasContext, cx, cy, color, pointSizeParam) { | |
134 | var dx = g.toDataXCoord(cx); | |
135 | xvalues.push(dx); | |
136 | Dygraph.Circles.DEFAULT.apply(this, arguments); | |
137 | }; | |
138 | ||
139 | var graph = document.getElementById("graph"); | |
140 | var testdata = [[10, 2], [11, 3], [12, NaN], [13, 2], [14, NaN], [15, 3]]; | |
141 | var graphOpts = { | |
142 | labels: ['X', 'Y'], | |
143 | valueRange: [0, 4], | |
144 | drawPoints : false, | |
145 | drawPointCallback : callback, | |
146 | pointSize : 8 | |
147 | }; | |
148 | ||
149 | // Test that isolated points get drawn | |
150 | g = new Dygraph(graph, testdata, graphOpts); | |
151 | assertEquals(2, xvalues.length); | |
152 | assertEquals(13, xvalues[0]); | |
153 | assertEquals(15, xvalues[1]); | |
154 | ||
a5a50727 KW |
155 | // Test that isolated points + gap points get drawn when |
156 | // drawGapEdgePoints is set. This should add one point at the right | |
157 | // edge of the segment at x=11, but not at the graph edge at x=10. | |
41273327 | 158 | xvalues = []; // Reset for new test |
a5a50727 | 159 | graphOpts.drawGapEdgePoints = true; |
41273327 KW |
160 | g = new Dygraph(graph, testdata, graphOpts); |
161 | assertEquals(3, xvalues.length); | |
162 | assertEquals(11, xvalues[0]); | |
163 | assertEquals(13, xvalues[1]); | |
164 | assertEquals(15, xvalues[2]); | |
165 | }; | |
166 | ||
167 | /** | |
72c12eda | 168 | * This tests that when the function idxToRow_ returns the proper row and the onHiglightCallback |
5469113b KW |
169 | * is properly called when the first series is hidden (setVisibility = false) |
170 | * | |
72c12eda | 171 | */ |
5879307d | 172 | CallbackTestCase.prototype.testDrawHighlightPointCallbackIsCalled = function() { |
72c12eda RK |
173 | var called = false; |
174 | ||
5879307d | 175 | var drawHighlightPointCallback = function() { |
72c12eda | 176 | called = true; |
5469113b | 177 | }; |
72c12eda RK |
178 | |
179 | var graph = document.getElementById("graph"); | |
180 | var g = new Dygraph(graph, data, | |
181 | { | |
182 | width: 100, | |
183 | height : 100, | |
5879307d | 184 | drawHighlightPointCallback : drawHighlightPointCallback |
72c12eda RK |
185 | }); |
186 | ||
187 | assertFalse(called); | |
188 | DygraphOps.dispatchMouseMove(g, 13, 10); | |
189 | assertTrue(called); | |
190 | }; | |
5469113b | 191 | |
475f7420 KW |
192 | /** |
193 | * Test the closest-series highlighting methods for normal and stacked modes. | |
194 | * Also pass in line widths for plain and highlighted lines for easier visual | |
195 | * confirmation that the highlighted line is drawn on top of the others. | |
196 | */ | |
857a6931 KW |
197 | var runClosestTest = function(isStacked, widthNormal, widthHighlighted) { |
198 | var h_row; | |
199 | var h_pts; | |
200 | var h_series; | |
201 | ||
202 | var graph = document.getElementById("graph"); | |
203 | var g = new Dygraph(graph, data, | |
204 | { | |
205 | width: 600, | |
475f7420 | 206 | height: 400, |
857a6931 KW |
207 | visibility: [false, true, true], |
208 | stackedGraph: isStacked, | |
209 | strokeWidth: widthNormal, | |
210 | strokeBorderWidth: 2, | |
211 | highlightCircleSize: widthNormal * 2, | |
afdb20d8 | 212 | highlightSeriesBackgroundAlpha: 0.3, |
857a6931 KW |
213 | |
214 | highlightSeriesOpts: { | |
215 | strokeWidth: widthHighlighted, | |
216 | highlightCircleSize: widthHighlighted * 2 | |
217 | } | |
218 | }); | |
219 | ||
220 | var highlightCallback = function(e, x, pts, row, set) { | |
221 | h_row = row; | |
222 | h_pts = pts; | |
223 | h_series = set; | |
224 | document.getElementById('selection').innerHTML='row=' + row + ', set=' + set; | |
225 | }; | |
226 | ||
227 | g.updateOptions({highlightCallback: highlightCallback}, true); | |
228 | ||
229 | if (isStacked) { | |
230 | DygraphOps.dispatchMouseMove(g, 11.45, 1.4); | |
231 | assertEquals(1, h_row); | |
232 | assertEquals('c', h_series); | |
233 | ||
234 | //now move up in the same row | |
235 | DygraphOps.dispatchMouseMove(g, 11.45, 1.5); | |
236 | assertEquals(1, h_row); | |
237 | assertEquals('b', h_series); | |
238 | ||
239 | //and a bit to the right | |
240 | DygraphOps.dispatchMouseMove(g, 11.55, 1.5); | |
241 | assertEquals(2, h_row); | |
242 | assertEquals('c', h_series); | |
243 | } else { | |
244 | DygraphOps.dispatchMouseMove(g, 11, 1.5); | |
245 | assertEquals(1, h_row); | |
246 | assertEquals('c', h_series); | |
247 | ||
248 | //now move up in the same row | |
249 | DygraphOps.dispatchMouseMove(g, 11, 2.5); | |
250 | assertEquals(1, h_row); | |
251 | assertEquals('b', h_series); | |
252 | } | |
253 | ||
254 | return g; | |
255 | }; | |
256 | ||
257 | /** | |
258 | * Test basic closest-point highlighting. | |
259 | */ | |
260 | CallbackTestCase.prototype.testClosestPointCallback = function() { | |
261 | runClosestTest(false, 1, 3); | |
262 | } | |
263 | ||
264 | /** | |
265 | * Test setSelection() with series name | |
266 | */ | |
267 | CallbackTestCase.prototype.testSetSelection = function() { | |
268 | var g = runClosestTest(false, 1, 3); | |
269 | assertEquals(1, g.attr_('strokeWidth', 'c')); | |
270 | g.setSelection(false, 'c'); | |
271 | assertEquals(3, g.attr_('strokeWidth', 'c')); | |
272 | } | |
273 | ||
274 | /** | |
275 | * Test closest-point highlighting for stacked graph | |
276 | */ | |
277 | CallbackTestCase.prototype.testClosestPointStackedCallback = function() { | |
278 | runClosestTest(true, 1, 3); | |
279 | } | |
280 | ||
281 | /** | |
282 | * Closest-point highlighting with legend CSS - border around active series. | |
283 | */ | |
284 | CallbackTestCase.prototype.testClosestPointCallbackCss1 = function() { | |
285 | var css = "div.dygraph-legend > span { display: block; }\n" + | |
286 | "div.dygraph-legend > span.highlight { border: 1px solid grey; }\n"; | |
287 | this.styleSheet.innerHTML = css; | |
288 | runClosestTest(false, 2, 4); | |
a937d031 | 289 | this.styleSheet.innerHTML = ''; |
857a6931 KW |
290 | } |
291 | ||
292 | /** | |
293 | * Closest-point highlighting with legend CSS - show only closest series. | |
294 | */ | |
295 | CallbackTestCase.prototype.testClosestPointCallbackCss2 = function() { | |
296 | var css = "div.dygraph-legend > span { display: none; }\n" + | |
297 | "div.dygraph-legend > span.highlight { display: inline; }\n"; | |
298 | this.styleSheet.innerHTML = css; | |
299 | runClosestTest(false, 10, 15); | |
a937d031 | 300 | this.styleSheet.innerHTML = ''; |
857a6931 KW |
301 | // TODO(klausw): verify that the highlighted line is drawn on top? |
302 | } | |
a937d031 KW |
303 | |
304 | /** | |
b9a3ece4 KW |
305 | * Closest-point highlighting with locked series. |
306 | */ | |
3f55b813 | 307 | CallbackTestCase.prototype.testSetSelectionLocking = function() { |
b9a3ece4 KW |
308 | var g = runClosestTest(false, 2, 4); |
309 | ||
310 | // Default behavior, 'b' is closest | |
311 | DygraphOps.dispatchMouseMove(g, 11, 4); | |
312 | assertEquals('b', g.getHighlightSeries()); | |
313 | ||
314 | // Now lock selection to 'c' | |
315 | g.setSelection(false, 'c', true); | |
316 | DygraphOps.dispatchMouseMove(g, 11, 4); | |
317 | assertEquals('c', g.getHighlightSeries()); | |
318 | ||
319 | // Unlock, should be back to 'b' | |
320 | g.clearSelection(); | |
321 | DygraphOps.dispatchMouseMove(g, 11, 4); | |
322 | assertEquals('b', g.getHighlightSeries()); | |
323 | } | |
324 | ||
325 | /** | |
a937d031 KW |
326 | * This tests that closest point searches work for data containing NaNs. |
327 | * | |
328 | * It's intended to catch a regression where a NaN Y value confuses the | |
329 | * closest-point algorithm, treating it as closer as any previous point. | |
330 | */ | |
331 | CallbackTestCase.prototype.testNaNData = function() { | |
332 | var dataNaN = [ | |
1069800f | 333 | [9, -1, NaN, NaN], |
a937d031 KW |
334 | [10, -1, 1, 2], |
335 | [11, 0, 3, 1], | |
336 | [12, 1, 4, NaN], | |
337 | [13, 0, 2, 3], | |
338 | [14, -1, 1, 4]]; | |
339 | ||
340 | var h_row; | |
341 | var h_pts; | |
342 | ||
343 | var highlightCallback = function(e, x, pts, row) { | |
344 | h_row = row; | |
345 | h_pts = pts; | |
346 | }; | |
347 | ||
348 | var graph = document.getElementById("graph"); | |
349 | var g = new Dygraph(graph, dataNaN, | |
350 | { | |
351 | width: 600, | |
352 | height: 400, | |
353 | labels: ['x', 'a', 'b', 'c'], | |
354 | visibility: [false, true, true], | |
355 | highlightCallback: highlightCallback | |
356 | }); | |
357 | ||
358 | DygraphOps.dispatchMouseMove(g, 10.1, 0.9); | |
359 | //check correct row is returned | |
1069800f | 360 | assertEquals(1, h_row); |
a937d031 KW |
361 | |
362 | // Explicitly test closest point algorithms | |
363 | var dom = g.toDomCoords(10.1, 0.9); | |
1069800f | 364 | assertEquals(1, g.findClosestRow(dom[0])); |
a937d031 KW |
365 | |
366 | var res = g.findClosestPoint(dom[0], dom[1]); | |
1069800f | 367 | assertEquals(1, res.row); |
a937d031 KW |
368 | assertEquals('b', res.seriesName); |
369 | ||
370 | res = g.findStackedPoint(dom[0], dom[1]); | |
1069800f | 371 | assertEquals(1, res.row); |
a937d031 KW |
372 | assertEquals('c', res.seriesName); |
373 | }; | |
04c104d7 | 374 | |
7d463f49 KW |
375 | /** |
376 | * This tests that stacked point searches work for data containing NaNs. | |
377 | */ | |
378 | CallbackTestCase.prototype.testNaNDataStack = function() { | |
379 | var dataNaN = [ | |
380 | [9, -1, NaN, NaN], | |
381 | [10, -1, 1, 2], | |
382 | [11, 0, 3, 1], | |
383 | [12, 1, NaN, 2], | |
384 | [13, 0, 2, 3], | |
385 | [14, -1, 1, 4], | |
386 | [15, 0, 2, NaN], | |
387 | [16, 1, 1, 3], | |
388 | [17, 1, NaN, 3], | |
389 | [18, 0, 2, 5], | |
390 | [19, 0, 1, 4]]; | |
391 | ||
392 | var h_row; | |
393 | var h_pts; | |
394 | ||
395 | var highlightCallback = function(e, x, pts, row) { | |
396 | h_row = row; | |
397 | h_pts = pts; | |
398 | }; | |
399 | ||
400 | var graph = document.getElementById("graph"); | |
401 | var g = new Dygraph(graph, dataNaN, | |
402 | { | |
403 | width: 600, | |
404 | height: 400, | |
405 | labels: ['x', 'a', 'b', 'c'], | |
406 | visibility: [false, true, true], | |
407 | stackedGraph: true, | |
408 | highlightCallback: highlightCallback | |
409 | }); | |
410 | ||
411 | DygraphOps.dispatchMouseMove(g, 10.1, 0.9); | |
412 | //check correct row is returned | |
413 | assertEquals(1, h_row); | |
414 | ||
415 | // Explicitly test stacked point algorithm. | |
416 | var dom = g.toDomCoords(10.1, 0.9); | |
417 | var res = g.findStackedPoint(dom[0], dom[1]); | |
418 | assertEquals(1, res.row); | |
419 | assertEquals('c', res.seriesName); | |
420 | ||
421 | // First gap, no data due to NaN contagion. | |
422 | dom = g.toDomCoords(12.1, 0.9); | |
423 | res = g.findStackedPoint(dom[0], dom[1]); | |
424 | assertEquals(3, res.row); | |
425 | assertEquals(undefined, res.seriesName); | |
426 | ||
427 | // Second gap, no data due to NaN contagion. | |
428 | dom = g.toDomCoords(15.1, 0.9); | |
429 | res = g.findStackedPoint(dom[0], dom[1]); | |
430 | assertEquals(6, res.row); | |
431 | assertEquals(undefined, res.seriesName); | |
432 | ||
433 | // Isolated points should work, finding series b in this case. | |
434 | dom = g.toDomCoords(15.9, 3.1); | |
435 | res = g.findStackedPoint(dom[0], dom[1]); | |
436 | assertEquals(7, res.row); | |
437 | assertEquals('b', res.seriesName); | |
438 | }; | |
439 | ||
04c104d7 | 440 | CallbackTestCase.prototype.testGapHighlight = function() { |
492ea455 | 441 | var dataGap = [ |
04c104d7 KW |
442 | [1, null, 3], |
443 | [2, 2, null], | |
444 | [3, null, 5], | |
445 | [4, 4, null], | |
446 | [5, null, 7], | |
447 | [6, NaN, null], | |
448 | [8, 8, null], | |
449 | [10, 10, null]]; | |
450 | ||
451 | var h_row; | |
452 | var h_pts; | |
453 | ||
454 | var highlightCallback = function(e, x, pts, row) { | |
455 | h_row = row; | |
456 | h_pts = pts; | |
457 | }; | |
458 | ||
459 | var graph = document.getElementById("graph"); | |
460 | var g = new Dygraph(graph, dataGap, { | |
461 | width: 400, | |
462 | height: 300, | |
463 | //stackedGraph: true, | |
464 | connectSeparatedPoints: true, | |
465 | drawPoints: true, | |
466 | labels: ['x', 'A', 'B'], | |
467 | highlightCallback : highlightCallback | |
468 | }); | |
469 | ||
470 | DygraphOps.dispatchMouseMove(g, 1.1, 10); | |
471 | //point from series B | |
472 | assertEquals(0, h_row); | |
473 | assertEquals(1, h_pts.length); | |
474 | assertEquals(3, h_pts[0].yval); | |
475 | assertEquals('B', h_pts[0].name); | |
476 | ||
477 | DygraphOps.dispatchMouseMove(g, 6.1, 10); | |
478 | // A is NaN at x=6 | |
479 | assertEquals(1, h_pts.length); | |
480 | assert(isNaN(h_pts[0].yval)); | |
481 | assertEquals('A', h_pts[0].name); | |
482 | ||
483 | DygraphOps.dispatchMouseMove(g, 8.1, 10); | |
484 | //point from series A | |
485 | assertEquals(6, h_row); | |
486 | assertEquals(1, h_pts.length); | |
487 | assertEquals(8, h_pts[0].yval); | |
488 | assertEquals('A', h_pts[0].name); | |
489 | }; |