michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: // Simple gestures tests michael@0: // michael@0: // These tests require the ability to disable the fact that the michael@0: // Firefox chrome intentionally prevents "simple gesture" events from michael@0: // reaching web content. michael@0: michael@0: let test_utils; michael@0: let test_commandset; michael@0: let test_prefBranch = "browser.gesture."; michael@0: michael@0: function test() michael@0: { michael@0: waitForExplicitFinish(); michael@0: michael@0: // Disable the default gestures support during the test michael@0: gGestureSupport.init(false); michael@0: michael@0: test_utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor). michael@0: getInterface(Components.interfaces.nsIDOMWindowUtils); michael@0: michael@0: // Run the tests of "simple gesture" events generally michael@0: test_EnsureConstantsAreDisjoint(); michael@0: test_TestEventListeners(); michael@0: test_TestEventCreation(); michael@0: michael@0: // Reenable the default gestures support. The remaining tests target michael@0: // the Firefox gesture functionality. michael@0: gGestureSupport.init(true); michael@0: michael@0: // Test Firefox's gestures support. michael@0: test_commandset = document.getElementById("mainCommandSet"); michael@0: test_swipeGestures(); michael@0: test_latchedGesture("pinch", "out", "in", "MozMagnifyGesture"); michael@0: test_thresholdGesture("pinch", "out", "in", "MozMagnifyGesture"); michael@0: test_rotateGestures(); michael@0: } michael@0: michael@0: let test_eventCount = 0; michael@0: let test_expectedType; michael@0: let test_expectedDirection; michael@0: let test_expectedDelta; michael@0: let test_expectedModifiers; michael@0: let test_expectedClickCount; michael@0: let test_imageTab; michael@0: michael@0: function test_gestureListener(evt) michael@0: { michael@0: is(evt.type, test_expectedType, michael@0: "evt.type (" + evt.type + ") does not match expected value"); michael@0: is(evt.target, test_utils.elementFromPoint(20, 20, false, false), michael@0: "evt.target (" + evt.target + ") does not match expected value"); michael@0: is(evt.clientX, 20, michael@0: "evt.clientX (" + evt.clientX + ") does not match expected value"); michael@0: is(evt.clientY, 20, michael@0: "evt.clientY (" + evt.clientY + ") does not match expected value"); michael@0: isnot(evt.screenX, 0, michael@0: "evt.screenX (" + evt.screenX + ") does not match expected value"); michael@0: isnot(evt.screenY, 0, michael@0: "evt.screenY (" + evt.screenY + ") does not match expected value"); michael@0: michael@0: is(evt.direction, test_expectedDirection, michael@0: "evt.direction (" + evt.direction + ") does not match expected value"); michael@0: is(evt.delta, test_expectedDelta, michael@0: "evt.delta (" + evt.delta + ") does not match expected value"); michael@0: michael@0: is(evt.shiftKey, (test_expectedModifiers & Components.interfaces.nsIDOMEvent.SHIFT_MASK) != 0, michael@0: "evt.shiftKey did not match expected value"); michael@0: is(evt.ctrlKey, (test_expectedModifiers & Components.interfaces.nsIDOMEvent.CONTROL_MASK) != 0, michael@0: "evt.ctrlKey did not match expected value"); michael@0: is(evt.altKey, (test_expectedModifiers & Components.interfaces.nsIDOMEvent.ALT_MASK) != 0, michael@0: "evt.altKey did not match expected value"); michael@0: is(evt.metaKey, (test_expectedModifiers & Components.interfaces.nsIDOMEvent.META_MASK) != 0, michael@0: "evt.metaKey did not match expected value"); michael@0: michael@0: if (evt.type == "MozTapGesture") { michael@0: is(evt.clickCount, test_expectedClickCount, "evt.clickCount does not match"); michael@0: } michael@0: michael@0: test_eventCount++; michael@0: } michael@0: michael@0: function test_helper1(type, direction, delta, modifiers) michael@0: { michael@0: // Setup the expected values michael@0: test_expectedType = type; michael@0: test_expectedDirection = direction; michael@0: test_expectedDelta = delta; michael@0: test_expectedModifiers = modifiers; michael@0: michael@0: let expectedEventCount = test_eventCount + 1; michael@0: michael@0: document.addEventListener(type, test_gestureListener, true); michael@0: test_utils.sendSimpleGestureEvent(type, 20, 20, direction, delta, modifiers); michael@0: document.removeEventListener(type, test_gestureListener, true); michael@0: michael@0: is(expectedEventCount, test_eventCount, "Event (" + type + ") was never received by event listener"); michael@0: } michael@0: michael@0: function test_clicks(type, clicks) michael@0: { michael@0: // Setup the expected values michael@0: test_expectedType = type; michael@0: test_expectedDirection = 0; michael@0: test_expectedDelta = 0; michael@0: test_expectedModifiers = 0; michael@0: test_expectedClickCount = clicks; michael@0: michael@0: let expectedEventCount = test_eventCount + 1; michael@0: michael@0: document.addEventListener(type, test_gestureListener, true); michael@0: test_utils.sendSimpleGestureEvent(type, 20, 20, 0, 0, 0, clicks); michael@0: document.removeEventListener(type, test_gestureListener, true); michael@0: michael@0: is(expectedEventCount, test_eventCount, "Event (" + type + ") was never received by event listener"); michael@0: } michael@0: michael@0: function test_TestEventListeners() michael@0: { michael@0: let e = test_helper1; // easier to type this name michael@0: michael@0: // Swipe gesture animation events michael@0: e("MozSwipeGestureStart", 0, -0.7, 0); michael@0: e("MozSwipeGestureUpdate", 0, -0.4, 0); michael@0: e("MozSwipeGestureEnd", 0, 0, 0); michael@0: e("MozSwipeGestureStart", 0, 0.6, 0); michael@0: e("MozSwipeGestureUpdate", 0, 0.3, 0); michael@0: e("MozSwipeGestureEnd", 0, 1, 0); michael@0: michael@0: // Swipe gesture event michael@0: e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_LEFT, 0.0, 0); michael@0: e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_RIGHT, 0.0, 0); michael@0: e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_UP, 0.0, 0); michael@0: e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_DOWN, 0.0, 0); michael@0: e("MozSwipeGesture", michael@0: SimpleGestureEvent.DIRECTION_UP | SimpleGestureEvent.DIRECTION_LEFT, 0.0, 0); michael@0: e("MozSwipeGesture", michael@0: SimpleGestureEvent.DIRECTION_DOWN | SimpleGestureEvent.DIRECTION_RIGHT, 0.0, 0); michael@0: e("MozSwipeGesture", michael@0: SimpleGestureEvent.DIRECTION_UP | SimpleGestureEvent.DIRECTION_RIGHT, 0.0, 0); michael@0: e("MozSwipeGesture", michael@0: SimpleGestureEvent.DIRECTION_DOWN | SimpleGestureEvent.DIRECTION_LEFT, 0.0, 0); michael@0: michael@0: // magnify gesture events michael@0: e("MozMagnifyGestureStart", 0, 50.0, 0); michael@0: e("MozMagnifyGestureUpdate", 0, -25.0, 0); michael@0: e("MozMagnifyGestureUpdate", 0, 5.0, 0); michael@0: e("MozMagnifyGesture", 0, 30.0, 0); michael@0: michael@0: // rotate gesture events michael@0: e("MozRotateGestureStart", SimpleGestureEvent.ROTATION_CLOCKWISE, 33.0, 0); michael@0: e("MozRotateGestureUpdate", SimpleGestureEvent.ROTATION_COUNTERCLOCKWISE, -13.0, 0); michael@0: e("MozRotateGestureUpdate", SimpleGestureEvent.ROTATION_CLOCKWISE, 13.0, 0); michael@0: e("MozRotateGesture", SimpleGestureEvent.ROTATION_CLOCKWISE, 33.0, 0); michael@0: michael@0: // Tap and presstap gesture events michael@0: test_clicks("MozTapGesture", 1); michael@0: test_clicks("MozTapGesture", 2); michael@0: test_clicks("MozTapGesture", 3); michael@0: test_clicks("MozPressTapGesture", 1); michael@0: michael@0: // simple delivery test for edgeui gestures michael@0: e("MozEdgeUIStarted", 0, 0, 0); michael@0: e("MozEdgeUICanceled", 0, 0, 0); michael@0: e("MozEdgeUICompleted", 0, 0, 0); michael@0: michael@0: // event.shiftKey michael@0: let modifier = Components.interfaces.nsIDOMEvent.SHIFT_MASK; michael@0: e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_RIGHT, 0, modifier); michael@0: michael@0: // event.metaKey michael@0: modifier = Components.interfaces.nsIDOMEvent.META_MASK; michael@0: e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_RIGHT, 0, modifier); michael@0: michael@0: // event.altKey michael@0: modifier = Components.interfaces.nsIDOMEvent.ALT_MASK; michael@0: e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_RIGHT, 0, modifier); michael@0: michael@0: // event.ctrlKey michael@0: modifier = Components.interfaces.nsIDOMEvent.CONTROL_MASK; michael@0: e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_RIGHT, 0, modifier); michael@0: } michael@0: michael@0: function test_eventDispatchListener(evt) michael@0: { michael@0: test_eventCount++; michael@0: evt.stopPropagation(); michael@0: } michael@0: michael@0: function test_helper2(type, direction, delta, altKey, ctrlKey, shiftKey, metaKey) michael@0: { michael@0: let event = null; michael@0: let successful; michael@0: michael@0: try { michael@0: event = document.createEvent("SimpleGestureEvent"); michael@0: successful = true; michael@0: } michael@0: catch (ex) { michael@0: successful = false; michael@0: } michael@0: ok(successful, "Unable to create SimpleGestureEvent"); michael@0: michael@0: try { michael@0: event.initSimpleGestureEvent(type, true, true, window, 1, michael@0: 10, 10, 10, 10, michael@0: ctrlKey, altKey, shiftKey, metaKey, michael@0: 1, window, michael@0: 0, direction, delta, 0); michael@0: successful = true; michael@0: } michael@0: catch (ex) { michael@0: successful = false; michael@0: } michael@0: ok(successful, "event.initSimpleGestureEvent should not fail"); michael@0: michael@0: // Make sure the event fields match the expected values michael@0: is(event.type, type, "Mismatch on evt.type"); michael@0: is(event.direction, direction, "Mismatch on evt.direction"); michael@0: is(event.delta, delta, "Mismatch on evt.delta"); michael@0: is(event.altKey, altKey, "Mismatch on evt.altKey"); michael@0: is(event.ctrlKey, ctrlKey, "Mismatch on evt.ctrlKey"); michael@0: is(event.shiftKey, shiftKey, "Mismatch on evt.shiftKey"); michael@0: is(event.metaKey, metaKey, "Mismatch on evt.metaKey"); michael@0: is(event.view, window, "Mismatch on evt.view"); michael@0: is(event.detail, 1, "Mismatch on evt.detail"); michael@0: is(event.clientX, 10, "Mismatch on evt.clientX"); michael@0: is(event.clientY, 10, "Mismatch on evt.clientY"); michael@0: is(event.screenX, 10, "Mismatch on evt.screenX"); michael@0: is(event.screenY, 10, "Mismatch on evt.screenY"); michael@0: is(event.button, 1, "Mismatch on evt.button"); michael@0: is(event.relatedTarget, window, "Mismatch on evt.relatedTarget"); michael@0: michael@0: // Test event dispatch michael@0: let expectedEventCount = test_eventCount + 1; michael@0: document.addEventListener(type, test_eventDispatchListener, true); michael@0: document.dispatchEvent(event); michael@0: document.removeEventListener(type, test_eventDispatchListener, true); michael@0: is(expectedEventCount, test_eventCount, "Dispatched event was never received by listener"); michael@0: } michael@0: michael@0: function test_TestEventCreation() michael@0: { michael@0: // Event creation michael@0: test_helper2("MozMagnifyGesture", SimpleGestureEvent.DIRECTION_RIGHT, 20.0, michael@0: true, false, true, false); michael@0: test_helper2("MozMagnifyGesture", SimpleGestureEvent.DIRECTION_LEFT, -20.0, michael@0: false, true, false, true); michael@0: } michael@0: michael@0: function test_EnsureConstantsAreDisjoint() michael@0: { michael@0: let up = SimpleGestureEvent.DIRECTION_UP; michael@0: let down = SimpleGestureEvent.DIRECTION_DOWN; michael@0: let left = SimpleGestureEvent.DIRECTION_LEFT; michael@0: let right = SimpleGestureEvent.DIRECTION_RIGHT; michael@0: michael@0: let clockwise = SimpleGestureEvent.ROTATION_CLOCKWISE; michael@0: let cclockwise = SimpleGestureEvent.ROTATION_COUNTERCLOCKWISE; michael@0: michael@0: ok(up ^ down, "DIRECTION_UP and DIRECTION_DOWN are not bitwise disjoint"); michael@0: ok(up ^ left, "DIRECTION_UP and DIRECTION_LEFT are not bitwise disjoint"); michael@0: ok(up ^ right, "DIRECTION_UP and DIRECTION_RIGHT are not bitwise disjoint"); michael@0: ok(down ^ left, "DIRECTION_DOWN and DIRECTION_LEFT are not bitwise disjoint"); michael@0: ok(down ^ right, "DIRECTION_DOWN and DIRECTION_RIGHT are not bitwise disjoint"); michael@0: ok(left ^ right, "DIRECTION_LEFT and DIRECTION_RIGHT are not bitwise disjoint"); michael@0: ok(clockwise ^ cclockwise, "ROTATION_CLOCKWISE and ROTATION_COUNTERCLOCKWISE are not bitwise disjoint"); michael@0: } michael@0: michael@0: // Helper for test of latched event processing. Emits the actual michael@0: // gesture events to test whether the commands associated with the michael@0: // gesture will only trigger once for each direction of movement. michael@0: function test_emitLatchedEvents(eventPrefix, initialDelta, cmd) michael@0: { michael@0: let cumulativeDelta = 0; michael@0: let isIncreasing = initialDelta > 0; michael@0: michael@0: let expect = {}; michael@0: // Reset the call counters and initialize expected values michael@0: for (let dir in cmd) michael@0: cmd[dir].callCount = expect[dir] = 0; michael@0: michael@0: let check = function(aDir, aMsg) ok(cmd[aDir].callCount == expect[aDir], aMsg); michael@0: let checkBoth = function(aNum, aInc, aDec) { michael@0: let prefix = "Step " + aNum + ": "; michael@0: check("inc", prefix + aInc); michael@0: check("dec", prefix + aDec); michael@0: }; michael@0: michael@0: // Send the "Start" event. michael@0: test_utils.sendSimpleGestureEvent(eventPrefix + "Start", 0, 0, 0, initialDelta, 0); michael@0: cumulativeDelta += initialDelta; michael@0: if (isIncreasing) { michael@0: expect.inc++; michael@0: checkBoth(1, "Increasing command was not triggered", "Decreasing command was triggered"); michael@0: } else { michael@0: expect.dec++; michael@0: checkBoth(1, "Increasing command was triggered", "Decreasing command was not triggered"); michael@0: } michael@0: michael@0: // Send random values in the same direction and ensure neither michael@0: // command triggers. michael@0: for (let i = 0; i < 5; i++) { michael@0: let delta = Math.random() * (isIncreasing ? 100 : -100); michael@0: test_utils.sendSimpleGestureEvent(eventPrefix + "Update", 0, 0, 0, delta, 0); michael@0: cumulativeDelta += delta; michael@0: checkBoth(2, "Increasing command was triggered", "Decreasing command was triggered"); michael@0: } michael@0: michael@0: // Now go back in the opposite direction. michael@0: test_utils.sendSimpleGestureEvent(eventPrefix + "Update", 0, 0, 0, michael@0: - initialDelta, 0); michael@0: cumulativeDelta += - initialDelta; michael@0: if (isIncreasing) { michael@0: expect.dec++; michael@0: checkBoth(3, "Increasing command was triggered", "Decreasing command was not triggered"); michael@0: } else { michael@0: expect.inc++; michael@0: checkBoth(3, "Increasing command was not triggered", "Decreasing command was triggered"); michael@0: } michael@0: michael@0: // Send random values in the opposite direction and ensure neither michael@0: // command triggers. michael@0: for (let i = 0; i < 5; i++) { michael@0: let delta = Math.random() * (isIncreasing ? -100 : 100); michael@0: test_utils.sendSimpleGestureEvent(eventPrefix + "Update", 0, 0, 0, delta, 0); michael@0: cumulativeDelta += delta; michael@0: checkBoth(4, "Increasing command was triggered", "Decreasing command was triggered"); michael@0: } michael@0: michael@0: // Go back to the original direction. The original command should trigger. michael@0: test_utils.sendSimpleGestureEvent(eventPrefix + "Update", 0, 0, 0, michael@0: initialDelta, 0); michael@0: cumulativeDelta += initialDelta; michael@0: if (isIncreasing) { michael@0: expect.inc++; michael@0: checkBoth(5, "Increasing command was not triggered", "Decreasing command was triggered"); michael@0: } else { michael@0: expect.dec++; michael@0: checkBoth(5, "Increasing command was triggered", "Decreasing command was not triggered"); michael@0: } michael@0: michael@0: // Send the wrap-up event. No commands should be triggered. michael@0: test_utils.sendSimpleGestureEvent(eventPrefix, 0, 0, 0, cumulativeDelta, 0); michael@0: checkBoth(6, "Increasing command was triggered", "Decreasing command was triggered"); michael@0: } michael@0: michael@0: function test_addCommand(prefName, id) michael@0: { michael@0: let cmd = test_commandset.appendChild(document.createElement("command")); michael@0: cmd.setAttribute("id", id); michael@0: cmd.setAttribute("oncommand", "this.callCount++;"); michael@0: michael@0: cmd.origPrefName = prefName; michael@0: cmd.origPrefValue = gPrefService.getCharPref(prefName); michael@0: gPrefService.setCharPref(prefName, id); michael@0: michael@0: return cmd; michael@0: } michael@0: michael@0: function test_removeCommand(cmd) michael@0: { michael@0: gPrefService.setCharPref(cmd.origPrefName, cmd.origPrefValue); michael@0: test_commandset.removeChild(cmd); michael@0: } michael@0: michael@0: // Test whether latched events are only called once per direction of motion. michael@0: function test_latchedGesture(gesture, inc, dec, eventPrefix) michael@0: { michael@0: let branch = test_prefBranch + gesture + "."; michael@0: michael@0: // Put the gesture into latched mode. michael@0: let oldLatchedValue = gPrefService.getBoolPref(branch + "latched"); michael@0: gPrefService.setBoolPref(branch + "latched", true); michael@0: michael@0: // Install the test commands for increasing and decreasing motion. michael@0: let cmd = { michael@0: inc: test_addCommand(branch + inc, "test:incMotion"), michael@0: dec: test_addCommand(branch + dec, "test:decMotion"), michael@0: }; michael@0: michael@0: // Test the gestures in each direction. michael@0: test_emitLatchedEvents(eventPrefix, 500, cmd); michael@0: test_emitLatchedEvents(eventPrefix, -500, cmd); michael@0: michael@0: // Restore the gesture to its original configuration. michael@0: gPrefService.setBoolPref(branch + "latched", oldLatchedValue); michael@0: for (let dir in cmd) michael@0: test_removeCommand(cmd[dir]); michael@0: } michael@0: michael@0: // Test whether non-latched events are triggered upon sufficient motion. michael@0: function test_thresholdGesture(gesture, inc, dec, eventPrefix) michael@0: { michael@0: let branch = test_prefBranch + gesture + "."; michael@0: michael@0: // Disable latched mode for this gesture. michael@0: let oldLatchedValue = gPrefService.getBoolPref(branch + "latched"); michael@0: gPrefService.setBoolPref(branch + "latched", false); michael@0: michael@0: // Set the triggering threshold value to 50. michael@0: let oldThresholdValue = gPrefService.getIntPref(branch + "threshold"); michael@0: gPrefService.setIntPref(branch + "threshold", 50); michael@0: michael@0: // Install the test commands for increasing and decreasing motion. michael@0: let cmdInc = test_addCommand(branch + inc, "test:incMotion"); michael@0: let cmdDec = test_addCommand(branch + dec, "test:decMotion"); michael@0: michael@0: // Send the start event but stop short of triggering threshold. michael@0: cmdInc.callCount = cmdDec.callCount = 0; michael@0: test_utils.sendSimpleGestureEvent(eventPrefix + "Start", 0, 0, 0, 49.5, 0); michael@0: ok(cmdInc.callCount == 0, "Increasing command was triggered"); michael@0: ok(cmdDec.callCount == 0, "Decreasing command was triggered"); michael@0: michael@0: // Now trigger the threshold. michael@0: cmdInc.callCount = cmdDec.callCount = 0; michael@0: test_utils.sendSimpleGestureEvent(eventPrefix + "Update", 0, 0, 0, 1, 0); michael@0: ok(cmdInc.callCount == 1, "Increasing command was not triggered"); michael@0: ok(cmdDec.callCount == 0, "Decreasing command was triggered"); michael@0: michael@0: // The tracking counter should go to zero. Go back the other way and michael@0: // stop short of triggering the threshold. michael@0: cmdInc.callCount = cmdDec.callCount = 0; michael@0: test_utils.sendSimpleGestureEvent(eventPrefix + "Update", 0, 0, 0, -49.5, 0); michael@0: ok(cmdInc.callCount == 0, "Increasing command was triggered"); michael@0: ok(cmdDec.callCount == 0, "Decreasing command was triggered"); michael@0: michael@0: // Now cross the threshold and trigger the decreasing command. michael@0: cmdInc.callCount = cmdDec.callCount = 0; michael@0: test_utils.sendSimpleGestureEvent(eventPrefix + "Update", 0, 0, 0, -1.5, 0); michael@0: ok(cmdInc.callCount == 0, "Increasing command was triggered"); michael@0: ok(cmdDec.callCount == 1, "Decreasing command was not triggered"); michael@0: michael@0: // Send the wrap-up event. No commands should trigger. michael@0: cmdInc.callCount = cmdDec.callCount = 0; michael@0: test_utils.sendSimpleGestureEvent(eventPrefix, 0, 0, 0, -0.5, 0); michael@0: ok(cmdInc.callCount == 0, "Increasing command was triggered"); michael@0: ok(cmdDec.callCount == 0, "Decreasing command was triggered"); michael@0: michael@0: // Restore the gesture to its original configuration. michael@0: gPrefService.setBoolPref(branch + "latched", oldLatchedValue); michael@0: gPrefService.setIntPref(branch + "threshold", oldThresholdValue); michael@0: test_removeCommand(cmdInc); michael@0: test_removeCommand(cmdDec); michael@0: } michael@0: michael@0: function test_swipeGestures() michael@0: { michael@0: // easier to type names for the direction constants michael@0: let up = SimpleGestureEvent.DIRECTION_UP; michael@0: let down = SimpleGestureEvent.DIRECTION_DOWN; michael@0: let left = SimpleGestureEvent.DIRECTION_LEFT; michael@0: let right = SimpleGestureEvent.DIRECTION_RIGHT; michael@0: michael@0: let branch = test_prefBranch + "swipe."; michael@0: michael@0: // Install the test commands for the swipe gestures. michael@0: let cmdUp = test_addCommand(branch + "up", "test:swipeUp"); michael@0: let cmdDown = test_addCommand(branch + "down", "test:swipeDown"); michael@0: let cmdLeft = test_addCommand(branch + "left", "test:swipeLeft"); michael@0: let cmdRight = test_addCommand(branch + "right", "test:swipeRight"); michael@0: michael@0: function resetCounts() { michael@0: cmdUp.callCount = 0; michael@0: cmdDown.callCount = 0; michael@0: cmdLeft.callCount = 0; michael@0: cmdRight.callCount = 0; michael@0: } michael@0: michael@0: // UP michael@0: resetCounts(); michael@0: test_utils.sendSimpleGestureEvent("MozSwipeGesture", 0, 0, up, 0, 0); michael@0: ok(cmdUp.callCount == 1, "Step 1: Up command was not triggered"); michael@0: ok(cmdDown.callCount == 0, "Step 1: Down command was triggered"); michael@0: ok(cmdLeft.callCount == 0, "Step 1: Left command was triggered"); michael@0: ok(cmdRight.callCount == 0, "Step 1: Right command was triggered"); michael@0: michael@0: // DOWN michael@0: resetCounts(); michael@0: test_utils.sendSimpleGestureEvent("MozSwipeGesture", 0, 0, down, 0, 0); michael@0: ok(cmdUp.callCount == 0, "Step 2: Up command was triggered"); michael@0: ok(cmdDown.callCount == 1, "Step 2: Down command was not triggered"); michael@0: ok(cmdLeft.callCount == 0, "Step 2: Left command was triggered"); michael@0: ok(cmdRight.callCount == 0, "Step 2: Right command was triggered"); michael@0: michael@0: // LEFT michael@0: resetCounts(); michael@0: test_utils.sendSimpleGestureEvent("MozSwipeGesture", 0, 0, left, 0, 0); michael@0: ok(cmdUp.callCount == 0, "Step 3: Up command was triggered"); michael@0: ok(cmdDown.callCount == 0, "Step 3: Down command was triggered"); michael@0: ok(cmdLeft.callCount == 1, "Step 3: Left command was not triggered"); michael@0: ok(cmdRight.callCount == 0, "Step 3: Right command was triggered"); michael@0: michael@0: // RIGHT michael@0: resetCounts(); michael@0: test_utils.sendSimpleGestureEvent("MozSwipeGesture", 0, 0, right, 0, 0); michael@0: ok(cmdUp.callCount == 0, "Step 4: Up command was triggered"); michael@0: ok(cmdDown.callCount == 0, "Step 4: Down command was triggered"); michael@0: ok(cmdLeft.callCount == 0, "Step 4: Left command was triggered"); michael@0: ok(cmdRight.callCount == 1, "Step 4: Right command was not triggered"); michael@0: michael@0: // Make sure combinations do not trigger events. michael@0: let combos = [ up | left, up | right, down | left, down | right]; michael@0: for (let i = 0; i < combos.length; i++) { michael@0: resetCounts(); michael@0: test_utils.sendSimpleGestureEvent("MozSwipeGesture", 0, 0, combos[i], 0, 0); michael@0: ok(cmdUp.callCount == 0, "Step 5-"+i+": Up command was triggered"); michael@0: ok(cmdDown.callCount == 0, "Step 5-"+i+": Down command was triggered"); michael@0: ok(cmdLeft.callCount == 0, "Step 5-"+i+": Left command was triggered"); michael@0: ok(cmdRight.callCount == 0, "Step 5-"+i+": Right command was triggered"); michael@0: } michael@0: michael@0: // Remove the test commands. michael@0: test_removeCommand(cmdUp); michael@0: test_removeCommand(cmdDown); michael@0: test_removeCommand(cmdLeft); michael@0: test_removeCommand(cmdRight); michael@0: } michael@0: michael@0: michael@0: function test_rotateHelperGetImageRotation(aImageElement) michael@0: { michael@0: // Get the true image rotation from the transform matrix, bounded michael@0: // to 0 <= result < 360 michael@0: let transformValue = content.window.getComputedStyle(aImageElement, null) michael@0: .transform; michael@0: if (transformValue == "none") michael@0: return 0; michael@0: michael@0: transformValue = transformValue.split("(")[1] michael@0: .split(")")[0] michael@0: .split(","); michael@0: var rotation = Math.round(Math.atan2(transformValue[1], transformValue[0]) * michael@0: (180 / Math.PI)); michael@0: return (rotation < 0 ? rotation + 360 : rotation); michael@0: } michael@0: michael@0: function test_rotateHelperOneGesture(aImageElement, aCurrentRotation, michael@0: aDirection, aAmount, aStop) michael@0: { michael@0: if (aAmount <= 0 || aAmount > 90) // Bound to 0 < aAmount <= 90 michael@0: return; michael@0: michael@0: // easier to type names for the direction constants michael@0: let clockwise = SimpleGestureEvent.ROTATION_CLOCKWISE; michael@0: let cclockwise = SimpleGestureEvent.ROTATION_COUNTERCLOCKWISE; michael@0: michael@0: let delta = aAmount * (aDirection == clockwise ? 1 : -1); michael@0: michael@0: // Kill transition time on image so test isn't wrong and doesn't take 10 seconds michael@0: aImageElement.style.transitionDuration = "0s"; michael@0: michael@0: // Start the gesture, perform an update, and force flush michael@0: test_utils.sendSimpleGestureEvent("MozRotateGestureStart", 0, 0, aDirection, .001, 0); michael@0: test_utils.sendSimpleGestureEvent("MozRotateGestureUpdate", 0, 0, aDirection, delta, 0); michael@0: aImageElement.clientTop; michael@0: michael@0: // If stop, check intermediate michael@0: if (aStop) { michael@0: // Send near-zero-delta to stop, and force flush michael@0: test_utils.sendSimpleGestureEvent("MozRotateGestureUpdate", 0, 0, aDirection, .001, 0); michael@0: aImageElement.clientTop; michael@0: michael@0: let stopExpectedRotation = (aCurrentRotation + delta) % 360; michael@0: if (stopExpectedRotation < 0) michael@0: stopExpectedRotation += 360; michael@0: michael@0: is(stopExpectedRotation, test_rotateHelperGetImageRotation(aImageElement), michael@0: "Image rotation at gesture stop/hold: expected=" + stopExpectedRotation + michael@0: ", observed=" + test_rotateHelperGetImageRotation(aImageElement) + michael@0: ", init=" + aCurrentRotation + michael@0: ", amt=" + aAmount + michael@0: ", dir=" + (aDirection == clockwise ? "cl" : "ccl")); michael@0: } michael@0: // End it and force flush michael@0: test_utils.sendSimpleGestureEvent("MozRotateGesture", 0, 0, aDirection, 0, 0); michael@0: aImageElement.clientTop; michael@0: michael@0: let finalExpectedRotation; michael@0: michael@0: if (aAmount < 45 && aStop) { michael@0: // Rotate a bit, then stop. Expect no change at end of gesture. michael@0: finalExpectedRotation = aCurrentRotation; michael@0: } michael@0: else { michael@0: // Either not stopping (expect 90 degree change in aDirection), OR michael@0: // stopping but after 45, (expect 90 degree change in aDirection) michael@0: finalExpectedRotation = (aCurrentRotation + michael@0: (aDirection == clockwise ? 1 : -1) * 90) % 360; michael@0: if (finalExpectedRotation < 0) michael@0: finalExpectedRotation += 360; michael@0: } michael@0: michael@0: is(finalExpectedRotation, test_rotateHelperGetImageRotation(aImageElement), michael@0: "Image rotation gesture end: expected=" + finalExpectedRotation + michael@0: ", observed=" + test_rotateHelperGetImageRotation(aImageElement) + michael@0: ", init=" + aCurrentRotation + michael@0: ", amt=" + aAmount + michael@0: ", dir=" + (aDirection == clockwise ? "cl" : "ccl")); michael@0: } michael@0: michael@0: function test_rotateGesturesOnTab() michael@0: { michael@0: gBrowser.selectedBrowser.removeEventListener("load", test_rotateGesturesOnTab, true); michael@0: michael@0: if (!(content.document instanceof ImageDocument)) { michael@0: ok(false, "Image document failed to open for rotation testing"); michael@0: gBrowser.removeTab(test_imageTab); michael@0: finish(); michael@0: return; michael@0: } michael@0: michael@0: // easier to type names for the direction constants michael@0: let cl = SimpleGestureEvent.ROTATION_CLOCKWISE; michael@0: let ccl = SimpleGestureEvent.ROTATION_COUNTERCLOCKWISE; michael@0: michael@0: let imgElem = content.document.body && michael@0: content.document.body.firstElementChild; michael@0: michael@0: if (!imgElem) { michael@0: ok(false, "Could not get image element on ImageDocument for rotation!"); michael@0: gBrowser.removeTab(test_imageTab); michael@0: finish(); michael@0: return; michael@0: } michael@0: michael@0: // Quick function to normalize rotation to 0 <= r < 360 michael@0: var normRot = function(rotation) { michael@0: rotation = rotation % 360; michael@0: if (rotation < 0) michael@0: rotation += 360; michael@0: return rotation; michael@0: } michael@0: michael@0: for (var initRot = 0; initRot < 360; initRot += 90) { michael@0: // Test each case: at each 90 degree snap; cl/ccl; michael@0: // amount more or less than 45; stop and hold or don't (32 total tests) michael@0: // The amount added to the initRot is where it is expected to be michael@0: test_rotateHelperOneGesture(imgElem, normRot(initRot + 0), cl, 35, true ); michael@0: test_rotateHelperOneGesture(imgElem, normRot(initRot + 0), cl, 35, false); michael@0: test_rotateHelperOneGesture(imgElem, normRot(initRot + 90), cl, 55, true ); michael@0: test_rotateHelperOneGesture(imgElem, normRot(initRot + 180), cl, 55, false); michael@0: test_rotateHelperOneGesture(imgElem, normRot(initRot + 270), ccl, 35, true ); michael@0: test_rotateHelperOneGesture(imgElem, normRot(initRot + 270), ccl, 35, false); michael@0: test_rotateHelperOneGesture(imgElem, normRot(initRot + 180), ccl, 55, true ); michael@0: test_rotateHelperOneGesture(imgElem, normRot(initRot + 90), ccl, 55, false); michael@0: michael@0: // Manually rotate it 90 degrees clockwise to prepare for next iteration, michael@0: // and force flush michael@0: test_utils.sendSimpleGestureEvent("MozRotateGestureStart", 0, 0, cl, .001, 0); michael@0: test_utils.sendSimpleGestureEvent("MozRotateGestureUpdate", 0, 0, cl, 90, 0); michael@0: test_utils.sendSimpleGestureEvent("MozRotateGestureUpdate", 0, 0, cl, .001, 0); michael@0: test_utils.sendSimpleGestureEvent("MozRotateGesture", 0, 0, cl, 0, 0); michael@0: imgElem.clientTop; michael@0: } michael@0: michael@0: gBrowser.removeTab(test_imageTab); michael@0: test_imageTab = null; michael@0: finish(); michael@0: } michael@0: michael@0: function test_rotateGestures() michael@0: { michael@0: test_imageTab = gBrowser.addTab("chrome://branding/content/about-logo.png"); michael@0: gBrowser.selectedTab = test_imageTab; michael@0: michael@0: gBrowser.selectedBrowser.addEventListener("load", test_rotateGesturesOnTab, true); michael@0: }