Bug 1189749: Implement full screen support in Marionette r?ato
This implements the Full Screen method described in the WebDriver specification
(http://w3c.github.io/webdriver/webdriver-spec.html#fullscreen-window) as well as
tests for it.
MozReview-Commit-ID: GKec7GNE6rm
--- a/testing/marionette/client/marionette_driver/marionette.py
+++ b/testing/marionette/client/marionette_driver/marionette.py
@@ -2213,8 +2213,17 @@ class Marionette(object):
body = {"width": width, "height": height}
return self._send_message("setWindowSize", body)
def maximize_window(self):
""" Resize the browser window currently receiving commands. The action
should be equivalent to the user pressing the the maximize button
"""
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.
+
+ :returns: dictionary representation of current window width and height
+ """
+ return self._send_message("fullscreen")
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -2910,16 +2910,56 @@ GeckoDriver.prototype.maximizeWindow = f
x: win.screenX,
y: win.screenY,
width: win.outerWidth,
height: win.outerHeight,
};
};
/**
+ * 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.
+ *
+ * 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.fullscreen = function* (cmd, resp) {
+ assert.firefox();
+ const win = assert.window(this.getCurrentWindow());
+ assert.noUserPrompt(this.dialog);
+
+ yield new Promise(resolve => {
+ win.addEventListener("resize", resolve, {once: true});
+
+ if (win.windowState == win.STATE_FULLSCREEN) {
+ win.document.exitFullscreen();
+ } else {
+ win.document.documentElement.requestFullscreen();
+ }
+ });
+
+ resp.body = {
+ 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());
this._checkIfAlertIsPresent();
let {button0, button1} = this.dialog.ui;
@@ -3353,16 +3393,17 @@ GeckoDriver.prototype.commands = {
"deleteAllCookies": GeckoDriver.prototype.deleteAllCookies,
"deleteCookie": GeckoDriver.prototype.deleteCookie,
"getActiveElement": GeckoDriver.prototype.getActiveElement,
"getScreenOrientation": GeckoDriver.prototype.getScreenOrientation,
"setScreenOrientation": GeckoDriver.prototype.setScreenOrientation,
"getWindowSize": GeckoDriver.prototype.getWindowRect, // Redirecting for compatibility
"setWindowSize": GeckoDriver.prototype.setWindowRect, // Redirecting for compatibility
"maximizeWindow": GeckoDriver.prototype.maximizeWindow,
+ "fullscreen": GeckoDriver.prototype.fullscreen,
"dismissDialog": GeckoDriver.prototype.dismissDialog,
"acceptDialog": GeckoDriver.prototype.acceptDialog,
"getTextFromDialog": GeckoDriver.prototype.getTextFromDialog,
"sendKeysToDialog": GeckoDriver.prototype.sendKeysToDialog,
"acceptConnections": GeckoDriver.prototype.acceptConnections,
"quitApplication": GeckoDriver.prototype.quit, // deprecated, can be removed in Firefox 56
"quit": GeckoDriver.prototype.quit,
new file mode 100644
--- /dev/null
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_window_fullscreen.py
@@ -0,0 +1,64 @@
+# 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_harness import MarionetteTestCase
+
+
+class TestWindowFullscreen(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 fullscreen
+ actual = self.marionette.set_window_rect(
+ width=self.max["width"] - 100, height=self.max["height"] - 100)
+ self.assertNotEqual(actual["width"], self.max["width"])
+ self.assertNotEqual(actual["height"], self.max["height"])
+
+ self.original_size = actual
+
+ def tearDown(self):
+ fullscreen = self.marionette.execute_script("""
+ return window.fullScreen;""", sandbox=None)
+ if fullscreen:
+ self.marionette.fullscreen()
+
+ def assert_window_fullscreen(self, actual):
+ self.assertGreater(actual["width"], self.max["width"])
+ self.assertGreater(actual["height"], self.max["height"])
+ self.assertTrue(self.marionette.execute_script("""
+ return window.fullScreen;""", sandbox=None))
+
+ 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_fullscreen(self):
+ rect = self.marionette.fullscreen()
+ self.assert_window_rect(rect)
+ size = self.marionette.window_size
+ self.assertEqual(size, rect)
+ self.assert_window_fullscreen(size)
+
+ def test_fullscreen_twice_restores(self):
+ fullscreen = self.marionette.fullscreen()
+ self.assert_window_fullscreen(fullscreen)
+
+ restored = self.marionette.fullscreen()
+ self.assert_window_restored(restored)
--- a/testing/marionette/harness/marionette_harness/tests/unit/test_window_management.py
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_window_management.py
@@ -161,8 +161,13 @@ class TestSwitchWindow(WindowManagerMixi
with self.marionette.using_context('content'):
self.assertEqual(self.marionette.title, "We Arrive Here")
# Let's close and check
self.marionette.close_chrome_window()
self.marionette.switch_to_window(self.start_window)
self.assertEqual(len(self.marionette.chrome_window_handles), 1)
+
+ def tearDown(self):
+ #ensure that we close the window, regardless of pass/failure
+ self.close_all_windows()
+ MarionetteTestCase.tearDown(self)