Commit | Line | Data |
---|---|---|
9c831431 RK |
1 | /** |
2 | * @fileoverview Test cases for the interaction model. | |
3 | * | |
4 | * @author konigsberg@google.com (Robert Konigsbrg) | |
5 | */ | |
9c831431 | 6 | |
e8c70e4e DV |
7 | import Dygraph from '../../src/dygraph'; |
8 | import DygraphInteraction from '../../src/dygraph-interaction-model'; | |
9 | import DygraphOps from './DygraphOps'; | |
9c831431 | 10 | |
e8c70e4e DV |
11 | describe("interaction-model", function() { |
12 | ||
13 | cleanupAfterEach(); | |
9c831431 | 14 | |
af3a17a8 RK |
15 | var data1 = "X,Y\n" + |
16 | "20,-1\n" + | |
17 | "21,0\n" + | |
18 | "22,1\n" + | |
19 | "23,0\n"; | |
20 | ||
21 | var data2 = | |
65129ba8 DV |
22 | "X,Y\n" + |
23 | "1,10\n" + | |
24 | "2,20\n" + | |
25 | "3,30\n" + | |
26 | "4,40\n" + | |
27 | "5,120\n" + | |
28 | "6,50\n" + | |
29 | "7,70\n" + | |
30 | "8,90\n" + | |
31 | "9,50\n"; | |
af3a17a8 | 32 | |
9c831431 RK |
33 | function getXLabels() { |
34 | var x_labels = document.getElementsByClassName("dygraph-axis-label-x"); | |
35 | var ary = []; | |
36 | for (var i = 0; i < x_labels.length; i++) { | |
37 | ary.push(x_labels[i].innerHTML); | |
38 | } | |
39 | return ary; | |
40 | } | |
41 | ||
89fdcedb DV |
42 | /* |
43 | it('testPan', function() { | |
9c831431 RK |
44 | var originalXRange = g.xAxisRange(); |
45 | var originalYRange = g.yAxisRange(0); | |
46 | ||
47 | DygraphOps.dispatchMouseDown(g, xRange[0], yRange[0]); | |
48 | DygraphOps.dispatchMouseMove(g, xRange[1], yRange[0]); // this is really necessary. | |
49 | DygraphOps.dispatchMouseUp(g, xRange[1], yRange[0]); | |
50 | ||
dc910fce DV |
51 | assert.closeTo(xRange, g.xAxisRange(), 0.2); |
52 | // assert.closeTo(originalYRange, g.yAxisRange(0), 0.2); // Not true, it's something in the middle. | |
9c831431 RK |
53 | |
54 | var midX = (xRange[1] - xRange[0]) / 2; | |
55 | DygraphOps.dispatchMouseDown(g, midX, yRange[0]); | |
56 | DygraphOps.dispatchMouseMove(g, midX, yRange[1]); // this is really necessary. | |
57 | DygraphOps.dispatchMouseUp(g, midX, yRange[1]); | |
58 | ||
dc910fce DV |
59 | assert.closeTo(xRange, g.xAxisRange(), 0.2); |
60 | assert.closeTo(yRange, g.yAxisRange(0), 0.2); | |
89fdcedb DV |
61 | }); |
62 | */ | |
9c831431 RK |
63 | |
64 | /** | |
65 | * This tests that when changing the interaction model so pan is used instead | |
66 | * of zoom as the default behavior, a standard click method is still called. | |
67 | */ | |
89fdcedb | 68 | it('testClickCallbackIsCalled', function() { |
9c831431 RK |
69 | var clicked; |
70 | ||
71 | var clickCallback = function(event, x) { | |
72 | clicked = x; | |
73 | }; | |
74 | ||
9c831431 | 75 | var graph = document.getElementById("graph"); |
af3a17a8 | 76 | var g = new Dygraph(graph, data1, |
9c831431 RK |
77 | { |
78 | width: 100, | |
79 | height : 100, | |
80 | clickCallback : clickCallback | |
81 | }); | |
82 | ||
83 | DygraphOps.dispatchMouseDown_Point(g, 10, 10); | |
84 | DygraphOps.dispatchMouseMove_Point(g, 10, 10); | |
85 | DygraphOps.dispatchMouseUp_Point(g, 10, 10); | |
86 | ||
89fdcedb DV |
87 | assert.equal(20, clicked); |
88 | }); | |
9c831431 RK |
89 | |
90 | /** | |
91 | * This tests that when changing the interaction model so pan is used instead | |
92 | * of zoom as the default behavior, a standard click method is still called. | |
93 | */ | |
89fdcedb | 94 | it('testClickCallbackIsCalledOnCustomPan', function() { |
9c831431 RK |
95 | var clicked; |
96 | ||
97 | var clickCallback = function(event, x) { | |
98 | clicked = x; | |
99 | }; | |
100 | ||
9c831431 RK |
101 | function customDown(event, g, context) { |
102 | context.initializeMouseDown(event, g, context); | |
e8c70e4e | 103 | DygraphInteraction.startPan(event, g, context); |
9c831431 RK |
104 | } |
105 | ||
106 | function customMove(event, g, context) { | |
e8c70e4e | 107 | DygraphInteraction.movePan(event, g, context); |
9c831431 RK |
108 | } |
109 | ||
110 | function customUp(event, g, context) { | |
e8c70e4e | 111 | DygraphInteraction.endPan(event, g, context); |
9c831431 RK |
112 | } |
113 | ||
114 | var opts = { | |
115 | width: 100, | |
116 | height : 100, | |
117 | clickCallback : clickCallback, | |
118 | interactionModel : { | |
119 | 'mousedown' : customDown, | |
120 | 'mousemove' : customMove, | |
121 | 'mouseup' : customUp, | |
122 | } | |
123 | }; | |
124 | ||
125 | var graph = document.getElementById("graph"); | |
af3a17a8 | 126 | var g = new Dygraph(graph, data1, opts); |
9c831431 RK |
127 | |
128 | DygraphOps.dispatchMouseDown_Point(g, 10, 10); | |
129 | DygraphOps.dispatchMouseMove_Point(g, 10, 10); | |
130 | DygraphOps.dispatchMouseUp_Point(g, 10, 10); | |
131 | ||
89fdcedb DV |
132 | assert.equal(20, clicked); |
133 | }); | |
9c831431 | 134 | |
319d0361 | 135 | var clickAt = function(g, x, y) { |
af3a17a8 RK |
136 | DygraphOps.dispatchMouseDown(g, x, y); |
137 | DygraphOps.dispatchMouseMove(g, x, y); | |
138 | DygraphOps.dispatchMouseUp(g, x, y); | |
319d0361 | 139 | }; |
af3a17a8 RK |
140 | |
141 | /** | |
027e9e9b DV |
142 | * This tests that clickCallback is still called with the nonInteractiveModel. |
143 | */ | |
89fdcedb | 144 | it('testClickCallbackIsCalledWithNonInteractiveModel', function() { |
027e9e9b DV |
145 | var clicked; |
146 | ||
147 | // TODO(danvk): also test pointClickCallback here. | |
148 | var clickCallback = function(event, x) { | |
149 | clicked = x; | |
150 | }; | |
151 | ||
152 | var opts = { | |
153 | width: 100, | |
154 | height : 100, | |
155 | clickCallback : clickCallback, | |
e8c70e4e | 156 | interactionModel : DygraphInteraction.nonInteractiveModel_ |
027e9e9b DV |
157 | }; |
158 | ||
159 | var graph = document.getElementById("graph"); | |
160 | var g = new Dygraph(graph, data1, opts); | |
161 | ||
162 | DygraphOps.dispatchMouseDown_Point(g, 10, 10); | |
163 | DygraphOps.dispatchMouseMove_Point(g, 10, 10); | |
164 | DygraphOps.dispatchMouseUp_Point(g, 10, 10); | |
165 | ||
89fdcedb DV |
166 | assert.equal(20, clicked); |
167 | }); | |
027e9e9b DV |
168 | |
169 | /** | |
af3a17a8 RK |
170 | * A sanity test to ensure pointClickCallback is called. |
171 | */ | |
89fdcedb | 172 | it('testPointClickCallback', function() { |
65129ba8 DV |
173 | var clicked = null; |
174 | var g = new Dygraph('graph', data2, { | |
175 | pointClickCallback: function(event, point) { | |
af3a17a8 RK |
176 | clicked = point; |
177 | } | |
178 | }); | |
179 | ||
319d0361 | 180 | clickAt(g, 4, 40); |
af3a17a8 | 181 | |
65129ba8 | 182 | assert.isNotNull(clicked); |
89fdcedb DV |
183 | assert.equal(4, clicked.xval); |
184 | assert.equal(40, clicked.yval); | |
185 | }); | |
af3a17a8 RK |
186 | |
187 | /** | |
188 | * A sanity test to ensure pointClickCallback is not called when out of range. | |
189 | */ | |
89fdcedb | 190 | it('testNoPointClickCallbackWhenOffPoint', function() { |
af3a17a8 RK |
191 | var clicked; |
192 | var g = new Dygraph(document.getElementById("graph"), data2, { | |
193 | pointClickCallback : function(event, point) { | |
194 | clicked = point; | |
195 | } | |
196 | }); | |
197 | ||
319d0361 | 198 | clickAt(g, 5, 40); |
af3a17a8 | 199 | |
89fdcedb DV |
200 | assert.isUndefined(clicked); |
201 | }); | |
af3a17a8 RK |
202 | |
203 | /** | |
204 | * Ensures pointClickCallback circle size is taken into account. | |
205 | */ | |
89fdcedb | 206 | it('testPointClickCallback_circleSize', function() { |
af3a17a8 | 207 | // TODO(konigsberg): Implement. |
89fdcedb | 208 | }); |
af3a17a8 RK |
209 | |
210 | /** | |
211 | * Ensures that pointClickCallback is called prior to clickCallback | |
212 | */ | |
89fdcedb | 213 | it('testPointClickCallbackCalledPriorToClickCallback', function() { |
af3a17a8 RK |
214 | var counter = 0; |
215 | var pointClicked; | |
216 | var clicked; | |
217 | var g = new Dygraph(document.getElementById("graph"), data2, { | |
218 | pointClickCallback : function(event, point) { | |
219 | counter++; | |
220 | pointClicked = counter; | |
221 | }, | |
222 | clickCallback : function(event, point) { | |
223 | counter++; | |
224 | clicked = counter; | |
225 | } | |
226 | }); | |
227 | ||
319d0361 | 228 | clickAt(g, 4, 40); |
89fdcedb DV |
229 | assert.equal(1, pointClicked); |
230 | assert.equal(2, clicked); | |
231 | }); | |
af3a17a8 RK |
232 | |
233 | /** | |
234 | * Ensures that when there's no pointClickCallback, clicking on a point still calls | |
235 | * clickCallback | |
236 | */ | |
89fdcedb | 237 | it('testClickCallback_clickOnPoint', function() { |
af3a17a8 RK |
238 | var clicked; |
239 | var g = new Dygraph(document.getElementById("graph"), data2, { | |
240 | clickCallback : function(event, point) { | |
241 | clicked = 1; | |
242 | } | |
243 | }); | |
244 | ||
319d0361 | 245 | clickAt(g, 4, 40); |
89fdcedb DV |
246 | assert.equal(1, clicked); |
247 | }); | |
af3a17a8 | 248 | |
89fdcedb | 249 | it('testIsZoomed_none', function() { |
32566cec RK |
250 | var g = new Dygraph(document.getElementById("graph"), data2, {}); |
251 | ||
89fdcedb DV |
252 | assert.isFalse(g.isZoomed()); |
253 | assert.isFalse(g.isZoomed("x")); | |
254 | assert.isFalse(g.isZoomed("y")); | |
255 | }); | |
357f7a8a | 256 | |
89fdcedb | 257 | it('testIsZoomed_x', function() { |
32566cec RK |
258 | var g = new Dygraph(document.getElementById("graph"), data2, {}); |
259 | ||
5ee26cc1 DV |
260 | DygraphOps.dispatchMouseDown_Point(g, 100, 100); |
261 | DygraphOps.dispatchMouseMove_Point(g, 130, 100); | |
262 | DygraphOps.dispatchMouseUp_Point(g, 130, 100); | |
32566cec | 263 | |
89fdcedb DV |
264 | assert.isTrue(g.isZoomed()); |
265 | assert.isTrue(g.isZoomed("x")); | |
266 | assert.isFalse(g.isZoomed("y")); | |
267 | }); | |
32566cec | 268 | |
89fdcedb | 269 | it('testIsZoomed_y', function() { |
32566cec RK |
270 | var g = new Dygraph(document.getElementById("graph"), data2, {}); |
271 | ||
272 | DygraphOps.dispatchMouseDown_Point(g, 10, 10); | |
273 | DygraphOps.dispatchMouseMove_Point(g, 10, 30); | |
274 | DygraphOps.dispatchMouseUp_Point(g, 10, 30); | |
275 | ||
89fdcedb DV |
276 | assert.isTrue(g.isZoomed()); |
277 | assert.isFalse(g.isZoomed("x")); | |
278 | assert.isTrue(g.isZoomed("y")); | |
279 | }); | |
32566cec | 280 | |
89fdcedb | 281 | it('testIsZoomed_both', function() { |
32566cec RK |
282 | var g = new Dygraph(document.getElementById("graph"), data2, {}); |
283 | ||
284 | // Zoom x axis | |
5ee26cc1 DV |
285 | DygraphOps.dispatchMouseDown_Point(g, 100, 100); |
286 | DygraphOps.dispatchMouseMove_Point(g, 130, 100); | |
287 | DygraphOps.dispatchMouseUp_Point(g, 130, 100); | |
32566cec RK |
288 | |
289 | // Now zoom y axis | |
5ee26cc1 DV |
290 | DygraphOps.dispatchMouseDown_Point(g, 100, 100); |
291 | DygraphOps.dispatchMouseMove_Point(g, 100, 130); | |
292 | DygraphOps.dispatchMouseUp_Point(g, 100, 130); | |
32566cec RK |
293 | |
294 | ||
89fdcedb DV |
295 | assert.isTrue(g.isZoomed()); |
296 | assert.isTrue(g.isZoomed("x")); | |
297 | assert.isTrue(g.isZoomed("y")); | |
298 | }); | |
32566cec | 299 | |
89fdcedb | 300 | it('testIsZoomed_updateOptions_none', function() { |
32566cec RK |
301 | var g = new Dygraph(document.getElementById("graph"), data2, {}); |
302 | ||
303 | g.updateOptions({}); | |
304 | ||
89fdcedb DV |
305 | assert.isFalse(g.isZoomed()); |
306 | assert.isFalse(g.isZoomed("x")); | |
307 | assert.isFalse(g.isZoomed("y")); | |
308 | }); | |
32566cec | 309 | |
89fdcedb | 310 | it('testIsZoomed_updateOptions_x', function() { |
32566cec RK |
311 | var g = new Dygraph(document.getElementById("graph"), data2, {}); |
312 | ||
313 | g.updateOptions({dateWindow: [-.5, .3]}); | |
89fdcedb DV |
314 | assert.isTrue(g.isZoomed()); |
315 | assert.isTrue(g.isZoomed("x")); | |
316 | assert.isFalse(g.isZoomed("y")); | |
317 | }); | |
32566cec | 318 | |
89fdcedb | 319 | it('testIsZoomed_updateOptions_y', function() { |
32566cec RK |
320 | var g = new Dygraph(document.getElementById("graph"), data2, {}); |
321 | ||
322 | g.updateOptions({valueRange: [1, 10]}); | |
323 | ||
89fdcedb DV |
324 | assert.isTrue(g.isZoomed()); |
325 | assert.isFalse(g.isZoomed("x")); | |
326 | assert.isTrue(g.isZoomed("y")); | |
327 | }); | |
32566cec | 328 | |
89fdcedb | 329 | it('testIsZoomed_updateOptions_both', function() { |
32566cec RK |
330 | var g = new Dygraph(document.getElementById("graph"), data2, {}); |
331 | ||
332 | g.updateOptions({dateWindow: [-1, 1], valueRange: [1, 10]}); | |
333 | ||
89fdcedb DV |
334 | assert.isTrue(g.isZoomed()); |
335 | assert.isTrue(g.isZoomed("x")); | |
336 | assert.isTrue(g.isZoomed("y")); | |
337 | }); | |
1357d81e US |
338 | |
339 | ||
89fdcedb | 340 | it('testCorrectAxisValueRangeAfterUnzoom', function() { |
5ee26cc1 DV |
341 | var g = new Dygraph(document.getElementById("graph"), |
342 | data2, { | |
343 | valueRange: [1, 50], | |
344 | dateWindow: [1, 9], | |
345 | animatedZooms:false | |
346 | }); | |
1357d81e | 347 | |
9aedaae3 | 348 | // Zoom x axis |
5ee26cc1 DV |
349 | DygraphOps.dispatchMouseDown_Point(g, 100, 100); |
350 | DygraphOps.dispatchMouseMove_Point(g, 130, 100); | |
351 | DygraphOps.dispatchMouseUp_Point(g, 130, 100); | |
1357d81e | 352 | |
9aedaae3 | 353 | // Zoom y axis |
5ee26cc1 DV |
354 | DygraphOps.dispatchMouseDown_Point(g, 100, 100); |
355 | DygraphOps.dispatchMouseMove_Point(g, 100, 130); | |
356 | DygraphOps.dispatchMouseUp_Point(g, 100, 130); | |
89fdcedb DV |
357 | var currentYAxisRange = g.yAxisRange(); |
358 | var currentXAxisRange = g.xAxisRange(); | |
9aedaae3 US |
359 | |
360 | //check that the range for the axis has changed | |
89fdcedb DV |
361 | assert.notEqual(1, currentXAxisRange[0]); |
362 | assert.notEqual(10, currentXAxisRange[1]); | |
363 | assert.notEqual(1, currentYAxisRange[0]); | |
364 | assert.notEqual(50, currentYAxisRange[1]); | |
9aedaae3 | 365 | |
f3cd243e DV |
366 | // unzoom by doubleclick. This is really the order in which a browser |
367 | // generates events, and we depend on it. | |
368 | DygraphOps.dispatchMouseDown_Point(g, 10, 10); | |
369 | DygraphOps.dispatchMouseUp_Point(g, 10, 10); | |
370 | DygraphOps.dispatchMouseDown_Point(g, 10, 10); | |
371 | DygraphOps.dispatchMouseUp_Point(g, 10, 10); | |
1357d81e US |
372 | DygraphOps.dispatchDoubleClick(g, null); |
373 | ||
9aedaae3 US |
374 | // check if range for y-axis was reset to original value |
375 | // TODO check if range for x-axis is correct. | |
376 | // Currently not possible because dateRange is set to null and extremes are returned | |
89fdcedb DV |
377 | var newYAxisRange = g.yAxisRange(); |
378 | assert.equal(1, newYAxisRange[0]); | |
379 | assert.equal(50, newYAxisRange[1]); | |
380 | }); | |
dbcf3e6d DV |
381 | |
382 | /** | |
383 | * Ensures pointClickCallback is called when some points along the y-axis don't | |
384 | * exist. | |
385 | */ | |
89fdcedb | 386 | it('testPointClickCallback_missingData', function() { |
dbcf3e6d DV |
387 | |
388 | // There's a B-value at 2, but no A-value. | |
389 | var data = | |
390 | "X,A,B\n" + | |
391 | "1,,100\n"+ | |
392 | "2,,110\n"+ | |
393 | "3,140,120\n"+ | |
394 | "4,130,110\n"+ | |
395 | ""; | |
396 | ||
397 | var clicked; | |
398 | var g = new Dygraph(document.getElementById("graph"), data, { | |
399 | pointClickCallback : function(event, point) { | |
400 | clicked = point; | |
401 | } | |
402 | }); | |
403 | ||
319d0361 | 404 | clickAt(g, 2, 110); |
dbcf3e6d | 405 | |
89fdcedb DV |
406 | assert.equal(2, clicked.xval); |
407 | assert.equal(110, clicked.yval); | |
408 | }); | |
409 | ||
bf7d192b DV |
410 | describe('animated zooms', function() { |
411 | var oldDuration; | |
412 | ||
413 | before(function() { | |
414 | oldDuration = Dygraph.ANIMATION_DURATION; | |
415 | Dygraph.ANIMATION_DURATION = 100; // speed up the animation for testing | |
416 | }); | |
417 | after(function() { | |
418 | Dygraph.ANIMATION_DURATION = oldDuration; | |
419 | }); | |
420 | ||
421 | it('should support animated zooms', function(done) { | |
422 | var data = | |
423 | "X,A,B\n" + | |
424 | "1,120,100\n"+ | |
425 | "2,110,110\n"+ | |
426 | "3,140,120\n"+ | |
427 | "4,130,110\n"; | |
428 | ||
429 | var ranges = []; | |
430 | ||
431 | var g = new Dygraph('graph', data, { | |
432 | animatedZooms: true, | |
433 | }); | |
434 | ||
435 | // updating the dateWindow does not result in an animation. | |
436 | assert.deepEqual([1, 4], g.xAxisRange()); | |
437 | g.updateOptions({dateWindow: [2, 4]}); | |
438 | assert.deepEqual([2, 4], g.xAxisRange()); | |
439 | ||
440 | g.updateOptions({ | |
441 | // zoomCallback is called once when the animation is complete. | |
442 | zoomCallback: function(xMin, xMax) { | |
443 | assert.equal(1, xMin); | |
444 | assert.equal(4, xMax); | |
445 | assert.deepEqual([1, 4], g.xAxisRange()); | |
446 | done(); | |
447 | } | |
448 | }, false); | |
449 | ||
450 | // Zoom out -- resetZoom() _does_ produce an animation. | |
451 | g.resetZoom(); | |
452 | assert.notDeepEqual([2, 4], g.xAxisRange()); // first frame is synchronous | |
453 | assert.notDeepEqual([1, 4], g.xAxisRange()); | |
454 | ||
455 | // at this point control flow goes up to zoomCallback | |
456 | }); | |
457 | ||
458 | }); | |
459 | ||
b56f033a KB |
460 | //bulk copied from "testCorrectAxisValueRangeAfterUnzoom" |
461 | //tests if the xRangePad is taken into account after unzoom. | |
1d2021b5 K |
462 | it('testCorrectAxisPaddingAfterUnzoom', function() { |
463 | var g = new Dygraph(document.getElementById("graph"), | |
464 | data2, { | |
465 | valueRange: [1, 50], | |
466 | dateWindow: [1, 9], | |
467 | xRangePad: 10, | |
468 | animatedZooms:false | |
469 | }); | |
470 | ||
471 | var extremes = g.xAxisExtremes(); | |
472 | ||
473 | // Zoom x axis | |
474 | DygraphOps.dispatchMouseDown_Point(g, 100, 100); | |
475 | DygraphOps.dispatchMouseMove_Point(g, 130, 100); | |
476 | DygraphOps.dispatchMouseUp_Point(g, 130, 100); | |
477 | ||
478 | // Zoom y axis | |
479 | DygraphOps.dispatchMouseDown_Point(g, 100, 100); | |
480 | DygraphOps.dispatchMouseMove_Point(g, 100, 130); | |
481 | DygraphOps.dispatchMouseUp_Point(g, 100, 130); | |
482 | var currentYAxisRange = g.yAxisRange(); | |
483 | var currentXAxisRange = g.xAxisRange(); | |
484 | ||
485 | //check that the range for the axis has changed | |
486 | assert.notEqual(1, currentXAxisRange[0]); | |
487 | assert.notEqual(10, currentXAxisRange[1]); | |
488 | assert.notEqual(1, currentYAxisRange[0]); | |
489 | assert.notEqual(50, currentYAxisRange[1]); | |
490 | ||
491 | // unzoom by doubleclick. This is really the order in which a browser | |
492 | // generates events, and we depend on it. | |
493 | DygraphOps.dispatchMouseDown_Point(g, 10, 10); | |
494 | DygraphOps.dispatchMouseUp_Point(g, 10, 10); | |
495 | DygraphOps.dispatchMouseDown_Point(g, 10, 10); | |
496 | DygraphOps.dispatchMouseUp_Point(g, 10, 10); | |
497 | DygraphOps.dispatchDoubleClick(g, null); | |
498 | ||
b56f033a | 499 | // check if range for x-axis was reset to original value |
1d2021b5 K |
500 | var newXAxisRange = g.xAxisRange(); |
501 | assert.equal(extremes[0], newXAxisRange[0]); | |
502 | assert.equal(extremes[1], newXAxisRange[1]); | |
503 | }); | |
504 | ||
89fdcedb | 505 | }); |