Skip to content

Commit

Permalink
Add w3c capabilities to Python options (#9870)
Browse files Browse the repository at this point in the history
* [py] move page load strategy methods into Base Options

* [py] move proxy and insecure certs capabilities to Base Options

* [py] implement remaining w3c compliant capabilities to Base Options class

Co-authored-by: David Burns <[email protected]>
  • Loading branch information
titusfortner and AutomatedTester authored Sep 27, 2021
1 parent 184ac78 commit 2835393
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 86 deletions.
11 changes: 0 additions & 11 deletions py/selenium/webdriver/chromium/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,17 +151,6 @@ def headless(self, value: bool):
else:
self._arguments = list(set(self._arguments) - args)

@property
def page_load_strategy(self) -> str:
return self._caps["pageLoadStrategy"]

@page_load_strategy.setter
def page_load_strategy(self, strategy: str):
if strategy in ["normal", "eager", "none"]:
self.set_capability("pageLoadStrategy", strategy)
else:
raise ValueError("Strategy can only be one of the following: normal, eager, none")

def to_capabilities(self) -> dict:
"""
Creates a capabilities with all the options that have been set
Expand Down
160 changes: 160 additions & 0 deletions py/selenium/webdriver/common/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
# under the License.

from abc import ABCMeta, abstractmethod
from typing import NoReturn
from selenium.webdriver.common.proxy import Proxy
from selenium.common.exceptions import InvalidArgumentException


class BaseOptions(metaclass=ABCMeta):
Expand All @@ -37,6 +40,100 @@ def set_capability(self, name, value):
""" Sets a capability """
self._caps[name] = value

@property
def browser_version(self) -> str:
"""
:returns: the version of the browser if set, otherwise None.
"""
return self._caps["browserVersion"]

@browser_version.setter
def browser_version(self, version: str) -> NoReturn:
"""
Requires the major version of the browser to match provided value:
https://w3c.github.io/webdriver/#dfn-browser-version
:param version: The required version of the browser
"""
self.set_capability("browserVersion", version)

@property
def platform_name(self) -> str:
"""
:returns: The name of the platform
"""
return self._caps["platformName"]

@platform_name.setter
def platform_name(self, platform: str) -> NoReturn:
"""
Requires the platform to match the provided value: https://w3c.github.io/webdriver/#dfn-platform-name
:param platform: the required name of the platform
"""
self.set_capability("platformName", platform)

@property
def page_load_strategy(self) -> str:
"""
:returns: page load strategy if set, the default is "normal"
"""
return self._caps["pageLoadStrategy"]

@page_load_strategy.setter
def page_load_strategy(self, strategy: str) -> NoReturn:
"""
Determines the point at which a navigation command is returned:
https://w3c.github.io/webdriver/#dfn-table-of-page-load-strategies
:param strategy: the strategy corresponding to a document readiness state
"""
if strategy in ["normal", "eager", "none"]:
self.set_capability("pageLoadStrategy", strategy)
else:
raise ValueError("Strategy can only be one of the following: normal, eager, none")

@property
def unhandled_prompt_behavior(self) -> str:
"""
:returns: unhandled prompt behavior if set, the default is "dismiss and notify"
"""
return self._caps["unhandledPromptBehavior"]

@unhandled_prompt_behavior.setter
def unhandled_prompt_behavior(self, behavior: str) -> NoReturn:
"""
How the driver should respond when an alert is present and the command sent is not handling the alert:
https://w3c.github.io/webdriver/#dfn-table-of-page-load-strategies
:param behavior: behavior to use when an alert is encountered
"""
if behavior in ["dismiss", "accept", "dismiss and notify", "accept and notify", "ignore"]:
self.set_capability("unhandledPromptBehavior", behavior)
else:
raise ValueError("Behavior can only be one of the following: dismiss, accept, dismiss and notify, "
"accept and notify, ignore")

@property
def timeouts(self) -> dict:
"""
:returns: Values for implicit timeout, pageLoad timeout and script timeout if set (in milliseconds)
"""
return self._caps["timeouts"]

@timeouts.setter
def timeouts(self, timeouts: dict) -> NoReturn:
"""
How long the driver should wait for actions to complete before returning an error
https://w3c.github.io/webdriver/#timeouts
:param timeouts: values in milliseconds for implicit wait, page load and script timeout
"""
if all(x in timeouts.keys() for x in ["implicit", "pageLoad", "script"]):
self.set_capability("timeouts", timeouts)
else:
raise ValueError("Timeout keys can only be one of the following: implicit, pageLoad, script")

def enable_mobile(self, android_package: str = None, android_activity: str = None, device_serial: str = None):
"""
Enables mobile browser use for browsers that support it
Expand All @@ -54,6 +151,69 @@ def enable_mobile(self, android_package: str = None, android_activity: str = Non
if device_serial:
self.mobile_options["androidDeviceSerial"] = device_serial

@property
def accept_insecure_certs(self) -> bool:
"""
:returns: whether the session accepts insecure certificates
"""
return self._caps.get('acceptInsecureCerts')

@accept_insecure_certs.setter
def accept_insecure_certs(self, value: bool) -> NoReturn:
"""
Whether untrusted and self-signed TLS certificates are implicitly trusted:
https://w3c.github.io/webdriver/#dfn-insecure-tls-certificates
:param value: whether to accept insecure certificates
"""
self._caps['acceptInsecureCerts'] = value

@property
def strict_file_interactability(self) -> bool:
"""
:returns: whether session is strict about file interactability
"""
return self._caps.get('strictFileInteractability')

@strict_file_interactability.setter
def strict_file_interactability(self, value: bool):
"""
Whether interactability checks will be applied to file type input elements. The default is false.
:param value: whether file interactability is strict
"""
self._caps['strictFileInteractability'] = value

@property
def set_window_rect(self) -> bool:
"""
:returns: whether the remote end supports setting window size and position
"""
return self._caps.get('setWindowRect')

@set_window_rect.setter
def set_window_rect(self, value: bool):
"""
Whether the remote end supports all of the resizing and positioning commands. The default is false.
https://w3c.github.io/webdriver/#dfn-strict-file-interactability
:param value: whether remote end must support setting window resizing and repositioning
"""
self._caps['setWindowRect'] = value

@property
def proxy(self) -> Proxy:
"""
:Returns: Proxy if set, otherwise None.
"""
return self._proxy

@proxy.setter
def proxy(self, value: Proxy):
if not isinstance(value, Proxy):
raise InvalidArgumentException("Only Proxy objects can be passed in.")
self._proxy = value

@abstractmethod
def to_capabilities(self):
"""Convert options into capabilities dictionary."""
Expand Down
34 changes: 0 additions & 34 deletions py/selenium/webdriver/firefox/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@
# under the License.
from typing import Union
import warnings
from selenium.common.exceptions import InvalidArgumentException
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.common.proxy import Proxy
from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
from selenium.webdriver.firefox.firefox_profile import FirefoxProfile
from selenium.webdriver.common.options import ArgOptions
Expand Down Expand Up @@ -72,14 +70,6 @@ def binary_location(self, value: str):
""" Sets the location of the browser binary by string """
self.binary = value

@property
def accept_insecure_certs(self) -> bool:
return self._caps.get('acceptInsecureCerts')

@accept_insecure_certs.setter
def accept_insecure_certs(self, value: bool):
self._caps['acceptInsecureCerts'] = value

@property
def preferences(self) -> dict:
""":Returns: A dict of preferences."""
Expand All @@ -89,19 +79,6 @@ def set_preference(self, name: str, value: Union[str, int, bool]):
"""Sets a preference."""
self._preferences[name] = value

@property
def proxy(self) -> Proxy:
"""
:Returns: Proxy if set, otherwise None.
"""
return self._proxy

@proxy.setter
def proxy(self, value: Proxy):
if not isinstance(value, Proxy):
raise InvalidArgumentException("Only Proxy objects can be passed in.")
self._proxy = value

@property
def profile(self) -> FirefoxProfile:
"""
Expand Down Expand Up @@ -150,17 +127,6 @@ def headless(self, value: bool):
elif '-headless' in self._arguments:
self._arguments.remove('-headless')

@property
def page_load_strategy(self) -> str:
return self._caps["pageLoadStrategy"]

@page_load_strategy.setter
def page_load_strategy(self, strategy: str):
if strategy in ["normal", "eager", "none"]:
self.set_capability("pageLoadStrategy", strategy)
else:
raise ValueError("Strategy can only be one of the following: normal, eager, none")

def enable_mobile(self, android_package: str = "org.mozilla.firefox", android_activity=None, device_serial=None):
super().enable_mobile(android_package, android_activity, device_serial)

Expand Down
11 changes: 0 additions & 11 deletions py/selenium/webdriver/opera/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,17 +79,6 @@ def android_command_line_file(self, value):
"""
self._android_command_line_file = value

@property
def page_load_strategy(self):
return self._caps["pageLoadStrategy"]

@page_load_strategy.setter
def page_load_strategy(self, strategy):
if strategy in ["normal", "eager", "none"]:
self.set_capability("pageLoadStrategy", strategy)
else:
raise ValueError("Strategy can only be one of the following: normal, eager, none")

def to_capabilities(self):
"""
Creates a capabilities with all the options that have been set and
Expand Down
19 changes: 0 additions & 19 deletions py/selenium/webdriver/safari/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,25 +54,6 @@ def binary_location(self, value: str):
"""
self._binary_location = value

@property
def accept_insecure_certs(self) -> bool:
return self._caps.get('acceptInsecureCerts')

@accept_insecure_certs.setter
def accept_insecure_certs(self, value: bool):
self._caps['acceptInsecureCerts'] = value

@property
def page_load_strategy(self) -> str:
return self._caps["pageLoadStrategy"]

@page_load_strategy.setter
def page_load_strategy(self, strategy: str):
if strategy in ["normal", "eager", "none"]:
self.set_capability("pageLoadStrategy", strategy)
else:
raise ValueError("Strategy can only be one of the following: normal, eager, none")

def to_capabilities(self) -> dict:
"""Marshals the options to an desired capabilities object.
"""
Expand Down
11 changes: 0 additions & 11 deletions py/selenium/webdriver/webkitgtk/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,6 @@ def overlay_scrollbars_enabled(self, value):
"""
self._overlay_scrollbars_enabled = value

@property
def page_load_strategy(self):
return self._caps["pageLoadStrategy"]

@page_load_strategy.setter
def page_load_strategy(self, strategy):
if strategy in ["normal", "eager", "none"]:
self.set_capability("pageLoadStrategy", strategy)
else:
raise ValueError("Strategy can only be one of the following: normal, eager, none")

def to_capabilities(self):
"""
Creates a capabilities with all the options that have been set and
Expand Down

0 comments on commit 2835393

Please sign in to comment.