Bug 1411045 - Provide response-to-error conversion. r?maja_zf draft
authorAndreas Tolfsen <ato@sny.no>
Mon, 23 Oct 2017 22:13:00 +0100
changeset 685979 699e988013340943fd4526860ad77369c206a7aa
parent 685978 f0b2cb27314d1b63d2868a88e8c462bc1f1195b1
child 685980 6444720f07af39e3fa4bdab35135d7358d526d65
push id86054
push userbmo:ato@sny.no
push dateWed, 25 Oct 2017 07:41:54 +0000
reviewersmaja_zf
bugs1411045
milestone58.0a1
Bug 1411045 - Provide response-to-error conversion. r?maja_zf This adds a new error.from_response(wdclient.Response) function that lets a WebDriverException be constructed from a wdclient.Response object. If the Response is not an error, i.e. has a 200 HTTP status code, an UnknownErrorException is raised. MozReview-Commit-ID: JW89Ily2voC
testing/web-platform/tests/tools/webdriver/webdriver/client.py
testing/web-platform/tests/tools/webdriver/webdriver/error.py
--- a/testing/web-platform/tests/tools/webdriver/webdriver/client.py
+++ b/testing/web-platform/tests/tools/webdriver/webdriver/client.py
@@ -417,32 +417,33 @@ class Session(object):
         Send a command to the remote end and validate its success.
 
         :param method: HTTP method to use in request.
         :param uri: "Command part" of the HTTP request URL,
             e.g. `window/rect`.
         :param body: Optional body of the HTTP request.
 
         :return: `None` if the HTTP response body was empty, otherwise
-            the result of parsing the body as JSON.
+            the `value` field returned after parsing the response
+            body as JSON.
 
         :raises error.WebDriverException: If the remote end returns
             an error.
         """
         response = self.transport.send(method, url, body)
 
+        if response.status != 200:
+            raise error.from_response(response)
+
         if "value" in response.body:
             value = response.body["value"]
         else:
-            raise error.UnknownErrorException("No 'value' key in response body:\n%s" %
-                                              json.dumps(response.body))
-
-        if response.status != 200:
-            cls = error.get(value.get("error"))
-            raise cls(value.get("message"))
+            raise error.UnknownErrorException(
+                "Expected 'value' key in response body:\n"
+                "%s" % json.dumps(response.body))
 
         return value
 
     def send_session_command(self, method, uri, body=None):
         """
         Send a command to an established session and validate its success.
 
         :param method: HTTP method to use in request.
--- a/testing/web-platform/tests/tools/webdriver/webdriver/error.py
+++ b/testing/web-platform/tests/tools/webdriver/webdriver/error.py
@@ -1,9 +1,10 @@
 import collections
+import json
 
 
 class WebDriverException(Exception):
     http_status = None
     status_code = None
 
     def __init__(self, message, stacktrace=None):
         super(WebDriverException, self)
@@ -140,16 +141,44 @@ class UnknownMethodException(WebDriverEx
     status_code = "unknown method"
 
 
 class UnsupportedOperationException(WebDriverException):
     http_status = 500
     status_code = "unsupported operation"
 
 
+def from_response(response):
+    """
+    Unmarshals an error from a ``Response``'s `body`, failing
+    if not all three required `error`, `message`, and `stacktrace`
+    fields are given.  Defaults to ``WebDriverException`` if `error`
+    is unknown.
+    """
+    if response.status == 200:
+        raise UnknownErrorException(
+            "Response is not an error:\n"
+            "%s" % json.dumps(response.body))
+
+    if "value" in response.body:
+        value = response.body["value"]
+    else:
+        raise UnknownErrorException(
+            "Expected 'value' key in response body:\n"
+            "%s" % json.dumps(response.body))
+
+    # all fields must exist, but stacktrace can be an empty string
+    code = value["error"]
+    message = value["message"]
+    stack = value["stacktrace"] or None
+
+    cls = get(code)
+    return cls(message, stacktrace=stack)
+
+
 def get(error_code):
     """
     Gets exception from `error_code`, falling back to
     ``WebDriverException`` if it is not found.
     """
     return _errors.get(error_code, WebDriverException)