Bug 1340775 - Allow window position to be set to negative coordinates; r?maja_zf draft
authorAndreas Tolfsen <ato@mozilla.com>
Thu, 23 Feb 2017 14:12:29 +0000
changeset 498308 10b718ec7a05568b5815307af8c30666ae0adfd2
parent 498295 08f709c14bf70434c153defd6049b29078acba9f
child 549110 d59704cfad41b5c14131666d1638fbffe2a12e90
push id49138
push userbmo:ato@mozilla.com
push dateTue, 14 Mar 2017 14:09:41 +0000
reviewersmaja_zf
bugs1340775
milestone55.0a1
Bug 1340775 - Allow window position to be set to negative coordinates; r?maja_zf It should be possible to set a window's position to a pair of negative coordinates, since the user may move the window off-screen. The window may also be situated off-screen by default: for example a maximised window on Windows will report window.screenX to be -8px. Relevant change to the specification: https://github.com/w3c/webdriver/pull/805 MozReview-Commit-ID: FdReDi8pLL0
testing/marionette/driver.js
testing/marionette/harness/marionette_harness/tests/unit/test_window_position.py
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -1227,18 +1227,18 @@ GeckoDriver.prototype.getWindowPosition 
  *
  * @return {Object.<string, number>}
  *     Object with |x| and |y| coordinates.
  */
 GeckoDriver.prototype.setWindowPosition = function* (cmd, resp) {
   assert.firefox()
 
   let {x, y} = cmd.parameters;
-  assert.positiveInteger(x);
-  assert.positiveInteger(y);
+  assert.integer(x);
+  assert.integer(y);
 
   let win = this.getCurrentWindow();
   let orig = {screenX: win.screenX, screenY: win.screenY};
 
   win.moveTo(x, y);
   yield wait.until((resolve, reject) => {
     if ((x == win.screenX && y == win.screenY) ||
       (win.screenX != orig.screenX || win.screenY != orig.screenY)) {
--- a/testing/marionette/harness/marionette_harness/tests/unit/test_window_position.py
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_window_position.py
@@ -3,38 +3,86 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from marionette_driver.errors import InvalidArgumentException
 
 from marionette_harness import MarionetteTestCase
 
 
 class TestWindowPosition(MarionetteTestCase):
+
+    def setUp(self):
+        MarionetteTestCase.setUp(self)
+        self.original_position = self.marionette.get_window_position()
+
+    def tearDown(self):
+        x, y = self.original_position["x"], self.original_position["y"]
+        self.marionette.set_window_position(x, y)
+        MarionetteTestCase.tearDown(self)
+
     def test_get_types(self):
         position = self.marionette.get_window_position()
         self.assertIsInstance(position["x"], int)
         self.assertIsInstance(position["y"], int)
 
     def test_set_types(self):
         for x, y in (["a", "b"], [1.2, 3.4], [True, False], [[], []], [{}, {}]):
             print("testing invalid type position ({},{})".format(x, y))
             with self.assertRaises(InvalidArgumentException):
                 self.marionette.set_window_position(x, y)
 
-    def test_out_of_bounds_arguments(self):
-        for x, y in [(-1,0), (0,-1), (-1,-1)]:
-            print("testing out of bounds position ({},{})".format(x, y))
-            with self.assertRaises(InvalidArgumentException):
-                self.marionette.set_window_position(x, y)
-
     def test_move_to_new_position(self):
         old_position = self.marionette.get_window_position()
         new_position = {"x": old_position["x"] + 10, "y": old_position["y"] + 10}
         self.marionette.set_window_position(new_position["x"], new_position["y"])
         self.assertNotEqual(old_position["x"], new_position["x"])
         self.assertNotEqual(old_position["y"], new_position["y"])
 
     def test_move_to_existing_position(self):
         old_position = self.marionette.get_window_position()
         self.marionette.set_window_position(old_position["x"], old_position["y"])
         new_position = self.marionette.get_window_position()
         self.assertEqual(old_position["x"], new_position["x"])
         self.assertEqual(old_position["y"], new_position["y"])
+
+    def test_move_to_negative_coordinates(self):
+        print("Current position: {}".format(
+            self.marionette.get_window_position()))
+        self.marionette.set_window_position(-8, -8)
+        position = self.marionette.get_window_position()
+        print("Position after requesting move to negative coordinates: {}".format(position))
+
+        # Different systems will report more or less than (-8,-8)
+        # depending on the characteristics of the window manager, since
+        # the screenX/screenY position measures the chrome boundaries,
+        # including any WM decorations.
+        #
+        # This makes this hard to reliably test across different
+        # environments.  Generally we are happy when calling
+        # marionette.set_window_position with negative coordinates does
+        # not throw.
+        #
+        # Because we have to cater to an unknown set of environments,
+        # the following assertions are the most common denominator that
+        # make this test pass, irregardless of system characteristics.
+
+        os = self.marionette.session_capabilities["platformName"]
+
+        # Certain WMs prohibit windows from being moved off-screen,
+        # but we don't have this information.  It should be safe to
+        # assume a window can be moved to (0,0) or less.
+        if os == "linux":
+            # certain WMs prohibit windows from being moved off-screen
+            self.assertLessEqual(position["x"], 0)
+            self.assertLessEqual(position["y"], 0)
+
+        # On macOS, windows can only be moved off the screen on the
+        # horizontal axis.  The system menu bar also blocks windows from
+        # being moved to (0,0).
+        elif os == "darwin":
+            self.assertEqual(-8, position["x"])
+            self.assertEqual(23, position["y"])
+
+        # It turns out that Windows is the only platform on which the
+        # window can be reliably positioned off-screen.
+        elif os == "windows_nt":
+            self.assertEqual(-8, position["x"])
+            self.assertEqual(-8, position["y"])