Bug 1378121 - Add Minimize Window command to marionette; r=ato draft
authoryangyi_peng@htc.com
Fri, 21 Jul 2017 17:00:41 +0800
changeset 616490 5b885bc39376
parent 609768 d43779e278d2
child 639491 ea10912c3673
push id70703
push userbmo:yangyi_peng@htc.com
push dateThu, 27 Jul 2017 03:34:09 +0000
reviewersato
bugs1378121
milestone56.0a1
Bug 1378121 - Add Minimize Window command to marionette; r=ato MozReview-Commit-ID: F5Z38LxhOJm
testing/marionette/client/marionette_driver/marionette.py
testing/marionette/driver.js
testing/marionette/harness/marionette_harness/tests/unit/test_window_minimize.py
testing/marionette/harness/marionette_harness/tests/unit/unit-tests.ini
--- a/testing/marionette/client/marionette_driver/marionette.py
+++ b/testing/marionette/client/marionette_driver/marionette.py
@@ -2037,16 +2037,22 @@ class Marionette(object):
         :param height: The height to resize the window to.
 
         """
         warnings.warn("set_window_size() has been deprecated, please use set_window_rect()",
                       DeprecationWarning)
         body = {"width": width, "height": height}
         return self._send_message("setWindowSize", body)
 
+    def minimize_window(self):
+        """ Resize the browser window currently receiving commands. The action
+        should be equivalent to the user pressing the minimize button
+        """
+        return self._send_message("WebDriver:MinimizeWindow")
+
     def maximize_window(self):
         """ Resize the browser window currently receiving commands. The action
         should be equivalent to the user pressing the maximize button
         """
         return self._send_message("maximizeWindow")
 
     def fullscreen(self):
         """ Synchronously sets the user agent window to full screen as if the user
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -2863,16 +2863,59 @@ GeckoDriver.prototype.setScreenOrientati
   }
 
   if (!win.screen.mozLockOrientation(mozOr)) {
     throw new WebDriverError(`Unable to set screen orientation: ${or}`);
   }
 };
 
 /**
+ * Synchronously minimizes the user agent window as if the user pressed
+ * the minimize button, or restores it if it is already minimized.
+ *
+ * Not supported on Fennec.
+ *
+ * @return {Map.<string, number>}
+ *     Window rect & windowState.
+ *
+ * @throws {UnsupportedOperationError}
+ *     Not available for current application.
+ * @throws {NoSuchWindowError}
+ *     Top-level browsing context has been discarded.
+ * @throws {UnexpectedAlertOpenError}
+ *     A modal dialog is open, blocking this operation.
+ */
+GeckoDriver.prototype.minimizeWindow = function* (cmd, resp) {
+  assert.firefox();
+  const win = assert.window(this.getCurrentWindow());
+  assert.noUserPrompt(this.dialog);
+
+  let state;
+  yield new Promise(resolve => {
+    win.addEventListener("sizemodechange", resolve, {once: true});
+
+    if (win.windowState == win.STATE_MINIMIZED) {
+      win.restore();
+      state = "normal";
+    } else {
+      win.minimize();
+      state = "minimized";
+    }
+  });
+
+  resp.body = {
+    x: win.screenX,
+    y: win.screenY,
+    width: win.outerWidth,
+    height: win.outerHeight,
+    state,
+  };
+};
+
+/**
  * Synchronously maximizes the user agent window as if the user pressed
  * the maximize button, or restores it if it is already maximized.
  *
  * Not supported on Fennec.
  *
  * @return {Map.<string, number>}
  *     Window rect.
  *
@@ -3398,16 +3441,17 @@ GeckoDriver.prototype.commands = {
   "WebDriver:GetTitle": GeckoDriver.prototype.getTitle,
   "WebDriver:GetWindowHandle": GeckoDriver.prototype.getWindowHandle,
   "WebDriver:GetWindowHandles": GeckoDriver.prototype.getWindowHandles,
   "WebDriver:GetWindowRect": GeckoDriver.prototype.getWindowRect,
   "WebDriver:GetWindowType": GeckoDriver.prototype.getWindowType,
   "WebDriver:IsElementDisplayed": GeckoDriver.prototype.isElementDisplayed,
   "WebDriver:IsElementEnabled": GeckoDriver.prototype.isElementEnabled,
   "WebDriver:IsElementSelected": GeckoDriver.prototype.isElementSelected,
+  "WebDriver:MinimizeWindow": GeckoDriver.prototype.minimizeWindow,
   "WebDriver:MaximizeWindow": GeckoDriver.prototype.maximizeWindow,
   "WebDriver:Navigate": GeckoDriver.prototype.get,
   "WebDriver:NewSession": GeckoDriver.prototype.newSession,
   "WebDriver:PerformActions": GeckoDriver.prototype.performActions,
   "WebDriver:Refresh":  GeckoDriver.prototype.refresh,
   "WebDriver:ReleaseActions": GeckoDriver.prototype.releaseActions,
   "WebDriver:SendAlertText": GeckoDriver.prototype.sendKeysToDialog,
   "WebDriver:SetScreenOrientation": GeckoDriver.prototype.setScreenOrientation,
new file mode 100644
--- /dev/null
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_window_minimize.py
@@ -0,0 +1,40 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from marionette_driver.errors import InvalidArgumentException
+
+from marionette_harness import MarionetteTestCase
+
+class TestWindowMinimize(MarionetteTestCase):
+
+    def setUp(self):
+        MarionetteTestCase.setUp(self)
+
+        self.original_size = self.marionette.window_size
+
+    def assert_window_minimized(self, resp):
+        self.assertEqual("minimized", resp["state"])
+
+    def assert_window_restored(self, actual):
+        self.assertEqual("normal", actual["state"])
+        self.assertEqual(self.original_size["width"], actual["width"])
+        self.assertEqual(self.original_size["height"], actual["height"])
+
+    def test_minimize_twice_restores(self):
+        resp = self.marionette.minimize_window()
+        self.assert_window_minimized(resp)
+
+        # restore the window
+        resp = self.marionette.minimize_window()
+        self.assert_window_restored(resp)
+
+    def test_minimize_stress(self):
+        for i in range(1, 25):
+            expect_minimized = bool(i % 2)
+
+            resp = self.marionette.minimize_window()
+            if expect_minimized:
+                self.assert_window_minimized(resp)
+            else:
+                self.assert_window_restored(resp)
--- a/testing/marionette/harness/marionette_harness/tests/unit/unit-tests.ini
+++ b/testing/marionette/harness/marionette_harness/tests/unit/unit-tests.ini
@@ -65,16 +65,18 @@ skip-if = appname == 'fennec'
 [test_window_handles_content.py]
 [test_window_close_chrome.py]
 skip-if = appname == 'fennec'
 [test_window_close_content.py]
 [test_window_rect.py]
 skip-if = appname == 'fennec'
 [test_window_maximize.py]
 skip-if = appname == 'fennec'
+[test_window_minimize.py]
+skip-if = appname == 'fennec'
 [test_window_status_content.py]
 [test_window_status_chrome.py]
 
 [test_screenshot.py]
 skip-if = headless # Relies on native styling which headless doesn't support.
 [test_cookies.py]
 [test_title.py]
 [test_title_chrome.py]