Bug 1396866 - Restore window state on maximizing, minimizing, and fullscreening. r?automatedtester draft
authorAndreas Tolfsen <ato@sny.no>
Sat, 09 Sep 2017 12:20:40 +0100
changeset 663135 efc535007e5c0084fb1e08bf9901ac6f36d60e3c
parent 663134 a73cc4e08bf5a005722c95b43f84ab0c8ff2bc7c
child 663136 1c4b69d415ecaab3819a9a6d1014eeaa23ada7a5
push id79339
push userbmo:ato@sny.no
push dateTue, 12 Sep 2017 18:05:14 +0000
reviewersautomatedtester
bugs1396866
milestone57.0a1
Bug 1396866 - Restore window state on maximizing, minimizing, and fullscreening. r?automatedtester When maximizing the window we must restore it from iconified state or exit fullscreen first. Likewise for minimizing the window, we must exit fullscreen. For fullscreening the window we need to also restore the window. MozReview-Commit-ID: AOQX2cV2C75
testing/marionette/driver.js
testing/web-platform/meta/MANIFEST.json
testing/web-platform/meta/webdriver/tests/contexts/maximize_window.py.ini
testing/web-platform/meta/webdriver/tests/get_window_rect.py.ini
testing/web-platform/meta/webdriver/tests/minimize_window.py.ini
testing/web-platform/meta/webdriver/tests/set_window_rect.py.ini
testing/web-platform/tests/webdriver/tests/contexts/maximize_window.py
testing/web-platform/tests/webdriver/tests/fullscreen_window.py
testing/web-platform/tests/webdriver/tests/get_window_rect.py
testing/web-platform/tests/webdriver/tests/minimize_window.py
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -1475,32 +1475,16 @@ GeckoDriver.prototype.getWindowRect = fu
 GeckoDriver.prototype.setWindowRect = async function(cmd, resp) {
   assert.firefox();
   const win = assert.window(this.getCurrentWindow());
   assert.noUserPrompt(this.dialog);
 
   let {x, y, width, height} = cmd.parameters;
   let origRect = this.curBrowser.rect;
 
-  // Exit fullscreen and wait for window to resize.
-  async function exitFullscreen() {
-    return new Promise(resolve => {
-      win.addEventListener("sizemodechange", whenIdle(win, resolve), {once: true});
-      win.fullScreen = false;
-    });
-  }
-
-  // Restore window and wait for the window state to change.
-  async function restoreWindow() {
-    return new Promise(resolve => {
-      win.addEventListener("sizemodechange", whenIdle(win, resolve), {once: true});
-      win.restore();
-    });
-  }
-
   // Synchronous resize to |width| and |height| dimensions.
   async function resizeWindow(width, height) {
     return new Promise(resolve => {
       win.addEventListener("resize", whenIdle(win, resolve), {once: true});
       win.resizeTo(width, height);
     });
   }
 
@@ -1526,23 +1510,23 @@ GeckoDriver.prototype.setWindowRect = as
           (win.screenX != origRect.x || win.screenY != origRect.y)) {
         resolve();
       } else {
         reject();
       }
     });
   }
 
