diff --git a/py/generate.py b/py/generate.py index 0763084423168..ec8edc82bd0b2 100644 --- a/py/generate.py +++ b/py/generate.py @@ -216,7 +216,7 @@ class CdpProperty: deprecated: bool @property - def py_name(self): + def py_name(self)->str: ''' Get this property's Python name. ''' return snake_case(self.name) @@ -590,7 +590,7 @@ class CdpCommand: domain: str @property - def py_name(self): + def py_name(self) -> str: ''' Get a Python name for this command. ''' return snake_case(self.name) @@ -794,7 +794,7 @@ class CdpDomain: events: List[CdpEvent] @property - def module(self): + def module(self) -> str: ''' The name of the Python module for this CDP domain. ''' return snake_case(self.domain) diff --git a/py/generate_api_module_listing.py b/py/generate_api_module_listing.py index 71605ca018d2e..72ac6046852dd 100644 --- a/py/generate_api_module_listing.py +++ b/py/generate_api_module_listing.py @@ -16,12 +16,13 @@ # under the License. -"""This script recursively scans the `selenium` package directory -to find all modules, then generates the `py/docs/source/api.rst` -file containing a listing of all modules in separate sections. -The `api.rst` file is later used by `sphinx-autogen` to generate -sphinx autodoc stub pages used in the Python API documentation. -See `py/tox.ini` for how it is invoked. +"""This script recursively scans the `selenium` package directory and generates an API listing. + +Recursively scans the `selenium` package directory to find all modules, +then generates the `py/docs/source/api.rst` file containing a listing of all +modules in separate sections. The `api.rst` file is later used by +`sphinx-autogen` to generate sphinx autodoc stub pages used in the Python API +documentation. See `py/tox.ini` for how it is invoked. """ import os diff --git a/py/pyproject.toml b/py/pyproject.toml index 2d74986b8b19b..80952d9a0f8d4 100644 --- a/py/pyproject.toml +++ b/py/pyproject.toml @@ -154,7 +154,6 @@ extend-ignore = [ "D104", # Missing docstring in public package "D105", # Missing docstring in magic method "D107", # Missing docstring in `__init__` - "D205", # 1 blank line required between summary line and description "D212", # Multi-line docstring summary should start at the first line ] diff --git a/py/selenium/common/exceptions.py b/py/selenium/common/exceptions.py index 9d895598ba430..3ff4e0b4fd549 100644 --- a/py/selenium/common/exceptions.py +++ b/py/selenium/common/exceptions.py @@ -91,9 +91,7 @@ class NoSuchAttributeException(WebDriverException): class NoSuchShadowRootException(WebDriverException): - """Thrown when trying to access the shadow root of an element when it does - not have a shadow root attached. - """ + """Thrown when trying to access the shadow root of an element when it does not have a shadow root attached.""" class StaleElementReferenceException(WebDriverException): @@ -121,11 +119,9 @@ def __init__( class InvalidElementStateException(WebDriverException): - """Thrown when a command could not be completed because the element is in - an invalid state. + """Thrown when a command could not be completed because the element is in an invalid state. - This can be caused by attempting to clear an element that isn't both - editable and resettable. + This can be caused by attempting to clear an element that isn't both editable and resettable. """ @@ -159,11 +155,9 @@ class NoAlertPresentException(WebDriverException): class ElementNotVisibleException(InvalidElementStateException): - """Thrown when an element is present on the DOM, but it is not visible, and - so is not able to be interacted with. + """Thrown when an element is present on the DOM, but it is not visible, and so is not able to be interacted with. - Most commonly encountered when trying to click or read text of an - element that is hidden from view. + Most commonly encountered when trying to click or read text of an element that is hidden from view. """ def __init__( @@ -175,9 +169,7 @@ def __init__( class ElementNotInteractableException(InvalidElementStateException): - """Thrown when an element is present in the DOM but interactions with that - element will hit another element due to paint order. - """ + """Thrown when element interactions will hit another element due to paint order.""" def __init__( self, msg: Optional[Any] = None, screen: Optional[str] = None, stacktrace: Optional[Sequence[str]] = None @@ -195,9 +187,7 @@ class ElementNotSelectableException(InvalidElementStateException): class InvalidCookieDomainException(WebDriverException): - """Thrown when attempting to add a cookie under a different domain than the - current URL. - """ + """Thrown when attempting to add a cookie under a different domain.""" class UnableToSetCookieException(WebDriverException): @@ -209,9 +199,7 @@ class TimeoutException(WebDriverException): class MoveTargetOutOfBoundsException(WebDriverException): - """Thrown when the target provided to the `ActionsChains` move() method is - invalid, i.e. out of document. - """ + """Thrown when the target provided to the `ActionsChains` move() method is invalid, i.e. out of document.""" class UnexpectedTagNameException(WebDriverException): @@ -219,13 +207,9 @@ class UnexpectedTagNameException(WebDriverException): class InvalidSelectorException(WebDriverException): - """Thrown when the selector which is used to find an element does not - return a WebElement. + """Thrown when the selector used to find an element does not return a WebElement. - Currently this only happens when the selector is an xpath expression - and it is either syntactically invalid (i.e. it is not a xpath - expression) or the expression does not select WebElements (e.g. - "count(//input)"). + Currently this only happens when the XPath expression is syntactically invalid or does not select WebElements. """ def __init__( @@ -257,9 +241,7 @@ class JavascriptException(WebDriverException): class NoSuchCookieException(WebDriverException): - """No cookie matching the given path name was found amongst the associated - cookies of the current browsing context's active document. - """ + """Thrown when no cookie matching the given path name was found.""" class ScreenshotException(WebDriverException): @@ -267,10 +249,7 @@ class ScreenshotException(WebDriverException): class ElementClickInterceptedException(WebDriverException): - """The Element Click command could not be completed because the element - receiving the events is obscuring the element that was requested to be - clicked. - """ + """Thrown when element click fails because another element obscures it.""" def __init__( self, msg: Optional[Any] = None, screen: Optional[str] = None, stacktrace: Optional[Sequence[str]] = None @@ -281,9 +260,7 @@ def __init__( class InsecureCertificateException(WebDriverException): - """Navigation caused the user agent to hit a certificate warning, which is - usually the result of an expired or invalid TLS certificate. - """ + """Thrown when the user agent hits a certificate warning (expired or invalid TLS certificate).""" class InvalidCoordinatesException(WebDriverException): @@ -291,9 +268,7 @@ class InvalidCoordinatesException(WebDriverException): class InvalidSessionIdException(WebDriverException): - """Occurs if the given session id is not in the list of active sessions, - meaning the session either does not exist or that it's not active. - """ + """Thrown when the given session id is not in the list of active sessions.""" def __init__( self, msg: Optional[Any] = None, screen: Optional[str] = None, stacktrace: Optional[Sequence[str]] = None @@ -315,9 +290,7 @@ def __init__( class UnknownMethodException(WebDriverException): - """The requested command matched a known URL but did not match any methods - for that URL. - """ + """The requested command matched a known URL but did not match any methods for that URL.""" class NoSuchDriverException(WebDriverException): diff --git a/py/selenium/webdriver/chrome/service.py b/py/selenium/webdriver/chrome/service.py index 8e9bd9c8c0e31..38f483d8acea8 100644 --- a/py/selenium/webdriver/chrome/service.py +++ b/py/selenium/webdriver/chrome/service.py @@ -24,8 +24,7 @@ class Service(service.ChromiumService): - """A Service class that is responsible for the starting and stopping of - `chromedriver`. + """Service class responsible for starting and stopping the chromedriver executable. Args: executable_path: Install path of the chromedriver executable, defaults @@ -65,6 +64,7 @@ def command_line_args(self) -> list[str]: @property def service_args(self) -> Sequence[str]: + """Returns the sequence of service arguments.""" return self._service_args @service_args.setter diff --git a/py/selenium/webdriver/chromium/options.py b/py/selenium/webdriver/chromium/options.py index 41dda79eee535..92363410a46b3 100644 --- a/py/selenium/webdriver/chromium/options.py +++ b/py/selenium/webdriver/chromium/options.py @@ -38,10 +38,7 @@ def __init__(self) -> None: @property def binary_location(self) -> str: - """ - Returns: - The location of the binary, otherwise an empty string. - """ + """Returns the location of the binary, otherwise an empty string.""" return self._binary_location @binary_location.setter @@ -57,16 +54,12 @@ def binary_location(self, value: str) -> None: @property def debugger_address(self) -> Optional[str]: - """ - Returns: - The address of the remote devtools instance. - """ + """Returns the address of the remote devtools instance.""" return self._debugger_address @debugger_address.setter def debugger_address(self, value: str) -> None: - """Allows you to set the address of the remote devtools instance that - the ChromeDriver instance will try to connect to during an active wait. + """Set the address of the remote devtools instance for active wait connection. Args: value: Address of remote devtools instance if any (hostname[:port]). @@ -77,10 +70,7 @@ def debugger_address(self, value: str) -> None: @property def extensions(self) -> list[str]: - """ - Returns: - A list of encoded extensions that will be loaded. - """ + """Returns a list of encoded extensions that will be loaded.""" def _decode(file_data: BinaryIO) -> str: # Should not use base64.encodestring() which inserts newlines every @@ -96,8 +86,7 @@ def _decode(file_data: BinaryIO) -> str: return encoded_extensions + self._extensions def add_extension(self, extension: str) -> None: - """Adds the path to the extension to a list that will be used to - extract it to the ChromeDriver. + """Add the path to an extension to be extracted to ChromeDriver. Args: extension: Path to the *.crx file. @@ -112,8 +101,7 @@ def add_extension(self, extension: str) -> None: raise ValueError("argument can not be null") def add_encoded_extension(self, extension: str) -> None: - """Adds Base64 encoded string with extension data to a list that will - be used to extract it to the ChromeDriver. + """Add Base64-encoded string with extension data to be extracted to ChromeDriver. Args: extension: Base64 encoded string with extension data. @@ -125,10 +113,7 @@ def add_encoded_extension(self, extension: str) -> None: @property def experimental_options(self) -> dict: - """ - Returns: - A dictionary of experimental options for chromium. - """ + """Returns a dictionary of experimental options for chromium.""" return self._experimental_options def add_experimental_option(self, name: str, value: Union[str, int, dict, list[str]]) -> None: @@ -142,11 +127,7 @@ def add_experimental_option(self, name: str, value: Union[str, int, dict, list[s @property def enable_webextensions(self) -> bool: - """ - Returns: - Whether webextension support is enabled for Chromium-based browsers. - True if webextension support is enabled, False otherwise. - """ + """Return whether webextension support is enabled for Chromium-based browsers.""" return self._enable_webextensions @enable_webextensions.setter diff --git a/py/selenium/webdriver/chromium/service.py b/py/selenium/webdriver/chromium/service.py index bb50c412ff37f..cd4394c0667d8 100644 --- a/py/selenium/webdriver/chromium/service.py +++ b/py/selenium/webdriver/chromium/service.py @@ -24,8 +24,7 @@ class ChromiumService(service.Service): - """A Service class that is responsible for the starting and stopping the - WebDriver instance of the ChromiumDriver. + """Service class responsible for starting and stopping the ChromiumDriver WebDriver instance. Args: executable_path: Install path of the executable. @@ -76,6 +75,7 @@ def command_line_args(self) -> list[str]: @property def service_args(self) -> Sequence[str]: + """Returns the sequence of service arguments.""" return self._service_args @service_args.setter diff --git a/py/selenium/webdriver/chromium/webdriver.py b/py/selenium/webdriver/chromium/webdriver.py index dee917f7598e2..894e26df3e97b 100644 --- a/py/selenium/webdriver/chromium/webdriver.py +++ b/py/selenium/webdriver/chromium/webdriver.py @@ -26,9 +26,7 @@ class ChromiumDriver(RemoteWebDriver): - """Controls the WebDriver instance of ChromiumDriver and allows you to - drive the browser. - """ + """Control the WebDriver instance of ChromiumDriver and drive the browser.""" def __init__( self, @@ -38,8 +36,7 @@ def __init__( service: Optional[ChromiumService] = None, keep_alive: bool = True, ) -> None: - """Creates a new WebDriver instance of the ChromiumDriver. Starts the - service and then creates new WebDriver instance of ChromiumDriver. + """Create a new WebDriver instance, start the service, and create new ChromiumDriver instance. Args: browser_name: Browser name used when matching capabilities. @@ -148,17 +145,11 @@ def execute_cdp_cmd(self, cmd: str, cmd_args: dict): return super().execute_cdp_cmd(cmd, cmd_args) def get_sinks(self) -> list: - """ - Returns: - A list of sinks available for Cast. - """ + """Get a list of sinks available for Cast.""" return self.execute("getSinks")["value"] def get_issue_message(self): - """ - Returns: - An error message when there is any issue in a Cast session. - """ + """Returns an error message when there is any issue in a Cast session.""" return self.execute("getIssueMessage")["value"] @property @@ -186,8 +177,7 @@ def get_log(self, log_type): return self.execute(Command.GET_LOG, {"type": log_type})["value"] def set_sink_to_use(self, sink_name: str) -> dict: - """Sets a specific sink, using its name, as a Cast session receiver - target. + """Set a specific sink as a Cast session receiver target. Args: sink_name: Name of the sink to use as the target. diff --git a/py/selenium/webdriver/common/action_chains.py b/py/selenium/webdriver/common/action_chains.py index a326bea402e5f..b849deeea292e 100644 --- a/py/selenium/webdriver/common/action_chains.py +++ b/py/selenium/webdriver/common/action_chains.py @@ -34,7 +34,9 @@ class ActionChains: - """ActionChains are a way to automate low level interactions such as mouse + """Automate low-level interactions like mouse movements, button actions, key presses, and context menus. + + ActionChains are a way to automate low level interactions such as mouse movements, mouse button actions, key press, and context menu interactions. This is useful for doing more complex actions like hover over and drag and drop. @@ -94,9 +96,7 @@ def perform(self) -> None: self.w3c_actions.perform() def reset_actions(self) -> None: - """Clears actions that are already stored locally and on the remote - end. - """ + """Clear actions stored locally and on the remote end.""" self.w3c_actions.clear_actions() for device in self.w3c_actions.devices: device.clear_actions() @@ -165,8 +165,7 @@ def double_click(self, on_element: WebElement | None = None) -> ActionChains: return self def drag_and_drop(self, source: WebElement, target: WebElement) -> ActionChains: - """Holds down the left mouse button on the source element, then moves - to the target element and releases the mouse button. + """Hold down the left mouse button on an element, then move to target and release. Args: source: The element to mouse down. @@ -177,8 +176,7 @@ def drag_and_drop(self, source: WebElement, target: WebElement) -> ActionChains: return self def drag_and_drop_by_offset(self, source: WebElement, xoffset: int, yoffset: int) -> ActionChains: - """Holds down the left mouse button on the source element, then moves - to the target offset and releases the mouse button. + """Hold down the left mouse button on an element, then move by offset and release. Args: source: The element to mouse down. @@ -191,8 +189,7 @@ def drag_and_drop_by_offset(self, source: WebElement, xoffset: int, yoffset: int return self def key_down(self, value: str, element: WebElement | None = None) -> ActionChains: - """Sends a key press only, without releasing it. Should only be used - with modifier keys (Control, Alt and Shift). + """Send a key press only without releasing it (modifier keys only). Args: value: The modifier key to send. Values are defined in `Keys` class. @@ -255,8 +252,9 @@ def move_to_element(self, to_element: WebElement) -> ActionChains: return self def move_to_element_with_offset(self, to_element: WebElement, xoffset: int, yoffset: int) -> ActionChains: - """Move the mouse by an offset of the specified element. Offsets are - relative to the in-view center point of the element. + """Move the mouse to an element with the specified offsets. + + Offsets are relative to the in-view center point of the element. Args: to_element: The WebElement to move to. @@ -318,8 +316,9 @@ def send_keys_to_element(self, element: WebElement, *keys_to_send: str) -> Actio return self def scroll_to_element(self, element: WebElement) -> ActionChains: - """If the element is outside the viewport, scrolls the bottom of the - element to the bottom of the viewport. + """Scroll the element into the viewport if it's outside it. + + Scrolls the bottom of the element to the bottom of the viewport. Args: element: Which element to scroll into the viewport. @@ -328,7 +327,9 @@ def scroll_to_element(self, element: WebElement) -> ActionChains: return self def scroll_by_amount(self, delta_x: int, delta_y: int) -> ActionChains: - """Scrolls by provided amounts with the origin in the top left corner + """Scroll by a provided amount with the origin in the top left corner. + + Scrolls by provided amounts with the origin in the top left corner of the viewport. Args: @@ -339,8 +340,9 @@ def scroll_by_amount(self, delta_x: int, delta_y: int) -> ActionChains: return self def scroll_from_origin(self, scroll_origin: ScrollOrigin, delta_x: int, delta_y: int) -> ActionChains: - """Scrolls by provided amount based on a provided origin. The scroll - origin is either the center of an element or the upper left of the + """Scroll by a provided amount based on a scroll origin (element or viewport). + + The scroll origin is either the center of an element or the upper left of the viewport plus any offsets. If the origin is an element, and the element is not in the viewport, the bottom of the element will first be scrolled to the bottom of the viewport. diff --git a/py/selenium/webdriver/common/bidi/browsing_context.py b/py/selenium/webdriver/common/bidi/browsing_context.py index a522528c7a6a2..132c9d65e9243 100644 --- a/py/selenium/webdriver/common/bidi/browsing_context.py +++ b/py/selenium/webdriver/common/bidi/browsing_context.py @@ -812,7 +812,9 @@ def get_tree( max_depth: Optional[int] = None, root: Optional[str] = None, ) -> list[BrowsingContextInfo]: - """Returns a tree of all descendent navigables including the given parent itself, or all top-level contexts + """Get a tree of all descendent navigables including the given parent itself. + + Returns a tree of all descendent navigables including the given parent itself, or all top-level contexts when no parent is provided. Args: @@ -917,8 +919,7 @@ def print( scale: float = 1.0, shrink_to_fit: bool = True, ) -> str: - """Creates a paginated representation of a document, and returns it as a PDF document represented as a - Base64-encoded string. + """Create a paginated PDF representation of the document as a Base64-encoded string. Args: context: The browsing context ID. diff --git a/py/selenium/webdriver/common/driver_finder.py b/py/selenium/webdriver/common/driver_finder.py index 14d2421c3258a..127c9658a2806 100644 --- a/py/selenium/webdriver/common/driver_finder.py +++ b/py/selenium/webdriver/common/driver_finder.py @@ -26,8 +26,7 @@ class DriverFinder: - """A Driver finding class responsible for obtaining the correct driver and - associated browser. + """Find and obtain the correct driver and associated browser. Args: service: instance of the driver service class. diff --git a/py/selenium/webdriver/common/log.py b/py/selenium/webdriver/common/log.py index 2c931edcccefb..65da4347dca87 100644 --- a/py/selenium/webdriver/common/log.py +++ b/py/selenium/webdriver/common/log.py @@ -34,8 +34,7 @@ def import_cdp(): class Log: - """This class allows access to logging APIs that use the new WebDriver Bidi - protocol. + """Class for accessing logging APIs using the WebDriver Bidi protocol. This class is not to be used directly and should be used from the webdriver base classes. @@ -95,8 +94,7 @@ async def mutation_events(self) -> AsyncGenerator[dict[str, Any], None]: @asynccontextmanager async def add_js_error_listener(self) -> AsyncGenerator[dict[str, Any], None]: - """Listen for JS errors and when the contextmanager exits check if - there were JS Errors. + """Listen for JS errors and check if they occurred when the context manager exits. Example: async with driver.log.add_js_error_listener() as error: diff --git a/py/selenium/webdriver/common/options.py b/py/selenium/webdriver/common/options.py index 4eb323c66c5b1..5599cc635b874 100644 --- a/py/selenium/webdriver/common/options.py +++ b/py/selenium/webdriver/common/options.py @@ -143,7 +143,8 @@ def __set__(self, obj, value): class _ProxyDescriptor: - """ + """Descriptor for proxy property access. + Returns: Proxy if set, otherwise None. """ @@ -379,9 +380,7 @@ def default_capabilities(self): """Return minimal capabilities necessary as a dictionary.""" def ignore_local_proxy_environment_variables(self) -> None: - """By calling this you will ignore HTTP_PROXY and HTTPS_PROXY from - being picked up and used. - """ + """Ignore HTTP_PROXY and HTTPS_PROXY environment variables.""" self._ignore_local_proxy = True @@ -396,10 +395,7 @@ def __init__(self) -> None: @property def arguments(self): - """ - Returns: - A list of arguments needed for the browser. - """ + """Returns a list of arguments needed for the browser.""" return self._arguments def add_argument(self, argument: str) -> None: @@ -414,8 +410,9 @@ def add_argument(self, argument: str) -> None: raise ValueError("argument can not be null") def ignore_local_proxy_environment_variables(self) -> None: - """By calling this you will ignore HTTP_PROXY and HTTPS_PROXY from - being picked up and used. + """Ignore HTTP_PROXY and HTTPS_PROXY environment variables. + + This method is deprecated; use a Proxy instance with ProxyType.DIRECT instead. """ warnings.warn( "using ignore_local_proxy_environment_variables in Options has been deprecated, " diff --git a/py/selenium/webdriver/common/print_page_options.py b/py/selenium/webdriver/common/print_page_options.py index fb5f93a90c930..cb13c32a32afa 100644 --- a/py/selenium/webdriver/common/print_page_options.py +++ b/py/selenium/webdriver/common/print_page_options.py @@ -335,10 +335,7 @@ def __init__(self) -> None: self._margin: _MarginOpts = {} def to_dict(self) -> _PrintOpts: - """ - Returns: - A hash of print options configured. - """ + """Returns a hash of print options configured.""" return self._print_options def set_page_size(self, page_size: dict) -> None: diff --git a/py/selenium/webdriver/common/proxy.py b/py/selenium/webdriver/common/proxy.py index eccd978f46d24..1f69720321a04 100644 --- a/py/selenium/webdriver/common/proxy.py +++ b/py/selenium/webdriver/common/proxy.py @@ -80,9 +80,7 @@ def __set__(self, obj, value): class Proxy: - """Proxy contains information about proxy type and necessary proxy - settings. - """ + """Proxy configuration containing proxy type and necessary proxy settings.""" proxyType = ProxyType.UNSPECIFIED autodetect = False diff --git a/py/selenium/webdriver/common/service.py b/py/selenium/webdriver/common/service.py index e84a00a059637..ed39ad9d70118 100644 --- a/py/selenium/webdriver/common/service.py +++ b/py/selenium/webdriver/common/service.py @@ -37,8 +37,9 @@ class Service(ABC): - """The abstract base class for all service objects. Services typically - launch a child program in a new process as an interim process to + """Abstract base class for all service objects that manage driver processes. + + Services typically launch a child program in a new process as an interim process to communicate with a browser. Args: @@ -123,15 +124,15 @@ def assert_process_still_running(self) -> None: raise WebDriverException(f"Service {self._path} unexpectedly exited. Status code was: {return_code}") def is_connectable(self) -> bool: - """Establishes a socket connection to determine if the service running - on the port is accessible. + """Establish a socket connection to determine if the service is accessible. + + Returns: + True if the service is connectable on the configured port, False otherwise. """ return utils.is_connectable(self.port) def send_remote_shutdown_command(self) -> None: - """Dispatch an HTTP request to the shutdown endpoint for the service in - an attempt to stop it. - """ + """Dispatch an HTTP request to the shutdown endpoint to stop the service.""" try: request.urlopen(f"{self.service_url}/shutdown") except URLError: diff --git a/py/selenium/webdriver/common/utils.py b/py/selenium/webdriver/common/utils.py index fac1b4b475477..ac3087fc17ddf 100644 --- a/py/selenium/webdriver/common/utils.py +++ b/py/selenium/webdriver/common/utils.py @@ -138,8 +138,7 @@ def is_url_connectable( host: Optional[str] = "127.0.0.1", scheme: Optional[str] = "http", ) -> bool: - """Sends a request to the HTTP server at the /status endpoint to see if it - responds successfully. + """Send a request to the HTTP server at the /status endpoint to verify connectivity. Args: port: port number diff --git a/py/selenium/webdriver/common/virtual_authenticator.py b/py/selenium/webdriver/common/virtual_authenticator.py index b3c951a98fdef..37355d45efe4b 100644 --- a/py/selenium/webdriver/common/virtual_authenticator.py +++ b/py/selenium/webdriver/common/virtual_authenticator.py @@ -85,6 +85,7 @@ def __init__( sign_count: int, ): """Constructor. A credential stored in a virtual authenticator. + https://w3c.github.io/webauthn/#credential-parameters. Args: @@ -192,9 +193,7 @@ def __str__(self) -> str: def required_chromium_based_browser(func): - """A decorator to ensure that the client used is a chromium based - browser. - """ + """Decorator to ensure that the client used is a chromium-based browser.""" @functools.wraps(func) def wrapper(self, *args, **kwargs): @@ -208,9 +207,7 @@ def wrapper(self, *args, **kwargs): def required_virtual_authenticator(func): - """A decorator to ensure that the function is called with a virtual - authenticator. - """ + """Decorator to ensure that the function is called with a virtual authenticator.""" @functools.wraps(func) @required_chromium_based_browser diff --git a/py/selenium/webdriver/edge/options.py b/py/selenium/webdriver/edge/options.py index 659b19ce8819d..d5182dd3fe281 100644 --- a/py/selenium/webdriver/edge/options.py +++ b/py/selenium/webdriver/edge/options.py @@ -29,10 +29,7 @@ def __init__(self) -> None: @property def use_webview(self) -> bool: - """ - Returns: - Whether WebView2 is enabled for Edge browser. - """ + """Returns Whether WebView2 is enabled for Edge browser.""" return self._use_webview @use_webview.setter @@ -58,8 +55,5 @@ def to_capabilities(self) -> dict: @property def default_capabilities(self) -> dict: - """ - Returns: - The default capabilities for Edge browser. - """ + """Returns the default capabilities for Edge browser.""" return DesiredCapabilities.EDGE.copy() diff --git a/py/selenium/webdriver/edge/service.py b/py/selenium/webdriver/edge/service.py index 1d2146a4b13ba..8eee39b24c0c6 100644 --- a/py/selenium/webdriver/edge/service.py +++ b/py/selenium/webdriver/edge/service.py @@ -23,8 +23,7 @@ class Service(service.ChromiumService): - """A Service class that is responsible for the starting and stopping of - `msedgedriver`. + """Service class responsible for starting and stopping msedgedriver. Args: executable_path: Install path of the msedgedriver executable, defaults to `msedgedriver`. @@ -61,10 +60,7 @@ def __init__( @property def service_args(self) -> Sequence[str]: - """ - Returns: - The sequence of service arguments. - """ + """Returns the sequence of service arguments.""" return self._service_args @service_args.setter diff --git a/py/selenium/webdriver/firefox/firefox_binary.py b/py/selenium/webdriver/firefox/firefox_binary.py index 58e1bcb819c86..339279409c031 100644 --- a/py/selenium/webdriver/firefox/firefox_binary.py +++ b/py/selenium/webdriver/firefox/firefox_binary.py @@ -217,9 +217,7 @@ def _extract_and_check(self, profile, x86, amd64): return built_path def which(self, fname): - """Returns the fully qualified path by searching Path of the given - name. - """ + """Return the fully qualified path by searching PATH for the given name.""" for pe in os.environ["PATH"].split(os.pathsep): checkname = os.path.join(pe, fname) if os.access(checkname, os.X_OK) and not os.path.isdir(checkname): diff --git a/py/selenium/webdriver/firefox/firefox_profile.py b/py/selenium/webdriver/firefox/firefox_profile.py index 506253325dd66..a2b4fd3019569 100644 --- a/py/selenium/webdriver/firefox/firefox_profile.py +++ b/py/selenium/webdriver/firefox/firefox_profile.py @@ -147,9 +147,7 @@ def assume_untrusted_cert_issuer(self, value) -> None: @property def encoded(self) -> str: - """Updates preferences and creates a zipped, base64 encoded string of - profile directory. - """ + """Update preferences and create a zipped, base64-encoded profile directory string.""" if self._desired_preferences: self.update_preferences() fp = BytesIO() @@ -162,9 +160,7 @@ def encoded(self) -> str: return base64.b64encode(fp.getvalue()).decode("UTF-8") def _read_existing_userjs(self, userjs): - """Reads existing preferences and adds them to desired preference - dictionary. - """ + """Read existing preferences and add them to the desired preference dictionary.""" pref_pattern = re.compile(r'user_pref\("(.*)",\s(.*)\)') with open(userjs, encoding="utf-8") as f: for usr in f: @@ -178,8 +174,7 @@ def _read_existing_userjs(self, userjs): @deprecated("Addons must be added after starting the session") def _install_extension(self, addon, unpack=True): - """Installs addon from a filepath, url or directory of addons in the - profile. + """Install addon from a filepath, URL, or directory of addons in the profile. Args: addon: url, absolute path to .xpi, or directory of addons @@ -263,9 +258,7 @@ def get_text(element): return "".join(rc).strip() def parse_manifest_json(content): - """Extracts the details from the contents of a WebExtensions - `manifest.json` file. - """ + """Extract details from the contents of a WebExtensions manifest.json file.""" manifest = json.loads(content) try: id = manifest["applications"]["gecko"]["id"] diff --git a/py/selenium/webdriver/firefox/options.py b/py/selenium/webdriver/firefox/options.py index 86894e1924de3..9f5a7bbe0bded 100644 --- a/py/selenium/webdriver/firefox/options.py +++ b/py/selenium/webdriver/firefox/options.py @@ -56,19 +56,14 @@ def binary(self) -> FirefoxBinary: @binary.setter @deprecated("use binary_location instead") def binary(self, new_binary: Union[str, FirefoxBinary]) -> None: - """Sets location of the browser binary, either by string or - ``FirefoxBinary`` instance. - """ + """Set location of browser binary (string or FirefoxBinary instance).""" if isinstance(new_binary, FirefoxBinary): new_binary = new_binary._start_cmd self.binary_location = str(new_binary) @property def binary_location(self) -> str: - """ - Returns: - The location of the binary. - """ + """Returns the location of the binary.""" return self._binary_location @binary_location.setter # noqa @@ -80,10 +75,7 @@ def binary_location(self, value: str) -> None: @property def preferences(self) -> dict: - """ - Returns: - A dict of preferences. - """ + """Returns a dict of preferences.""" return self._preferences def set_preference(self, name: str, value: Union[str, int, bool]): @@ -92,17 +84,12 @@ def set_preference(self, name: str, value: Union[str, int, bool]): @property def profile(self) -> Optional[FirefoxProfile]: - """ - Returns: - The Firefox profile to use. - """ + """Returns the Firefox profile to use.""" return self._profile @profile.setter def profile(self, new_profile: Union[str, FirefoxProfile]) -> None: - """Sets location of the browser profile to use, either by string or - ``FirefoxProfile``. - """ + """Set the location of the browser profile to use (string or FirefoxProfile object).""" if not isinstance(new_profile, FirefoxProfile): new_profile = FirefoxProfile(new_profile) self._profile = new_profile diff --git a/py/selenium/webdriver/firefox/service.py b/py/selenium/webdriver/firefox/service.py index 00848c5378d5d..e0096b1e1d77c 100644 --- a/py/selenium/webdriver/firefox/service.py +++ b/py/selenium/webdriver/firefox/service.py @@ -23,8 +23,7 @@ class Service(service.Service): - """A Service class that is responsible for the starting and stopping of - `geckodriver`. + """Service class responsible for starting and stopping geckodriver. Args: executable_path: install path of the geckodriver executable, defaults to `geckodriver`. @@ -67,6 +66,7 @@ def command_line_args(self) -> list[str]: @property def service_args(self) -> Sequence[str]: + """Returns the sequence of service arguments.""" return self._service_args @service_args.setter diff --git a/py/selenium/webdriver/firefox/webdriver.py b/py/selenium/webdriver/firefox/webdriver.py index 560a7bdb0ad9c..65b9eb5760d47 100644 --- a/py/selenium/webdriver/firefox/webdriver.py +++ b/py/selenium/webdriver/firefox/webdriver.py @@ -41,8 +41,7 @@ def __init__( service: Optional[Service] = None, keep_alive: bool = True, ) -> None: - """Creates a new instance of the Firefox driver. Starts the service and - then creates new instance of Firefox driver. + """Create a new instance of the Firefox driver, start the service, and create new instance. Args: options: Instance of ``options.Options``. @@ -94,9 +93,10 @@ def set_context(self, context) -> None: @contextmanager def context(self, context): - """Sets the context that Selenium commands are running in using a - `with` statement. The state of the context on the server is saved - before entering the block, and restored upon exiting it. + """Set the context that Selenium commands are running in using a `with` statement. + + The state of the context on the server is saved before entering the block, + and restored upon exiting it. Args: context: Context, may be one of the class properties @@ -161,14 +161,15 @@ def uninstall_addon(self, identifier) -> None: self.execute("UNINSTALL_ADDON", {"id": identifier}) def get_full_page_screenshot_as_file(self, filename) -> bool: - """Saves a full document screenshot of the current window to a PNG - image file. Returns False if there is any IOError, else returns True. - Use full paths in your filename. + """Save a full document screenshot of the current window to a PNG image file. Args: filename: The full path you wish to save your screenshot to. This should end with a `.png` extension. + Returns: + False if there is any IOError, else returns True. Use full paths in your filename. + Example: driver.get_full_page_screenshot_as_file("/Screenshots/foo.png") """ @@ -188,22 +189,22 @@ def get_full_page_screenshot_as_file(self, filename) -> bool: return True def save_full_page_screenshot(self, filename) -> bool: - """Saves a full document screenshot of the current window to a PNG - image file. Returns False if there is any IOError, else returns True. - Use full paths in your filename. + """Save a full document screenshot of the current window to a PNG image file. Args: filename: The full path you wish to save your screenshot to. This should end with a `.png` extension. + Returns: + False if there is any IOError, else returns True. Use full paths in your filename. + Example: driver.save_full_page_screenshot("/Screenshots/foo.png") """ return self.get_full_page_screenshot_as_file(filename) def get_full_page_screenshot_as_png(self) -> bytes: - """Gets the full document screenshot of the current window as a binary - data. + """Get the full document screenshot of the current window as binary data. Returns: Binary data of the screenshot. @@ -214,8 +215,7 @@ def get_full_page_screenshot_as_png(self) -> bytes: return base64.b64decode(self.get_full_page_screenshot_as_base64().encode("ascii")) def get_full_page_screenshot_as_base64(self) -> str: - """Gets the full document screenshot of the current window as a base64 - encoded string which is useful in embedded images in HTML. + """Get the full document screenshot of the current window as a base64-encoded string. Returns: Base64 encoded string of the screenshot. diff --git a/py/selenium/webdriver/ie/options.py b/py/selenium/webdriver/ie/options.py index a38a64d49ea76..fdf6cfce9342b 100644 --- a/py/selenium/webdriver/ie/options.py +++ b/py/selenium/webdriver/ie/options.py @@ -302,18 +302,12 @@ def __init__(self) -> None: @property def options(self) -> dict: - """ - Returns: - A dictionary of browser options. - """ + """Returns a dictionary of browser options.""" return self._options @property def additional_options(self) -> dict: - """ - Returns: - The additional options. - """ + """Returns the additional options.""" return self._additional def add_additional_option(self, name: str, value) -> None: diff --git a/py/selenium/webdriver/ie/service.py b/py/selenium/webdriver/ie/service.py index 3627c4a4cb372..35a14fcfb51f0 100644 --- a/py/selenium/webdriver/ie/service.py +++ b/py/selenium/webdriver/ie/service.py @@ -71,6 +71,7 @@ def command_line_args(self) -> list[str]: @property def service_args(self) -> Sequence[str]: + """Returns the sequence of service arguments.""" return self._service_args @service_args.setter diff --git a/py/selenium/webdriver/ie/webdriver.py b/py/selenium/webdriver/ie/webdriver.py index 5209294f9f76b..b2380e22550fd 100644 --- a/py/selenium/webdriver/ie/webdriver.py +++ b/py/selenium/webdriver/ie/webdriver.py @@ -26,9 +26,7 @@ class WebDriver(RemoteWebDriver): - """Controls the IEServerDriver and allows you to drive Internet - Explorer. - """ + """Control the IEServerDriver and drive Internet Explorer.""" def __init__( self, diff --git a/py/selenium/webdriver/remote/errorhandler.py b/py/selenium/webdriver/remote/errorhandler.py index 050970206f757..9916893ea8de1 100644 --- a/py/selenium/webdriver/remote/errorhandler.py +++ b/py/selenium/webdriver/remote/errorhandler.py @@ -143,8 +143,7 @@ class ErrorHandler: """Handles errors returned by the WebDriver server.""" def check_response(self, response: dict[str, Any]) -> None: - """Checks that a JSON response from the WebDriver does not have an - error. + """Check that a JSON response from the WebDriver does not have an error. Args: response: The JSON response from the WebDriver server as a dictionary diff --git a/py/selenium/webdriver/remote/file_detector.py b/py/selenium/webdriver/remote/file_detector.py index 3691328bdab11..a72cb205be39a 100644 --- a/py/selenium/webdriver/remote/file_detector.py +++ b/py/selenium/webdriver/remote/file_detector.py @@ -25,9 +25,7 @@ class FileDetector(metaclass=ABCMeta): - """Used for identifying whether a sequence of chars represents the path to - a file. - """ + """Identify whether a sequence of characters represents a file path.""" @abstractmethod def is_local_file(self, *keys: AnyKey) -> Optional[str]: diff --git a/py/selenium/webdriver/remote/remote_connection.py b/py/selenium/webdriver/remote/remote_connection.py index 0c3bdab00bd7f..2b3751ef3b8ef 100644 --- a/py/selenium/webdriver/remote/remote_connection.py +++ b/py/selenium/webdriver/remote/remote_connection.py @@ -224,9 +224,9 @@ def get_certificate_bundle_path(cls): @classmethod def set_certificate_bundle_path(cls, path): - """Set the path to the certificate bundle to verify connection to - command executor. Can also be set to None to disable certificate - validation. + """Set the path to the certificate bundle for verifying command executor connection. + + Can also be set to None to disable certificate validation. Args: path: path of a .pem encoded certificate chain. diff --git a/py/selenium/webdriver/remote/shadowroot.py b/py/selenium/webdriver/remote/shadowroot.py index 61c92797e05ed..101649249822b 100644 --- a/py/selenium/webdriver/remote/shadowroot.py +++ b/py/selenium/webdriver/remote/shadowroot.py @@ -45,8 +45,7 @@ def id(self) -> str: return self._id def find_element(self, by: str = By.ID, value: str = None): - """Find an element inside a shadow root given a By strategy and - locator. + """Find an element inside a shadow root given a By strategy and locator. Args: by: The locating strategy to use. Default is `By.ID`. Supported values include: diff --git a/py/selenium/webdriver/remote/switch_to.py b/py/selenium/webdriver/remote/switch_to.py index 0f9e5418bae24..89aabfef79773 100644 --- a/py/selenium/webdriver/remote/switch_to.py +++ b/py/selenium/webdriver/remote/switch_to.py @@ -59,12 +59,11 @@ def default_content(self) -> None: self._driver.execute(Command.SWITCH_TO_FRAME, {"id": None}) def frame(self, frame_reference: Union[str, int, WebElement]) -> None: - """Switches focus to the specified frame, by index, name, or - webelement. + """Switch focus to the specified frame by index, name, or element. Args: - frame_reference: The name of the window to switch to, an integer representing the index, - or a webelement that is an (i)frame to switch to. + frame_reference: The name of the frame to switch to, an integer representing the index, + or a WebElement that is an (i)frame to switch to. Example: driver.switch_to.frame("frame_name") @@ -95,8 +94,9 @@ def new_window(self, type_hint: Optional[str] = None) -> None: self._w3c_window(value["handle"]) def parent_frame(self) -> None: - """Switches focus to the parent context. If the current context is the - top level browsing context, the context remains unchanged. + """Switch focus to the parent browsing context. + + If the current context is already the top level browsing context, it remains unchanged. Example: driver.switch_to.parent_frame() diff --git a/py/selenium/webdriver/remote/webdriver.py b/py/selenium/webdriver/remote/webdriver.py index 0a603f5fa307d..81c7cc088e917 100644 --- a/py/selenium/webdriver/remote/webdriver.py +++ b/py/selenium/webdriver/remote/webdriver.py @@ -78,13 +78,13 @@ cdp = None -def import_cdp(): +def import_cdp() -> None: global cdp if not cdp: cdp = import_module("selenium.webdriver.common.bidi.cdp") -def _create_caps(caps): +def _create_caps(caps) -> dict: """Makes a W3C alwaysMatch capabilities object. Filters out capability names that are not in the W3C spec. Spec-compliant @@ -178,9 +178,10 @@ class BaseWebDriver(metaclass=ABCMeta): class WebDriver(BaseWebDriver): - """Controls a browser by sending commands to a remote server. This server - is expected to be running the WebDriver wire protocol as defined at - https://www.selenium.dev/documentation/legacy/json_wire_protocol/. + """Control a browser by sending commands to a remote WebDriver server. + + This class expects the remote server to be running the WebDriver wire protocol + as defined at https://www.selenium.dev/documentation/legacy/json_wire_protocol/. Attributes: ----------- @@ -204,8 +205,7 @@ def __init__( web_element_cls: Optional[type[WebElement]] = None, client_config: Optional[ClientConfig] = None, ) -> None: - """Create a new driver that will issue commands using the wire - protocol. + """Create a new driver instance that issues commands using the WebDriver protocol. Args: command_executor: Either a string representing the URL of the remote @@ -270,10 +270,10 @@ def __init__( self._input = None self._devtools = None - def __repr__(self): + def __repr__(self) -> str: return f'<{type(self).__module__}.{type(self).__name__} (session="{self.session_id}")>' - def __enter__(self): + def __enter__(self) -> "WebDriver": return self def __exit__( @@ -286,8 +286,9 @@ def __exit__( @contextmanager def file_detector_context(self, file_detector_class, *args, **kwargs): - """Overrides the current file detector (if necessary) in limited - context. Ensures the original file detector is set afterwards. + """Override the current file detector temporarily within a limited context. + + Ensures the original file detector is set after exiting the context. Args: file_detector_class: Class of the desired file detector. If the @@ -325,14 +326,14 @@ def name(self) -> str: return self.caps["browserName"] raise KeyError("browserName not specified in session capabilities") - def start_client(self): + def start_client(self) -> None: """Called before starting a new session. This method may be overridden to define custom startup behavior. """ pass - def stop_client(self): + def stop_client(self) -> None: """Called after executing a quit command. This method may be overridden to define custom shutdown @@ -436,11 +437,10 @@ def execute(self, driver_command: str, params: Optional[dict[str, Any]] = None) return {"success": 0, "value": None, "sessionId": self.session_id} def get(self, url: str) -> None: - """Navigate the browser to the specified URL in the current window or - tab. + """Navigate the browser to the specified URL. The method does not return until the page is fully loaded (i.e. the - onload event has fired). + onload event has fired) in the current window or tab. Args: url: The URL to be opened by the browser. Must include the protocol @@ -464,8 +464,7 @@ def title(self) -> str: return self.execute(Command.GET_TITLE).get("value", "") def pin_script(self, script: str, script_key=None) -> ScriptKey: - """Store common javascript scripts to be executed later by a unique - hashable ID. + """Store a JavaScript script by a unique hashable ID for later execution. Example: `script = "return document.getElementById('foo').value"` @@ -518,7 +517,7 @@ def execute_script(self, script: str, *args): return self.execute(command, {"script": script, "args": converted_args})["value"] - def execute_async_script(self, script: str, *args): + def execute_async_script(self, script: str, *args) -> dict: """Asynchronously Executes JavaScript in the current window/frame. Args: @@ -628,8 +627,7 @@ def refresh(self) -> None: self.execute(Command.REFRESH) def get_cookies(self) -> list[dict]: - """Returns a set of dictionaries, corresponding to cookies visible in - the current session. + """Get all cookies visible to the current WebDriver instance. Returns: A list of dictionaries, corresponding to cookies visible in the @@ -638,8 +636,13 @@ def get_cookies(self) -> list[dict]: return self.execute(Command.GET_ALL_COOKIES)["value"] def get_cookie(self, name) -> Optional[dict]: - """Get a single cookie by name. Raises ValueError if the name is empty - or whitespace. Returns the cookie if found, None if not. + """Get a single cookie by name (case-sensitive,). + + Returns: + A cookie dictionary or None if not found. + + Raises: + ValueError if the name is empty or whitespace. Example: `cookie = driver.get_cookie("my_cookie")` @@ -653,8 +656,10 @@ def get_cookie(self, name) -> Optional[dict]: return None def delete_cookie(self, name) -> None: - """Deletes a single cookie with the given name. Raises ValueError if - the name is empty or whitespace. + """Delete a single cookie with the given name (case-sensitive). + + Raises: + ValueError if the name is empty or whitespace. Example: `driver.delete_cookie("my_cookie")` @@ -691,10 +696,11 @@ def add_cookie(self, cookie_dict) -> None: # Timeouts def implicitly_wait(self, time_to_wait: float) -> None: - """Sets a sticky timeout to implicitly wait for an element to be found, - or a command to complete. This method only needs to be called one time - per session. To set the timeout for calls to execute_async_script, see - set_script_timeout. + """Set a sticky implicit timeout for element location and command completion. + + This method sets a timeout that applies to all element location strategies + for the duration of the session. It only needs to be called once per session. + To set the timeout for asynchronous script execution, see set_script_timeout. Args: time_to_wait: Amount of time to wait (in seconds). @@ -705,7 +711,9 @@ def implicitly_wait(self, time_to_wait: float) -> None: self.execute(Command.SET_TIMEOUTS, {"implicit": int(float(time_to_wait) * 1000)}) def set_script_timeout(self, time_to_wait: float) -> None: - """Set the amount of time that the script should wait during an + """Set the timeout for asynchronous script execution. + + This timeout specifies how long a script can run during an execute_async_script call before throwing an error. Args: @@ -717,7 +725,9 @@ def set_script_timeout(self, time_to_wait: float) -> None: self.execute(Command.SET_TIMEOUTS, {"script": int(float(time_to_wait) * 1000)}) def set_page_load_timeout(self, time_to_wait: float) -> None: - """Set the amount of time to wait for a page load to complete before + """Set the timeout for page load completion. + + This specifies how long to wait for a page load to complete before throwing an error. Args: @@ -752,8 +762,9 @@ def timeouts(self) -> Timeouts: @timeouts.setter def timeouts(self, timeouts) -> None: - """Set all timeouts for the session. This will override any previously - set timeouts. + """Set all timeouts for the session. + + This will override any previously set timeouts. Example: ``` @@ -827,9 +838,10 @@ def capabilities(self) -> dict: return self.caps def get_screenshot_as_file(self, filename) -> bool: - """Saves a screenshot of the current window to a PNG image file. - Returns False if there is any IOError, else returns True. Use full - paths in your filename. + """Save a screenshot of the current window to a PNG image file. + + Returns: + False if there is any IOError, else returns True. Use full paths in your filename. Args: filename: The full path you wish to save your screenshot to. This @@ -855,9 +867,10 @@ def get_screenshot_as_file(self, filename) -> bool: return True def save_screenshot(self, filename) -> bool: - """Saves a screenshot of the current window to a PNG image file. - Returns False if there is any IOError, else returns True. Use full - paths in your filename. + """Save a screenshot of the current window to a PNG image file. + + Returns: + False if there is any IOError, else returns True. Use full paths in your filename. Args: filename: The full path you wish to save your screenshot to. This @@ -877,8 +890,9 @@ def get_screenshot_as_png(self) -> bytes: return b64decode(self.get_screenshot_as_base64().encode("ascii")) def get_screenshot_as_base64(self) -> str: - """Gets the screenshot of the current window as a base64 encoded string - which is useful in embedded images in HTML. + """Get a base64-encoded screenshot of the current window. + + This encoding is useful for embedding screenshots in HTML. Example: `driver.get_screenshot_as_base64()` @@ -944,8 +958,10 @@ def _check_if_window_handle_is_current(self, windowHandle: str) -> None: warnings.warn("Only 'current' window is supported for W3C compatible browsers.", stacklevel=2) def get_window_rect(self) -> dict: - """Gets the x, y coordinates of the window as well as height and width - of the current window. + """Get the window's position and size. + + Returns: + x, y coordinates and height and width of the current window. Example: `driver.get_window_rect()` @@ -953,10 +969,11 @@ def get_window_rect(self) -> dict: return self.execute(Command.GET_WINDOW_RECT)["value"] def set_window_rect(self, x=None, y=None, width=None, height=None) -> dict: - """Sets the x, y coordinates of the window as well as height and width - of the current window. This method is only supported for W3C compatible - browsers; other browsers should use `set_window_position` and - `set_window_size`. + """Set the window's position and size. + + Sets the x, y coordinates and height and width of the current window. + This method is only supported for W3C compatible browsers; other browsers + should use `set_window_position` and `set_window_size`. Example: `driver.set_window_rect(x=10, y=10)` @@ -974,9 +991,9 @@ def file_detector(self) -> FileDetector: @file_detector.setter def file_detector(self, detector) -> None: - """Set the file detector to be used when sending keyboard input. By - default, this is set to a file detector that does nothing. + """Set the file detector for keyboard input. + By default, this is set to a file detector that does nothing. See FileDetector, LocalFileDetector, and UselessFileDetector. Args: @@ -989,7 +1006,7 @@ def file_detector(self, detector) -> None: self._file_detector = detector @property - def orientation(self): + def orientation(self) -> dict: """Gets the current orientation of the device. Example: @@ -1013,7 +1030,7 @@ def orientation(self, value) -> None: else: raise WebDriverException("You can only set the orientation to 'LANDSCAPE' and 'PORTRAIT'") - def start_devtools(self): + def start_devtools(self) -> tuple[Any, WebSocketConnection]: global cdp import_cdp() if self.caps.get("se:cdp"): @@ -1068,7 +1085,7 @@ async def bidi_connection(self): yield BidiConnection(session, cdp, devtools) @property - def script(self): + def script(self) -> Script: if not self._websocket_connection: self._start_bidi() @@ -1077,7 +1094,7 @@ def script(self): return self._script - def _start_bidi(self): + def _start_bidi(self) -> None: if self.caps.get("webSocketUrl"): ws_url = self.caps.get("webSocketUrl") else: @@ -1090,7 +1107,7 @@ def _start_bidi(self): ) @property - def network(self): + def network(self) -> Network: if not self._websocket_connection: self._start_bidi() @@ -1100,7 +1117,7 @@ def network(self): return self._network @property - def browser(self): + def browser(self) -> Browser: """Returns a browser module object for BiDi browser commands. Returns: @@ -1121,10 +1138,8 @@ def browser(self): return self._browser @property - def _session(self): - """Returns the BiDi session object for the current WebDriver - session. - """ + def _session(self) -> Session: + """Returns the BiDi session object for the current WebDriver session.""" if not self._websocket_connection: self._start_bidi() @@ -1134,9 +1149,8 @@ def _session(self): return self._bidi_session @property - def browsing_context(self): - """Returns a browsing context module object for BiDi browsing context - commands. + def browsing_context(self) -> BrowsingContext: + """Returns a browsing context module object for BiDi browsing context commands. Returns: An object containing access to BiDi browsing context commands. @@ -1156,7 +1170,7 @@ def browsing_context(self): return self._browsing_context @property - def storage(self): + def storage(self) -> Storage: """Returns a storage module object for BiDi storage commands. Returns: @@ -1181,8 +1195,8 @@ def storage(self): return self._storage @property - def permissions(self): - """Returns a permissions module object for BiDi permissions commands. + def permissions(self) -> Permissions: + """Get a permissions module object for BiDi permissions commands. Returns: An object containing access to BiDi permissions commands. @@ -1204,8 +1218,8 @@ def permissions(self): return self._permissions @property - def webextension(self): - """Returns a webextension module object for BiDi webextension commands. + def webextension(self) -> WebExtension: + """Get a webextension module object for BiDi webextension commands. Returns: An object containing access to BiDi webextension commands. @@ -1224,8 +1238,8 @@ def webextension(self): return self._webextension @property - def emulation(self): - """Returns an emulation module object for BiDi emulation commands. + def emulation(self) -> Emulation: + """Get an emulation module object for BiDi emulation commands. Returns: An object containing access to BiDi emulation commands. @@ -1247,8 +1261,8 @@ def emulation(self): return self._emulation @property - def input(self): - """Returns an input module object for BiDi input commands. + def input(self) -> Input: + """Get an input module object for BiDi input commands. Returns: An object containing access to BiDi input commands. @@ -1368,8 +1382,7 @@ def remove_all_credentials(self) -> None: @required_virtual_authenticator def set_user_verified(self, verified: bool) -> None: - """Sets whether the authenticator will simulate success or fail on user - verification. + """Set whether the authenticator will simulate success or failure on user verification. Args: verified: True if the authenticator will pass user verification, @@ -1388,13 +1401,11 @@ def get_downloadable_files(self) -> list: return self.execute(Command.GET_DOWNLOADABLE_FILES)["value"]["names"] def download_file(self, file_name: str, target_directory: str) -> None: - """Downloads a file with the specified file name to the target - directory. + """Download a file with the specified file name to the target directory. Args: file_name: The name of the file to download. - target_directory: The path to the directory to save the downloaded - file. + target_directory: The path to the directory to save the downloaded file. Example: `driver.download_file("example.zip", "/path/to/directory")` @@ -1424,8 +1435,7 @@ def delete_downloadable_files(self) -> None: @property def fedcm(self) -> FedCM: - """Returns the Federated Credential Management (FedCM) dialog object - for interaction. + """Get the Federated Credential Management (FedCM) dialog commands. Returns: An object providing access to all Federated Credential Management @@ -1450,7 +1460,7 @@ def supports_fedcm(self) -> bool: """Returns whether the browser supports FedCM capabilities.""" return self.capabilities.get(ArgOptions.FEDCM_CAPABILITY, False) - def _require_fedcm_support(self): + def _require_fedcm_support(self) -> None: """Raises an exception if FedCM is not supported.""" if not self.supports_fedcm: raise WebDriverException( @@ -1459,7 +1469,7 @@ def _require_fedcm_support(self): ) @property - def dialog(self): + def dialog(self) -> Dialog: """Returns the FedCM dialog object for interaction.""" self._require_fedcm_support() return Dialog(self) @@ -1487,7 +1497,7 @@ def fedcm_dialog(self, timeout=5, poll_frequency=0.5, ignored_exceptions=None): if ignored_exceptions is None: ignored_exceptions = (NoAlertPresentException,) - def _check_fedcm(): + def _check_fedcm() -> Optional[Dialog]: try: dialog = Dialog(self) return dialog if dialog.type else None diff --git a/py/selenium/webdriver/remote/webelement.py b/py/selenium/webdriver/remote/webelement.py index 61977e58a7591..e329d021a2ad2 100644 --- a/py/selenium/webdriver/remote/webelement.py +++ b/py/selenium/webdriver/remote/webelement.py @@ -14,6 +14,7 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. + from __future__ import annotations import os @@ -31,8 +32,7 @@ from selenium.webdriver.remote.command import Command from selenium.webdriver.remote.shadowroot import ShadowRoot -# TODO: When moving to supporting python 3.9 as the minimum version we can -# use built in importlib_resources.files. +# TODO: Use built in importlib_resources.files. getAttribute_js = None isDisplayed_js = None @@ -64,7 +64,7 @@ class WebElement(BaseWebElement): All method calls will do a freshness check to ensure that the element reference is still valid. This essentially determines whether the element is still attached to the DOM. If this test fails, then an - ``StaleElementReferenceException`` is thrown, and all future calls to this + `StaleElementReferenceException` is thrown, and all future calls to this instance will fail. """ @@ -81,13 +81,13 @@ def session_id(self) -> str: @property def tag_name(self) -> str: - """This element's ``tagName`` property. + """This element's `tagName` property. Returns: The tag name of the element. Example: - >>> element = driver.find_element(By.ID, "foo") + element = driver.find_element(By.ID, "foo") """ return self._execute(Command.GET_ELEMENT_TAG_NAME)["value"] @@ -99,8 +99,8 @@ def text(self) -> str: The text of the element. Example: - >>> element = driver.find_element(By.ID, "foo") - >>> print(element.text) + element = driver.find_element(By.ID, "foo") + print(element.text) """ return self._execute(Command.GET_ELEMENT_TEXT)["value"] @@ -108,8 +108,8 @@ def click(self) -> None: """Clicks the element. Example: - >>> element = driver.find_element(By.ID, "foo") - >>> element.click() + element = driver.find_element(By.ID, "foo") + element.click() """ self._execute(Command.CLICK_ELEMENT) @@ -117,8 +117,8 @@ def submit(self) -> None: """Submits a form. Example: - >>> form = driver.find_element(By.NAME, "login") - >>> form.submit() + form = driver.find_element(By.NAME, "login") + form.submit() """ script = ( "/* submitForm */var form = arguments[0];\n" @@ -141,8 +141,8 @@ def clear(self) -> None: """Clears the text if it's a text entry element. Example: - >>> text_field = driver.find_element(By.NAME, "username") - >>> text_field.clear() + text_field = driver.find_element(By.NAME, "username") + text_field.clear() """ self._execute(Command.CLEAR_ELEMENT) @@ -156,7 +156,7 @@ def get_property(self, name) -> str | bool | WebElement | dict: The value of the property. Example: - >>> text_length = target_element.get_property("text_length") + text_length = target_element.get_property("text_length") """ try: return self._execute(Command.GET_ELEMENT_PROPERTY, {"name": name})["value"] @@ -165,9 +165,10 @@ def get_property(self, name) -> str | bool | WebElement | dict: return self.parent.execute_script("return arguments[0][arguments[1]]", self, name) def get_dom_attribute(self, name) -> str: - """Gets the given attribute of the element. Unlike - :func:`~selenium.webdriver.remote.BaseWebElement.get_attribute`, this - method only returns attributes declared in the element's HTML markup. + """Get the HTML attribute value (not reflected properties) of the element. + + Returns only attributes declared in the element's HTML markup, unlike + `selenium.webdriver.remote.BaseWebElement.get_attribute`. Args: name: Name of the attribute to retrieve. @@ -176,7 +177,7 @@ def get_dom_attribute(self, name) -> str: The value of the attribute. Example: - >>> text_length = target_element.get_dom_attribute("class") + text_length = target_element.get_dom_attribute("class") """ return self._execute(Command.GET_ELEMENT_ATTRIBUTE, {"name": name})["value"] @@ -204,8 +205,8 @@ def get_attribute(self, name) -> str | None: The value of the attribute/property. Example: - >>> # Check if the "active" CSS class is applied to an element. - >>> is_active = "active" in target_element.get_attribute("class") + # Check if the "active" CSS class is applied to an element. + is_active = "active" in target_element.get_attribute("class") """ if getAttribute_js is None: _load_js() @@ -221,7 +222,7 @@ def is_selected(self) -> bool: and radio buttons. Example: - >>> is_selected = element.is_selected() + is_selected = element.is_selected() """ return self._execute(Command.IS_ELEMENT_SELECTED)["value"] @@ -229,7 +230,7 @@ def is_enabled(self) -> bool: """Returns whether the element is enabled. Example: - >>> is_enabled = element.is_enabled() + is_enabled = element.is_enabled() """ return self._execute(Command.IS_ELEMENT_ENABLED)["value"] @@ -246,16 +247,16 @@ def send_keys(self, *value: str) -> None: Examples: To send a simple key event:: - >>> form_textfield = driver.find_element(By.NAME, "username") - >>> form_textfield.send_keys("admin") + form_textfield = driver.find_element(By.NAME, "username") + form_textfield.send_keys("admin") or to set a file input field:: - >>> file_input = driver.find_element(By.NAME, "profilePic") - >>> file_input.send_keys("path/to/profilepic.gif") - >>> # Generally it's better to wrap the file path in one of the methods - >>> # in os.path to return the actual path to support cross OS testing. - >>> # file_input.send_keys(os.path.abspath("path/to/profilepic.gif")) + file_input = driver.find_element(By.NAME, "profilePic") + file_input.send_keys("path/to/profilepic.gif") + # Generally it's better to wrap the file path in one of the methods + # in os.path to return the actual path to support cross OS testing. + # file_input.send_keys(os.path.abspath("path/to/profilepic.gif")) """ # transfer file to another machine only if remote driver is used # the same behaviour as for java binding @@ -278,10 +279,7 @@ def send_keys(self, *value: str) -> None: @property def shadow_root(self) -> ShadowRoot: - """Returns a shadow root of the element if there is one or an error. - Only works from Chromium 96, Firefox 96, and Safari 16.4 onwards. - - If the alert is present it switches the given driver to it. + """Get the shadow root attached to this element if present (Chromium, Firefox, Safari). Returns: The ShadowRoot object. @@ -290,10 +288,10 @@ def shadow_root(self) -> ShadowRoot: NoSuchShadowRoot: If no shadow root was attached to element. Example: - >>> try: - ... shadow_root = element.shadow_root - >>> except NoSuchShadowRoot: - ... print("No shadow root attached to element") + try: + shadow_root = element.shadow_root + except NoSuchShadowRoot: + print("No shadow root attached to element") """ return self._execute(Command.GET_SHADOW_ROOT)["value"] @@ -302,7 +300,7 @@ def is_displayed(self) -> bool: """Whether the element is visible to a user. Example: - >>> is_displayed = element.is_displayed() + is_displayed = element.is_displayed() """ # Only go into this conditional for browsers that don't use the atom themselves if isDisplayed_js is None: @@ -311,16 +309,17 @@ def is_displayed(self) -> bool: @property def location_once_scrolled_into_view(self) -> dict: - """THIS PROPERTY MAY CHANGE WITHOUT WARNING. Use this to discover where - on the screen an element is so that we can click it. This method should - cause the element to be scrolled into view. + """Get the element's location on screen after scrolling it into view. + + This may change without warning and scrolls the element into view + before calculating coordinates for clicking purposes. Returns: The top lefthand corner location on the screen, or zero coordinates if the element is not visible. Example: - >>> loc = element.location_once_scrolled_into_view + loc = element.location_once_scrolled_into_view """ old_loc = self._execute( Command.W3C_EXECUTE_SCRIPT, @@ -333,20 +332,20 @@ def location_once_scrolled_into_view(self) -> dict: @property def size(self) -> dict: - """The size of the element. + """Get the size of the element. Returns: The width and height of the element. Example: - >>> size = element.size + size = element.size """ size = self._execute(Command.GET_ELEMENT_RECT)["value"] new_size = {"height": size["height"], "width": size["width"]} return new_size def value_of_css_property(self, property_name) -> str: - """The value of a CSS property. + """Get the value of a CSS property. Args: property_name: The name of the CSS property to get the value of. @@ -355,19 +354,19 @@ def value_of_css_property(self, property_name) -> str: The value of the CSS property. Example: - >>> value = element.value_of_css_property("color") + value = element.value_of_css_property("color") """ return self._execute(Command.GET_ELEMENT_VALUE_OF_CSS_PROPERTY, {"propertyName": property_name})["value"] @property def location(self) -> dict: - """The location of the element in the renderable canvas. + """Get the location of the element in the renderable canvas. Returns: The x and y coordinates of the element. Example: - >>> loc = element.location + loc = element.location """ old_loc = self._execute(Command.GET_ELEMENT_RECT)["value"] new_loc = {"x": round(old_loc["x"]), "y": round(old_loc["y"])} @@ -375,69 +374,68 @@ def location(self) -> dict: @property def rect(self) -> dict: - """A dictionary with the size and location of the element. + """Get the size and location of the element. Returns: - The size and location of the element. + A dictionary with size and location of the element. Example: - >>> rect = element.rect + rect = element.rect """ return self._execute(Command.GET_ELEMENT_RECT)["value"] @property def aria_role(self) -> str: - """Returns the ARIA role of the current web element. + """Get the ARIA role of the current web element. Returns: The ARIA role of the element. Example: - >>> role = element.aria_role + role = element.aria_role """ return self._execute(Command.GET_ELEMENT_ARIA_ROLE)["value"] @property def accessible_name(self) -> str: - """Returns the ARIA Level of the current webelement. + """Get the ARIA Level of the current webelement. Returns: The ARIA Level of the element. Example: - >>> name = element.accessible_name + name = element.accessible_name """ return self._execute(Command.GET_ELEMENT_ARIA_LABEL)["value"] @property def screenshot_as_base64(self) -> str: - """Gets the screenshot of the current element as a base64 encoded - string. + """Get a base64-encoded screenshot of the current element. Returns: The screenshot of the element as a base64 encoded string. Example: - >>> img_b64 = element.screenshot_as_base64 + img_b64 = element.screenshot_as_base64 """ return self._execute(Command.ELEMENT_SCREENSHOT)["value"] @property def screenshot_as_png(self) -> bytes: - """Gets the screenshot of the current element as a binary data. + """Get the screenshot of the current element as a binary data. Returns: The screenshot of the element as binary data. Example: - >>> element_png = element.screenshot_as_png + element_png = element.screenshot_as_png """ return b64decode(self.screenshot_as_base64.encode("ascii")) def screenshot(self, filename) -> bool: - """Saves a screenshot of the current element to a PNG image file. - Returns False if there is any IOError, else returns True. Use full - paths in your filename. + """Save a PNG screenshot of the current element to a file. + + Use full paths in your filename. Args: filename: The full path you wish to save your screenshot to. This @@ -447,7 +445,7 @@ def screenshot(self, filename) -> bool: True if the screenshot was saved successfully, False otherwise. Example: - >>> element.screenshot("/Screenshots/foo.png") + element.screenshot("/Screenshots/foo.png") """ if not filename.lower().endswith(".png"): warnings.warn( @@ -466,25 +464,24 @@ def screenshot(self, filename) -> bool: @property def parent(self): - """Internal reference to the WebDriver instance this element was found - from. + """Get the WebDriver instance this element was found from. Example: - >>> element = driver.find_element(By.ID, "foo") - >>> parent_element = element.parent + element = driver.find_element(By.ID, "foo") + parent_element = element.parent """ return self._parent @property def id(self) -> str: - """Internal ID used by selenium. + """Get the ID used by selenium. This is mainly for internal use. Simple use cases such as checking if 2 webelements refer to the same element, can be done using ``==``:: Example: - >>> if element1 == element2: - ... print("These 2 are equal") + if element1 == element2: + print("These 2 are equal") """ return self._id @@ -530,7 +527,7 @@ def find_element(self, by=By.ID, value=None) -> WebElement: The first matching `WebElement` found on the page. Example: - >>> element = driver.find_element(By.ID, "foo") + element = driver.find_element(By.ID, "foo") """ by, value = self._parent.locator_converter.convert(by, value) return self._execute(Command.FIND_CHILD_ELEMENT, {"using": by, "value": value})["value"] @@ -555,7 +552,7 @@ def find_elements(self, by=By.ID, value=None) -> list[WebElement]: List of `WebElements` matching locator strategy found on the page. Example: - >>> element = driver.find_elements(By.ID, "foo") + element = driver.find_elements(By.ID, "foo") """ by, value = self._parent.locator_converter.convert(by, value) return self._execute(Command.FIND_CHILD_ELEMENTS, {"using": by, "value": value})["value"] diff --git a/py/selenium/webdriver/safari/service.py b/py/selenium/webdriver/safari/service.py index 3e8062616a780..46595cf8da318 100644 --- a/py/selenium/webdriver/safari/service.py +++ b/py/selenium/webdriver/safari/service.py @@ -22,8 +22,9 @@ class Service(service.Service): - """A Service class that is responsible for the starting and stopping of - `safaridriver` This is only supported on MAC OSX. + """Manage the safaridriver service lifecycle (start/stop). + + This service is only supported on macOS. Args: executable_path: install path of the safaridriver executable, defaults to `/usr/bin/safaridriver`. @@ -81,6 +82,7 @@ def reuse_service(self, reuse: bool) -> None: @property def service_args(self) -> Sequence[str]: + """Returns the sequence of service arguments.""" return self._service_args @service_args.setter diff --git a/py/selenium/webdriver/safari/webdriver.py b/py/selenium/webdriver/safari/webdriver.py index c0dae2a8c282a..ed16c6df90ccc 100644 --- a/py/selenium/webdriver/safari/webdriver.py +++ b/py/selenium/webdriver/safari/webdriver.py @@ -34,8 +34,7 @@ def __init__( options: Optional[Options] = None, service: Optional[Service] = None, ) -> None: - """Creates a new Safari driver instance and launches or finds a running - safaridriver service. + """Create a new Safari driver instance and launch or find a running safaridriver service. Args: keep_alive: Whether to configure SafariRemoteConnection to use diff --git a/py/selenium/webdriver/support/event_firing_webdriver.py b/py/selenium/webdriver/support/event_firing_webdriver.py index f98ab2cec9b50..44d903371569c 100644 --- a/py/selenium/webdriver/support/event_firing_webdriver.py +++ b/py/selenium/webdriver/support/event_firing_webdriver.py @@ -36,8 +36,10 @@ def _wrap_elements(result, ef_driver): class EventFiringWebDriver: - """A wrapper around an arbitrary WebDriver instance which supports firing - events. + """Wrap an arbitrary WebDriver instance and support firing events. + + This wrapper allows you to hook into various WebDriver events through an + AbstractEventListener implementation. """ def __init__(self, driver: WebDriver, event_listener: AbstractEventListener) -> None: @@ -75,10 +77,7 @@ def after_navigate_to(self, url, driver): @property def wrapped_driver(self) -> WebDriver: - """ - Returns: - The WebDriver instance wrapped by this EventsFiringWebDriver. - """ + """Returns the WebDriver instance wrapped by this EventsFiringWebDriver.""" return self._driver def get(self, url: str) -> None: @@ -173,10 +172,7 @@ def __init__(self, webelement: WebElement, ef_driver: EventFiringWebDriver) -> N @property def wrapped_element(self) -> WebElement: - """ - Returns: - The WebElement wrapped by this EventFiringWebElement instance. - """ + """Returns the WebElement wrapped by this EventFiringWebElement instance.""" return self._webelement def click(self) -> None: diff --git a/py/selenium/webdriver/support/expected_conditions.py b/py/selenium/webdriver/support/expected_conditions.py index 2dd80ba8b7d8e..0349d0cf84a02 100644 --- a/py/selenium/webdriver/support/expected_conditions.py +++ b/py/selenium/webdriver/support/expected_conditions.py @@ -57,8 +57,7 @@ def _predicate(driver: WebDriver): def title_contains(title: str) -> Callable[[WebDriver], bool]: - """An expectation for checking that the title contains a case-sensitive - substring. + """Check that the title contains a case-sensitive substring. Args: title: The fragment of title expected. @@ -74,8 +73,7 @@ def _predicate(driver: WebDriver): def presence_of_element_located(locator: tuple[str, str]) -> Callable[[WebDriverOrWebElement], WebElement]: - """An expectation for checking that an element is present on the DOM of a - page. This does not necessarily mean that the element is visible. + """Check that an element is present on the DOM (not necessarily visible). Args: locator: Used to find the element. @@ -84,10 +82,10 @@ def presence_of_element_located(locator: tuple[str, str]) -> Callable[[WebDriver The WebElement once it is located. Example: - >>> from selenium.webdriver.common.by import By - >>> from selenium.webdriver.support.ui import WebDriverWait - >>> from selenium.webdriver.support import expected_conditions as EC - >>> element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.NAME, "q"))) + from selenium.webdriver.common.by import By + from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support import expected_conditions as EC + element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.NAME, "q"))) """ def _predicate(driver: WebDriverOrWebElement): @@ -97,8 +95,7 @@ def _predicate(driver: WebDriverOrWebElement): def url_contains(url: str) -> Callable[[WebDriver], bool]: - """An expectation for checking that the current url contains a case- - sensitive substring. + """Check that the current url contains a case-sensitive substring. Args: url: The fragment of url expected. @@ -149,8 +146,7 @@ def _predicate(driver: WebDriver): def url_changes(url: str) -> Callable[[WebDriver], bool]: - """An expectation for checking the current url is different than a given - string. + """Check that the current url differs from a given string. Args: url: The expected url, which must not be an exact match. @@ -168,9 +164,7 @@ def _predicate(driver: WebDriver): def visibility_of_element_located( locator: tuple[str, str], ) -> Callable[[WebDriverOrWebElement], Union[Literal[False], WebElement]]: - """An expectation for checking that an element is present on the DOM of a - page and visible. Visibility means that the element is not only displayed - but also has a height and width that is greater than 0. + """Check that an element is visible (present in DOM and width/height greater than zero). Args: locator: Used to find the element. @@ -179,10 +173,10 @@ def visibility_of_element_located( The WebElement once it is located and visible. Example: - >>> from selenium.webdriver.common.by import By - >>> from selenium.webdriver.support.ui import WebDriverWait - >>> from selenium.webdriver.support import expected_conditions as EC - >>> element = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.NAME, "q"))) + from selenium.webdriver.common.by import By + from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support import expected_conditions as EC + element = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.NAME, "q"))) """ def _predicate(driver: WebDriverOrWebElement): @@ -195,11 +189,7 @@ def _predicate(driver: WebDriverOrWebElement): def visibility_of(element: WebElement) -> Callable[[Any], Union[Literal[False], WebElement]]: - """An expectation for checking that an element, known to be present on the - DOM of a page, is visible. - - Visibility means that the element is not only displayed but also has - a height and width that is greater than 0. + """Check that an element is visible (present in DOM and width/height greater than zero). Args: element: The WebElement to check. @@ -208,10 +198,10 @@ def visibility_of(element: WebElement) -> Callable[[Any], Union[Literal[False], The WebElement once it is visible. Example: - >>> from selenium.webdriver.common.by import By - >>> from selenium.webdriver.support.ui import WebDriverWait - >>> from selenium.webdriver.support import expected_conditions as EC - >>> element = WebDriverWait(driver, 10).until(EC.visibility_of(driver.find_element(By.NAME, "q"))) + from selenium.webdriver.common.by import By + from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support import expected_conditions as EC + element = WebDriverWait(driver, 10).until(EC.visibility_of(driver.find_element(By.NAME, "q"))) """ def _predicate(_): @@ -221,8 +211,7 @@ def _predicate(_): def _element_if_visible(element: WebElement, visibility: bool = True) -> Union[Literal[False], WebElement]: - """An expectation for checking that an element, known to be present on the - DOM of a page, is of the expected visibility. + """Check if an element has the expected visibility state. Args: element: The WebElement to check. @@ -235,8 +224,7 @@ def _element_if_visible(element: WebElement, visibility: bool = True) -> Union[L def presence_of_all_elements_located(locator: tuple[str, str]) -> Callable[[WebDriverOrWebElement], list[WebElement]]: - """An expectation for checking that there is at least one element present - on a web page. + """Check that all elements matching the locator are present on the DOM. Args: locator: Used to find the element. @@ -245,10 +233,10 @@ def presence_of_all_elements_located(locator: tuple[str, str]) -> Callable[[WebD The list of WebElements once they are located. Example: - >>> from selenium.webdriver.common.by import By - >>> from selenium.webdriver.support.ui import WebDriverWait - >>> from selenium.webdriver.support import expected_conditions as EC - >>> elements = WebDriverWait(driver, 10).until(EC.presence_of_all_elements_located((By.CLASS_NAME, "foo"))) + from selenium.webdriver.common.by import By + from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support import expected_conditions as EC + elements = WebDriverWait(driver, 10).until(EC.presence_of_all_elements_located((By.CLASS_NAME, "foo"))) """ def _predicate(driver: WebDriverOrWebElement): @@ -258,8 +246,7 @@ def _predicate(driver: WebDriverOrWebElement): def visibility_of_any_elements_located(locator: tuple[str, str]) -> Callable[[WebDriverOrWebElement], list[WebElement]]: - """An expectation for checking that there is at least one element visible - on a web page. + """Check that at least one element is visible on the web page (present in DOM and width/height greater than zero). Args: locator: Used to find the element. @@ -268,10 +255,10 @@ def visibility_of_any_elements_located(locator: tuple[str, str]) -> Callable[[We The list of WebElements once they are located and visible. Example: - >>> from selenium.webdriver.common.by import By - >>> from selenium.webdriver.support.ui import WebDriverWait - >>> from selenium.webdriver.support import expected_conditions as EC - >>> elements = WebDriverWait(driver, 10).until(EC.visibility_of_any_elements_located((By.CLASS_NAME, "foo"))) + from selenium.webdriver.common.by import By + from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support import expected_conditions as EC + elements = WebDriverWait(driver, 10).until(EC.visibility_of_any_elements_located((By.CLASS_NAME, "foo"))) """ def _predicate(driver: WebDriverOrWebElement): @@ -283,9 +270,7 @@ def _predicate(driver: WebDriverOrWebElement): def visibility_of_all_elements_located( locator: tuple[str, str], ) -> Callable[[WebDriverOrWebElement], Union[list[WebElement], Literal[False]]]: - """An expectation for checking that all elements are present on the DOM of - a page and visible. Visibility means that the elements are not only - displayed but also has a height and width that is greater than 0. + """Check that all elements are visible (present in DOM and width/height greater than zero). Args: locator: Used to find the elements. @@ -294,10 +279,10 @@ def visibility_of_all_elements_located( The list of WebElements once they are located and visible. Example: - >>> from selenium.webdriver.common.by import By - >>> from selenium.webdriver.support.ui import WebDriverWait - >>> from selenium.webdriver.support import expected_conditions as EC - >>> elements = WebDriverWait(driver, 10).until(EC.visibility_of_all_elements_located((By.CLASS_NAME, "foo"))) + from selenium.webdriver.common.by import By + from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support import expected_conditions as EC + elements = WebDriverWait(driver, 10).until(EC.visibility_of_all_elements_located((By.CLASS_NAME, "foo"))) """ def _predicate(driver: WebDriverOrWebElement): @@ -314,8 +299,7 @@ def _predicate(driver: WebDriverOrWebElement): def text_to_be_present_in_element(locator: tuple[str, str], text_: str) -> Callable[[WebDriverOrWebElement], bool]: - """An expectation for checking if the given text is present in the - specified element. + """Check that the given text is present in the specified element. Args: locator: Used to find the element. @@ -325,12 +309,12 @@ def text_to_be_present_in_element(locator: tuple[str, str], text_: str) -> Calla True when the text is present, False otherwise. Example: - >>> from selenium.webdriver.common.by import By - >>> from selenium.webdriver.support.ui import WebDriverWait - >>> from selenium.webdriver.support import expected_conditions as EC - >>> is_text_in_element = WebDriverWait(driver, 10).until( - EC.text_to_be_present_in_element((By.CLASS_NAME, "foo"), "bar") - ) + from selenium.webdriver.common.by import By + from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support import expected_conditions as EC + is_text_in_element = WebDriverWait(driver, 10).until( + EC.text_to_be_present_in_element((By.CLASS_NAME, "foo"), "bar") + ) """ def _predicate(driver: WebDriverOrWebElement): @@ -346,8 +330,7 @@ def _predicate(driver: WebDriverOrWebElement): def text_to_be_present_in_element_value( locator: tuple[str, str], text_: str ) -> Callable[[WebDriverOrWebElement], bool]: - """An expectation for checking if the given text is present in the - element's value. + """Check that the given text is present in the element's value. Args: locator: Used to find the element. @@ -357,12 +340,12 @@ def text_to_be_present_in_element_value( True when the text is present, False otherwise. Example: - >>> from selenium.webdriver.common.by import By - >>> from selenium.webdriver.support.ui import WebDriverWait - >>> from selenium.webdriver.support import expected_conditions as EC - >>> is_text_in_element_value = WebDriverWait(driver, 10).until( - ... EC.text_to_be_present_in_element_value((By.CLASS_NAME, "foo"), "bar") - ... ) + from selenium.webdriver.common.by import By + from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support import expected_conditions as EC + is_text_in_element_value = WebDriverWait(driver, 10).until( + EC.text_to_be_present_in_element_value((By.CLASS_NAME, "foo"), "bar") + ) """ def _predicate(driver: WebDriverOrWebElement): @@ -380,8 +363,7 @@ def _predicate(driver: WebDriverOrWebElement): def text_to_be_present_in_element_attribute( locator: tuple[str, str], attribute_: str, text_: str ) -> Callable[[WebDriverOrWebElement], bool]: - """An expectation for checking if the given text is present in the - element's attribute. + """Check that the given text is present in the element's attribute. Args: locator: Used to find the element. @@ -392,12 +374,12 @@ def text_to_be_present_in_element_attribute( True when the text is present, False otherwise. Example: - >>> from selenium.webdriver.common.by import By - >>> from selenium.webdriver.support.ui import WebDriverWait - >>> from selenium.webdriver.support import expected_conditions as EC - >>> is_text_in_element_attribute = WebDriverWait(driver, 10).until( - ... EC.text_to_be_present_in_element_attribute((By.CLASS_NAME, "foo"), "bar", "baz") - ... ) + from selenium.webdriver.common.by import By + from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support import expected_conditions as EC + is_text_in_element_attribute = WebDriverWait(driver, 10).until( + EC.text_to_be_present_in_element_attribute((By.CLASS_NAME, "foo"), "bar", "baz") + ) """ def _predicate(driver: WebDriverOrWebElement): @@ -415,11 +397,7 @@ def _predicate(driver: WebDriverOrWebElement): def frame_to_be_available_and_switch_to_it( locator: Union[tuple[str, str], str, WebElement], ) -> Callable[[WebDriver], bool]: - """An expectation for checking whether the given frame is available to - switch to. - - If the frame is available it switches the given driver to the - specified frame. + """Check that the given frame is available and switch to it. Args: locator: Used to find the frame. @@ -428,9 +406,9 @@ def frame_to_be_available_and_switch_to_it( True when the frame is available, False otherwise. Example: - >>> from selenium.webdriver.support.ui import WebDriverWait - >>> from selenium.webdriver.support import expected_conditions as EC - >>> WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it("frame_name")) + from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support import expected_conditions as EC + WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it("frame_name")) """ def _predicate(driver: WebDriver): @@ -449,8 +427,7 @@ def _predicate(driver: WebDriver): def invisibility_of_element_located( locator: Union[WebElement, tuple[str, str]], ) -> Callable[[WebDriverOrWebElement], Union[WebElement, bool]]: - """An Expectation for checking that an element is either invisible or not - present on the DOM. + """Check that an element is either invisible or not present on the DOM. Args: locator: Used to find the element. @@ -459,10 +436,10 @@ def invisibility_of_element_located( True when the element is invisible or not present, False otherwise. Example: - >>> from selenium.webdriver.common.by import By - >>> from selenium.webdriver.support.ui import WebDriverWait - >>> from selenium.webdriver.support import expected_conditions as EC - >>> is_invisible = WebDriverWait(driver, 10).until(EC.invisibility_of_element_located((By.CLASS_NAME, "foo"))) + from selenium.webdriver.common.by import By + from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support import expected_conditions as EC + is_invisible = WebDriverWait(driver, 10).until(EC.invisibility_of_element_located((By.CLASS_NAME, "foo"))) Note: In the case of NoSuchElement, returns true because the element is not @@ -492,8 +469,7 @@ def _predicate(driver: WebDriverOrWebElement): def invisibility_of_element( element: Union[WebElement, tuple[str, str]], ) -> Callable[[WebDriverOrWebElement], Union[WebElement, bool]]: - """An Expectation for checking that an element is either invisible or not - present on the DOM. + """Check that an element is either invisible or not present on the DOM. Args: element: Used to find the element. @@ -502,12 +478,12 @@ def invisibility_of_element( True when the element is invisible or not present, False otherwise. Example: - >>> from selenium.webdriver.common.by import By - >>> from selenium.webdriver.support.ui import WebDriverWait - >>> from selenium.webdriver.support import expected_conditions as EC - >>> is_invisible_or_not_present = WebDriverWait(driver, 10).until( - ... EC.invisibility_of_element(driver.find_element(By.CLASS_NAME, "foo")) - ... ) + from selenium.webdriver.common.by import By + from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support import expected_conditions as EC + is_invisible_or_not_present = WebDriverWait(driver, 10).until( + EC.invisibility_of_element(driver.find_element(By.CLASS_NAME, "foo")) + ) """ return invisibility_of_element_located(element) @@ -515,8 +491,7 @@ def invisibility_of_element( def element_to_be_clickable( mark: Union[WebElement, tuple[str, str]], ) -> Callable[[WebDriverOrWebElement], Union[Literal[False], WebElement]]: - """An Expectation for checking an element is visible and enabled such that - you can click it. + """Check that an element is visible and enabled so it can be clicked. Args: mark: Used to find the element. @@ -525,10 +500,10 @@ def element_to_be_clickable( The WebElement once it is located and clickable. Example: - >>> from selenium.webdriver.common.by import By - >>> from selenium.webdriver.support.ui import WebDriverWait - >>> from selenium.webdriver.support import expected_conditions as EC - >>> element = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CLASS_NAME, "foo"))) + from selenium.webdriver.common.by import By + from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support import expected_conditions as EC + element = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CLASS_NAME, "foo"))) """ # renamed argument to 'mark', to indicate that both locator @@ -555,10 +530,10 @@ def staleness_of(element: WebElement) -> Callable[[Any], bool]: False if the element is still attached to the DOM, true otherwise. Example: - >>> from selenium.webdriver.common.by import By - >>> from selenium.webdriver.support.ui import WebDriverWait - >>> from selenium.webdriver.support import expected_conditions as EC - >>> is_stale = WebDriverWait(driver, 10).until(EC.staleness_of(driver.find_element(By.CLASS_NAME, "foo"))) + from selenium.webdriver.common.by import By + from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support import expected_conditions as EC + is_stale = WebDriverWait(driver, 10).until(EC.staleness_of(driver.find_element(By.CLASS_NAME, "foo"))) """ def _predicate(_): @@ -582,12 +557,12 @@ def element_to_be_selected(element: WebElement) -> Callable[[Any], bool]: True if the element is selected, False otherwise. Example: - >>> from selenium.webdriver.common.by import By - >>> from selenium.webdriver.support.ui import WebDriverWait - >>> from selenium.webdriver.support import expected_conditions as EC - >>> is_selected = WebDriverWait(driver, 10).until(EC.element_to_be_selected(driver.find_element( - By.CLASS_NAME, "foo")) - ) + from selenium.webdriver.common.by import By + from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support import expected_conditions as EC + is_selected = WebDriverWait(driver, 10).until(EC.element_to_be_selected(driver.find_element( + By.CLASS_NAME, "foo")) + ) """ def _predicate(_): @@ -606,10 +581,10 @@ def element_located_to_be_selected(locator: tuple[str, str]) -> Callable[[WebDri True if the element is selected, False otherwise. Example: - >>> from selenium.webdriver.common.by import By - >>> from selenium.webdriver.support.ui import WebDriverWait - >>> from selenium.webdriver.support import expected_conditions as EC - >>> is_selected = WebDriverWait(driver, 10).until(EC.element_located_to_be_selected((By.CLASS_NAME, "foo"))) + from selenium.webdriver.common.by import By + from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support import expected_conditions as EC + is_selected = WebDriverWait(driver, 10).until(EC.element_located_to_be_selected((By.CLASS_NAME, "foo"))) """ def _predicate(driver: WebDriverOrWebElement): @@ -629,12 +604,12 @@ def element_selection_state_to_be(element: WebElement, is_selected: bool) -> Cal True if the element's selection state is the same as is_selected. Example: - >>> from selenium.webdriver.common.by import By - >>> from selenium.webdriver.support.ui import WebDriverWait - >>> from selenium.webdriver.support import expected_conditions as EC - >>> is_selected = WebDriverWait(driver, 10).until( - ... EC.element_selection_state_to_be(driver.find_element(By.CLASS_NAME, "foo"), True) - ... ) + from selenium.webdriver.common.by import By + from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support import expected_conditions as EC + is_selected = WebDriverWait(driver, 10).until( + EC.element_selection_state_to_be(driver.find_element(By.CLASS_NAME, "foo"), True) + ) """ def _predicate(_): @@ -646,8 +621,7 @@ def _predicate(_): def element_located_selection_state_to_be( locator: tuple[str, str], is_selected: bool ) -> Callable[[WebDriverOrWebElement], bool]: - """An expectation to locate an element and check if the selection state - specified is in that state. + """Check that an element's selection state matches the expected state. Args: locator: Used to find the element. @@ -657,12 +631,12 @@ def element_located_selection_state_to_be( True if the element's selection state is the same as is_selected. Example: - >>> from selenium.webdriver.common.by import By - >>> from selenium.webdriver.support.ui import WebDriverWait - >>> from selenium.webdriver.support import expected_conditions as EC - >>> is_selected = WebDriverWait(driver, 10).until(EC.element_located_selection_state_to_be( - (By.CLASS_NAME, "foo"), True) - ) + from selenium.webdriver.common.by import By + from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support import expected_conditions as EC + is_selected = WebDriverWait(driver, 10).until(EC.element_located_selection_state_to_be( + (By.CLASS_NAME, "foo"), True) + ) """ def _predicate(driver: WebDriverOrWebElement): @@ -685,9 +659,9 @@ def number_of_windows_to_be(num_windows: int) -> Callable[[WebDriver], bool]: True when the number of windows matches, False otherwise. Example: - >>> from selenium.webdriver.support.ui import WebDriverWait - >>> from selenium.webdriver.support import expected_conditions as EC - >>> is_number_of_windows = WebDriverWait(driver, 10).until(EC.number_of_windows_to_be(2)) + from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support import expected_conditions as EC + is_number_of_windows = WebDriverWait(driver, 10).until(EC.number_of_windows_to_be(2)) """ def _predicate(driver: WebDriver): @@ -696,9 +670,8 @@ def _predicate(driver: WebDriver): return _predicate -def new_window_is_opened(current_handles: list[str]) -> Callable[[WebDriver], bool]: - """An expectation that a new window will be opened and have the number of - windows handles increase. +def new_window_is_opened(current_handles: set[str]) -> Callable[[WebDriver], bool]: + """Check that a new window has been opened (window handles count increased). Args: current_handles: The current window handles. @@ -707,10 +680,10 @@ def new_window_is_opened(current_handles: list[str]) -> Callable[[WebDriver], bo True when a new window is opened, False otherwise. Example: - >>> from selenium.webdriver.support.ui import By - >>> from selenium.webdriver.support.ui import WebDriverWait - >>> from selenium.webdriver.support import expected_conditions as EC - >>> is_new_window_opened = WebDriverWait(driver, 10).until(EC.new_window_is_opened(driver.window_handles)) + from selenium.webdriver.support.ui import By + from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support import expected_conditions as EC + is_new_window_opened = WebDriverWait(driver, 10).until(EC.new_window_is_opened(driver.window_handles)) """ def _predicate(driver: WebDriver): @@ -719,17 +692,16 @@ def _predicate(driver: WebDriver): return _predicate -def alert_is_present() -> Callable[[WebDriver], Union[Alert, Literal[False]]]: - """An expectation for checking if an alert is currently present and - switching to it. +def alert_is_present() -> Callable[[WebDriver], Union[Alert, bool]]: + """Check that an alert is present and switch to it. Returns: The Alert once it is located. Example: - >>> from selenium.webdriver.support.ui import WebDriverWait - >>> from selenium.webdriver.support import expected_conditions as EC - >>> alert = WebDriverWait(driver, 10).until(EC.alert_is_present()) + from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support import expected_conditions as EC + alert = WebDriverWait(driver, 10).until(EC.alert_is_present()) Note: If the alert is present it switches the given driver to it. @@ -745,8 +717,7 @@ def _predicate(driver: WebDriver): def element_attribute_to_include(locator: tuple[str, str], attribute_: str) -> Callable[[WebDriverOrWebElement], bool]: - """An expectation for checking if the given attribute is included in the - specified element. + """Check if the given attribute is included in the specified element. Args: locator: Used to find the element. @@ -756,12 +727,12 @@ def element_attribute_to_include(locator: tuple[str, str], attribute_: str) -> C True when the attribute is included, False otherwise. Example: - >>> from selenium.webdriver.common.by import By - >>> from selenium.webdriver.support.ui import WebDriverWait - >>> from selenium.webdriver.support import expected_conditions as EC - >>> is_attribute_in_element = WebDriverWait(driver, 10).until( - ... EC.element_attribute_to_include((By.CLASS_NAME, "foo"), "bar") - ... ) + from selenium.webdriver.common.by import By + from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support import expected_conditions as EC + is_attribute_in_element = WebDriverWait(driver, 10).until( + EC.element_attribute_to_include((By.CLASS_NAME, "foo"), "bar") + ) """ def _predicate(driver: WebDriverOrWebElement): @@ -787,12 +758,13 @@ def any_of(*expected_conditions: Callable[[D], T]) -> Callable[[D], Union[Litera The result of the first matching condition, or False if none do. Example: - >>> from selenium.webdriver.common.by import By - >>> from selenium.webdriver.support.ui import WebDriverWait - >>> from selenium.webdriver.support import expected_conditions as EC - >>> element = WebDriverWait(driver, 10).until( - ... EC.any_of(EC.presence_of_element_located((By.NAME, "q"), - ... EC.visibility_of_element_located((By.NAME, "q")))) + from selenium.webdriver.common.by import By + from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support import expected_conditions as EC + element = WebDriverWait(driver, 10).until( + EC.any_of(EC.presence_of_element_located((By.NAME, "q"), + EC.visibility_of_element_located((By.NAME, "q"))) + ) """ def any_of_condition(driver: D): @@ -824,12 +796,13 @@ def all_of( The results of all the matching conditions, or False if any do not. Example: - >>> from selenium.webdriver.common.by import By - >>> from selenium.webdriver.support.ui import WebDriverWait - >>> from selenium.webdriver.support import expected_conditions as EC - >>> elements = WebDriverWait(driver, 10).until( - ... EC.all_of(EC.presence_of_element_located((By.NAME, "q"), - ... EC.visibility_of_element_located((By.NAME, "q")))) + from selenium.webdriver.common.by import By + from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support import expected_conditions as EC + elements = WebDriverWait(driver, 10).until( + EC.all_of(EC.presence_of_element_located((By.NAME, "q"), + EC.visibility_of_element_located((By.NAME, "q"))) + ) """ def all_of_condition(driver: D): @@ -859,12 +832,13 @@ def none_of(*expected_conditions: Callable[[D], Any]) -> Callable[[D], bool]: True if none of the conditions are true, False otherwise. Example: - >>> from selenium.webdriver.common.by import By - >>> from selenium.webdriver.support.ui import WebDriverWait - >>> from selenium.webdriver.support import expected_conditions as EC - >>> element = WebDriverWait(driver, 10).until( - ... EC.none_of(EC.presence_of_element_located((By.NAME, "q"), - ... EC.visibility_of_element_located((By.NAME, "q")))) + from selenium.webdriver.common.by import By + from selenium.webdriver.support.ui import WebDriverWait + from selenium.webdriver.support import expected_conditions as EC + element = WebDriverWait(driver, 10).until( + EC.none_of(EC.presence_of_element_located((By.NAME, "q"), + EC.visibility_of_element_located((By.NAME, "q"))) + ) """ def none_of_condition(driver: D): diff --git a/py/selenium/webdriver/support/relative_locator.py b/py/selenium/webdriver/support/relative_locator.py index 7f6e6717e9f6e..3863cb3010ae9 100644 --- a/py/selenium/webdriver/support/relative_locator.py +++ b/py/selenium/webdriver/support/relative_locator.py @@ -64,9 +64,9 @@ def locate_with(by: ByType, using: str) -> "RelativeBy": class RelativeBy: - """Gives the opportunity to find elements based on their relative location - on the page from a root element. It is recommended that you use the helper - function to create it. + """Find elements based on their relative location from a root element. + + It is recommended that you use the helper function to create instances. Example: -------- @@ -80,8 +80,7 @@ class RelativeBy: LocatorType = dict[ByType, str] def __init__(self, root: Optional[dict[ByType, str]] = None, filters: Optional[list] = None): - """Creates a new RelativeBy object. It is preferred if you use the - `locate_with` method as this signature could change. + """Create a RelativeBy object (prefer using `locate_with` instead). Args: root: A dict with `By` enum as the key and the search query as the value @@ -309,9 +308,7 @@ def near(self, element_or_locator: Union[WebElement, LocatorType, None] = None, return self def to_dict(self) -> dict: - """Create a dict that will be passed to the driver to start searching - for the element. - """ + """Create a dict to be passed to the driver for element searching.""" return { "relative": { "root": self.root, diff --git a/py/selenium/webdriver/support/select.py b/py/selenium/webdriver/support/select.py index dde724b954350..52f905ce91a46 100644 --- a/py/selenium/webdriver/support/select.py +++ b/py/selenium/webdriver/support/select.py @@ -23,8 +23,7 @@ class Select: def __init__(self, webelement: WebElement) -> None: - """Constructor. A check is made that the given element is, indeed, a - SELECT tag. If it is not, then an UnexpectedTagNameException is thrown. + """Constructor. A check is made that the given element is a SELECT tag. Args: webelement: SELECT element to wrap @@ -32,6 +31,9 @@ def __init__(self, webelement: WebElement) -> None: Example: from selenium.webdriver.support.ui import Select Select(driver.find_element(By.TAG_NAME, "select")).select_by_index(2) + + Raises: + UnexpectedTagNameException: If the element is not a SELECT tag """ if webelement.tag_name.lower() != "select": raise UnexpectedTagNameException(f"Select only works on