Path: blob/trunk/py/selenium/webdriver/remote/errorhandler.py
1864 views
# Licensed to the Software Freedom Conservancy (SFC) under one1# or more contributor license agreements. See the NOTICE file2# distributed with this work for additional information3# regarding copyright ownership. The SFC licenses this file4# to you under the Apache License, Version 2.0 (the5# "License"); you may not use this file except in compliance6# with the License. You may obtain a copy of the License at7#8# http://www.apache.org/licenses/LICENSE-2.09#10# Unless required by applicable law or agreed to in writing,11# software distributed under the License is distributed on an12# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY13# KIND, either express or implied. See the License for the14# specific language governing permissions and limitations15# under the License.1617import json18from typing import Any1920from selenium.common.exceptions import (21DetachedShadowRootException,22ElementClickInterceptedException,23ElementNotInteractableException,24ElementNotSelectableException,25ElementNotVisibleException,26ImeActivationFailedException,27ImeNotAvailableException,28InsecureCertificateException,29InvalidArgumentException,30InvalidCookieDomainException,31InvalidCoordinatesException,32InvalidElementStateException,33InvalidSelectorException,34InvalidSessionIdException,35JavascriptException,36MoveTargetOutOfBoundsException,37NoAlertPresentException,38NoSuchCookieException,39NoSuchElementException,40NoSuchFrameException,41NoSuchShadowRootException,42NoSuchWindowException,43ScreenshotException,44SessionNotCreatedException,45StaleElementReferenceException,46TimeoutException,47UnableToSetCookieException,48UnexpectedAlertPresentException,49UnknownMethodException,50WebDriverException,51)525354class ExceptionMapping:55"""56:Maps each errorcode in ErrorCode object to corresponding exception57Please refer to https://www.w3.org/TR/webdriver2/#errors for w3c specification58"""5960NO_SUCH_ELEMENT = NoSuchElementException61NO_SUCH_FRAME = NoSuchFrameException62NO_SUCH_SHADOW_ROOT = NoSuchShadowRootException63STALE_ELEMENT_REFERENCE = StaleElementReferenceException64ELEMENT_NOT_VISIBLE = ElementNotVisibleException65INVALID_ELEMENT_STATE = InvalidElementStateException66UNKNOWN_ERROR = WebDriverException67ELEMENT_IS_NOT_SELECTABLE = ElementNotSelectableException68JAVASCRIPT_ERROR = JavascriptException69TIMEOUT = TimeoutException70NO_SUCH_WINDOW = NoSuchWindowException71INVALID_COOKIE_DOMAIN = InvalidCookieDomainException72UNABLE_TO_SET_COOKIE = UnableToSetCookieException73UNEXPECTED_ALERT_OPEN = UnexpectedAlertPresentException74NO_ALERT_OPEN = NoAlertPresentException75SCRIPT_TIMEOUT = TimeoutException76IME_NOT_AVAILABLE = ImeNotAvailableException77IME_ENGINE_ACTIVATION_FAILED = ImeActivationFailedException78INVALID_SELECTOR = InvalidSelectorException79SESSION_NOT_CREATED = SessionNotCreatedException80MOVE_TARGET_OUT_OF_BOUNDS = MoveTargetOutOfBoundsException81INVALID_XPATH_SELECTOR = InvalidSelectorException82INVALID_XPATH_SELECTOR_RETURN_TYPER = InvalidSelectorException83ELEMENT_NOT_INTERACTABLE = ElementNotInteractableException84INSECURE_CERTIFICATE = InsecureCertificateException85INVALID_ARGUMENT = InvalidArgumentException86INVALID_COORDINATES = InvalidCoordinatesException87INVALID_SESSION_ID = InvalidSessionIdException88NO_SUCH_COOKIE = NoSuchCookieException89UNABLE_TO_CAPTURE_SCREEN = ScreenshotException90ELEMENT_CLICK_INTERCEPTED = ElementClickInterceptedException91UNKNOWN_METHOD = UnknownMethodException92DETACHED_SHADOW_ROOT = DetachedShadowRootException939495class ErrorCode:96"""Error codes defined in the WebDriver wire protocol."""9798# Keep in sync with org.openqa.selenium.remote.ErrorCodes and errorcodes.h99SUCCESS = 0100NO_SUCH_ELEMENT = [7, "no such element"]101NO_SUCH_FRAME = [8, "no such frame"]102NO_SUCH_SHADOW_ROOT = ["no such shadow root"]103UNKNOWN_COMMAND = [9, "unknown command"]104STALE_ELEMENT_REFERENCE = [10, "stale element reference"]105ELEMENT_NOT_VISIBLE = [11, "element not visible"]106INVALID_ELEMENT_STATE = [12, "invalid element state"]107UNKNOWN_ERROR = [13, "unknown error"]108ELEMENT_IS_NOT_SELECTABLE = [15, "element not selectable"]109JAVASCRIPT_ERROR = [17, "javascript error"]110XPATH_LOOKUP_ERROR = [19, "invalid selector"]111TIMEOUT = [21, "timeout"]112NO_SUCH_WINDOW = [23, "no such window"]113INVALID_COOKIE_DOMAIN = [24, "invalid cookie domain"]114UNABLE_TO_SET_COOKIE = [25, "unable to set cookie"]115UNEXPECTED_ALERT_OPEN = [26, "unexpected alert open"]116NO_ALERT_OPEN = [27, "no such alert"]117SCRIPT_TIMEOUT = [28, "script timeout"]118INVALID_ELEMENT_COORDINATES = [29, "invalid element coordinates"]119IME_NOT_AVAILABLE = [30, "ime not available"]120IME_ENGINE_ACTIVATION_FAILED = [31, "ime engine activation failed"]121INVALID_SELECTOR = [32, "invalid selector"]122SESSION_NOT_CREATED = [33, "session not created"]123MOVE_TARGET_OUT_OF_BOUNDS = [34, "move target out of bounds"]124INVALID_XPATH_SELECTOR = [51, "invalid selector"]125INVALID_XPATH_SELECTOR_RETURN_TYPER = [52, "invalid selector"]126127ELEMENT_NOT_INTERACTABLE = [60, "element not interactable"]128INSECURE_CERTIFICATE = ["insecure certificate"]129INVALID_ARGUMENT = [61, "invalid argument"]130INVALID_COORDINATES = ["invalid coordinates"]131INVALID_SESSION_ID = ["invalid session id"]132NO_SUCH_COOKIE = [62, "no such cookie"]133UNABLE_TO_CAPTURE_SCREEN = [63, "unable to capture screen"]134ELEMENT_CLICK_INTERCEPTED = [64, "element click intercepted"]135UNKNOWN_METHOD = ["unknown method exception"]136DETACHED_SHADOW_ROOT = [65, "detached shadow root"]137138METHOD_NOT_ALLOWED = [405, "unsupported operation"]139140141class ErrorHandler:142"""Handles errors returned by the WebDriver server."""143144def check_response(self, response: dict[str, Any]) -> None:145"""Checks that a JSON response from the WebDriver does not have an146error.147148:Args:149- response - The JSON response from the WebDriver server as a dictionary150object.151152:Raises: If the response contains an error message.153"""154status = response.get("status", None)155if not status or status == ErrorCode.SUCCESS:156return157value = None158message = response.get("message", "")159screen: str = response.get("screen", "")160stacktrace = None161if isinstance(status, int):162value_json = response.get("value", None)163if value_json and isinstance(value_json, str):164try:165value = json.loads(value_json)166if isinstance(value, dict):167if len(value) == 1:168value = value["value"]169status = value.get("error", None)170if not status:171status = value.get("status", ErrorCode.UNKNOWN_ERROR)172message = value.get("value") or value.get("message")173if not isinstance(message, str):174value = message175message = message.get("message") if isinstance(message, dict) else None176else:177message = value.get("message", None)178except ValueError:179pass180181exception_class: type[WebDriverException]182e = ErrorCode()183error_codes = [item for item in dir(e) if not item.startswith("__")]184for error_code in error_codes:185error_info = getattr(ErrorCode, error_code)186if isinstance(error_info, list) and status in error_info:187exception_class = getattr(ExceptionMapping, error_code, WebDriverException)188break189else:190exception_class = WebDriverException191192if not value:193value = response["value"]194if isinstance(value, str):195raise exception_class(value)196if message == "" and "message" in value:197message = value["message"]198199screen = None # type: ignore[assignment]200if "screen" in value:201screen = value["screen"]202203stacktrace = None204st_value = value.get("stackTrace") or value.get("stacktrace")205if st_value:206if isinstance(st_value, str):207stacktrace = st_value.split("\n")208else:209stacktrace = []210try:211for frame in st_value:212line = frame.get("lineNumber", "")213file = frame.get("fileName", "<anonymous>")214if line:215file = f"{file}:{line}"216meth = frame.get("methodName", "<anonymous>")217if "className" in frame:218meth = f"{frame['className']}.{meth}"219msg = " at %s (%s)"220msg = msg % (meth, file)221stacktrace.append(msg)222except TypeError:223pass224if exception_class == UnexpectedAlertPresentException:225alert_text = None226if "data" in value:227alert_text = value["data"].get("text")228elif "alert" in value:229alert_text = value["alert"].get("text")230raise exception_class(message, screen, stacktrace, alert_text) # type: ignore[call-arg] # mypy is not smart enough here231raise exception_class(message, screen, stacktrace)232233234