-  switch (win.windowState) {
-    case win.STATE_FULLSCREEN:
-      await exitFullscreen();
+  switch (WindowState.from(win.windowState)) {
+    case WindowState.Fullscreen:
+      await exitFullscreen(win);
       break;
 
-    case win.STATE_MINIMIZED:
-      await restoreWindow();
+    case WindowState.Minimized:
+      await restoreWindow(win);
       break;
   }
 
   if (height != null && width != null) {
     assert.positiveInteger(height);
     assert.positiveInteger(width);
 
     if (win.outerWidth != width || win.outerHeight != height) {
@@ -3010,18 +2994,21 @@ GeckoDriver.prototype.setScreenOrientati
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.minimizeWindow = async function(cmd, resp) {
   assert.firefox();
   const win = assert.window(this.getCurrentWindow());
   assert.noUserPrompt(this.dialog);
 
-  let state = WindowState.from(win.windowState);
-  if (state != WindowState.Minimized) {
+  if (WindowState.from(win.windowState) == WindowState.Fullscreen) {
+    await exitFullscreen(win);
+  }
+
+  if (WindowState.from(win.windowState) != WindowState.Minimized) {
     await new Promise(resolve => {
       win.addEventListener("sizemodechange", whenIdle(win, resolve), {once: true});
       win.minimize();
     });
   }
 
   return this.curBrowser.rect;
 };
@@ -3044,16 +3031,26 @@ GeckoDriver.prototype.minimizeWindow = a
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.maximizeWindow = async function(cmd, resp) {
   assert.firefox();
   const win = assert.window(this.getCurrentWindow());
   assert.noUserPrompt(this.dialog);
 
+  switch (WindowState.from(win.windowState)) {
+    case WindowState.Fullscreen:
+      await exitFullscreen(win);
+      break;
+
+    case WindowState.Minimized:
+      await restoreWindow(win);
+      break;
+  }
+
   const origSize = {
     outerWidth: win.outerWidth,
     outerHeight: win.outerHeight,
   };
 
   // Wait for the window size to change.
   async function windowSizeChange(from) {
     return wait.until((resolve, reject) => {
@@ -3065,18 +3062,17 @@ GeckoDriver.prototype.maximizeWindow = a
           curSize.outerHeight != origSize.outerHeight) {
         resolve();
       } else {
         reject();
       }
     });
   }
 
-  let state = WindowState.from(win.windowState);
-  if (state != WindowState.Maximized) {
+  if (WindowState.from(win.windowState) != win.Maximized) {
     await new TimedPromise(resolve => {
       win.addEventListener("sizemodechange", resolve, {once: true});
       win.maximize();
     }, {throws: null});
 
     // Transitioning into a window state is asynchronous on Linux,
     // and we cannot rely on sizemodechange to accurately tell us when
     // the transition has completed.
@@ -3121,18 +3117,21 @@ GeckoDriver.prototype.maximizeWindow = a
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.fullscreenWindow = async function(cmd, resp) {
   assert.firefox();
   const win = assert.window(this.getCurrentWindow());
   assert.noUserPrompt(this.dialog);
 
-  let state = WindowState.from(win.windowState);
-  if (state != WindowState.Fullscreen) {
+  if (WindowState.from(win.windowState) == WindowState.Minimized) {
+    await restoreWindow(win);
+  }
+
+  if (WindowState.from(win.windowState) != WindowState.Fullscreen) {
     await new Promise(resolve => {
       win.addEventListener("sizemodechange", resolve, {once: true});
       win.fullScreen = true;
     });
   }
 
   return this.curBrowser.rect;
 };
@@ -3694,16 +3693,42 @@ function copy(obj) {
 
 function getOuterWindowId(win) {
   return win.QueryInterface(Ci.nsIInterfaceRequestor)
       .getInterface(Ci.nsIDOMWindowUtils)
       .outerWindowID;
 }
 
 /**
+ * Exit fullscreen and wait for <var>window</var> to resize.
+ *
+ * @param {ChromeWindow} window
+ *     Window to exit fullscreen.
+ */
+async function exitFullscreen(window) {
+  return new Promise(resolve => {
+    window.addEventListener("sizemodechange", whenIdle(window, resolve), {once: true});
+    window.fullScreen = false;
+  });
+}
+
+/**
+ * Restore window and wait for the window state to change.
+ *
+ * @param {ChromeWindow} window
+ *     Window to restore.
+ */
+async function restoreWindow(window) {
+  return new Promise(resolve => {
+    window.addEventListener("sizemodechange", whenIdle(window, resolve), {once: true});
+    window.restore();
+  });
+}
+
+/**
  * Throttle <var>callback</var> until the main thread is idle and
  * <var>window</var> has performed an animation frame.
  *
  * @param {ChromeWindow} window
  *     Window to request the animation frame from.
  * @param {function()} callback
  *     Called when done.
  *
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -407150,17 +407150,19 @@
      {
       "timeout": "long"
      }
     ]
    ],
    "webdriver/tests/contexts/maximize_window.py": [
     [
      "/webdriver/tests/contexts/maximize_window.py",
-     {}
+     {
+      "timeout": "long"
+     }
     ]
    ],
    "webdriver/tests/contexts/resizing_and_positioning.py": [
     [
      "/webdriver/tests/contexts/resizing_and_positioning.py",
      {}
     ]
    ],
@@ -407252,17 +407254,19 @@
      {
       "timeout": "long"
      }
     ]
    ],
    "webdriver/tests/set_window_rect.py": [
     [
      "/webdriver/tests/set_window_rect.py",
-     {}
+     {
+      "timeout": "long"
+     }
     ]
    ],
    "webdriver/tests/state/get_element_attribute.py": [
     [
      "/webdriver/tests/state/get_element_attribute.py",
      {}
     ]
    ],
@@ -628351,17 +628355,17 @@
    "94b6f474bb4417cf2c06cb5fc6042c01bde98aa2",
    "support"
   ],
   "webdriver/tests/conftest.py": [
    "ab95734024a8e152ed84128eb804344740be91d4",
    "support"
   ],
   "webdriver/tests/contexts/maximize_window.py": [
-   "9864125364246c98762419ea2d301b1dac91392d",
+   "904dd1db0e9731148a1793065b1d38acf0ac094b",
    "wdspec"
   ],
   "webdriver/tests/contexts/resizing_and_positioning.py": [
    "479379109115668183643e8a050396219332887d",
    "wdspec"
   ],
   "webdriver/tests/cookies/cookies.py": [
    "e31177e638269864031e44808945fa1e7c46031c",
@@ -628371,33 +628375,33 @@
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webdriver/tests/element_click/select.py": [
    "5ba51b660c7203bba3ada597c2f56fe094358e1f",
    "wdspec"
   ],
   "webdriver/tests/fullscreen_window.py": [
-   "51f9d5c190aea6da51a05bc1981548ce8908ae55",
+   "6b1e481aac6856b6e858df17731d037997b99f83",
    "wdspec"
   ],
   "webdriver/tests/get_window_rect.py": [
-   "2d4c13edc4e659af864750d0341c06ff969a687f",
+   "45770411dd6f6468aaf1d59d7f6fe2db63aad79a",
    "wdspec"
   ],
   "webdriver/tests/interaction/send_keys_content_editable.py": [
    "130c57e80a0738ed500f59b0178753f8acaf15bf",
    "wdspec"
   ],
   "webdriver/tests/interface.html": [
    "d783d0dd370f58b264ef238d8da5cd8601dc3c7f",
    "testharness"
   ],
   "webdriver/tests/minimize_window.py": [
-   "777db2156525571b58d477434345d824a257f342",
+   "e0950b165c0cbf76e8adcd865176ea164a1ea768",
    "wdspec"
   ],
   "webdriver/tests/navigation/current_url.py": [
    "cec2987258d9c807a247da9e0216b3af1f171484",
    "wdspec"
   ],
   "webdriver/tests/navigation/get_title.py": [
    "16bdf435f3d05ceca30394dee6d82adcb64c997b",
@@ -628423,17 +628427,17 @@
    "e58b671da735c6040248c80a3384760ee4496c88",
    "wdspec"
   ],
   "webdriver/tests/sessions/new_session/response.py": [
    "3eca8e1d571b0c94b2a08fccfbe8cb9f1b1ba6d5",
    "wdspec"
   ],
   "webdriver/tests/set_window_rect.py": [
-   "a361a0eb524c3e5ea0387cc98b2aeb818e1a4e97",
+   "e84559c2ee94009fe808c3008c58e6e4b9ca27aa",
    "wdspec"
   ],
   "webdriver/tests/state/__init__.py": [
    "da39a3ee5e6b4b0d3255bfef95601890afd80709",
    "support"
   ],
   "webdriver/tests/state/get_element_attribute.py": [
    "7d531acbe34c1f48f519158f813c5bce88b33259",
--- a/testing/web-platform/meta/webdriver/tests/contexts/maximize_window.py.ini
+++ b/testing/web-platform/meta/webdriver/tests/contexts/maximize_window.py.ini
@@ -1,6 +1,8 @@
 [maximize_window.py]
   type: wdspec
-  expected: TIMEOUT
-  [maximize_window.py::test_maximize_when_resized_to_max_size]
+
+  [maximize_window.py::test_handle_prompt_accept]
     expected: FAIL
 
+  [maximize_window.py::test_handle_prompt_missing_value]
+    expected: FAIL
--- a/testing/web-platform/meta/webdriver/tests/get_window_rect.py.ini
+++ b/testing/web-platform/meta/webdriver/tests/get_window_rect.py.ini
@@ -1,8 +1,7 @@
 [get_window_rect.py]
   type: wdspec
-  [get_window_rect.py::test_get_window_rect_prompt_accept]
+  [get_window_rect.py::test_handle_prompt_accept]
     expected: FAIL
 
-  [get_window_rect.py::test_get_window_rect_handle_prompt_missing_value]
+  [get_window_rect.py::test_handle_prompt_missing_value]
     expected: FAIL
-
--- a/testing/web-platform/meta/webdriver/tests/minimize_window.py.ini
+++ b/testing/web-platform/meta/webdriver/tests/minimize_window.py.ini
@@ -1,6 +1,8 @@
 [minimize_window.py]
   type: wdspec
-  [minimize_window.py::test_payload]
-    expected:
-      if debug: FAIL
 
+  [minimize_window.py::test_handle_prompt_accept]
+    expected: FAIL
+
+  [minimize_window.py::test_handle_prompt_missing_value]
+    expected: FAIL
--- a/testing/web-platform/meta/webdriver/tests/set_window_rect.py.ini
+++ b/testing/web-platform/meta/webdriver/tests/set_window_rect.py.ini
@@ -1,14 +1,7 @@
 [set_window_rect.py]
   type: wdspec
   [set_window_rect.py::test_handle_prompt_accept]
     expected: FAIL
 
   [set_window_rect.py::test_handle_prompt_missing_value]
     expected: FAIL
-
-  [set_window_rect.py::test_width_height_floats]
-    expected: FAIL
-
-  [set_window_rect.py::test_x_y_floats]
-    expected: FAIL
-
--- a/testing/web-platform/tests/webdriver/tests/contexts/maximize_window.py
+++ b/testing/web-platform/tests/webdriver/tests/contexts/maximize_window.py
@@ -1,41 +1,194 @@
+# META: timeout=long
+
+from tests.support.asserts import assert_error, assert_dialog_handled, assert_success
+from tests.support.fixtures import create_dialog
 from tests.support.inline import inline
-from tests.support.asserts import assert_error, assert_success
 
 
 alert_doc = inline("<script>window.alert()</script>")
 
 
 def maximize(session):
     return session.transport.send("POST", "session/%s/window/maximize" % session.session_id)
 
 
 # 10.7.3 Maximize Window
 
 
 def test_no_browsing_context(session, create_window):
-    # step 1
+    """
+    2. If the current top-level browsing context is no longer open,
+    return error with error code no such window.
+
+    """
     session.window_handle = create_window()
     session.close()
     response = maximize(session)
     assert_error(response, "no such window")
 
 
-def test_handle_user_prompt(session):
-    # step 2
-    session.url = alert_doc
+def test_handle_prompt_dismiss_and_notify():
+    """TODO"""
+
+
+def test_handle_prompt_accept_and_notify():
+    """TODO"""
+
+
+def test_handle_prompt_ignore():
+    """TODO"""
+
+
+def test_handle_prompt_accept(new_session):
+    """
+    3. Handle any user prompts and return its value if it is an error.
+
+    [...]
+
+    In order to handle any user prompts a remote end must take the
+    following steps:
+
+      [...]
+
+      2. Perform the following substeps based on the current session's
+      user prompt handler:
+
+        [...]
+
+        - accept state
+           Accept the current user prompt.
+
+    """
+    _, session = new_session({"alwaysMatch": {"unhandledPromptBehavior": "accept"}})
+    session.url = inline("<title>WD doc title</title>")
+
+    create_dialog(session)("alert", text="dismiss #1", result_var="dismiss1")
+    response = maximize(session)
+    assert response.status == 200
+    assert_dialog_handled(session, "dismiss #1")
+
+    create_dialog(session)("confirm", text="dismiss #2", result_var="dismiss2")
+    response = maximize(session)
+    assert response.status == 200
+    assert_dialog_handled(session, "dismiss #2")
+
+    create_dialog(session)("prompt", text="dismiss #3", result_var="dismiss3")
+    response = maximize(session)
+    assert response.status == 200
+    assert_dialog_handled(session, "dismiss #3")
+
+
+def test_handle_prompt_missing_value(session, create_dialog):
+    """
+    3. Handle any user prompts and return its value if it is an error.
+
+    [...]
+
+    In order to handle any user prompts a remote end must take the
+    following steps:
+
+      [...]
+
+      2. Perform the following substeps based on the current session's
+      user prompt handler:
+
+        [...]
+
+        - missing value default state
+           1. Dismiss the current user prompt.
+           2. Return error with error code unexpected alert open.
+
+    """
+    session.url = inline("<title>WD doc title</title>")
+    create_dialog("alert", text="dismiss #1", result_var="dismiss1")
+
+    response = maximize(session)
+
+    assert_error(response, "unexpected alert open")
+    assert_dialog_handled(session, "dismiss #1")
+
+    create_dialog("confirm", text="dismiss #2", result_var="dismiss2")
+
     response = maximize(session)
     assert_error(response, "unexpected alert open")
+    assert_dialog_handled(session, "dismiss #2")
+
+    create_dialog("prompt", text="dismiss #3", result_var="dismiss3")
+
+    response = maximize(session)
+    assert_error(response, "unexpected alert open")
+    assert_dialog_handled(session, "dismiss #3")
+
+
+def test_fully_exit_fullscreen(session):
+    """
+    4. Fully exit fullscreen.
+
+    [...]
+
+    To fully exit fullscreen a document document, run these steps:
+
+      1. If document's fullscreen element is null, terminate these steps.
+
+      2. Unfullscreen elements whose fullscreen flag is set, within
+      document's top layer, except for document's fullscreen element.
+
+      3. Exit fullscreen document.
+
+    """
+    session.window.fullscreen()
+    assert session.execute_script("return window.fullScreen") is True
+
+    response = maximize(session)
+    assert_success(response)
+    assert session.execute_script("return window.fullScreen") is False
+
+
+def test_restore_the_window(session):
+    """
+    5. Restore the window.
+
+    [...]
+
+    To restore the window, given an operating system level window with
+    an associated top-level browsing context, run implementation-specific
+    steps to restore or unhide the window to the visible screen.  Do not
+    return from this operation until the visibility state of the top-level
+    browsing context's active document has reached the visible state,
+    or until the operation times out.
+
+    """
+    session.window.minimize()
+    assert session.execute_script("return document.hidden") is True
+
+    response = maximize(session)
+    assert_success(response)
 
 
 def test_maximize(session):
+    """
+    6. Maximize the window of the current browsing context.
+
+    [...]
+
+    To maximize the window, given an operating system level window with an
+    associated top-level browsing context, run the implementation-specific
+    steps to transition the operating system level window into the
+    maximized window state.  If the window manager supports window
+    resizing but does not have a concept of window maximation, the window
+    dimensions must be increased to the maximum available size permitted
+    by the window manager for the current screen.  Return when the window
+    has completed the transition, or within an implementation-defined
+    timeout.
+
+    """
     before_size = session.window.size
 
-    # step 4
     response = maximize(session)
     assert_success(response)
 
     assert before_size != session.window.size
 
 
 def test_payload(session):
     before_size = session.window.size
--- a/testing/web-platform/tests/webdriver/tests/fullscreen_window.py
+++ b/testing/web-platform/tests/webdriver/tests/fullscreen_window.py
@@ -1,53 +1,73 @@
 # META: timeout=long
 
-from tests.support.inline import inline
 from tests.support.asserts import assert_error, assert_success, assert_dialog_handled
 from tests.support.fixtures import create_dialog
+from tests.support.inline import inline
 
 
 alert_doc = inline("<script>window.alert()</script>")
 
 
 def read_global(session, name):
     return session.execute_script("return %s;" % name)
 
 
 def fullscreen(session):
     return session.transport.send("POST", "session/%s/window/fullscreen" % session.session_id)
 
 
 # 10.7.5 Fullscreen Window
 
 
-# 1. If the current top-level browsing context is no longer open, return error
-#    with error code no such window.
 def test_no_browsing_context(session, create_window):
-    # step 1
+    """
+    1. If the current top-level browsing context is no longer open,
+    return error with error code no such window.
+
+    """
     session.window_handle = create_window()
     session.close()
     response = fullscreen(session)
     assert_error(response, "no such window")
 
 
-# [...]
-# 2. Handle any user prompts and return its value if it is an error.
-# [...]
-# In order to handle any user prompts a remote end must take the following
-# steps:
-# 2. Run the substeps of the first matching user prompt handler:
-#
-#    [...]
-#    - accept state
-#      1. Accept the current user prompt.
-#    [...]
-#
-# 3. Return success.
+def test_handle_prompt_dismiss_and_notify():
+    """TODO"""
+
+
+def test_handle_prompt_accept_and_notify():
+    """TODO"""
+
+
+def test_handle_prompt_ignore():
+    """TODO"""
+
+
 def test_handle_prompt_accept(new_session):
+    """
+    2. Handle any user prompts and return its value if it is an error.
+
+    [...]
+
+    In order to handle any user prompts a remote end must take the
+    following steps:
+
+      [...]
+
+      2. Perform the following substeps based on the current session's
+      user prompt handler:
+
+        [...]
+
+        - accept state
+           Accept the current user prompt.
+
+    """
     _, session = new_session({"alwaysMatch": {"unhandledPromptBehavior": "accept"}})
     session.url = inline("<title>WD doc title</title>")
     create_dialog(session)("alert", text="accept #1", result_var="accept1")
 
     expected_title = read_global(session, "document.title")
     response = fullscreen(session)
 
     assert_success(response, expected_title)
@@ -68,29 +88,37 @@ def test_handle_prompt_accept(new_sessio
 
     response = fullscreen(session)
 
     assert_success(response, expected_title)
     assert_dialog_handled(session, "accept #3")
     assert read_global(session, "accept3") == ""
 
 
-# [...]
-# 2. Handle any user prompts and return its value if it is an error.
-# [...]
-# In order to handle any user prompts a remote end must take the following
-# steps:
-# 2. Run the substeps of the first matching user prompt handler:
-#
-#    [...]
-#    - missing value default state
-#    - not in the table of simple dialogs
-#      1. Dismiss the current user prompt.
-#      2. Return error with error code unexpected alert open.
 def test_handle_prompt_missing_value(session, create_dialog):
+    """
+    2. Handle any user prompts and return its value if it is an error.
+
+    [...]
+
+    In order to handle any user prompts a remote end must take the
+    following steps:
+
+      [...]
+
+      2. Perform the following substeps based on the current session's
+      user prompt handler:
+
+        [...]
+
+        - missing value default state
+           1. Dismiss the current user prompt.
+           2. Return error with error code unexpected alert open.
+
+    """
     session.url = inline("<title>WD doc title</title>")
     create_dialog("alert", text="dismiss #1", result_var="dismiss1")
 
     response = fullscreen(session)
 
     assert_error(response, "unexpected alert open")
     assert_dialog_handled(session, "dismiss #1")
     assert read_global(session, "accept1") == None
@@ -107,23 +135,25 @@ def test_handle_prompt_missing_value(ses
 
     response = fullscreen(session)
 
     assert_error(response, "unexpected alert open")
     assert_dialog_handled(session, "dismiss #3")
     assert read_global(session, "dismiss3") == None
 
 
-# 4. Call fullscreen an element with the current top-level browsing
-# context's active document's document element.
 def test_fullscreen(session):
-    # step 4
+    """
+    4. Call fullscreen an element with the current top-level browsing
+    context's active document's document element.
+
+    """
     response = fullscreen(session)
     assert_success(response)
-    assert session.execute_script("return window.fullScreen") == True
+    assert session.execute_script("return window.fullScreen") is True
 
 
 # 5. Return success with the JSON serialization of the current top-level
 # browsing context's window rect.
 #
 # [...]
 #
 # A top-level browsing context's window rect is defined as a
--- a/testing/web-platform/tests/webdriver/tests/get_window_rect.py
+++ b/testing/web-platform/tests/webdriver/tests/get_window_rect.py
@@ -1,85 +1,161 @@
-from support.asserts import assert_error, assert_dialog_handled, assert_success
-from support.fixtures import create_dialog
-from support.inline import inline
+from tests.support.asserts import assert_error, assert_dialog_handled, assert_success
+from tests.support.fixtures import create_dialog
+from tests.support.inline import inline
 
 
 alert_doc = inline("<script>window.alert()</script>")
 
 
+def get_window_rect(session):
+    return session.transport.send("POST", "session/%s/window/rect" % session.session_id)
+
+
 # 10.7.1 Get Window Rect
 
-def test_get_window_rect_no_browsing_context(session, create_window):
-    # Step 1
+
+def test_no_browsing_context(session, create_window):
+    """
+    1. If the current top-level browsing context is no longer open,
+    return error with error code no such window.
+
+    """
     session.window_handle = create_window()
     session.close()
-    result = session.transport.send("GET", "session/%s/window/rect" % session.session_id)
+    response = get_window_rect(session)
+    assert_error(response, "no such window")
+
+
+def test_handle_prompt_dismiss_and_notify():
+    """TODO"""
 
-    assert_error(result, "no such window")
+
+def test_handle_prompt_accept_and_notify():
+    """TODO"""
+
+
+def test_handle_prompt_ignore():
+    """TODO"""
 
 
-def test_get_window_rect_prompt_accept(new_session):
-    # Step 2
+def test_handle_prompt_accept(new_session):
+    """
+    2. Handle any user prompts and return its value if it is an error.
+
+    [...]
+
+    In order to handle any user prompts a remote end must take the
+    following steps:
+
+      [...]
+
+      2. Perform the following substeps based on the current session's
+      user prompt handler:
+
+        [...]
+
+        - accept state
+           Accept the current user prompt.
+
+    """
     _, session = new_session({"alwaysMatch": {"unhandledPromptBehavior": "accept"}})
     session.url = inline("<title>WD doc title</title>")
 
     create_dialog(session)("alert", text="dismiss #1", result_var="dismiss1")
-    result = session.transport.send("GET",
-                                    "session/%s/window/rect" % session.session_id)
-    assert result.status == 200
+    response = get_window_rect(session)
+    assert response.status == 200
     assert_dialog_handled(session, "dismiss #1")
 
     create_dialog(session)("confirm", text="dismiss #2", result_var="dismiss2")
-    result = session.transport.send("GET",
-                                    "session/%s/window/rect" % session.session_id)
-    assert result.status == 200
+    response = get_window_rect(session)
+    assert response.status == 200
     assert_dialog_handled(session, "dismiss #2")
 
     create_dialog(session)("prompt", text="dismiss #3", result_var="dismiss3")
-    result = session.transport.send("GET",
-                                    "session/%s/window/rect" % session.session_id)
-    assert result.status == 200
+    response = get_window_rect(session)
+    assert response.status == 200
     assert_dialog_handled(session, "dismiss #3")
 
 
-def test_get_window_rect_handle_prompt_missing_value(session, create_dialog):
-    # Step 2
+def test_handle_prompt_missing_value(session, create_dialog):
+    """
+    2. Handle any user prompts and return its value if it is an error.
+
+    [...]
+
+    In order to handle any user prompts a remote end must take the
+    following steps:
+
+      [...]
+
+      2. Perform the following substeps based on the current session's
+      user prompt handler:
+
+        [...]
+
+        - missing value default state
+           1. Dismiss the current user prompt.
+           2. Return error with error code unexpected alert open.
+
+    """
     session.url = inline("<title>WD doc title</title>")
     create_dialog("alert", text="dismiss #1", result_var="dismiss1")
 
-    result = session.transport.send("GET",
-                                    "session/%s/window/rect" % session.session_id)
+    response = get_window_rect(session)
 
     assert_error(result, "unexpected alert open")
     assert_dialog_handled(session, "dismiss #1")
 
     create_dialog("confirm", text="dismiss #2", result_var="dismiss2")
 
-    result = session.transport.send("GET",
-                                    "session/%s/window/rect" % session.session_id)
-
-    assert_error(result, "unexpected alert open")
+    response = get_window_rect(session)
+    assert_error(response, "unexpected alert open")
     assert_dialog_handled(session, "dismiss #2")
 
     create_dialog("prompt", text="dismiss #3", result_var="dismiss3")
 
-    result = session.transport.send("GET",
-                                    "session/%s/window/rect" % session.session_id)
-
-    assert_error(result, "unexpected alert open")
+    response = get_window_rect(session)
+    assert_error(response, "unexpected alert open")
     assert_dialog_handled(session, "dismiss #3")
 
 
-def test_get_window_rect_payload(session):
-    # step 3
-    result = session.transport.send("GET", "session/%s/window/rect" % session.session_id)
+def test_payload(session):
+    """
+    3. Return success with the JSON serialization of the current top-level
+    browsing context's window rect.
+
+    [...]
+
+    A top-level browsing context's window rect is defined as a
+    dictionary of the screenX, screenY, width and height attributes of
+    the WindowProxy. Its JSON representation is the following:
+
+    "x"
+        WindowProxy's screenX attribute.
+
+    "y"
+        WindowProxy's screenY attribute.
 
-    assert result.status == 200
-    assert isinstance(result.body["value"], dict)
-    assert "width" in result.body["value"]
-    assert "height" in result.body["value"]
-    assert "x" in result.body["value"]
-    assert "y" in result.body["value"]
-    assert isinstance(result.body["value"]["width"], (int, float))
-    assert isinstance(result.body["value"]["height"], (int, float))
-    assert isinstance(result.body["value"]["x"], (int, float))
-    assert isinstance(result.body["value"]["y"], (int, float))
+    "width"
+        Width of the top-level browsing context's outer dimensions,
+        including any browser chrome and externally drawn window
+        decorations in CSS reference pixels.
+
+    "height"
+        Height of the top-level browsing context's outer dimensions,
+        including any browser chrome and externally drawn window
+        decorations in CSS reference pixels.
+
+    """
+    response = get_window_rect(session)
+
+    assert response.status == 200
+    assert isinstance(response.body["value"], dict)
+    value = response.body["value"]
+    assert "width" in value
+    assert "height" in value
+    assert "x" in value
+    assert "y" in value
+    assert isinstance(value["width"], int)
+    assert isinstance(value["height"], int)
+    assert isinstance(value["x"], int)
+    assert isinstance(value["y"], int)
--- a/testing/web-platform/tests/webdriver/tests/minimize_window.py
+++ b/testing/web-platform/tests/webdriver/tests/minimize_window.py
@@ -1,41 +1,169 @@
+from tests.support.asserts import assert_error, assert_success, assert_dialog_handled
+from tests.support.fixtures import create_dialog
 from tests.support.inline import inline
-from tests.support.asserts import assert_error, assert_success
 
 
 alert_doc = inline("<script>window.alert()</script>")
 
 
 def minimize(session):
     return session.transport.send("POST", "session/%s/window/minimize" % session.session_id)
 
 
 # 10.7.4 Minimize Window
 
 
-def test_minimize_no_browsing_context(session, create_window):
-    # step 1
+def test_no_browsing_context(session, create_window):
+    """
+    1. If the current top-level browsing context is no longer open,
+    return error with error code no such window.
+
+    """
     session.window_handle = create_window()
     session.close()
     response = minimize(session)
     assert_error(response, "no such window")
 
 
-def test_handle_user_prompt(session):
-    # step 2
-    session.url = alert_doc
+def test_handle_prompt_dismiss_and_notify():
+    """TODO"""
+
+
+def test_handle_prompt_accept_and_notify():
+    """TODO"""
+
+
+def test_handle_prompt_ignore():
+    """TODO"""
+
+
+def test_handle_prompt_accept(new_session):
+    """
+    2. Handle any user prompts and return its value if it is an error.
+
+    [...]
+
+    In order to handle any user prompts a remote end must take the
+    following steps:
+
+      [...]
+
+      2. Perform the following substeps based on the current session's
+      user prompt handler:
+
+        [...]
+
+        - accept state
+           Accept the current user prompt.
+
+    """
+    _, session = new_session({"alwaysMatch": {"unhandledPromptBehavior": "accept"}})
+    session.url = inline("<title>WD doc title</title>")
+
+    create_dialog(session)("alert", text="dismiss #1", result_var="dismiss1")
+    response = minimize(session)
+    assert response.status == 200
+    assert_dialog_handled(session, "dismiss #1")
+
+    create_dialog(session)("confirm", text="dismiss #2", result_var="dismiss2")
+    response = minimize(session)
+    assert response.status == 200
+    assert_dialog_handled(session, "dismiss #2")
+
+    create_dialog(session)("prompt", text="dismiss #3", result_var="dismiss3")
+    response = minimize(session)
+    assert response.status == 200
+    assert_dialog_handled(session, "dismiss #3")
+
+
+def test_handle_prompt_missing_value(session, create_dialog):
+    """
+    2. Handle any user prompts and return its value if it is an error.
+
+    [...]
+
+    In order to handle any user prompts a remote end must take the
+    following steps:
+
+      [...]
+
+      2. Perform the following substeps based on the current session's
+      user prompt handler:
+
+        [...]
+
+        - missing value default state
+           1. Dismiss the current user prompt.
+           2. Return error with error code unexpected alert open.
+
+    """
+    session.url = inline("<title>WD doc title</title>")
+    create_dialog("alert", text="dismiss #1", result_var="dismiss1")
+
+    response = minimize(session)
+
+    assert_error(response, "unexpected alert open")
+    assert_dialog_handled(session, "dismiss #1")
+
+    create_dialog("confirm", text="dismiss #2", result_var="dismiss2")
+
     response = minimize(session)
     assert_error(response, "unexpected alert open")
+    assert_dialog_handled(session, "dismiss #2")
+
+    create_dialog("prompt", text="dismiss #3", result_var="dismiss3")
+
+    response = minimize(session)
+    assert_error(response, "unexpected alert open")
+    assert_dialog_handled(session, "dismiss #3")
+
+
+def test_fully_exit_fullscreen(session):
+    """
+    4. Fully exit fullscreen.
+
+    [...]
+
+    To fully exit fullscreen a document document, run these steps:
+
+      1. If document's fullscreen element is null, terminate these steps.
+
+      2. Unfullscreen elements whose fullscreen flag is set, within
+      document's top layer, except for document's fullscreen element.
+
+      3. Exit fullscreen document.
+
+    """
+    session.window.fullscreen()
+    assert session.execute_script("return window.fullScreen") is True
+
+    response = minimize(session)
+    assert_success(response)
+    assert session.execute_script("return window.fullScreen") is False
+    assert session.execute_script("return document.hidden") is True
 
 
 def test_minimize(session):
+    """
+    5. Iconify the window.
+
+    [...]
+
+    To iconify the window, given an operating system level window with an
+    associated top-level browsing context, run implementation-specific
+    steps to iconify, minimize, or hide the window from the visible
+    screen. Do not return from this operation until the visibility state
+    of the top-level browsing context's active document has reached the
+    hidden state, or until the operation times out.
+
+    """
     assert not session.execute_script("return document.hidden")
 
-    # step 4
     response = minimize(session)
     assert_success(response)
 
     assert session.execute_script("return document.hidden")
 
 
 def test_payload(session):
     assert not session.execute_script("return document.hidden")