Bug 1357878 - Maximize window synchronously and restore when maximized; r?maja_zf
When refactoring the tests for the Set Window Rect command, it was
discovered that the Maximize Window command was not synchronous.
This patch makes GeckoDriver#maximizeWindow synchronous by waiting for
the DOM resize event to fire before returning the window rect to the user.
It also aligns the command with the WebDriver standard by making it
restore the window to its original size when calling the command a
second time.
MozReview-Commit-ID: Ft3tn2A4m7u
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -2853,32 +2853,52 @@ GeckoDriver.prototype.setScreenOrientati
}
if (!win.screen.mozLockOrientation(mozOr)) {
throw new WebDriverError(`Unable to set screen orientation: ${or}`);
}
};
/**
- * Maximizes the user agent window as if the user pressed the maximise
- * button.
+ * 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.
*
* @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.maximizeWindow = function (cmd, resp) {
+GeckoDriver.prototype.maximizeWindow = function* (cmd, resp) {
assert.firefox();
const win = assert.window(this.getCurrentWindow());
assert.noUserPrompt(this.dialog);
- win.maximize()
+ yield new Promise(resolve => {
+ win.addEventListener("resize", resolve, {once: true});
+
+ if (win.windowState == win.STATE_MAXIMIZED) {
+ win.restore();
+ } else {
+ win.maximize();
+ }
+ });
+
+ return {
+ x: win.screenX,
+ y: win.screenY,
+ width: win.outerWidth,
+ height: win.outerHeight,
+ };
};
/**
* Dismisses a currently displayed tab modal, or returns no such alert if
* no modal is displayed.
*/
GeckoDriver.prototype.dismissDialog = function (cmd, resp) {
assert.window(this.getCurrentWindow());
new file mode 100644
--- /dev/null
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_window_maximize.py
@@ -0,0 +1,90 @@
+# 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 TestWindowMaximize(MarionetteTestCase):
+
+ def setUp(self):
+ MarionetteTestCase.setUp(self)
+ self.max = self.marionette.execute_script("""
+ return {
+ width: window.screen.availWidth,
+ height: window.screen.availHeight,
+ }""", sandbox=None)
+
+ # ensure window is not maximized
+ self.marionette.set_window_size(
+ self.max["width"] - 100, self.max["height"] - 100)
+ actual = self.marionette.window_size
+ self.assertNotEqual(actual["width"], self.max["width"])
+ self.assertNotEqual(actual["height"], self.max["height"])
+
+ self.original_size = actual
+
+ def tearDown(self):
+ self.marionette.set_window_size(
+ self.original_size["width"], self.original_size["height"])
+
+ def assert_window_maximized(self, actual, delta=None):
+ if self.marionette.session_capabilities["platformName"] == "windows_nt":
+ delta = 16
+ else:
+ delta = 8
+
+ self.assertAlmostEqual(
+ actual["width"], self.max["width"],
+ delta=delta,
+ msg="Window width is not within {} px of availWidth: "
+ "current width {} and max width {}"
+ .format(delta, actual["width"], self.max["width"]))
+ self.assertAlmostEqual(
+ actual["height"], self.max["height"],
+ delta=delta,
+ msg="Window height is not within {} px of availHeight, "
+ "current height {} and max height {}"
+ .format(delta, actual["height"], self.max["height"]))
+
+ def assert_window_restored(self, actual):
+ self.assertEqual(self.original_size["width"], actual["width"])
+ self.assertEqual(self.original_size["height"], actual["height"])
+
+ def assert_window_rect(self, rect):
+ self.assertIn("width", rect)
+ self.assertIn("height", rect)
+ self.assertIn("x", rect)
+ self.assertIn("y", rect)
+ self.assertIsInstance(rect["width"], int)
+ self.assertIsInstance(rect["height"], int)
+ self.assertIsInstance(rect["x"], int)
+ self.assertIsInstance(rect["y"], int)
+
+ def test_maximize(self):
+ rect = self.marionette.maximize_window()
+ self.assert_window_rect(rect)
+ size = self.marionette.window_size
+ self.assertEqual(size, rect)
+ self.assert_window_maximized(size)
+
+ def test_maximize_twice_restores(self):
+ maximized = self.marionette.maximize_window()
+ self.assert_window_maximized(maximized)
+
+ restored = self.marionette.maximize_window()
+ self.assert_window_restored(restored)
+
+ def test_stress(self):
+ maximized = False
+
+ for i in range(1, 25):
+ expect_maximized = bool(i % 2)
+
+ rect = self.marionette.maximize_window()
+ if expect_maximized:
+ self.assert_window_maximized(rect)
+ else:
+ self.assert_window_restored(rect)
--- a/testing/marionette/harness/marionette_harness/tests/unit/unit-tests.ini
+++ b/testing/marionette/harness/marionette_harness/tests/unit/unit-tests.ini
@@ -69,16 +69,18 @@ skip-if = appname == 'fennec'
[test_window_handles_chrome.py]
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_status_content.py]
[test_window_status_chrome.py]
[test_screenshot.py]
[test_cookies.py]
[test_title.py]
[test_title_chrome.py]
skip-if = appname == 'fennec'