|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 // Simple gestures tests |
|
6 // |
|
7 // These tests require the ability to disable the fact that the |
|
8 // Firefox chrome intentionally prevents "simple gesture" events from |
|
9 // reaching web content. |
|
10 |
|
11 let test_utils; |
|
12 let test_commandset; |
|
13 let test_prefBranch = "browser.gesture."; |
|
14 |
|
15 function test() |
|
16 { |
|
17 waitForExplicitFinish(); |
|
18 |
|
19 // Disable the default gestures support during the test |
|
20 gGestureSupport.init(false); |
|
21 |
|
22 test_utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor). |
|
23 getInterface(Components.interfaces.nsIDOMWindowUtils); |
|
24 |
|
25 // Run the tests of "simple gesture" events generally |
|
26 test_EnsureConstantsAreDisjoint(); |
|
27 test_TestEventListeners(); |
|
28 test_TestEventCreation(); |
|
29 |
|
30 // Reenable the default gestures support. The remaining tests target |
|
31 // the Firefox gesture functionality. |
|
32 gGestureSupport.init(true); |
|
33 |
|
34 // Test Firefox's gestures support. |
|
35 test_commandset = document.getElementById("mainCommandSet"); |
|
36 test_swipeGestures(); |
|
37 test_latchedGesture("pinch", "out", "in", "MozMagnifyGesture"); |
|
38 test_thresholdGesture("pinch", "out", "in", "MozMagnifyGesture"); |
|
39 test_rotateGestures(); |
|
40 } |
|
41 |
|
42 let test_eventCount = 0; |
|
43 let test_expectedType; |
|
44 let test_expectedDirection; |
|
45 let test_expectedDelta; |
|
46 let test_expectedModifiers; |
|
47 let test_expectedClickCount; |
|
48 let test_imageTab; |
|
49 |
|
50 function test_gestureListener(evt) |
|
51 { |
|
52 is(evt.type, test_expectedType, |
|
53 "evt.type (" + evt.type + ") does not match expected value"); |
|
54 is(evt.target, test_utils.elementFromPoint(20, 20, false, false), |
|
55 "evt.target (" + evt.target + ") does not match expected value"); |
|
56 is(evt.clientX, 20, |
|
57 "evt.clientX (" + evt.clientX + ") does not match expected value"); |
|
58 is(evt.clientY, 20, |
|
59 "evt.clientY (" + evt.clientY + ") does not match expected value"); |
|
60 isnot(evt.screenX, 0, |
|
61 "evt.screenX (" + evt.screenX + ") does not match expected value"); |
|
62 isnot(evt.screenY, 0, |
|
63 "evt.screenY (" + evt.screenY + ") does not match expected value"); |
|
64 |
|
65 is(evt.direction, test_expectedDirection, |
|
66 "evt.direction (" + evt.direction + ") does not match expected value"); |
|
67 is(evt.delta, test_expectedDelta, |
|
68 "evt.delta (" + evt.delta + ") does not match expected value"); |
|
69 |
|
70 is(evt.shiftKey, (test_expectedModifiers & Components.interfaces.nsIDOMEvent.SHIFT_MASK) != 0, |
|
71 "evt.shiftKey did not match expected value"); |
|
72 is(evt.ctrlKey, (test_expectedModifiers & Components.interfaces.nsIDOMEvent.CONTROL_MASK) != 0, |
|
73 "evt.ctrlKey did not match expected value"); |
|
74 is(evt.altKey, (test_expectedModifiers & Components.interfaces.nsIDOMEvent.ALT_MASK) != 0, |
|
75 "evt.altKey did not match expected value"); |
|
76 is(evt.metaKey, (test_expectedModifiers & Components.interfaces.nsIDOMEvent.META_MASK) != 0, |
|
77 "evt.metaKey did not match expected value"); |
|
78 |
|
79 if (evt.type == "MozTapGesture") { |
|
80 is(evt.clickCount, test_expectedClickCount, "evt.clickCount does not match"); |
|
81 } |
|
82 |
|
83 test_eventCount++; |
|
84 } |
|
85 |
|
86 function test_helper1(type, direction, delta, modifiers) |
|
87 { |
|
88 // Setup the expected values |
|
89 test_expectedType = type; |
|
90 test_expectedDirection = direction; |
|
91 test_expectedDelta = delta; |
|
92 test_expectedModifiers = modifiers; |
|
93 |
|
94 let expectedEventCount = test_eventCount + 1; |
|
95 |
|
96 document.addEventListener(type, test_gestureListener, true); |
|
97 test_utils.sendSimpleGestureEvent(type, 20, 20, direction, delta, modifiers); |
|
98 document.removeEventListener(type, test_gestureListener, true); |
|
99 |
|
100 is(expectedEventCount, test_eventCount, "Event (" + type + ") was never received by event listener"); |
|
101 } |
|
102 |
|
103 function test_clicks(type, clicks) |
|
104 { |
|
105 // Setup the expected values |
|
106 test_expectedType = type; |
|
107 test_expectedDirection = 0; |
|
108 test_expectedDelta = 0; |
|
109 test_expectedModifiers = 0; |
|
110 test_expectedClickCount = clicks; |
|
111 |
|
112 let expectedEventCount = test_eventCount + 1; |
|
113 |
|
114 document.addEventListener(type, test_gestureListener, true); |
|
115 test_utils.sendSimpleGestureEvent(type, 20, 20, 0, 0, 0, clicks); |
|
116 document.removeEventListener(type, test_gestureListener, true); |
|
117 |
|
118 is(expectedEventCount, test_eventCount, "Event (" + type + ") was never received by event listener"); |
|
119 } |
|
120 |
|
121 function test_TestEventListeners() |
|
122 { |
|
123 let e = test_helper1; // easier to type this name |
|
124 |
|
125 // Swipe gesture animation events |
|
126 e("MozSwipeGestureStart", 0, -0.7, 0); |
|
127 e("MozSwipeGestureUpdate", 0, -0.4, 0); |
|
128 e("MozSwipeGestureEnd", 0, 0, 0); |
|
129 e("MozSwipeGestureStart", 0, 0.6, 0); |
|
130 e("MozSwipeGestureUpdate", 0, 0.3, 0); |
|
131 e("MozSwipeGestureEnd", 0, 1, 0); |
|
132 |
|
133 // Swipe gesture event |
|
134 e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_LEFT, 0.0, 0); |
|
135 e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_RIGHT, 0.0, 0); |
|
136 e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_UP, 0.0, 0); |
|
137 e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_DOWN, 0.0, 0); |
|
138 e("MozSwipeGesture", |
|
139 SimpleGestureEvent.DIRECTION_UP | SimpleGestureEvent.DIRECTION_LEFT, 0.0, 0); |
|
140 e("MozSwipeGesture", |
|
141 SimpleGestureEvent.DIRECTION_DOWN | SimpleGestureEvent.DIRECTION_RIGHT, 0.0, 0); |
|
142 e("MozSwipeGesture", |
|
143 SimpleGestureEvent.DIRECTION_UP | SimpleGestureEvent.DIRECTION_RIGHT, 0.0, 0); |
|
144 e("MozSwipeGesture", |
|
145 SimpleGestureEvent.DIRECTION_DOWN | SimpleGestureEvent.DIRECTION_LEFT, 0.0, 0); |
|
146 |
|
147 // magnify gesture events |
|
148 e("MozMagnifyGestureStart", 0, 50.0, 0); |
|
149 e("MozMagnifyGestureUpdate", 0, -25.0, 0); |
|
150 e("MozMagnifyGestureUpdate", 0, 5.0, 0); |
|
151 e("MozMagnifyGesture", 0, 30.0, 0); |
|
152 |
|
153 // rotate gesture events |
|
154 e("MozRotateGestureStart", SimpleGestureEvent.ROTATION_CLOCKWISE, 33.0, 0); |
|
155 e("MozRotateGestureUpdate", SimpleGestureEvent.ROTATION_COUNTERCLOCKWISE, -13.0, 0); |
|
156 e("MozRotateGestureUpdate", SimpleGestureEvent.ROTATION_CLOCKWISE, 13.0, 0); |
|
157 e("MozRotateGesture", SimpleGestureEvent.ROTATION_CLOCKWISE, 33.0, 0); |
|
158 |
|
159 // Tap and presstap gesture events |
|
160 test_clicks("MozTapGesture", 1); |
|
161 test_clicks("MozTapGesture", 2); |
|
162 test_clicks("MozTapGesture", 3); |
|
163 test_clicks("MozPressTapGesture", 1); |
|
164 |
|
165 // simple delivery test for edgeui gestures |
|
166 e("MozEdgeUIStarted", 0, 0, 0); |
|
167 e("MozEdgeUICanceled", 0, 0, 0); |
|
168 e("MozEdgeUICompleted", 0, 0, 0); |
|
169 |
|
170 // event.shiftKey |
|
171 let modifier = Components.interfaces.nsIDOMEvent.SHIFT_MASK; |
|
172 e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_RIGHT, 0, modifier); |
|
173 |
|
174 // event.metaKey |
|
175 modifier = Components.interfaces.nsIDOMEvent.META_MASK; |
|
176 e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_RIGHT, 0, modifier); |
|
177 |
|
178 // event.altKey |
|
179 modifier = Components.interfaces.nsIDOMEvent.ALT_MASK; |
|
180 e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_RIGHT, 0, modifier); |
|
181 |
|
182 // event.ctrlKey |
|
183 modifier = Components.interfaces.nsIDOMEvent.CONTROL_MASK; |
|
184 e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_RIGHT, 0, modifier); |
|
185 } |
|
186 |
|
187 function test_eventDispatchListener(evt) |
|
188 { |
|
189 test_eventCount++; |
|
190 evt.stopPropagation(); |
|
191 } |
|
192 |
|
193 function test_helper2(type, direction, delta, altKey, ctrlKey, shiftKey, metaKey) |
|
194 { |
|
195 let event = null; |
|
196 let successful; |
|
197 |
|
198 try { |
|
199 event = document.createEvent("SimpleGestureEvent"); |
|
200 successful = true; |
|
201 } |
|
202 catch (ex) { |
|
203 successful = false; |
|
204 } |
|
205 ok(successful, "Unable to create SimpleGestureEvent"); |
|
206 |
|
207 try { |
|
208 event.initSimpleGestureEvent(type, true, true, window, 1, |
|
209 10, 10, 10, 10, |
|
210 ctrlKey, altKey, shiftKey, metaKey, |
|
211 1, window, |
|
212 0, direction, delta, 0); |
|
213 successful = true; |
|
214 } |
|
215 catch (ex) { |
|
216 successful = false; |
|
217 } |
|
218 ok(successful, "event.initSimpleGestureEvent should not fail"); |
|
219 |
|
220 // Make sure the event fields match the expected values |
|
221 is(event.type, type, "Mismatch on evt.type"); |
|
222 is(event.direction, direction, "Mismatch on evt.direction"); |
|
223 is(event.delta, delta, "Mismatch on evt.delta"); |
|
224 is(event.altKey, altKey, "Mismatch on evt.altKey"); |
|
225 is(event.ctrlKey, ctrlKey, "Mismatch on evt.ctrlKey"); |
|
226 is(event.shiftKey, shiftKey, "Mismatch on evt.shiftKey"); |
|
227 is(event.metaKey, metaKey, "Mismatch on evt.metaKey"); |
|
228 is(event.view, window, "Mismatch on evt.view"); |
|
229 is(event.detail, 1, "Mismatch on evt.detail"); |
|
230 is(event.clientX, 10, "Mismatch on evt.clientX"); |
|
231 is(event.clientY, 10, "Mismatch on evt.clientY"); |
|
232 is(event.screenX, 10, "Mismatch on evt.screenX"); |
|
233 is(event.screenY, 10, "Mismatch on evt.screenY"); |
|
234 is(event.button, 1, "Mismatch on evt.button"); |
|
235 is(event.relatedTarget, window, "Mismatch on evt.relatedTarget"); |
|
236 |
|
237 // Test event dispatch |
|
238 let expectedEventCount = test_eventCount + 1; |
|
239 document.addEventListener(type, test_eventDispatchListener, true); |
|
240 document.dispatchEvent(event); |
|
241 document.removeEventListener(type, test_eventDispatchListener, true); |
|
242 is(expectedEventCount, test_eventCount, "Dispatched event was never received by listener"); |
|
243 } |
|
244 |
|
245 function test_TestEventCreation() |
|
246 { |
|
247 // Event creation |
|
248 test_helper2("MozMagnifyGesture", SimpleGestureEvent.DIRECTION_RIGHT, 20.0, |
|
249 true, false, true, false); |
|
250 test_helper2("MozMagnifyGesture", SimpleGestureEvent.DIRECTION_LEFT, -20.0, |
|
251 false, true, false, true); |
|
252 } |
|
253 |
|
254 function test_EnsureConstantsAreDisjoint() |
|
255 { |
|
256 let up = SimpleGestureEvent.DIRECTION_UP; |
|
257 let down = SimpleGestureEvent.DIRECTION_DOWN; |
|
258 let left = SimpleGestureEvent.DIRECTION_LEFT; |
|
259 let right = SimpleGestureEvent.DIRECTION_RIGHT; |
|
260 |
|
261 let clockwise = SimpleGestureEvent.ROTATION_CLOCKWISE; |
|
262 let cclockwise = SimpleGestureEvent.ROTATION_COUNTERCLOCKWISE; |
|
263 |
|
264 ok(up ^ down, "DIRECTION_UP and DIRECTION_DOWN are not bitwise disjoint"); |
|
265 ok(up ^ left, "DIRECTION_UP and DIRECTION_LEFT are not bitwise disjoint"); |
|
266 ok(up ^ right, "DIRECTION_UP and DIRECTION_RIGHT are not bitwise disjoint"); |
|
267 ok(down ^ left, "DIRECTION_DOWN and DIRECTION_LEFT are not bitwise disjoint"); |
|
268 ok(down ^ right, "DIRECTION_DOWN and DIRECTION_RIGHT are not bitwise disjoint"); |
|
269 ok(left ^ right, "DIRECTION_LEFT and DIRECTION_RIGHT are not bitwise disjoint"); |
|
270 ok(clockwise ^ cclockwise, "ROTATION_CLOCKWISE and ROTATION_COUNTERCLOCKWISE are not bitwise disjoint"); |
|
271 } |
|
272 |
|
273 // Helper for test of latched event processing. Emits the actual |
|
274 // gesture events to test whether the commands associated with the |
|
275 // gesture will only trigger once for each direction of movement. |
|
276 function test_emitLatchedEvents(eventPrefix, initialDelta, cmd) |
|
277 { |
|
278 let cumulativeDelta = 0; |
|
279 let isIncreasing = initialDelta > 0; |
|
280 |
|
281 let expect = {}; |
|
282 // Reset the call counters and initialize expected values |
|
283 for (let dir in cmd) |
|
284 cmd[dir].callCount = expect[dir] = 0; |
|
285 |
|
286 let check = function(aDir, aMsg) ok(cmd[aDir].callCount == expect[aDir], aMsg); |
|
287 let checkBoth = function(aNum, aInc, aDec) { |
|
288 let prefix = "Step " + aNum + ": "; |
|
289 check("inc", prefix + aInc); |
|
290 check("dec", prefix + aDec); |
|
291 }; |
|
292 |
|
293 // Send the "Start" event. |
|
294 test_utils.sendSimpleGestureEvent(eventPrefix + "Start", 0, 0, 0, initialDelta, 0); |
|
295 cumulativeDelta += initialDelta; |
|
296 if (isIncreasing) { |
|
297 expect.inc++; |
|
298 checkBoth(1, "Increasing command was not triggered", "Decreasing command was triggered"); |
|
299 } else { |
|
300 expect.dec++; |
|
301 checkBoth(1, "Increasing command was triggered", "Decreasing command was not triggered"); |
|
302 } |
|
303 |
|
304 // Send random values in the same direction and ensure neither |
|
305 // command triggers. |
|
306 for (let i = 0; i < 5; i++) { |
|
307 let delta = Math.random() * (isIncreasing ? 100 : -100); |
|
308 test_utils.sendSimpleGestureEvent(eventPrefix + "Update", 0, 0, 0, delta, 0); |
|
309 cumulativeDelta += delta; |
|
310 checkBoth(2, "Increasing command was triggered", "Decreasing command was triggered"); |
|
311 } |
|
312 |
|
313 // Now go back in the opposite direction. |
|
314 test_utils.sendSimpleGestureEvent(eventPrefix + "Update", 0, 0, 0, |
|
315 - initialDelta, 0); |
|
316 cumulativeDelta += - initialDelta; |
|
317 if (isIncreasing) { |
|
318 expect.dec++; |
|
319 checkBoth(3, "Increasing command was triggered", "Decreasing command was not triggered"); |
|
320 } else { |
|
321 expect.inc++; |
|
322 checkBoth(3, "Increasing command was not triggered", "Decreasing command was triggered"); |
|
323 } |
|
324 |
|
325 // Send random values in the opposite direction and ensure neither |
|
326 // command triggers. |
|
327 for (let i = 0; i < 5; i++) { |
|
328 let delta = Math.random() * (isIncreasing ? -100 : 100); |
|
329 test_utils.sendSimpleGestureEvent(eventPrefix + "Update", 0, 0, 0, delta, 0); |
|
330 cumulativeDelta += delta; |
|
331 checkBoth(4, "Increasing command was triggered", "Decreasing command was triggered"); |
|
332 } |
|
333 |
|
334 // Go back to the original direction. The original command should trigger. |
|
335 test_utils.sendSimpleGestureEvent(eventPrefix + "Update", 0, 0, 0, |
|
336 initialDelta, 0); |
|
337 cumulativeDelta += initialDelta; |
|
338 if (isIncreasing) { |
|
339 expect.inc++; |
|
340 checkBoth(5, "Increasing command was not triggered", "Decreasing command was triggered"); |
|
341 } else { |
|
342 expect.dec++; |
|
343 checkBoth(5, "Increasing command was triggered", "Decreasing command was not triggered"); |
|
344 } |
|
345 |
|
346 // Send the wrap-up event. No commands should be triggered. |
|
347 test_utils.sendSimpleGestureEvent(eventPrefix, 0, 0, 0, cumulativeDelta, 0); |
|
348 checkBoth(6, "Increasing command was triggered", "Decreasing command was triggered"); |
|
349 } |
|
350 |
|
351 function test_addCommand(prefName, id) |
|
352 { |
|
353 let cmd = test_commandset.appendChild(document.createElement("command")); |
|
354 cmd.setAttribute("id", id); |
|
355 cmd.setAttribute("oncommand", "this.callCount++;"); |
|
356 |
|
357 cmd.origPrefName = prefName; |
|
358 cmd.origPrefValue = gPrefService.getCharPref(prefName); |
|
359 gPrefService.setCharPref(prefName, id); |
|
360 |
|
361 return cmd; |
|
362 } |
|
363 |
|
364 function test_removeCommand(cmd) |
|
365 { |
|
366 gPrefService.setCharPref(cmd.origPrefName, cmd.origPrefValue); |
|
367 test_commandset.removeChild(cmd); |
|
368 } |
|
369 |
|
370 // Test whether latched events are only called once per direction of motion. |
|
371 function test_latchedGesture(gesture, inc, dec, eventPrefix) |
|
372 { |
|
373 let branch = test_prefBranch + gesture + "."; |
|
374 |
|
375 // Put the gesture into latched mode. |
|
376 let oldLatchedValue = gPrefService.getBoolPref(branch + "latched"); |
|
377 gPrefService.setBoolPref(branch + "latched", true); |
|
378 |
|
379 // Install the test commands for increasing and decreasing motion. |
|
380 let cmd = { |
|
381 inc: test_addCommand(branch + inc, "test:incMotion"), |
|
382 dec: test_addCommand(branch + dec, "test:decMotion"), |
|
383 }; |
|
384 |
|
385 // Test the gestures in each direction. |
|
386 test_emitLatchedEvents(eventPrefix, 500, cmd); |
|
387 test_emitLatchedEvents(eventPrefix, -500, cmd); |
|
388 |
|
389 // Restore the gesture to its original configuration. |
|
390 gPrefService.setBoolPref(branch + "latched", oldLatchedValue); |
|
391 for (let dir in cmd) |
|
392 test_removeCommand(cmd[dir]); |
|
393 } |
|
394 |
|
395 // Test whether non-latched events are triggered upon sufficient motion. |
|
396 function test_thresholdGesture(gesture, inc, dec, eventPrefix) |
|
397 { |
|
398 let branch = test_prefBranch + gesture + "."; |
|
399 |
|
400 // Disable latched mode for this gesture. |
|
401 let oldLatchedValue = gPrefService.getBoolPref(branch + "latched"); |
|
402 gPrefService.setBoolPref(branch + "latched", false); |
|
403 |
|
404 // Set the triggering threshold value to 50. |
|
405 let oldThresholdValue = gPrefService.getIntPref(branch + "threshold"); |
|
406 gPrefService.setIntPref(branch + "threshold", 50); |
|
407 |
|
408 // Install the test commands for increasing and decreasing motion. |
|
409 let cmdInc = test_addCommand(branch + inc, "test:incMotion"); |
|
410 let cmdDec = test_addCommand(branch + dec, "test:decMotion"); |
|
411 |
|
412 // Send the start event but stop short of triggering threshold. |
|
413 cmdInc.callCount = cmdDec.callCount = 0; |
|
414 test_utils.sendSimpleGestureEvent(eventPrefix + "Start", 0, 0, 0, 49.5, 0); |
|
415 ok(cmdInc.callCount == 0, "Increasing command was triggered"); |
|
416 ok(cmdDec.callCount == 0, "Decreasing command was triggered"); |
|
417 |
|
418 // Now trigger the threshold. |
|
419 cmdInc.callCount = cmdDec.callCount = 0; |
|
420 test_utils.sendSimpleGestureEvent(eventPrefix + "Update", 0, 0, 0, 1, 0); |
|
421 ok(cmdInc.callCount == 1, "Increasing command was not triggered"); |
|
422 ok(cmdDec.callCount == 0, "Decreasing command was triggered"); |
|
423 |
|
424 // The tracking counter should go to zero. Go back the other way and |
|
425 // stop short of triggering the threshold. |
|
426 cmdInc.callCount = cmdDec.callCount = 0; |
|
427 test_utils.sendSimpleGestureEvent(eventPrefix + "Update", 0, 0, 0, -49.5, 0); |
|
428 ok(cmdInc.callCount == 0, "Increasing command was triggered"); |
|
429 ok(cmdDec.callCount == 0, "Decreasing command was triggered"); |
|
430 |
|
431 // Now cross the threshold and trigger the decreasing command. |
|
432 cmdInc.callCount = cmdDec.callCount = 0; |
|
433 test_utils.sendSimpleGestureEvent(eventPrefix + "Update", 0, 0, 0, -1.5, 0); |
|
434 ok(cmdInc.callCount == 0, "Increasing command was triggered"); |
|
435 ok(cmdDec.callCount == 1, "Decreasing command was not triggered"); |
|
436 |
|
437 // Send the wrap-up event. No commands should trigger. |
|
438 cmdInc.callCount = cmdDec.callCount = 0; |
|
439 test_utils.sendSimpleGestureEvent(eventPrefix, 0, 0, 0, -0.5, 0); |
|
440 ok(cmdInc.callCount == 0, "Increasing command was triggered"); |
|
441 ok(cmdDec.callCount == 0, "Decreasing command was triggered"); |
|
442 |
|
443 // Restore the gesture to its original configuration. |
|
444 gPrefService.setBoolPref(branch + "latched", oldLatchedValue); |
|
445 gPrefService.setIntPref(branch + "threshold", oldThresholdValue); |
|
446 test_removeCommand(cmdInc); |
|
447 test_removeCommand(cmdDec); |
|
448 } |
|
449 |
|
450 function test_swipeGestures() |
|
451 { |
|
452 // easier to type names for the direction constants |
|
453 let up = SimpleGestureEvent.DIRECTION_UP; |
|
454 let down = SimpleGestureEvent.DIRECTION_DOWN; |
|
455 let left = SimpleGestureEvent.DIRECTION_LEFT; |
|
456 let right = SimpleGestureEvent.DIRECTION_RIGHT; |
|
457 |
|
458 let branch = test_prefBranch + "swipe."; |
|
459 |
|
460 // Install the test commands for the swipe gestures. |
|
461 let cmdUp = test_addCommand(branch + "up", "test:swipeUp"); |
|
462 let cmdDown = test_addCommand(branch + "down", "test:swipeDown"); |
|
463 let cmdLeft = test_addCommand(branch + "left", "test:swipeLeft"); |
|
464 let cmdRight = test_addCommand(branch + "right", "test:swipeRight"); |
|
465 |
|
466 function resetCounts() { |
|
467 cmdUp.callCount = 0; |
|
468 cmdDown.callCount = 0; |
|
469 cmdLeft.callCount = 0; |
|
470 cmdRight.callCount = 0; |
|
471 } |
|
472 |
|
473 // UP |
|
474 resetCounts(); |
|
475 test_utils.sendSimpleGestureEvent("MozSwipeGesture", 0, 0, up, 0, 0); |
|
476 ok(cmdUp.callCount == 1, "Step 1: Up command was not triggered"); |
|
477 ok(cmdDown.callCount == 0, "Step 1: Down command was triggered"); |
|
478 ok(cmdLeft.callCount == 0, "Step 1: Left command was triggered"); |
|
479 ok(cmdRight.callCount == 0, "Step 1: Right command was triggered"); |
|
480 |
|
481 // DOWN |
|
482 resetCounts(); |
|
483 test_utils.sendSimpleGestureEvent("MozSwipeGesture", 0, 0, down, 0, 0); |
|
484 ok(cmdUp.callCount == 0, "Step 2: Up command was triggered"); |
|
485 ok(cmdDown.callCount == 1, "Step 2: Down command was not triggered"); |
|
486 ok(cmdLeft.callCount == 0, "Step 2: Left command was triggered"); |
|
487 ok(cmdRight.callCount == 0, "Step 2: Right command was triggered"); |
|
488 |
|
489 // LEFT |
|
490 resetCounts(); |
|
491 test_utils.sendSimpleGestureEvent("MozSwipeGesture", 0, 0, left, 0, 0); |
|
492 ok(cmdUp.callCount == 0, "Step 3: Up command was triggered"); |
|
493 ok(cmdDown.callCount == 0, "Step 3: Down command was triggered"); |
|
494 ok(cmdLeft.callCount == 1, "Step 3: Left command was not triggered"); |
|
495 ok(cmdRight.callCount == 0, "Step 3: Right command was triggered"); |
|
496 |
|
497 // RIGHT |
|
498 resetCounts(); |
|
499 test_utils.sendSimpleGestureEvent("MozSwipeGesture", 0, 0, right, 0, 0); |
|
500 ok(cmdUp.callCount == 0, "Step 4: Up command was triggered"); |
|
501 ok(cmdDown.callCount == 0, "Step 4: Down command was triggered"); |
|
502 ok(cmdLeft.callCount == 0, "Step 4: Left command was triggered"); |
|
503 ok(cmdRight.callCount == 1, "Step 4: Right command was not triggered"); |
|
504 |
|
505 // Make sure combinations do not trigger events. |
|
506 let combos = [ up | left, up | right, down | left, down | right]; |
|
507 for (let i = 0; i < combos.length; i++) { |
|
508 resetCounts(); |
|
509 test_utils.sendSimpleGestureEvent("MozSwipeGesture", 0, 0, combos[i], 0, 0); |
|
510 ok(cmdUp.callCount == 0, "Step 5-"+i+": Up command was triggered"); |
|
511 ok(cmdDown.callCount == 0, "Step 5-"+i+": Down command was triggered"); |
|
512 ok(cmdLeft.callCount == 0, "Step 5-"+i+": Left command was triggered"); |
|
513 ok(cmdRight.callCount == 0, "Step 5-"+i+": Right command was triggered"); |
|
514 } |
|
515 |
|
516 // Remove the test commands. |
|
517 test_removeCommand(cmdUp); |
|
518 test_removeCommand(cmdDown); |
|
519 test_removeCommand(cmdLeft); |
|
520 test_removeCommand(cmdRight); |
|
521 } |
|
522 |
|
523 |
|
524 function test_rotateHelperGetImageRotation(aImageElement) |
|
525 { |
|
526 // Get the true image rotation from the transform matrix, bounded |
|
527 // to 0 <= result < 360 |
|
528 let transformValue = content.window.getComputedStyle(aImageElement, null) |
|
529 .transform; |
|
530 if (transformValue == "none") |
|
531 return 0; |
|
532 |
|
533 transformValue = transformValue.split("(")[1] |
|
534 .split(")")[0] |
|
535 .split(","); |
|
536 var rotation = Math.round(Math.atan2(transformValue[1], transformValue[0]) * |
|
537 (180 / Math.PI)); |
|
538 return (rotation < 0 ? rotation + 360 : rotation); |
|
539 } |
|
540 |
|
541 function test_rotateHelperOneGesture(aImageElement, aCurrentRotation, |
|
542 aDirection, aAmount, aStop) |
|
543 { |
|
544 if (aAmount <= 0 || aAmount > 90) // Bound to 0 < aAmount <= 90 |
|
545 return; |
|
546 |
|
547 // easier to type names for the direction constants |
|
548 let clockwise = SimpleGestureEvent.ROTATION_CLOCKWISE; |
|
549 let cclockwise = SimpleGestureEvent.ROTATION_COUNTERCLOCKWISE; |
|
550 |
|
551 let delta = aAmount * (aDirection == clockwise ? 1 : -1); |
|
552 |
|
553 // Kill transition time on image so test isn't wrong and doesn't take 10 seconds |
|
554 aImageElement.style.transitionDuration = "0s"; |
|
555 |
|
556 // Start the gesture, perform an update, and force flush |
|
557 test_utils.sendSimpleGestureEvent("MozRotateGestureStart", 0, 0, aDirection, .001, 0); |
|
558 test_utils.sendSimpleGestureEvent("MozRotateGestureUpdate", 0, 0, aDirection, delta, 0); |
|
559 aImageElement.clientTop; |
|
560 |
|
561 // If stop, check intermediate |
|
562 if (aStop) { |
|
563 // Send near-zero-delta to stop, and force flush |
|
564 test_utils.sendSimpleGestureEvent("MozRotateGestureUpdate", 0, 0, aDirection, .001, 0); |
|
565 aImageElement.clientTop; |
|
566 |
|
567 let stopExpectedRotation = (aCurrentRotation + delta) % 360; |
|
568 if (stopExpectedRotation < 0) |
|
569 stopExpectedRotation += 360; |
|
570 |
|
571 is(stopExpectedRotation, test_rotateHelperGetImageRotation(aImageElement), |
|
572 "Image rotation at gesture stop/hold: expected=" + stopExpectedRotation + |
|
573 ", observed=" + test_rotateHelperGetImageRotation(aImageElement) + |
|
574 ", init=" + aCurrentRotation + |
|
575 ", amt=" + aAmount + |
|
576 ", dir=" + (aDirection == clockwise ? "cl" : "ccl")); |
|
577 } |
|
578 // End it and force flush |
|
579 test_utils.sendSimpleGestureEvent("MozRotateGesture", 0, 0, aDirection, 0, 0); |
|
580 aImageElement.clientTop; |
|
581 |
|
582 let finalExpectedRotation; |
|
583 |
|
584 if (aAmount < 45 && aStop) { |
|
585 // Rotate a bit, then stop. Expect no change at end of gesture. |
|
586 finalExpectedRotation = aCurrentRotation; |
|
587 } |
|
588 else { |
|
589 // Either not stopping (expect 90 degree change in aDirection), OR |
|
590 // stopping but after 45, (expect 90 degree change in aDirection) |
|
591 finalExpectedRotation = (aCurrentRotation + |
|
592 (aDirection == clockwise ? 1 : -1) * 90) % 360; |
|
593 if (finalExpectedRotation < 0) |
|
594 finalExpectedRotation += 360; |
|
595 } |
|
596 |
|
597 is(finalExpectedRotation, test_rotateHelperGetImageRotation(aImageElement), |
|
598 "Image rotation gesture end: expected=" + finalExpectedRotation + |
|
599 ", observed=" + test_rotateHelperGetImageRotation(aImageElement) + |
|
600 ", init=" + aCurrentRotation + |
|
601 ", amt=" + aAmount + |
|
602 ", dir=" + (aDirection == clockwise ? "cl" : "ccl")); |
|
603 } |
|
604 |
|
605 function test_rotateGesturesOnTab() |
|
606 { |
|
607 gBrowser.selectedBrowser.removeEventListener("load", test_rotateGesturesOnTab, true); |
|
608 |
|
609 if (!(content.document instanceof ImageDocument)) { |
|
610 ok(false, "Image document failed to open for rotation testing"); |
|
611 gBrowser.removeTab(test_imageTab); |
|
612 finish(); |
|
613 return; |
|
614 } |
|
615 |
|
616 // easier to type names for the direction constants |
|
617 let cl = SimpleGestureEvent.ROTATION_CLOCKWISE; |
|
618 let ccl = SimpleGestureEvent.ROTATION_COUNTERCLOCKWISE; |
|
619 |
|
620 let imgElem = content.document.body && |
|
621 content.document.body.firstElementChild; |
|
622 |
|
623 if (!imgElem) { |
|
624 ok(false, "Could not get image element on ImageDocument for rotation!"); |
|
625 gBrowser.removeTab(test_imageTab); |
|
626 finish(); |
|
627 return; |
|
628 } |
|
629 |
|
630 // Quick function to normalize rotation to 0 <= r < 360 |
|
631 var normRot = function(rotation) { |
|
632 rotation = rotation % 360; |
|
633 if (rotation < 0) |
|
634 rotation += 360; |
|
635 return rotation; |
|
636 } |
|
637 |
|
638 for (var initRot = 0; initRot < 360; initRot += 90) { |
|
639 // Test each case: at each 90 degree snap; cl/ccl; |
|
640 // amount more or less than 45; stop and hold or don't (32 total tests) |
|
641 // The amount added to the initRot is where it is expected to be |
|
642 test_rotateHelperOneGesture(imgElem, normRot(initRot + 0), cl, 35, true ); |
|
643 test_rotateHelperOneGesture(imgElem, normRot(initRot + 0), cl, 35, false); |
|
644 test_rotateHelperOneGesture(imgElem, normRot(initRot + 90), cl, 55, true ); |
|
645 test_rotateHelperOneGesture(imgElem, normRot(initRot + 180), cl, 55, false); |
|
646 test_rotateHelperOneGesture(imgElem, normRot(initRot + 270), ccl, 35, true ); |
|
647 test_rotateHelperOneGesture(imgElem, normRot(initRot + 270), ccl, 35, false); |
|
648 test_rotateHelperOneGesture(imgElem, normRot(initRot + 180), ccl, 55, true ); |
|
649 test_rotateHelperOneGesture(imgElem, normRot(initRot + 90), ccl, 55, false); |
|
650 |
|
651 // Manually rotate it 90 degrees clockwise to prepare for next iteration, |
|
652 // and force flush |
|
653 test_utils.sendSimpleGestureEvent("MozRotateGestureStart", 0, 0, cl, .001, 0); |
|
654 test_utils.sendSimpleGestureEvent("MozRotateGestureUpdate", 0, 0, cl, 90, 0); |
|
655 test_utils.sendSimpleGestureEvent("MozRotateGestureUpdate", 0, 0, cl, .001, 0); |
|
656 test_utils.sendSimpleGestureEvent("MozRotateGesture", 0, 0, cl, 0, 0); |
|
657 imgElem.clientTop; |
|
658 } |
|
659 |
|
660 gBrowser.removeTab(test_imageTab); |
|
661 test_imageTab = null; |
|
662 finish(); |
|
663 } |
|
664 |
|
665 function test_rotateGestures() |
|
666 { |
|
667 test_imageTab = gBrowser.addTab("chrome://branding/content/about-logo.png"); |
|
668 gBrowser.selectedTab = test_imageTab; |
|
669 |
|
670 gBrowser.selectedBrowser.addEventListener("load", test_rotateGesturesOnTab, true); |
|
671 } |