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 | /** | |
126 | * This tests that when the function idxToRow_ returns the proper row and the onHiglightCallback | |
5469113b KW |
127 | * is properly called when the first series is hidden (setVisibility = false) |
128 | * | |
72c12eda | 129 | */ |
5879307d | 130 | CallbackTestCase.prototype.testDrawHighlightPointCallbackIsCalled = function() { |
72c12eda RK |
131 | var called = false; |
132 | ||
5879307d | 133 | var drawHighlightPointCallback = function() { |
72c12eda | 134 | called = true; |
5469113b | 135 | }; |
72c12eda RK |
136 | |
137 | var graph = document.getElementById("graph"); | |
138 | var g = new Dygraph(graph, data, | |
139 | { | |
140 | width: 100, | |
141 | height : 100, | |
5879307d | 142 | drawHighlightPointCallback : drawHighlightPointCallback |
72c12eda RK |
143 | }); |
144 | ||
145 | assertFalse(called); | |
146 | DygraphOps.dispatchMouseMove(g, 13, 10); | |
147 | assertTrue(called); | |
148 | }; | |
5469113b | 149 | |
475f7420 KW |
150 | /** |
151 | * Test the closest-series highlighting methods for normal and stacked modes. | |
152 | * Also pass in line widths for plain and highlighted lines for easier visual | |
153 | * confirmation that the highlighted line is drawn on top of the others. | |
154 | */ | |
857a6931 KW |
155 | var runClosestTest = function(isStacked, widthNormal, widthHighlighted) { |
156 | var h_row; | |
157 | var h_pts; | |
158 | var h_series; | |
159 | ||
160 | var graph = document.getElementById("graph"); | |
161 | var g = new Dygraph(graph, data, | |
162 | { | |
163 | width: 600, | |
475f7420 | 164 | height: 400, |
857a6931 KW |
165 | visibility: [false, true, true], |
166 | stackedGraph: isStacked, | |
167 | strokeWidth: widthNormal, | |
168 | strokeBorderWidth: 2, | |
169 | highlightCircleSize: widthNormal * 2, | |
afdb20d8 | 170 | highlightSeriesBackgroundAlpha: 0.3, |
857a6931 KW |
171 | |
172 | highlightSeriesOpts: { | |
173 | strokeWidth: widthHighlighted, | |
174 | highlightCircleSize: widthHighlighted * 2 | |
175 | } | |
176 | }); | |
177 | ||
178 | var highlightCallback = function(e, x, pts, row, set) { | |
179 | h_row = row; | |
180 | h_pts = pts; | |
181 | h_series = set; | |
182 | document.getElementById('selection').innerHTML='row=' + row + ', set=' + set; | |
183 | }; | |
184 | ||
185 | g.updateOptions({highlightCallback: highlightCallback}, true); | |
186 | ||
187 | if (isStacked) { | |
188 | DygraphOps.dispatchMouseMove(g, 11.45, 1.4); | |
189 | assertEquals(1, h_row); | |
190 | assertEquals('c', h_series); | |
191 | ||
192 | //now move up in the same row | |
193 | DygraphOps.dispatchMouseMove(g, 11.45, 1.5); | |
194 | assertEquals(1, h_row); | |
195 | assertEquals('b', h_series); | |
196 | ||
197 | //and a bit to the right | |
198 | DygraphOps.dispatchMouseMove(g, 11.55, 1.5); | |
199 | assertEquals(2, h_row); | |
200 | assertEquals('c', h_series); | |
201 | } else { | |
202 | DygraphOps.dispatchMouseMove(g, 11, 1.5); | |
203 | assertEquals(1, h_row); | |
204 | assertEquals('c', h_series); | |
205 | ||
206 | //now move up in the same row | |
207 | DygraphOps.dispatchMouseMove(g, 11, 2.5); | |
208 | assertEquals(1, h_row); | |
209 | assertEquals('b', h_series); | |
210 | } | |
211 | ||
212 | return g; | |
213 | }; | |
214 | ||
215 | /** | |
216 | * Test basic closest-point highlighting. | |
217 | */ | |
218 | CallbackTestCase.prototype.testClosestPointCallback = function() { | |
219 | runClosestTest(false, 1, 3); | |
220 | } | |
221 | ||
222 | /** | |
223 | * Test setSelection() with series name | |
224 | */ | |
225 | CallbackTestCase.prototype.testSetSelection = function() { | |
226 | var g = runClosestTest(false, 1, 3); | |
227 | assertEquals(1, g.attr_('strokeWidth', 'c')); | |
228 | g.setSelection(false, 'c'); | |
229 | assertEquals(3, g.attr_('strokeWidth', 'c')); | |
230 | } | |
231 | ||
232 | /** | |
233 | * Test closest-point highlighting for stacked graph | |
234 | */ | |
235 | CallbackTestCase.prototype.testClosestPointStackedCallback = function() { | |
236 | runClosestTest(true, 1, 3); | |
237 | } | |
238 | ||
239 | /** | |
240 | * Closest-point highlighting with legend CSS - border around active series. | |
241 | */ | |
242 | CallbackTestCase.prototype.testClosestPointCallbackCss1 = function() { | |
243 | var css = "div.dygraph-legend > span { display: block; }\n" + | |
244 | "div.dygraph-legend > span.highlight { border: 1px solid grey; }\n"; | |
245 | this.styleSheet.innerHTML = css; | |
246 | runClosestTest(false, 2, 4); | |
a937d031 | 247 | this.styleSheet.innerHTML = ''; |
857a6931 KW |
248 | } |
249 | ||
250 | /** | |
251 | * Closest-point highlighting with legend CSS - show only closest series. | |
252 | */ | |
253 | CallbackTestCase.prototype.testClosestPointCallbackCss2 = function() { | |
254 | var css = "div.dygraph-legend > span { display: none; }\n" + | |
255 | "div.dygraph-legend > span.highlight { display: inline; }\n"; | |
256 | this.styleSheet.innerHTML = css; | |
257 | runClosestTest(false, 10, 15); | |
a937d031 | 258 | this.styleSheet.innerHTML = ''; |
857a6931 KW |
259 | // TODO(klausw): verify that the highlighted line is drawn on top? |
260 | } | |
a937d031 KW |
261 | |
262 | /** | |
263 | * This tests that closest point searches work for data containing NaNs. | |
264 | * | |
265 | * It's intended to catch a regression where a NaN Y value confuses the | |
266 | * closest-point algorithm, treating it as closer as any previous point. | |
267 | */ | |
268 | CallbackTestCase.prototype.testNaNData = function() { | |
269 | var dataNaN = [ | |
1069800f | 270 | [9, -1, NaN, NaN], |
a937d031 KW |
271 | [10, -1, 1, 2], |
272 | [11, 0, 3, 1], | |
273 | [12, 1, 4, NaN], | |
274 | [13, 0, 2, 3], | |
275 | [14, -1, 1, 4]]; | |
276 | ||
277 | var h_row; | |
278 | var h_pts; | |
279 | ||
280 | var highlightCallback = function(e, x, pts, row) { | |
281 | h_row = row; | |
282 | h_pts = pts; | |
283 | }; | |
284 | ||
285 | var graph = document.getElementById("graph"); | |
286 | var g = new Dygraph(graph, dataNaN, | |
287 | { | |
288 | width: 600, | |
289 | height: 400, | |
290 | labels: ['x', 'a', 'b', 'c'], | |
291 | visibility: [false, true, true], | |
292 | highlightCallback: highlightCallback | |
293 | }); | |
294 | ||
295 | DygraphOps.dispatchMouseMove(g, 10.1, 0.9); | |
296 | //check correct row is returned | |
1069800f | 297 | assertEquals(1, h_row); |
a937d031 KW |
298 | |
299 | // Explicitly test closest point algorithms | |
300 | var dom = g.toDomCoords(10.1, 0.9); | |
1069800f | 301 | assertEquals(1, g.findClosestRow(dom[0])); |
a937d031 KW |
302 | |
303 | var res = g.findClosestPoint(dom[0], dom[1]); | |
1069800f | 304 | assertEquals(1, res.row); |
a937d031 KW |
305 | assertEquals('b', res.seriesName); |
306 | ||
307 | res = g.findStackedPoint(dom[0], dom[1]); | |
1069800f | 308 | assertEquals(1, res.row); |
a937d031 KW |
309 | assertEquals('c', res.seriesName); |
310 | }; | |
04c104d7 | 311 | |
7d463f49 KW |
312 | /** |
313 | * This tests that stacked point searches work for data containing NaNs. | |
314 | */ | |
315 | CallbackTestCase.prototype.testNaNDataStack = function() { | |
316 | var dataNaN = [ | |
317 | [9, -1, NaN, NaN], | |
318 | [10, -1, 1, 2], | |
319 | [11, 0, 3, 1], | |
320 | [12, 1, NaN, 2], | |
321 | [13, 0, 2, 3], | |
322 | [14, -1, 1, 4], | |
323 | [15, 0, 2, NaN], | |
324 | [16, 1, 1, 3], | |
325 | [17, 1, NaN, 3], | |
326 | [18, 0, 2, 5], | |
327 | [19, 0, 1, 4]]; | |
328 | ||
329 | var h_row; | |
330 | var h_pts; | |
331 | ||
332 | var highlightCallback = function(e, x, pts, row) { | |
333 | h_row = row; | |
334 | h_pts = pts; | |
335 | }; | |
336 | ||
337 | var graph = document.getElementById("graph"); | |
338 | var g = new Dygraph(graph, dataNaN, | |
339 | { | |
340 | width: 600, | |
341 | height: 400, | |
342 | labels: ['x', 'a', 'b', 'c'], | |
343 | visibility: [false, true, true], | |
344 | stackedGraph: true, | |
345 | highlightCallback: highlightCallback | |
346 | }); | |
347 | ||
348 | DygraphOps.dispatchMouseMove(g, 10.1, 0.9); | |
349 | //check correct row is returned | |
350 | assertEquals(1, h_row); | |
351 | ||
352 | // Explicitly test stacked point algorithm. | |
353 | var dom = g.toDomCoords(10.1, 0.9); | |
354 | var res = g.findStackedPoint(dom[0], dom[1]); | |
355 | assertEquals(1, res.row); | |
356 | assertEquals('c', res.seriesName); | |
357 | ||
358 | // First gap, no data due to NaN contagion. | |
359 | dom = g.toDomCoords(12.1, 0.9); | |
360 | res = g.findStackedPoint(dom[0], dom[1]); | |
361 | assertEquals(3, res.row); | |
362 | assertEquals(undefined, res.seriesName); | |
363 | ||
364 | // Second gap, no data due to NaN contagion. | |
365 | dom = g.toDomCoords(15.1, 0.9); | |
366 | res = g.findStackedPoint(dom[0], dom[1]); | |
367 | assertEquals(6, res.row); | |
368 | assertEquals(undefined, res.seriesName); | |
369 | ||
370 | // Isolated points should work, finding series b in this case. | |
371 | dom = g.toDomCoords(15.9, 3.1); | |
372 | res = g.findStackedPoint(dom[0], dom[1]); | |
373 | assertEquals(7, res.row); | |
374 | assertEquals('b', res.seriesName); | |
375 | }; | |
376 | ||
04c104d7 | 377 | CallbackTestCase.prototype.testGapHighlight = function() { |
492ea455 | 378 | var dataGap = [ |
04c104d7 KW |
379 | [1, null, 3], |
380 | [2, 2, null], | |
381 | [3, null, 5], | |
382 | [4, 4, null], | |
383 | [5, null, 7], | |
384 | [6, NaN, null], | |
385 | [8, 8, null], | |
386 | [10, 10, null]]; | |
387 | ||
388 | var h_row; | |
389 | var h_pts; | |
390 | ||
391 | var highlightCallback = function(e, x, pts, row) { | |
392 | h_row = row; | |
393 | h_pts = pts; | |
394 | }; | |
395 | ||
396 | var graph = document.getElementById("graph"); | |
397 | var g = new Dygraph(graph, dataGap, { | |
398 | width: 400, | |
399 | height: 300, | |
400 | //stackedGraph: true, | |
401 | connectSeparatedPoints: true, | |
402 | drawPoints: true, | |
403 | labels: ['x', 'A', 'B'], | |
404 | highlightCallback : highlightCallback | |
405 | }); | |
406 | ||
407 | DygraphOps.dispatchMouseMove(g, 1.1, 10); | |
408 | //point from series B | |
409 | assertEquals(0, h_row); | |
410 | assertEquals(1, h_pts.length); | |
411 | assertEquals(3, h_pts[0].yval); | |
412 | assertEquals('B', h_pts[0].name); | |
413 | ||
414 | DygraphOps.dispatchMouseMove(g, 6.1, 10); | |
415 | // A is NaN at x=6 | |
416 | assertEquals(1, h_pts.length); | |
417 | assert(isNaN(h_pts[0].yval)); | |
418 | assertEquals('A', h_pts[0].name); | |
419 | ||
420 | DygraphOps.dispatchMouseMove(g, 8.1, 10); | |
421 | //point from series A | |
422 | assertEquals(6, h_row); | |
423 | assertEquals(1, h_pts.length); | |
424 | assertEquals(8, h_pts[0].yval); | |
425 | assertEquals('A', h_pts[0].name); | |
426 | }; |