Merge pull request #292 from joanpau
[dygraphs.git] / auto_tests / tests / interaction_model.js
1 /**
2 * @fileoverview Test cases for the interaction model.
3 *
4 * @author konigsberg@google.com (Robert Konigsbrg)
5 */
6 var InteractionModelTestCase = TestCase("interaction-model");
7
8 InteractionModelTestCase.prototype.setUp = function() {
9 document.body.innerHTML = "<div id='graph'></div>";
10 };
11
12 InteractionModelTestCase.prototype.tearDown = function() {
13 };
14
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 =
22 [[1, 10],
23 [2, 20],
24 [3, 30],
25 [4, 40],
26 [5, 120],
27 [6, 50],
28 [7, 70],
29 [8, 90],
30 [9, 50]];
31
32 function getXLabels() {
33 var x_labels = document.getElementsByClassName("dygraph-axis-label-x");
34 var ary = [];
35 for (var i = 0; i < x_labels.length; i++) {
36 ary.push(x_labels[i].innerHTML);
37 }
38 return ary;
39 }
40
41 InteractionModelTestCase.prototype.pan = function(g, xRange, yRange) {
42 var originalXRange = g.xAxisRange();
43 var originalYRange = g.yAxisRange(0);
44
45 DygraphOps.dispatchMouseDown(g, xRange[0], yRange[0]);
46 DygraphOps.dispatchMouseMove(g, xRange[1], yRange[0]); // this is really necessary.
47 DygraphOps.dispatchMouseUp(g, xRange[1], yRange[0]);
48
49 assertEqualsDelta(xRange, g.xAxisRange(), 0.2);
50 // assertEqualsDelta(originalYRange, g.yAxisRange(0), 0.2); // Not true, it's something in the middle.
51
52 var midX = (xRange[1] - xRange[0]) / 2;
53 DygraphOps.dispatchMouseDown(g, midX, yRange[0]);
54 DygraphOps.dispatchMouseMove(g, midX, yRange[1]); // this is really necessary.
55 DygraphOps.dispatchMouseUp(g, midX, yRange[1]);
56
57 assertEqualsDelta(xRange, g.xAxisRange(), 0.2);
58 assertEqualsDelta(yRange, g.yAxisRange(0), 0.2);
59 }
60
61 /**
62 * This tests that when changing the interaction model so pan is used instead
63 * of zoom as the default behavior, a standard click method is still called.
64 */
65 InteractionModelTestCase.prototype.testClickCallbackIsCalled = function() {
66 var clicked;
67
68 var clickCallback = function(event, x) {
69 clicked = x;
70 };
71
72 var graph = document.getElementById("graph");
73 var g = new Dygraph(graph, data1,
74 {
75 width: 100,
76 height : 100,
77 clickCallback : clickCallback
78 });
79
80 DygraphOps.dispatchMouseDown_Point(g, 10, 10);
81 DygraphOps.dispatchMouseMove_Point(g, 10, 10);
82 DygraphOps.dispatchMouseUp_Point(g, 10, 10);
83
84 assertEquals(20, clicked);
85 };
86
87 /**
88 * This tests that when changing the interaction model so pan is used instead
89 * of zoom as the default behavior, a standard click method is still called.
90 */
91 InteractionModelTestCase.prototype.testClickCallbackIsCalledOnCustomPan = function() {
92 var clicked;
93
94 var clickCallback = function(event, x) {
95 clicked = x;
96 };
97
98 function customDown(event, g, context) {
99 context.initializeMouseDown(event, g, context);
100 Dygraph.startPan(event, g, context);
101 }
102
103 function customMove(event, g, context) {
104 Dygraph.movePan(event, g, context);
105 }
106
107 function customUp(event, g, context) {
108 Dygraph.endPan(event, g, context);
109 }
110
111 var opts = {
112 width: 100,
113 height : 100,
114 clickCallback : clickCallback,
115 interactionModel : {
116 'mousedown' : customDown,
117 'mousemove' : customMove,
118 'mouseup' : customUp,
119 }
120 };
121
122 var graph = document.getElementById("graph");
123 var g = new Dygraph(graph, data1, opts);
124
125 DygraphOps.dispatchMouseDown_Point(g, 10, 10);
126 DygraphOps.dispatchMouseMove_Point(g, 10, 10);
127 DygraphOps.dispatchMouseUp_Point(g, 10, 10);
128
129 assertEquals(20, clicked);
130 };
131
132 InteractionModelTestCase.clickAt = function(g, x, y) {
133 DygraphOps.dispatchMouseDown(g, x, y);
134 DygraphOps.dispatchMouseMove(g, x, y);
135 DygraphOps.dispatchMouseUp(g, x, y);
136 }
137
138 /**
139 * This tests that clickCallback is still called with the nonInteractiveModel.
140 */
141 InteractionModelTestCase.prototype.testClickCallbackIsCalledWithNonInteractiveModel = function() {
142 var clicked;
143
144 // TODO(danvk): also test pointClickCallback here.
145 var clickCallback = function(event, x) {
146 clicked = x;
147 };
148
149 var opts = {
150 width: 100,
151 height : 100,
152 clickCallback : clickCallback,
153 interactionModel : Dygraph.Interaction.nonInteractiveModel_
154 };
155
156 var graph = document.getElementById("graph");
157 var g = new Dygraph(graph, data1, opts);
158
159 DygraphOps.dispatchMouseDown_Point(g, 10, 10);
160 DygraphOps.dispatchMouseMove_Point(g, 10, 10);
161 DygraphOps.dispatchMouseUp_Point(g, 10, 10);
162
163 assertEquals(20, clicked);
164 };
165
166 /**
167 * A sanity test to ensure pointClickCallback is called.
168 */
169 InteractionModelTestCase.prototype.testPointClickCallback = function() {
170 var clicked;
171 var g = new Dygraph(document.getElementById("graph"), data2, {
172 pointClickCallback : function(event, point) {
173 clicked = point;
174 }
175 });
176
177 InteractionModelTestCase.clickAt(g, 4, 40);
178
179 assertEquals(4, clicked.xval);
180 assertEquals(40, clicked.yval);
181 };
182
183 /**
184 * A sanity test to ensure pointClickCallback is not called when out of range.
185 */
186 InteractionModelTestCase.prototype.testNoPointClickCallbackWhenOffPoint = function() {
187 var clicked;
188 var g = new Dygraph(document.getElementById("graph"), data2, {
189 pointClickCallback : function(event, point) {
190 clicked = point;
191 }
192 });
193
194 InteractionModelTestCase.clickAt(g, 5, 40);
195
196 assertUndefined(clicked);
197 };
198
199 /**
200 * Ensures pointClickCallback circle size is taken into account.
201 */
202 InteractionModelTestCase.prototype.testPointClickCallback_circleSize = function() {
203 // TODO(konigsberg): Implement.
204 };
205
206 /**
207 * Ensures that pointClickCallback is called prior to clickCallback
208 */
209 InteractionModelTestCase.prototype.testPointClickCallbackCalledPriorToClickCallback = function() {
210 var counter = 0;
211 var pointClicked;
212 var clicked;
213 var g = new Dygraph(document.getElementById("graph"), data2, {
214 pointClickCallback : function(event, point) {
215 counter++;
216 pointClicked = counter;
217 },
218 clickCallback : function(event, point) {
219 counter++;
220 clicked = counter;
221 }
222 });
223
224 InteractionModelTestCase.clickAt(g, 4, 40);
225 assertEquals(1, pointClicked);
226 assertEquals(2, clicked);
227 };
228
229 /**
230 * Ensures that when there's no pointClickCallback, clicking on a point still calls
231 * clickCallback
232 */
233 InteractionModelTestCase.prototype.testClickCallback_clickOnPoint = function() {
234 var clicked;
235 var g = new Dygraph(document.getElementById("graph"), data2, {
236 clickCallback : function(event, point) {
237 clicked = 1;
238 }
239 });
240
241 InteractionModelTestCase.clickAt(g, 4, 40);
242 assertEquals(1, clicked);
243 };
244
245 InteractionModelTestCase.prototype.testIsZoomed_none = function() {
246 var g = new Dygraph(document.getElementById("graph"), data2, {});
247
248 assertFalse(g.isZoomed());
249 assertFalse(g.isZoomed("x"));
250 assertFalse(g.isZoomed("y"));
251 };
252
253 InteractionModelTestCase.prototype.testIsZoomed_x = function() {
254 var g = new Dygraph(document.getElementById("graph"), data2, {});
255
256 DygraphOps.dispatchMouseDown_Point(g, 100, 100);
257 DygraphOps.dispatchMouseMove_Point(g, 130, 100);
258 DygraphOps.dispatchMouseUp_Point(g, 130, 100);
259
260 assertTrue(g.isZoomed());
261 assertTrue(g.isZoomed("x"));
262 assertFalse(g.isZoomed("y"));
263 };
264
265 InteractionModelTestCase.prototype.testIsZoomed_y = function() {
266 var g = new Dygraph(document.getElementById("graph"), data2, {});
267
268 DygraphOps.dispatchMouseDown_Point(g, 10, 10);
269 DygraphOps.dispatchMouseMove_Point(g, 10, 30);
270 DygraphOps.dispatchMouseUp_Point(g, 10, 30);
271
272 assertTrue(g.isZoomed());
273 assertFalse(g.isZoomed("x"));
274 assertTrue(g.isZoomed("y"));
275 };
276
277 InteractionModelTestCase.prototype.testIsZoomed_both = function() {
278 var g = new Dygraph(document.getElementById("graph"), data2, {});
279
280 // Zoom x axis
281 DygraphOps.dispatchMouseDown_Point(g, 100, 100);
282 DygraphOps.dispatchMouseMove_Point(g, 130, 100);
283 DygraphOps.dispatchMouseUp_Point(g, 130, 100);
284
285 // Now zoom y axis
286 DygraphOps.dispatchMouseDown_Point(g, 100, 100);
287 DygraphOps.dispatchMouseMove_Point(g, 100, 130);
288 DygraphOps.dispatchMouseUp_Point(g, 100, 130);
289
290
291 assertTrue(g.isZoomed());
292 assertTrue(g.isZoomed("x"));
293 assertTrue(g.isZoomed("y"));
294 };
295
296 InteractionModelTestCase.prototype.testIsZoomed_updateOptions_none = function() {
297 var g = new Dygraph(document.getElementById("graph"), data2, {});
298
299 g.updateOptions({});
300
301 assertFalse(g.isZoomed());
302 assertFalse(g.isZoomed("x"));
303 assertFalse(g.isZoomed("y"));
304 };
305
306 InteractionModelTestCase.prototype.testIsZoomed_updateOptions_x = function() {
307 var g = new Dygraph(document.getElementById("graph"), data2, {});
308
309 g.updateOptions({dateWindow: [-.5, .3]});
310 assertTrue(g.isZoomed());
311 assertTrue(g.isZoomed("x"));
312 assertFalse(g.isZoomed("y"));
313 };
314
315 InteractionModelTestCase.prototype.testIsZoomed_updateOptions_y = function() {
316 var g = new Dygraph(document.getElementById("graph"), data2, {});
317
318 g.updateOptions({valueRange: [1, 10]});
319
320 assertTrue(g.isZoomed());
321 assertFalse(g.isZoomed("x"));
322 assertTrue(g.isZoomed("y"));
323 };
324
325 InteractionModelTestCase.prototype.testIsZoomed_updateOptions_both = function() {
326 var g = new Dygraph(document.getElementById("graph"), data2, {});
327
328 g.updateOptions({dateWindow: [-1, 1], valueRange: [1, 10]});
329
330 assertTrue(g.isZoomed());
331 assertTrue(g.isZoomed("x"));
332 assertTrue(g.isZoomed("y"));
333 };
334
335
336 InteractionModelTestCase.prototype.testCorrectAxisValueRangeAfterUnzoom = function() {
337 var g = new Dygraph(document.getElementById("graph"),
338 data2, {
339 valueRange: [1, 50],
340 dateWindow: [1, 9],
341 animatedZooms:false
342 });
343
344 // Zoom x axis
345 DygraphOps.dispatchMouseDown_Point(g, 100, 100);
346 DygraphOps.dispatchMouseMove_Point(g, 130, 100);
347 DygraphOps.dispatchMouseUp_Point(g, 130, 100);
348
349 // Zoom y axis
350 DygraphOps.dispatchMouseDown_Point(g, 100, 100);
351 DygraphOps.dispatchMouseMove_Point(g, 100, 130);
352 DygraphOps.dispatchMouseUp_Point(g, 100, 130);
353 currentYAxisRange = g.yAxisRange();
354 currentXAxisRange = g.xAxisRange();
355
356 //check that the range for the axis has changed
357 assertNotEquals(1, currentXAxisRange[0]);
358 assertNotEquals(10, currentXAxisRange[1]);
359 assertNotEquals(1, currentYAxisRange[0]);
360 assertNotEquals(50, currentYAxisRange[1]);
361
362 // unzoom by doubleclick. This is really the order in which a browser
363 // generates events, and we depend on it.
364 DygraphOps.dispatchMouseDown_Point(g, 10, 10);
365 DygraphOps.dispatchMouseUp_Point(g, 10, 10);
366 DygraphOps.dispatchMouseDown_Point(g, 10, 10);
367 DygraphOps.dispatchMouseUp_Point(g, 10, 10);
368 DygraphOps.dispatchDoubleClick(g, null);
369
370 // check if range for y-axis was reset to original value
371 // TODO check if range for x-axis is correct.
372 // Currently not possible because dateRange is set to null and extremes are returned
373 newYAxisRange = g.yAxisRange();
374 assertEquals(1, newYAxisRange[0]);
375 assertEquals(50, newYAxisRange[1]);
376 };
377
378 /**
379 * Ensures pointClickCallback is called when some points along the y-axis don't
380 * exist.
381 */
382 InteractionModelTestCase.prototype.testPointClickCallback_missingData = function() {
383
384 // There's a B-value at 2, but no A-value.
385 var data =
386 "X,A,B\n" +
387 "1,,100\n"+
388 "2,,110\n"+
389 "3,140,120\n"+
390 "4,130,110\n"+
391 "";
392
393 var clicked;
394 var g = new Dygraph(document.getElementById("graph"), data, {
395 pointClickCallback : function(event, point) {
396 clicked = point;
397 }
398 });
399
400 InteractionModelTestCase.clickAt(g, 2, 110);
401
402 assertEquals(2, clicked.xval);
403 assertEquals(110, clicked.yval);
404 };