Bug 1378121 - Add WebDriver:MinimizeWindow command to Marionette; r=ato
Implements the backend for the WebDriver standard's Minimize Window
command.
Signed-off-by: Andreas Tolfsen <ato@sny.no>
MozReview-Commit-ID: F5Z38LxhOJm
--- a/testing/marionette/client/marionette_driver/marionette.py
+++ b/testing/marionette/client/marionette_driver/marionette.py
@@ -2012,17 +2012,17 @@ class Marionette(object):
@property
def window_size(self):
"""Get the current browser window size.
Will return the current browser window size in pixels. Refers to
window outerWidth and outerHeight values, which include scroll bars,
title bars, etc.
- :returns: dictionary representation of current window width and height
+ :returns: Window rect.
"""
warnings.warn("window_size property has been deprecated, please use get_window_rect()",
DeprecationWarning)
return self._send_message("getWindowSize",
key="value" if self.protocol == 1 else None)
def set_window_size(self, width, height):
"""Resize the browser window currently in focus.
@@ -2031,28 +2031,48 @@ class Marionette(object):
and `outerHeight` values, which include scroll bars, title bars, etc.
An error will be returned if the requested window size would result
in the window being in the maximised state.
:param width: The width to resize the window to.
:param height: The height to resize the window to.
+ :returns Window rect.
"""
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):
+ """Iconify the browser window currently receiving commands.
+ The action should be equivalent to the user pressing the minimize
+ button in the OS window.
+
+ Note that this command is not available on Fennec. It may also
+ not be available in certain window managers.
+
+ :returns Window rect.
+ """
+ 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
+ """Resize the browser window currently receiving commands.
+ The action should be equivalent to the user pressing the maximize
+ button in the OS window.
+
+
+ Note that this command is not available on Fennec. It may also
+ not be available in certain window managers.
+
+ :returns: Window rect.
"""
return self._send_message("maximizeWindow")
def fullscreen(self):
- """ Synchronously sets the user agent window to full screen as if the user
- had done "View > Enter Full Screen", or restores it if it is already
- in full screen.
+ """Synchronously sets the user agent window to full screen as
+ if the user had done "View > Enter Full Screen", or restores
+ it if it is already in full screen.
- :returns: dictionary representation of current window width and height
+ :returns: Window rect.
"""
return self._send_message("fullscreen")
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -2886,16 +2886,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 {Object.<string, number>}
+ * Window rect and window state.
+ *
+ * @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.
*
@@ -3421,16 +3464,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
@@ -64,16 +64,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' || headless
[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]