Introduction<
SeleniumLibrary is a web testing library for Robot Framework that
utilizes the Selenium tool internally. The project is hosted on GitHub
and downloads can be found from PyPI.
-SeleniumLibrary currently works with Selenium 4. It supports Python 3.8 through 3.13.
+
SeleniumLibrary currently works with Selenium 4. It supports Python 3.10 through 3.13.
In addition to the normal Python interpreter, it works also
with PyPy.
SeleniumLibrary is based on the "old SeleniumLibrary" that was forked to
diff --git a/pyproject.toml b/pyproject.toml
index dd1b9775e..6a8f881ef 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,20 +1,51 @@
-[tool.black]
-target-version = ['py36']
-exclude = '''
-/(
- | \.git
- | \.venv
- | _build
- | dist
- | generated
- | src/SeleniumLibrary/__init__\.pyi
-)/
-'''
+[tool.ruff]
+target-version = "py310"
+line-length = 88
+exclude = [
+ "src/SeleniumLibrary/__init__.pyi",
+]
+
+[tool.ruff.lint]
+select = [
+ "E",
+ "F",
+ "W",
+ "C90",
+ "I",
+ "N",
+ "B",
+ "PYI",
+ "PL",
+ "UP",
+ "A",
+ "C4",
+ "DTZ",
+ "ISC",
+ "ICN",
+ "INP",
+ "PIE",
+ "T20",
+ "PYI",
+ "PT",
+ "RSE",
+ "RET",
+ "SIM",
+ "RUF"
+]
+ignore = [
+ "E501", # line too long
+ "N803", # argument name should be lowercase
+ "N812", # lowercase imported as non lowercase
+ "N999", # Invalid module name: 'SeleniumLibrary'
+ "PLR0913", # too many arguments
+ "PLR2004", # Magic value used in comparison
+ "DTZ006", # No timezone specified
+ "PTH", # Use Path instead of os.path -> maybe soon
+ "N818", # exception naming convention
+]
-[tool.isort]
-profile = "black"
-src_paths="."
-skip_glob = ["src/SeleniumLibrary/__init__.pyi"]
+[tool.ruff.format]
+quote-style = "double"
[tool.pytest.ini_options]
diff --git a/requirements-dev.txt b/requirements-dev.txt
index 90b82779d..71bc8bb10 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -15,8 +15,7 @@ pytest-mockito == 0.0.4
pytest-approvaltests == 0.2.4
requests == 2.33.1
robotframework-pabot == 5.2.2
-black == 26.3.1
-flake8 == 6.1.0
+ruff == 0.15.12
# Requirements needed when generating releases. See BUILD.rst for details.
rellu == 0.7
diff --git a/setup.py b/setup.py
index f24a0b8a9..9652afb5d 100755
--- a/setup.py
+++ b/setup.py
@@ -42,7 +42,7 @@
keywords = 'robotframework testing testautomation selenium webdriver web',
platforms = 'any',
classifiers = CLASSIFIERS,
- python_requires = '>=3.8',
+ python_requires = '>=3.10',
install_requires = REQUIREMENTS,
package_dir = {'': 'src'},
packages = find_packages('src'),
diff --git a/src/SeleniumLibrary/__init__.py b/src/SeleniumLibrary/__init__.py
index f371f3b1d..bdddc45e7 100644
--- a/src/SeleniumLibrary/__init__.py
+++ b/src/SeleniumLibrary/__init__.py
@@ -13,19 +13,17 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-from collections import namedtuple
-from datetime import timedelta
import importlib
+import pkgutil
+from datetime import timedelta
from inspect import getdoc, isclass
from pathlib import Path
-import pkgutil
-from typing import Optional, List, Union
+from typing import NamedTuple
from robot.api import logger
from robot.errors import DataError
from robot.libraries.BuiltIn import BuiltIn
from robot.utils.importer import Importer
-
from robotlibcore import DynamicCore
from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.remote.webelement import WebElement
@@ -49,10 +47,14 @@
WebDriverCache,
WindowKeywords,
)
-from SeleniumLibrary.keywords.screenshot import EMBED, BASE64
+from SeleniumLibrary.keywords.screenshot import BASE64, EMBED
from SeleniumLibrary.locators import ElementFinder
-from SeleniumLibrary.utils import LibraryListener, is_truthy, _convert_timeout, _convert_delay
-
+from SeleniumLibrary.utils import (
+ LibraryListener,
+ _convert_delay,
+ _convert_timeout,
+ is_truthy,
+)
__version__ = "6.8.0"
@@ -597,12 +599,12 @@ def __init__(
timeout=timedelta(seconds=5),
implicit_wait=timedelta(seconds=0),
run_on_failure="Capture Page Screenshot",
- screenshot_root_directory: Optional[str] = None,
- plugins: Optional[str] = None,
- event_firing_webdriver: Optional[str] = None,
+ screenshot_root_directory: str | None = None,
+ plugins: str | None = None,
+ event_firing_webdriver: str | None = None,
page_load_timeout=timedelta(minutes=5),
action_chain_delay=timedelta(seconds=0.25),
- language: Optional[str] = None,
+ language: str | None = None,
):
"""SeleniumLibrary can be imported with several optional arguments.
@@ -689,10 +691,13 @@ def get_keyword_documentation(self, name: str) -> str:
return self._get_intro_documentation()
return DynamicCore.get_keyword_documentation(self, name)
+ class Doc(NamedTuple):
+ doc: str
+ name: str
+
def _parse_plugin_doc(self):
- Doc = namedtuple("Doc", "doc, name")
for plugin in self._plugins:
- yield Doc(
+ yield self.Doc(
doc=getdoc(plugin) or "No plugin documentation found.",
name=plugin.__class__.__name__,
)
@@ -751,7 +756,7 @@ def driver(self) -> WebDriver:
return self._drivers.current
def find_element(
- self, locator: str, parent: Optional[WebElement] = None
+ self, locator: str, parent: WebElement | None = None
) -> WebElement:
"""Find element matching `locator`.
@@ -769,7 +774,7 @@ def find_element(
def find_elements(
self, locator: str, parent: WebElement = None
- ) -> List[WebElement]:
+ ) -> list[WebElement]:
"""Find all elements matching `locator`.
:param locator: Locator to use when searching the element.
@@ -807,7 +812,7 @@ def _parse_listener(self, event_firing_webdriver):
listener_module = self._string_to_modules(event_firing_webdriver)
listener_count = len(listener_module)
if listener_count > 1:
- message = f"Is is possible import only one listener but there was {listener_count} listeners."
+ message = f"It is possible to import only one listener but there were {listener_count} listeners."
raise ValueError(message)
listener_module = listener_module[0]
importer = Importer("test library")
@@ -817,12 +822,15 @@ def _parse_listener(self, event_firing_webdriver):
raise DataError(message)
return listener
+ class Module(NamedTuple):
+ module: str
+ args: list
+ kw_args: dict
+
def _string_to_modules(self, modules):
- Module = namedtuple("Module", "module, args, kw_args")
parsed_modules = []
for module in modules.split(","):
- module = module.strip()
- module_and_args = module.split(";")
+ module_and_args = module.strip().split(";")
module_name = module_and_args.pop(0)
kw_args = {}
args = []
@@ -832,8 +840,9 @@ def _string_to_modules(self, modules):
kw_args[key] = value
else:
args.append(argument)
- module = Module(module=module_name, args=args, kw_args=kw_args)
- parsed_modules.append(module)
+ parsed_modules.append(
+ self.Module(module=module_name, args=args, kw_args=kw_args)
+ )
return parsed_modules
def _store_plugin_keywords(self, plugin):
@@ -849,7 +858,7 @@ def _resolve_screenshot_root_directory(self):
self.screenshot_root_directory = BASE64
@staticmethod
- def _get_translation(language: Union[str, None]) -> Union[Path, None]:
+ def _get_translation(language: str | None) -> Path | None:
if not language:
return None
discovered_plugins = {
diff --git a/src/SeleniumLibrary/base/context.py b/src/SeleniumLibrary/base/context.py
index e55aecdc4..d8fbddffc 100644
--- a/src/SeleniumLibrary/base/context.py
+++ b/src/SeleniumLibrary/base/context.py
@@ -13,7 +13,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-from typing import Any, Optional, List
+from typing import Any
from selenium.webdriver.remote.webelement import WebElement
@@ -56,7 +56,7 @@ def event_firing_webdriver(self, event_firing_webdriver: Any):
def find_element(
self,
locator: str,
- tag: Optional[str] = None,
+ tag: str | None = None,
required: bool = True,
parent: WebElement = None,
) -> WebElement:
@@ -82,8 +82,8 @@ def find_element(
return self.element_finder.find(locator, tag, True, required, parent)
def find_elements(
- self, locator: str, tag: Optional[str] = None, parent: WebElement = None
- ) -> List[WebElement]:
+ self, locator: str, tag: str | None = None, parent: WebElement = None
+ ) -> list[WebElement]:
"""Find all elements matching `locator`.
:param locator: Locator to use when searching the element.
@@ -103,7 +103,7 @@ def is_text_present(self, text: str):
locator = f"xpath://*[contains(., {escape_xpath_value(text)})]"
return self.find_element(locator, required=False) is not None
- def is_element_enabled(self, locator: str, tag: Optional[str] = None) -> bool:
+ def is_element_enabled(self, locator: str, tag: str | None = None) -> bool:
element = self.find_element(locator, tag)
return element.is_enabled() and element.get_attribute("readonly") is None
diff --git a/src/SeleniumLibrary/base/librarycomponent.py b/src/SeleniumLibrary/base/librarycomponent.py
index d7174f4de..ae24d57c8 100644
--- a/src/SeleniumLibrary/base/librarycomponent.py
+++ b/src/SeleniumLibrary/base/librarycomponent.py
@@ -16,14 +16,14 @@
import os
from datetime import timedelta
-from typing import Optional, Union
-from SeleniumLibrary.utils import is_noney
from robot.api import logger
from robot.libraries.BuiltIn import BuiltIn, RobotNotRunningError
-from .context import ContextAware
+from SeleniumLibrary.utils import is_noney
+
from ..utils import _convert_timeout
+from .context import ContextAware
class LibraryComponent(ContextAware):
@@ -46,8 +46,8 @@ def log_source(self, loglevel: str = "INFO"):
def assert_page_contains(
self,
locator: str,
- tag: Optional[str] = None,
- message: Optional[str] = None,
+ tag: str | None = None,
+ message: str | None = None,
loglevel: str = "TRACE",
):
tag_message = tag or "element"
@@ -63,8 +63,8 @@ def assert_page_contains(
def assert_page_not_contains(
self,
locator: str,
- tag: Optional[str] = None,
- message: Optional[str] = None,
+ tag: str | None = None,
+ message: str | None = None,
loglevel: str = "TRACE",
):
tag_message = tag or "element"
@@ -75,7 +75,7 @@ def assert_page_not_contains(
raise AssertionError(message)
logger.info(f"Current page does not contain {tag_message} '{locator}'.")
- def get_timeout(self, timeout: Union[str, int, timedelta, None] = None) -> float:
+ def get_timeout(self, timeout: str | int | timedelta | None = None) -> float:
if timeout is None:
return self.ctx.timeout
return _convert_timeout(timeout)
diff --git a/src/SeleniumLibrary/entry/__main__.py b/src/SeleniumLibrary/entry/__main__.py
index 47e049233..61c96462e 100644
--- a/src/SeleniumLibrary/entry/__main__.py
+++ b/src/SeleniumLibrary/entry/__main__.py
@@ -16,13 +16,12 @@
import json
from pathlib import Path
-from typing import Optional
+
import click
from .get_versions import get_version
from .translation import compare_translation, get_library_translation
-
CONTEXT_SETTINGS = {"help_option_names": ["-h", "--help"]}
VERSION = get_version()
@@ -39,7 +38,6 @@ def cli():
See each command argument help for more details what (optional) arguments that command supports.
"""
- pass
@cli.command()
@@ -63,7 +61,7 @@ def cli():
)
def translation(
filename: Path,
- plugins: Optional[str] = None,
+ plugins: str | None = None,
compare: bool = False,
):
"""Default translation file from library keywords.
@@ -88,17 +86,17 @@ def translation(
lib_translation = get_library_translation(plugins)
if compare:
if table := compare_translation(filename, lib_translation):
- print(
+ click.echo(
"Found differences between translation and library, see below for details."
)
for line in table:
- print(line)
+ click.echo(line)
else:
- print("Translation is valid, no updated needed.")
+ click.echo("Translation is valid, no updated needed.")
else:
with filename.open("w") as file:
json.dump(lib_translation, file, indent=4)
- print(f"Translation file created in {filename.absolute()}")
+ click.echo(f"Translation file created in {filename.absolute()}")
if __name__ == "__main__":
diff --git a/src/SeleniumLibrary/entry/get_versions.py b/src/SeleniumLibrary/entry/get_versions.py
index 51e68da7a..4ad9a7ce5 100644
--- a/src/SeleniumLibrary/entry/get_versions.py
+++ b/src/SeleniumLibrary/entry/get_versions.py
@@ -14,10 +14,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from pathlib import Path
import re
import subprocess
import sys
+from pathlib import Path
from selenium import __version__
diff --git a/src/SeleniumLibrary/entry/translation.py b/src/SeleniumLibrary/entry/translation.py
index 3c98dddaa..0cfdb0e7b 100644
--- a/src/SeleniumLibrary/entry/translation.py
+++ b/src/SeleniumLibrary/entry/translation.py
@@ -18,7 +18,6 @@
import inspect
import json
from pathlib import Path
-from typing import List, Optional
KEYWORD_NAME = "Keyword name"
DOC_CHANGED = "Documentation update needed"
@@ -33,8 +32,8 @@
)
-def get_library_translation(plugins: Optional[str] = None) -> dict:
- from SeleniumLibrary import SeleniumLibrary
+def get_library_translation(plugins: str | None = None) -> dict:
+ from SeleniumLibrary import SeleniumLibrary # noqa: PLC0415
selib = SeleniumLibrary(plugins=plugins)
translation = {}
@@ -65,7 +64,7 @@ def _max_kw_name_length(project_translation: dict) -> int:
return max_lenght
-def _get_heading(max_kw_length: int) -> List[str]:
+def _get_heading(max_kw_length: int) -> list[str]:
heading = f"| {KEYWORD_NAME} "
next_line = f"| {'-' * len(KEYWORD_NAME)}"
if (padding := max_kw_length - len(KEYWORD_NAME)) > 0:
diff --git a/src/SeleniumLibrary/errors.py b/src/SeleniumLibrary/errors.py
index 5dd4310d1..636a13a87 100644
--- a/src/SeleniumLibrary/errors.py
+++ b/src/SeleniumLibrary/errors.py
@@ -40,4 +40,4 @@ class PluginError(SeleniumLibraryException):
class UnkownExpectedCondition(SeleniumLibraryException):
- pass
\ No newline at end of file
+ pass
diff --git a/src/SeleniumLibrary/keywords/alert.py b/src/SeleniumLibrary/keywords/alert.py
index 406946d0f..9484360e1 100644
--- a/src/SeleniumLibrary/keywords/alert.py
+++ b/src/SeleniumLibrary/keywords/alert.py
@@ -14,13 +14,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from datetime import timedelta
-from typing import Optional
from selenium.common.exceptions import TimeoutException, WebDriverException
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
-from SeleniumLibrary.base import keyword, LibraryComponent
+from SeleniumLibrary.base import LibraryComponent, keyword
from SeleniumLibrary.utils import secs_to_timestr
@@ -32,7 +31,7 @@ class AlertKeywords(LibraryComponent):
@keyword
def input_text_into_alert(
- self, text: str, action: str = ACCEPT, timeout: Optional[timedelta] = None
+ self, text: str, action: str = ACCEPT, timeout: timedelta | None = None
):
"""Types the given ``text`` into an input field in an alert.
@@ -53,7 +52,7 @@ def alert_should_be_present(
self,
text: str = "",
action: str = ACCEPT,
- timeout: Optional[timedelta] = None,
+ timeout: timedelta | None = None,
):
"""Verifies that an alert is present and by default, accepts it.
@@ -72,12 +71,12 @@ def alert_should_be_present(
message = self.handle_alert(action, timeout)
if text and text != message:
raise AssertionError(
- f"Alert message should have been '{text}' but it " f"was '{message}'."
+ f"Alert message should have been '{text}' but it was '{message}'."
)
@keyword
def alert_should_not_be_present(
- self, action: str = ACCEPT, timeout: Optional[timedelta] = None
+ self, action: str = ACCEPT, timeout: timedelta | None = None
):
"""Verifies that no alert is present.
@@ -101,7 +100,7 @@ def alert_should_not_be_present(
raise AssertionError(f"Alert with message '{text}' present.")
@keyword
- def handle_alert(self, action: str = ACCEPT, timeout: Optional[timedelta] = None):
+ def handle_alert(self, action: str = ACCEPT, timeout: timedelta | None = None):
"""Handles the current alert and returns its message.
By default, the alert is accepted, but this can be controlled
@@ -146,7 +145,11 @@ def _wait_alert(self, timeout=None):
wait = WebDriverWait(self.driver, timeout)
try:
return wait.until(EC.alert_is_present())
- except TimeoutException:
- raise AssertionError(f"Alert not found in {secs_to_timestr(timeout)}.")
+ except TimeoutException as original_exception:
+ raise AssertionError(
+ f"Alert not found in {secs_to_timestr(timeout)}."
+ ) from original_exception
except WebDriverException as err:
- raise AssertionError(f"An exception occurred waiting for alert: {err}")
+ raise AssertionError(
+ f"An exception occurred waiting for alert: {err}"
+ ) from err
diff --git a/src/SeleniumLibrary/keywords/browsermanagement.py b/src/SeleniumLibrary/keywords/browsermanagement.py
index 042d12d50..102695317 100644
--- a/src/SeleniumLibrary/keywords/browsermanagement.py
+++ b/src/SeleniumLibrary/keywords/browsermanagement.py
@@ -17,15 +17,20 @@
import time
import types
from datetime import timedelta
-from typing import Optional, Union, Any, List
+from typing import Any
from selenium import webdriver
from selenium.webdriver import FirefoxProfile
from selenium.webdriver.support.event_firing_webdriver import EventFiringWebDriver
-from SeleniumLibrary.base import keyword, LibraryComponent
+from SeleniumLibrary.base import LibraryComponent, keyword
from SeleniumLibrary.locators import WindowManager
-from SeleniumLibrary.utils import timestr_to_secs, secs_to_timestr, _convert_timeout, _convert_delay
+from SeleniumLibrary.utils import (
+ _convert_delay,
+ _convert_timeout,
+ secs_to_timestr,
+ timestr_to_secs,
+)
from .webdrivertools import WebDriverCreator
@@ -59,15 +64,15 @@ def close_browser(self):
@keyword
def open_browser(
self,
- url: Optional[str] = None,
+ url: str | None = None,
browser: str = "firefox",
- alias: Optional[str] = None,
- remote_url: Union[bool, str] = False,
- desired_capabilities: Union[dict, None, str] = None,
- ff_profile_dir: Union[FirefoxProfile, str, None] = None,
+ alias: str | None = None,
+ remote_url: bool | str = False,
+ desired_capabilities: dict | None | str = None,
+ ff_profile_dir: FirefoxProfile | str | None = None,
options: Any = None,
- service_log_path: Optional[str] = None,
- executable_path: Optional[str] = None,
+ service_log_path: str | None = None,
+ executable_path: str | None = None,
service: Any = None,
) -> str:
"""Opens a new browser instance to the optional ``url``.
@@ -212,11 +217,17 @@ def open_browser(
self.go_to(url)
return index
if desired_capabilities:
- self.warn("desired_capabilities has been deprecated and removed. Please use options to configure browsers as per documentation.")
+ self.warn(
+ "desired_capabilities has been deprecated and removed. Please use options to configure browsers as per documentation."
+ )
if service_log_path:
- self.warn("service_log_path is being deprecated. Please use service to configure log_output or equivalent service attribute.")
+ self.warn(
+ "service_log_path is being deprecated. Please use service to configure log_output or equivalent service attribute."
+ )
if executable_path:
- self.warn("executable_path is being deprecated. Please use service to configure the driver's executable_path as per documentation.")
+ self.warn(
+ "executable_path is being deprecated. Please use service to configure the driver's executable_path as per documentation."
+ )
return self._make_new_browser(
url,
browser,
@@ -275,7 +286,11 @@ def _make_new_browser(
@keyword
def create_webdriver(
- self, driver_name: str, alias: Optional[str] = None, kwargs: Optional[dict] = None, **init_kwargs
+ self,
+ driver_name: str,
+ alias: str | None = None,
+ kwargs: dict | None = None,
+ **init_kwargs,
) -> str:
"""Creates an instance of Selenium WebDriver.
@@ -314,8 +329,10 @@ def create_webdriver(
driver_name = driver_name.strip()
try:
creation_func = getattr(webdriver, driver_name)
- except AttributeError:
- raise RuntimeError(f"'{driver_name}' is not a valid WebDriver name.")
+ except AttributeError as original_exception:
+ raise RuntimeError(
+ f"'{driver_name}' is not a valid WebDriver name."
+ ) from original_exception
self.info(f"Creating an instance of the {driver_name} WebDriver.")
driver = creation_func(**init_kwargs)
self.debug(
@@ -359,16 +376,16 @@ def switch_browser(self, index_or_alias: str):
"""
try:
self.drivers.switch(index_or_alias)
- except RuntimeError:
+ except RuntimeError as original_exception:
raise RuntimeError(
f"No browser with index or alias '{index_or_alias}' found."
- )
+ ) from original_exception
self.debug(
f"Switched to browser with Selenium session id {self.driver.session_id}."
)
@keyword
- def get_browser_ids(self) -> List[str]:
+ def get_browser_ids(self) -> list[str]:
"""Returns index of all active browser as list.
Example:
@@ -385,7 +402,7 @@ def get_browser_ids(self) -> List[str]:
return self.drivers.active_driver_ids
@keyword
- def get_browser_aliases(self) -> List[str]:
+ def get_browser_aliases(self) -> list[str]:
"""Returns aliases of all active browser that has an alias as NormalizedDict.
The dictionary contains the aliases as keys and the index as value.
This can be accessed as dictionary ``${aliases.key}`` or as list ``@{aliases}[0]``.
@@ -429,7 +446,7 @@ def get_location(self) -> str:
return self.driver.current_url
@keyword
- def location_should_be(self, url: str, message: Optional[str] = None):
+ def location_should_be(self, url: str, message: str | None = None):
"""Verifies that the current URL is exactly ``url``.
The ``url`` argument contains the exact url that should exist in browser.
@@ -442,12 +459,12 @@ def location_should_be(self, url: str, message: Optional[str] = None):
actual = self.get_location()
if actual != url:
if message is None:
- message = f"Location should have been '{url}' but " f"was '{actual}'."
+ message = f"Location should have been '{url}' but was '{actual}'."
raise AssertionError(message)
self.info(f"Current location is '{url}'.")
@keyword
- def location_should_contain(self, expected: str, message: Optional[str] = None):
+ def location_should_contain(self, expected: str, message: str | None = None):
"""Verifies that the current URL contains ``expected``.
The ``expected`` argument contains the expected value in url.
@@ -494,7 +511,7 @@ def log_title(self) -> str:
return title
@keyword
- def title_should_be(self, title: str, message: Optional[str] = None):
+ def title_should_be(self, title: str, message: str | None = None):
"""Verifies that the current page title equals ``title``.
The ``message`` argument can be used to override the default error
@@ -654,8 +671,7 @@ def set_action_chain_delay(self, value: timedelta) -> str:
@keyword
def get_action_chain_delay(self):
- """Gets the currently stored value for chain_delay_value in timestr format.
- """
+ """Gets the currently stored value for chain_delay_value in timestr format."""
return timestr_to_secs(f"{self.ctx.action_chain_delay} milliseconds")
@keyword
diff --git a/src/SeleniumLibrary/keywords/cookie.py b/src/SeleniumLibrary/keywords/cookie.py
index c2c49e8c7..32af0f861 100644
--- a/src/SeleniumLibrary/keywords/cookie.py
+++ b/src/SeleniumLibrary/keywords/cookie.py
@@ -14,7 +14,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from datetime import datetime
-from typing import Union, Optional
from robot.libraries.DateTime import convert_date
from robot.utils import DotDict
@@ -45,7 +44,7 @@ def __init__(
self.extra = extra
def __str__(self):
- items = "name value path domain secure httpOnly expiry".split()
+ items = ["name", "value", "path", "domain", "secure", "httpOnly", "expiry"]
string = "\n".join(f"{item}={getattr(self, item)}" for item in items)
if self.extra:
string = f"{string}\nextra={self.extra}\n"
@@ -67,7 +66,7 @@ def delete_cookie(self, name):
self.driver.delete_cookie(name)
@keyword
- def get_cookies(self, as_dict: bool = False) -> Union[str, dict]:
+ def get_cookies(self, as_dict: bool = False) -> str | dict:
"""Returns all cookies of the current page.
If ``as_dict`` argument evaluates as false, see `Boolean arguments`
@@ -87,11 +86,10 @@ def get_cookies(self, as_dict: bool = False) -> Union[str, dict]:
for cookie in self.driver.get_cookies():
pairs.append(f"{cookie['name']}={cookie['value']}")
return "; ".join(pairs)
- else:
- pairs = DotDict()
- for cookie in self.driver.get_cookies():
- pairs[cookie["name"]] = cookie["value"]
- return pairs
+ pairs = DotDict()
+ for cookie in self.driver.get_cookies():
+ pairs[cookie["name"]] = cookie["value"]
+ return pairs
@keyword
def get_cookie(self, name: str) -> CookieInformation:
@@ -144,10 +142,10 @@ def add_cookie(
self,
name: str,
value: str,
- path: Optional[str] = None,
- domain: Optional[str] = None,
- secure: Optional[bool] = None,
- expiry: Optional[str] = None,
+ path: str | None = None,
+ domain: str | None = None,
+ secure: bool | None = None,
+ expiry: str | None = None,
):
"""Adds a cookie to your current session.
diff --git a/src/SeleniumLibrary/keywords/element.py b/src/SeleniumLibrary/keywords/element.py
index c61076286..c74bb1d5a 100644
--- a/src/SeleniumLibrary/keywords/element.py
+++ b/src/SeleniumLibrary/keywords/element.py
@@ -14,18 +14,17 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from collections import namedtuple
-from typing import List, Optional, Tuple, Union
+from typing import NamedTuple
-from SeleniumLibrary.utils import is_noney
-from robot.utils import plural_or_not, is_truthy
+from robot.utils import is_truthy, plural_or_not
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.remote.webelement import WebElement
from SeleniumLibrary.base import LibraryComponent, keyword
from SeleniumLibrary.errors import ElementNotFound
-from SeleniumLibrary.utils.types import type_converter, Locator
+from SeleniumLibrary.utils import is_noney
+from SeleniumLibrary.utils.types import Locator, type_converter
class ElementKeywords(LibraryComponent):
@@ -39,7 +38,7 @@ def get_webelement(self, locator: Locator) -> WebElement:
return self.find_element(locator)
@keyword(name="Get WebElements")
- def get_webelements(self, locator: Locator) -> List[WebElement]:
+ def get_webelements(self, locator: Locator) -> list[WebElement]:
"""Returns a list of WebElement objects matching the ``locator``.
See the `Locating elements` section for details about the locator
@@ -55,8 +54,8 @@ def get_webelements(self, locator: Locator) -> List[WebElement]:
def element_should_contain(
self,
locator: Locator,
- expected: Union[None, str],
- message: Optional[str] = None,
+ expected: None | str,
+ message: str | None = None,
ignore_case: bool = False,
):
"""Verifies that element ``locator`` contains text ``expected``.
@@ -93,8 +92,8 @@ def element_should_contain(
def element_should_not_contain(
self,
locator: Locator,
- expected: Union[None, str],
- message: Optional[str] = None,
+ expected: None | str,
+ message: str | None = None,
ignore_case: bool = False,
):
"""Verifies that element ``locator`` does not contain text ``expected``.
@@ -151,9 +150,9 @@ def page_should_contain(self, text: str, loglevel: str = "TRACE"):
def page_should_contain_element(
self,
locator: Locator,
- message: Optional[str] = None,
+ message: str | None = None,
loglevel: str = "TRACE",
- limit: Optional[int] = None,
+ limit: int | None = None,
):
"""Verifies that element ``locator`` is found on the current page.
@@ -186,14 +185,14 @@ def page_should_contain_element(
count = len(self.find_elements(locator))
if count == limit:
self.info(f"Current page contains {count} element(s).")
- else:
- if message is None:
- message = (
- f'Page should have contained "{limit}" element(s), '
- f'but it did contain "{count}" element(s).'
- )
- self.ctx.log_source(loglevel)
- raise AssertionError(message)
+ return None
+ if message is None:
+ message = (
+ f'Page should have contained "{limit}" element(s), '
+ f'but it did contain "{count}" element(s).'
+ )
+ self.ctx.log_source(loglevel)
+ raise AssertionError(message)
@keyword
def page_should_not_contain(self, text: str, loglevel: str = "TRACE"):
@@ -211,7 +210,7 @@ def page_should_not_contain(self, text: str, loglevel: str = "TRACE"):
def page_should_not_contain_element(
self,
locator: Locator,
- message: Optional[str] = None,
+ message: str | None = None,
loglevel: str = "TRACE",
):
"""Verifies that element ``locator`` is not found on the current page.
@@ -225,7 +224,7 @@ def page_should_not_contain_element(
self.assert_page_not_contains(locator, message=message, loglevel=loglevel)
@keyword
- def assign_id_to_element(self, locator: Locator, id: str):
+ def assign_id_to_element(self, locator: Locator, id: str): # noqa: A002
"""Assigns a temporary ``id`` to the element specified by ``locator``.
This is mainly useful if the locator is complicated and/or slow XPath
@@ -287,9 +286,7 @@ def element_should_be_focused(self, locator: Locator):
raise AssertionError(f"Element '{locator}' does not have focus.")
@keyword
- def element_should_be_visible(
- self, locator: Locator, message: Optional[str] = None
- ):
+ def element_should_be_visible(self, locator: Locator, message: str | None = None):
"""Verifies that the element identified by ``locator`` is visible.
Herein, visible means that the element is logically visible, not
@@ -311,7 +308,7 @@ def element_should_be_visible(
@keyword
def element_should_not_be_visible(
- self, locator: Locator, message: Optional[str] = None
+ self, locator: Locator, message: str | None = None
):
"""Verifies that the element identified by ``locator`` is NOT visible.
@@ -332,8 +329,8 @@ def element_should_not_be_visible(
def element_text_should_be(
self,
locator: Locator,
- expected: Union[None, str],
- message: Optional[str] = None,
+ expected: None | str,
+ message: str | None = None,
ignore_case: bool = False,
):
"""Verifies that element ``locator`` contains exact the text ``expected``.
@@ -368,8 +365,8 @@ def element_text_should_be(
def element_text_should_not_be(
self,
locator: Locator,
- not_expected: Union[None, str],
- message: Optional[str] = None,
+ not_expected: None | str,
+ message: str | None = None,
ignore_case: bool = False,
):
"""Verifies that element ``locator`` does not contain exact the text ``not_expected``.
@@ -399,9 +396,7 @@ def element_text_should_not_be(
raise AssertionError(message)
@keyword
- def get_element_attribute(
- self, locator: Locator, attribute: str
- ) -> str:
+ def get_element_attribute(self, locator: Locator, attribute: str) -> str:
"""Returns the value of ``attribute`` from the element ``locator``.
See the `Locating elements` section for details about the locator
@@ -417,9 +412,7 @@ def get_element_attribute(
return self.find_element(locator).get_attribute(attribute)
@keyword
- def get_dom_attribute(
- self, locator: Locator, attribute: str
- ) -> str:
+ def get_dom_attribute(self, locator: Locator, attribute: str) -> str:
"""Returns the value of ``attribute`` from the element ``locator``. `Get DOM Attribute` keyword
only returns attributes declared within the element's HTML markup. If the requested attribute
is not there, the keyword returns ${None}.
@@ -435,7 +428,9 @@ def get_dom_attribute(
@keyword
def get_property(
- self, locator: Locator, property: str
+ self,
+ locator: Locator,
+ property: str, # noqa: A002
) -> str:
"""Returns the value of ``property`` from the element ``locator``.
@@ -453,8 +448,8 @@ def element_attribute_value_should_be(
self,
locator: Locator,
attribute: str,
- expected: Union[None, str],
- message: Optional[str] = None,
+ expected: None | str,
+ message: str | None = None,
):
"""Verifies element identified by ``locator`` contains expected attribute value.
@@ -494,7 +489,7 @@ def get_horizontal_position(self, locator: Locator) -> int:
return self.find_element(locator).location["x"]
@keyword
- def get_element_size(self, locator: Locator) -> Tuple[int, int]:
+ def get_element_size(self, locator: Locator) -> tuple[int, int]:
"""Returns width and height of the element identified by ``locator``.
See the `Locating elements` section for details about the locator
@@ -582,9 +577,7 @@ def get_vertical_position(self, locator: Locator) -> int:
return self.find_element(locator).location["y"]
@keyword
- def click_button(
- self, locator: Locator, modifier: Union[bool, str] = False
- ):
+ def click_button(self, locator: Locator, modifier: bool | str = False):
"""Clicks the button identified by ``locator``.
See the `Locating elements` section for details about the locator
@@ -606,9 +599,7 @@ def click_button(
self._click_with_modifier(locator, ["button", "input"], modifier)
@keyword
- def click_image(
- self, locator: Locator, modifier: Union[bool, str] = False
- ):
+ def click_image(self, locator: Locator, modifier: bool | str = False):
"""Clicks an image identified by ``locator``.
See the `Locating elements` section for details about the locator
@@ -631,9 +622,7 @@ def click_image(
self._click_with_modifier(locator, ["image", "input"], modifier)
@keyword
- def click_link(
- self, locator: Locator, modifier: Union[bool, str] = False
- ):
+ def click_link(self, locator: Locator, modifier: bool | str = False):
"""Clicks a link identified by ``locator``.
See the `Locating elements` section for details about the locator
@@ -655,7 +644,7 @@ def click_link(
def click_element(
self,
locator: Locator,
- modifier: Union[bool, str] = False,
+ modifier: bool | str = False,
action_chain: bool = False,
):
"""Click the element identified by ``locator``.
@@ -775,12 +764,12 @@ def scroll_element_into_view(self, locator: Locator):
New in SeleniumLibrary 3.2.0
"""
element = self.find_element(locator)
- ActionChains(self.driver, duration=self.ctx.action_chain_delay).move_to_element(element).perform()
+ ActionChains(self.driver, duration=self.ctx.action_chain_delay).move_to_element(
+ element
+ ).perform()
@keyword
- def drag_and_drop(
- self, locator: Locator, target: Locator
- ):
+ def drag_and_drop(self, locator: Locator, target: Locator):
"""Drags the element identified by ``locator`` into the ``target`` element.
The ``locator`` argument is the locator of the dragged element
@@ -796,9 +785,7 @@ def drag_and_drop(
action.drag_and_drop(element, target).perform()
@keyword
- def drag_and_drop_by_offset(
- self, locator: Locator, xoffset: int, yoffset: int
- ):
+ def drag_and_drop_by_offset(self, locator: Locator, xoffset: int, yoffset: int):
"""Drags the element identified with ``locator`` by ``xoffset/yoffset``.
See the `Locating elements` section for details about the locator
@@ -870,7 +857,9 @@ def mouse_up(self, locator: Locator):
"""
self.info(f"Simulating Mouse Up on element '{locator}'.")
element = self.find_element(locator)
- ActionChains(self.driver, duration=self.ctx.action_chain_delay).release(element).perform()
+ ActionChains(self.driver, duration=self.ctx.action_chain_delay).release(
+ element
+ ).perform()
@keyword
def open_context_menu(self, locator: Locator):
@@ -989,7 +978,9 @@ def press_keys(self, locator: Locator | None = None, *keys: str):
if not is_noney(locator):
self.info(f"Sending key(s) {keys} to {locator} element.")
element = self.find_element(locator)
- ActionChains(self.driver, duration=self.ctx.action_chain_delay).click(element).perform()
+ ActionChains(self.driver, duration=self.ctx.action_chain_delay).click(
+ element
+ ).perform()
else:
self.info(f"Sending key(s) {keys} to page.")
element = None
@@ -1025,7 +1016,7 @@ def _special_key_up(self, actions, parsed_key):
actions.key_up(key.converted)
@keyword
- def get_all_links(self) -> List[str]:
+ def get_all_links(self) -> list[str]:
"""Returns a list containing ids of all links found in current page.
If a link has no id, an empty string will be in the list instead.
@@ -1049,7 +1040,7 @@ def mouse_down_on_link(self, locator: Locator):
def page_should_contain_link(
self,
locator: Locator,
- message: Optional[str] = None,
+ message: str | None = None,
loglevel: str = "TRACE",
):
"""Verifies link identified by ``locator`` is found from current page.
@@ -1067,7 +1058,7 @@ def page_should_contain_link(
def page_should_not_contain_link(
self,
locator: Locator,
- message: Optional[str] = None,
+ message: str | None = None,
loglevel: str = "TRACE",
):
"""Verifies link identified by ``locator`` is not found from current page.
@@ -1097,7 +1088,7 @@ def mouse_down_on_image(self, locator: Locator):
def page_should_contain_image(
self,
locator: Locator,
- message: Optional[str] = None,
+ message: str | None = None,
loglevel: str = "TRACE",
):
"""Verifies image identified by ``locator`` is found from current page.
@@ -1115,7 +1106,7 @@ def page_should_contain_image(
def page_should_not_contain_image(
self,
locator: Locator,
- message: Optional[str] = None,
+ message: str | None = None,
loglevel: str = "TRACE",
):
"""Verifies image identified by ``locator`` is not found from current page.
@@ -1172,7 +1163,7 @@ def remove_location_strategy(self, strategy_name: str):
self.element_finder.unregister(strategy_name)
def _map_ascii_key_code_to_key(self, key_code):
- map = {
+ key_map = {
0: Keys.NULL,
8: Keys.BACK_SPACE,
9: Keys.TAB,
@@ -1191,7 +1182,7 @@ def _map_ascii_key_code_to_key(self, key_code):
61: Keys.EQUALS,
127: Keys.DELETE,
}
- key = map.get(key_code)
+ key = key_map.get(key_code)
if key is None:
key = chr(key_code)
return key
@@ -1199,10 +1190,10 @@ def _map_ascii_key_code_to_key(self, key_code):
def _map_named_key_code_to_special_key(self, key_name):
try:
return getattr(Keys, key_name)
- except AttributeError:
+ except AttributeError as original_exception:
message = f"Unknown key named '{key_name}'."
self.debug(message)
- raise ValueError(message)
+ raise ValueError(message) from original_exception
def _page_contains(self, text):
self.driver.switch_to.default_content()
@@ -1225,12 +1216,13 @@ def parse_modifier(self, modifier):
modifiers = modifier.split("+")
keys = []
for item in modifiers:
- item = item.strip()
- item = self._parse_aliases(item)
- if hasattr(Keys, item):
- keys.append(getattr(Keys, item))
+ modifier = self._parse_aliases(item.strip())
+ if hasattr(Keys, modifier):
+ keys.append(getattr(Keys, modifier))
else:
- raise ValueError(f"'{item}' modifier does not match to Selenium Keys")
+ raise ValueError(
+ f"'{modifier}' modifier does not match to Selenium Keys"
+ )
return keys
def _parse_keys(self, *keys):
@@ -1263,24 +1255,30 @@ def _separate_key(self, key):
list_keys.append(one_key)
return list_keys
+ class KeysRecord(NamedTuple):
+ converted: object
+ original: str
+ special: bool
+
def _convert_special_keys(self, keys):
- KeysRecord = namedtuple("KeysRecord", "converted, original special")
converted_keys = []
for key in keys:
- key = self._parse_aliases(key)
- if self._selenium_keys_has_attr(key):
- converted_keys.append(KeysRecord(getattr(Keys, key), key, True))
+ resolved_key = self._parse_aliases(key)
+ if self._selenium_keys_has_attr(resolved_key):
+ converted_keys.append(
+ self.KeysRecord(getattr(Keys, resolved_key), resolved_key, True)
+ )
else:
- converted_keys.append(KeysRecord(key, key, False))
+ converted_keys.append(
+ self.KeysRecord(resolved_key, resolved_key, False)
+ )
return converted_keys
def _selenium_keys_has_attr(self, key):
return hasattr(Keys, key)
@keyword("Get CSS Property Value")
- def get_css_property_value(
- self, locator: Locator, css_property: str
- ) -> str:
+ def get_css_property_value(self, locator: Locator, css_property: str) -> str:
"""Returns the computed value of ``css_property`` from the element ``locator``.
See the `Locating elements` section for details about the locator syntax.
@@ -1293,4 +1291,4 @@ def get_css_property_value(
| ${color}= | `Get CSS Property Value` | css:button.submit | background-color |
| ${size}= | `Get CSS Property Value` | id:username | font-size |
"""
- return self.find_element(locator).value_of_css_property(css_property)
\ No newline at end of file
+ return self.find_element(locator).value_of_css_property(css_property)
diff --git a/src/SeleniumLibrary/keywords/expectedconditions.py b/src/SeleniumLibrary/keywords/expectedconditions.py
index c0272ae75..016d239a4 100644
--- a/src/SeleniumLibrary/keywords/expectedconditions.py
+++ b/src/SeleniumLibrary/keywords/expectedconditions.py
@@ -12,16 +12,19 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import string
-from typing import Optional
+
+from selenium.webdriver.support import expected_conditions as EC
+from selenium.webdriver.support.wait import WebDriverWait
from SeleniumLibrary.base import LibraryComponent, keyword
from SeleniumLibrary.errors import UnkownExpectedCondition
-from selenium.webdriver.support.wait import WebDriverWait
-from selenium.webdriver.support import expected_conditions as EC
+
class ExpectedConditionKeywords(LibraryComponent):
@keyword
- def wait_for_expected_condition(self, condition: string, *args, timeout: Optional[float]=10):
+ def wait_for_expected_condition(
+ self, condition: string, *args, timeout: float | None = 10
+ ):
"""Waits until ``condition`` is true or ``timeout`` expires.
The condition must be one of selenium's expected condition which
@@ -51,13 +54,15 @@ def wait_for_expected_condition(self, condition: string, *args, timeout: Optiona
condition = self._parse_condition(condition)
wait = WebDriverWait(self.driver, timeout, 0.1)
try:
- c = getattr(EC, condition)
- except:
- # ToDo: provide hints as to what is avaialbel or find closet match
- raise UnkownExpectedCondition(f"{condition} is an unknown expected condition")
- result = wait.until(c(*args), message="Expected Condition not met within set timeout of " + str(timeout))
- return result
+ condition_func = getattr(EC, condition)
+ except AttributeError as original_exception:
+ raise UnkownExpectedCondition(
+ f"{condition} is an unknown expected condition"
+ ) from original_exception
+ return wait.until(
+ condition_func(*args),
+ message=f"Expected Condition not met within set timeout of {timeout}s",
+ )
def _parse_condition(self, condition: string):
- parsed = condition.replace(' ','_').lower()
- return parsed
\ No newline at end of file
+ return condition.replace(" ", "_").lower()
diff --git a/src/SeleniumLibrary/keywords/formelement.py b/src/SeleniumLibrary/keywords/formelement.py
index 43816e04f..cbf774190 100644
--- a/src/SeleniumLibrary/keywords/formelement.py
+++ b/src/SeleniumLibrary/keywords/formelement.py
@@ -15,7 +15,6 @@
# limitations under the License.
import os
-from typing import Optional
from robot.libraries.BuiltIn import BuiltIn
@@ -70,7 +69,7 @@ def checkbox_should_not_be_selected(self, locator: Locator):
def page_should_contain_checkbox(
self,
locator: Locator,
- message: Optional[str] = None,
+ message: str | None = None,
loglevel: str = "TRACE",
):
"""Verifies checkbox ``locator`` is found from the current page.
@@ -87,7 +86,7 @@ def page_should_contain_checkbox(
def page_should_not_contain_checkbox(
self,
locator: Locator,
- message: Optional[str] = None,
+ message: str | None = None,
loglevel: str = "TRACE",
):
"""Verifies checkbox ``locator`` is not found from the current page.
@@ -132,7 +131,7 @@ def unselect_checkbox(self, locator: Locator):
def page_should_contain_radio_button(
self,
locator: Locator,
- message: Optional[str] = None,
+ message: str | None = None,
loglevel: str = "TRACE",
):
"""Verifies radio button ``locator`` is found from current page.
@@ -150,7 +149,7 @@ def page_should_contain_radio_button(
def page_should_not_contain_radio_button(
self,
locator: Locator,
- message: Optional[str] = None,
+ message: str | None = None,
loglevel: str = "TRACE",
):
"""Verifies radio button ``locator`` is not found from current page.
@@ -239,9 +238,7 @@ def choose_file(self, locator: Locator, file_path: str):
self.ctx._running_keyword = None
@keyword
- def input_password(
- self, locator: Locator, password: str, clear: bool = True
- ):
+ def input_password(self, locator: Locator, password: str, clear: bool = True):
"""Types the given password into the text field identified by ``locator``.
See the `Locating elements` section for details about the locator
@@ -269,9 +266,7 @@ def input_password(
self._input_text_into_text_field(locator, password, clear, disable_log=True)
@keyword
- def input_text(
- self, locator: Locator, text: str, clear: bool = True
- ):
+ def input_text(self, locator: Locator, text: str, clear: bool = True):
"""Types the given ``text`` into the text field identified by ``locator``.
When ``clear`` is true, the input element is cleared before
@@ -300,7 +295,7 @@ def input_text(
def page_should_contain_textfield(
self,
locator: Locator,
- message: Optional[str] = None,
+ message: str | None = None,
loglevel: str = "TRACE",
):
"""Verifies text field ``locator`` is found from current page.
@@ -317,7 +312,7 @@ def page_should_contain_textfield(
def page_should_not_contain_textfield(
self,
locator: Locator,
- message: Optional[str] = None,
+ message: str | None = None,
loglevel: str = "TRACE",
):
"""Verifies text field ``locator`` is not found from current page.
@@ -335,7 +330,7 @@ def textfield_should_contain(
self,
locator: Locator,
expected: str,
- message: Optional[str] = None,
+ message: str | None = None,
):
"""Verifies text field ``locator`` contains text ``expected``.
@@ -359,7 +354,7 @@ def textfield_value_should_be(
self,
locator: Locator,
expected: str,
- message: Optional[str] = None,
+ message: str | None = None,
):
"""Verifies text field ``locator`` has exactly text ``expected``.
@@ -383,7 +378,7 @@ def textarea_should_contain(
self,
locator: Locator,
expected: str,
- message: Optional[str] = None,
+ message: str | None = None,
):
"""Verifies text area ``locator`` contains text ``expected``.
@@ -407,7 +402,7 @@ def textarea_value_should_be(
self,
locator: Locator,
expected: str,
- message: Optional[str] = None,
+ message: str | None = None,
):
"""Verifies text area ``locator`` has exactly text ``expected``.
@@ -430,7 +425,7 @@ def textarea_value_should_be(
def page_should_contain_button(
self,
locator: Locator,
- message: Optional[str] = None,
+ message: str | None = None,
loglevel: str = "TRACE",
):
"""Verifies button ``locator`` is found from current page.
@@ -451,7 +446,7 @@ def page_should_contain_button(
def page_should_not_contain_button(
self,
locator: Locator,
- message: Optional[str] = None,
+ message: str | None = None,
loglevel: str = "TRACE",
):
"""Verifies button ``locator`` is not found from current page.
@@ -488,11 +483,10 @@ def _get_radio_button_with_value(self, group_name, value):
self.debug(f"Radio group locator: {xpath}")
try:
return self.find_element(xpath)
- except ElementNotFound:
+ except ElementNotFound as original_exception:
raise ElementNotFound(
- f"No radio button with name '{group_name}' "
- f"and value '{value}' found."
- )
+ f"No radio button with name '{group_name}' and value '{value}' found."
+ ) from original_exception
def _get_value_from_radio_buttons(self, elements):
for element in elements:
diff --git a/src/SeleniumLibrary/keywords/javascript.py b/src/SeleniumLibrary/keywords/javascript.py
index 9c2bb1c90..7166ad573 100644
--- a/src/SeleniumLibrary/keywords/javascript.py
+++ b/src/SeleniumLibrary/keywords/javascript.py
@@ -15,17 +15,14 @@
# limitations under the License.
import os
-from collections import namedtuple
-from typing import Any, Union
+from typing import Any, NamedTuple
from robot.utils import plural_or_not, seq2str
-from selenium.webdriver.remote.webelement import WebElement
from SeleniumLibrary.base import LibraryComponent, keyword
class JavaScriptKeywords(LibraryComponent):
-
js_marker = "JAVASCRIPT"
arg_marker = "ARGUMENTS"
@@ -130,11 +127,9 @@ def _separate_code_and_args(self, code):
return code[index.js + 1 :], []
if self.js_marker not in code:
return code[0 : index.arg], code[index.arg + 1 :]
- else:
- if index.js == 0:
- return code[index.js + 1 : index.arg], code[index.arg + 1 :]
- else:
- return code[index.js + 1 :], code[index.arg + 1 : index.js]
+ if index.js == 0:
+ return code[index.js + 1 : index.arg], code[index.arg + 1 :]
+ return code[index.js + 1 :], code[index.arg + 1 : index.js]
def _check_marker_error(self, code):
if not code:
@@ -151,17 +146,14 @@ def _check_marker_error(self, code):
if message:
raise ValueError(message)
+ class Index(NamedTuple):
+ js: int
+ arg: int
+
def _get_marker_index(self, code):
- Index = namedtuple("Index", "js arg")
- if self.js_marker in code:
- js = code.index(self.js_marker)
- else:
- js = -1
- if self.arg_marker in code:
- arg = code.index(self.arg_marker)
- else:
- arg = -1
- return Index(js=js, arg=arg)
+ js = code.index(self.js_marker) if self.js_marker in code else -1
+ arg = code.index(self.arg_marker) if self.arg_marker in code else -1
+ return self.Index(js=js, arg=arg)
def _read_javascript_from_file(self, path):
self.info(
diff --git a/src/SeleniumLibrary/keywords/runonfailure.py b/src/SeleniumLibrary/keywords/runonfailure.py
index 4d23c5ade..98f454578 100644
--- a/src/SeleniumLibrary/keywords/runonfailure.py
+++ b/src/SeleniumLibrary/keywords/runonfailure.py
@@ -13,14 +13,13 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-from typing import Optional
from SeleniumLibrary.base import LibraryComponent, keyword
class RunOnFailureKeywords(LibraryComponent):
@keyword
- def register_keyword_to_run_on_failure(self, keyword: Optional[str]) -> str:
+ def register_keyword_to_run_on_failure(self, keyword: str | None) -> str:
"""Sets the keyword to execute, when a SeleniumLibrary keyword fails.
``keyword`` is the name of a keyword that will be executed if a
@@ -65,9 +64,7 @@ def resolve_keyword(name):
if name is None:
return None
if (
- isinstance(name, str)
- and name.upper() == "NOTHING"
- or name.upper() == "NONE"
- ):
+ isinstance(name, str) and name.upper() == "NOTHING"
+ ) or name.upper() == "NONE":
return None
return name
diff --git a/src/SeleniumLibrary/keywords/screenshot.py b/src/SeleniumLibrary/keywords/screenshot.py
index 6963b4e28..4a4c7da0e 100644
--- a/src/SeleniumLibrary/keywords/screenshot.py
+++ b/src/SeleniumLibrary/keywords/screenshot.py
@@ -15,11 +15,10 @@
# limitations under the License.
import os
-from typing import Optional, Union
from base64 import b64decode
from robot.utils import get_link_path
-from selenium.webdriver.common.print_page_options import PrintOptions, Orientation
+from selenium.webdriver.common.print_page_options import Orientation, PrintOptions
from SeleniumLibrary.base import LibraryComponent, keyword
from SeleniumLibrary.utils.path_formatter import _format_path
@@ -35,7 +34,7 @@
class ScreenshotKeywords(LibraryComponent):
@keyword
- def set_screenshot_directory(self, path: Union[None, str]) -> str:
+ def set_screenshot_directory(self, path: None | str) -> str:
"""Sets the directory for captured screenshots.
``path`` argument specifies the absolute path to a directory where
@@ -123,7 +122,7 @@ def capture_page_screenshot(self, filename: str = DEFAULT_FILENAME_PAGE) -> str:
"""
if not self.drivers.current:
self.info("Cannot capture screenshot because no browser is open.")
- return
+ return None
is_embedded, method = self._decide_embedded(filename)
if is_embedded:
return self._capture_page_screen_to_log(method)
@@ -179,7 +178,7 @@ def capture_element_screenshot(
self.info(
"Cannot capture screenshot from element because no browser is open."
)
- return
+ return None
element = self.find_element(locator, required=True)
is_embedded, method = self._decide_embedded(filename)
if is_embedded:
@@ -263,24 +262,25 @@ def _embed_to_log_as_file(self, path, width):
f'
',
html=True,
)
-
+
@keyword
- def print_page_as_pdf(self,
- filename: str = DEFAULT_FILENAME_PDF,
- background: Optional[bool] = None,
- margin_bottom: Optional[float] = None,
- margin_left: Optional[float] = None,
- margin_right: Optional[float] = None,
- margin_top: Optional[float] = None,
- orientation: Optional[Orientation] = None,
- page_height: Optional[float] = None,
- page_ranges: Optional[list] = None,
- page_width: Optional[float] = None,
- scale: Optional[float] = None,
- shrink_to_fit: Optional[bool] = None,
- # path_to_file=None,
- ):
- """ Print the current page as a PDF
+ def print_page_as_pdf( # noqa : PLR0912 C901
+ self,
+ filename: str = DEFAULT_FILENAME_PDF,
+ background: bool | None = None,
+ margin_bottom: float | None = None,
+ margin_left: float | None = None,
+ margin_right: float | None = None,
+ margin_top: float | None = None,
+ orientation: Orientation | None = None,
+ page_height: float | None = None,
+ page_ranges: list | None = None,
+ page_width: float | None = None,
+ scale: float | None = None,
+ shrink_to_fit: bool | None = None,
+ # path_to_file=None,
+ ):
+ """Print the current page as a PDF
``page_ranges`` defaults to `['-']` or "all" pages. ``page_ranges`` takes a list of
strings indicating the ranges.
@@ -304,11 +304,11 @@ def print_page_as_pdf(self,
"""
if page_ranges is None:
- page_ranges = ['-']
+ page_ranges = ["-"]
print_options = PrintOptions()
if background is not None:
- print_options.background = background
+ print_options.background = background
if margin_bottom is not None:
print_options.margin_bottom = margin_bottom
if margin_left is not None:
@@ -332,7 +332,7 @@ def print_page_as_pdf(self,
if not self.drivers.current:
self.info("Cannot print page to pdf because no browser is open.")
- return
+ return None
return self._print_page_as_pdf_to_file(filename, print_options)
def _print_page_as_pdf_to_file(self, filename, options):
@@ -340,13 +340,13 @@ def _print_page_as_pdf_to_file(self, filename, options):
self._create_directory(path)
pdfdata = self.driver.print_page(options)
if not pdfdata:
- raise RuntimeError(f"Failed to print page.")
+ raise RuntimeError("Failed to print page.")
self._save_pdf_to_file(pdfdata, path)
return path
def _save_pdf_to_file(self, pdfbase64, path):
pdfdata = b64decode(pdfbase64)
- with open(path, mode='wb') as pdf:
+ with open(path, mode="wb") as pdf:
pdf.write(pdfdata)
def _get_pdf_path(self, filename):
diff --git a/src/SeleniumLibrary/keywords/selectelement.py b/src/SeleniumLibrary/keywords/selectelement.py
index 68290f1fd..24b45978f 100644
--- a/src/SeleniumLibrary/keywords/selectelement.py
+++ b/src/SeleniumLibrary/keywords/selectelement.py
@@ -13,9 +13,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-from typing import List, Optional, Union
-from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support.ui import Select
from SeleniumLibrary.base import LibraryComponent, keyword
@@ -25,9 +23,7 @@
class SelectElementKeywords(LibraryComponent):
@keyword
- def get_list_items(
- self, locator: Locator, values: bool = False
- ) -> List[str]:
+ def get_list_items(self, locator: Locator, values: bool = False) -> list[str]:
"""Returns all labels or values of selection list ``locator``.
See the `Locating elements` section for details about the locator
@@ -46,8 +42,7 @@ def get_list_items(
options = self._get_options(locator)
if is_truthy(values):
return self._get_values(options)
- else:
- return self._get_labels(options)
+ return self._get_labels(options)
@keyword
def get_selected_list_label(self, locator: Locator) -> str:
@@ -63,7 +58,7 @@ def get_selected_list_label(self, locator: Locator) -> str:
return select.first_selected_option.text
@keyword
- def get_selected_list_labels(self, locator: Locator) -> List[str]:
+ def get_selected_list_labels(self, locator: Locator) -> list[str]:
"""Returns labels of selected options from selection list ``locator``.
Starting from SeleniumLibrary 3.0, returns an empty list if there
@@ -89,7 +84,7 @@ def get_selected_list_value(self, locator: Locator) -> str:
return select.first_selected_option.get_attribute("value")
@keyword
- def get_selected_list_values(self, locator: Locator) -> List[str]:
+ def get_selected_list_values(self, locator: Locator) -> list[str]:
"""Returns values of selected options from selection list ``locator``.
Starting from SeleniumLibrary 3.0, returns an empty list if there
@@ -136,7 +131,9 @@ def list_selection_should_be(self, locator: Locator, *expected: str):
)
def _format_selection(self, labels, values):
- return " | ".join(f"{label} ({value})" for label, value in zip(labels, values))
+ return " | ".join(
+ f"{label} ({value})" for label, value in zip(labels, values, strict=True)
+ )
@keyword
def list_should_have_no_selections(self, locator: Locator):
@@ -160,7 +157,7 @@ def list_should_have_no_selections(self, locator: Locator):
def page_should_contain_list(
self,
locator: Locator,
- message: Optional[str] = None,
+ message: str | None = None,
loglevel: str = "TRACE",
):
"""Verifies selection list ``locator`` is found from current page.
@@ -177,7 +174,7 @@ def page_should_contain_list(
def page_should_not_contain_list(
self,
locator: Locator,
- message: Optional[str] = None,
+ message: str | None = None,
loglevel: str = "TRACE",
):
"""Verifies selection list ``locator`` is not found from current page.
@@ -293,9 +290,7 @@ def unselect_all_from_list(self, locator: Locator):
select.deselect_all()
@keyword
- def unselect_from_list_by_index(
- self, locator: Locator, *indexes: str
- ):
+ def unselect_from_list_by_index(self, locator: Locator, *indexes: str):
"""Unselects options from selection list ``locator`` by ``indexes``.
Indexes of list options start from 0. This keyword works only with
@@ -320,9 +315,7 @@ def unselect_from_list_by_index(
select.deselect_by_index(int(index))
@keyword
- def unselect_from_list_by_value(
- self, locator: Locator, *values: str
- ):
+ def unselect_from_list_by_value(self, locator: Locator, *values: str):
"""Unselects options from selection list ``locator`` by ``values``.
This keyword works only with multi-selection lists.
@@ -345,9 +338,7 @@ def unselect_from_list_by_value(
select.deselect_by_value(value)
@keyword
- def unselect_from_list_by_label(
- self, locator: Locator, *labels: str
- ):
+ def unselect_from_list_by_label(self, locator: Locator, *labels: str):
"""Unselects options from selection list ``locator`` by ``labels``.
This keyword works only with multi-selection lists.
diff --git a/src/SeleniumLibrary/keywords/waiting.py b/src/SeleniumLibrary/keywords/waiting.py
index b8bb9473e..2d6cfe81e 100644
--- a/src/SeleniumLibrary/keywords/waiting.py
+++ b/src/SeleniumLibrary/keywords/waiting.py
@@ -16,7 +16,6 @@
import time
from datetime import timedelta
-from typing import Optional
from selenium.common.exceptions import StaleElementReferenceException
@@ -31,8 +30,8 @@ class WaitingKeywords(LibraryComponent):
def wait_for_condition(
self,
condition: str,
- timeout: Optional[timedelta] = None,
- error: Optional[str] = None,
+ timeout: timedelta | None = None,
+ error: str | None = None,
):
"""Waits until ``condition`` is true or ``timeout`` expires.
@@ -66,8 +65,8 @@ def wait_for_condition(
def wait_until_location_is(
self,
expected: str,
- timeout: Optional[timedelta] = None,
- message: Optional[str] = None,
+ timeout: timedelta | None = None,
+ message: str | None = None,
):
"""Waits until the current URL is ``expected``.
@@ -95,8 +94,8 @@ def wait_until_location_is(
def wait_until_location_is_not(
self,
location: str,
- timeout: Optional[timedelta] = None,
- message: Optional[str] = None,
+ timeout: timedelta | None = None,
+ message: str | None = None,
):
"""Waits until the current URL is not ``location``.
@@ -123,8 +122,8 @@ def wait_until_location_is_not(
def wait_until_location_contains(
self,
expected: str,
- timeout: Optional[timedelta] = None,
- message: Optional[str] = None,
+ timeout: timedelta | None = None,
+ message: str | None = None,
):
"""Waits until the current URL contains ``expected``.
@@ -151,8 +150,8 @@ def wait_until_location_contains(
def wait_until_location_does_not_contain(
self,
location: str,
- timeout: Optional[timedelta] = None,
- message: Optional[str] = None,
+ timeout: timedelta | None = None,
+ message: str | None = None,
):
"""Waits until the current URL does not contains ``location``.
@@ -179,8 +178,8 @@ def wait_until_location_does_not_contain(
def wait_until_page_contains(
self,
text: str,
- timeout: Optional[timedelta] = None,
- error: Optional[str] = None,
+ timeout: timedelta | None = None,
+ error: str | None = None,
):
"""Waits until ``text`` appears on the current page.
@@ -201,8 +200,8 @@ def wait_until_page_contains(
def wait_until_page_does_not_contain(
self,
text: str,
- timeout: Optional[timedelta] = None,
- error: Optional[str] = None,
+ timeout: timedelta | None = None,
+ error: str | None = None,
):
"""Waits until ``text`` disappears from the current page.
@@ -223,9 +222,9 @@ def wait_until_page_does_not_contain(
def wait_until_page_contains_element(
self,
locator: Locator,
- timeout: Optional[timedelta] = None,
- error: Optional[str] = None,
- limit: Optional[int] = None,
+ timeout: timedelta | None = None,
+ error: str | None = None,
+ limit: int | None = None,
):
"""Waits until the element ``locator`` appears on the current page.
@@ -244,12 +243,13 @@ def wait_until_page_contains_element(
``limit`` is new in SeleniumLibrary 4.4
"""
if limit is None:
- return self._wait_until(
+ self._wait_until(
lambda: self.find_element(locator, required=False) is not None,
f"Element '{locator}' did not appear in .",
timeout,
error,
)
+ return
self._wait_until(
lambda: len(self.find_elements(locator)) == limit,
f'Page should have contained "{limit}" {locator} element(s) within .',
@@ -261,9 +261,9 @@ def wait_until_page_contains_element(
def wait_until_page_does_not_contain_element(
self,
locator: Locator,
- timeout: Optional[timedelta] = None,
- error: Optional[str] = None,
- limit: Optional[int] = None,
+ timeout: timedelta | None = None,
+ error: str | None = None,
+ limit: int | None = None,
):
"""Waits until the element ``locator`` disappears from the current page.
@@ -282,12 +282,13 @@ def wait_until_page_does_not_contain_element(
``limit`` is new in SeleniumLibrary 4.4
"""
if limit is None:
- return self._wait_until(
+ self._wait_until(
lambda: self.find_element(locator, required=False) is None,
f"Element '{locator}' did not disappear in .",
timeout,
error,
)
+ return
self._wait_until(
lambda: len(self.find_elements(locator)) != limit,
f'Page should have not contained "{limit}" {locator} element(s) within .',
@@ -299,8 +300,8 @@ def wait_until_page_does_not_contain_element(
def wait_until_element_is_visible(
self,
locator: Locator,
- timeout: Optional[timedelta] = None,
- error: Optional[str] = None,
+ timeout: timedelta | None = None,
+ error: str | None = None,
):
"""Waits until the element ``locator`` is visible.
@@ -322,8 +323,8 @@ def wait_until_element_is_visible(
def wait_until_element_is_not_visible(
self,
locator: Locator,
- timeout: Optional[timedelta] = None,
- error: Optional[str] = None,
+ timeout: timedelta | None = None,
+ error: str | None = None,
):
"""Waits until the element ``locator`` is not visible.
@@ -345,8 +346,8 @@ def wait_until_element_is_not_visible(
def wait_until_element_is_enabled(
self,
locator: Locator,
- timeout: Optional[timedelta] = None,
- error: Optional[str] = None,
+ timeout: timedelta | None = None,
+ error: str | None = None,
):
"""Waits until the element ``locator`` is enabled.
@@ -374,8 +375,8 @@ def wait_until_element_contains(
self,
locator: Locator,
text: str,
- timeout: Optional[timedelta] = None,
- error: Optional[str] = None,
+ timeout: timedelta | None = None,
+ error: str | None = None,
):
"""Waits until the element ``locator`` contains ``text``.
@@ -398,8 +399,8 @@ def wait_until_element_does_not_contain(
self,
locator: Locator,
text: str,
- timeout: Optional[timedelta] = None,
- error: Optional[str] = None,
+ timeout: timedelta | None = None,
+ error: str | None = None,
):
"""Waits until the element ``locator`` does not contain ``text``.
diff --git a/src/SeleniumLibrary/keywords/webdrivertools/sl_file_detector.py b/src/SeleniumLibrary/keywords/webdrivertools/sl_file_detector.py
index 73d26f539..841c357c6 100644
--- a/src/SeleniumLibrary/keywords/webdrivertools/sl_file_detector.py
+++ b/src/SeleniumLibrary/keywords/webdrivertools/sl_file_detector.py
@@ -33,12 +33,11 @@ def choose_file(self):
sl = self._get_sl()
except Exception:
sl = None
- if sl and sl._running_keyword == "choose_file":
- return True
- return False
+ return bool(sl and sl._running_keyword == "choose_file")
def _get_sl(self):
libraries = BuiltIn().get_library_instance(all=True)
for library in libraries:
if isinstance(libraries[library], SeleniumLibrary.SeleniumLibrary):
return libraries[library]
+ return None
diff --git a/src/SeleniumLibrary/keywords/webdrivertools/webdrivertools.py b/src/SeleniumLibrary/keywords/webdrivertools/webdrivertools.py
index 3e05294ae..695717f77 100644
--- a/src/SeleniumLibrary/keywords/webdrivertools/webdrivertools.py
+++ b/src/SeleniumLibrary/keywords/webdrivertools/webdrivertools.py
@@ -18,7 +18,7 @@
import inspect
import os
import token
-import warnings
+from inspect import signature
from io import StringIO
from tokenize import generate_tokens
@@ -26,7 +26,6 @@
from robot.utils import ConnectionCache
from selenium import webdriver
from selenium.webdriver import FirefoxProfile
-
from selenium.webdriver.chrome.service import Service as ChromeService
from selenium.webdriver.edge.service import Service as EdgeService
from selenium.webdriver.firefox.service import Service as FirefoxService
@@ -40,22 +39,20 @@
class WebDriverCreator:
-
- browser_names = {
- "googlechrome": "chrome",
- "gc": "chrome",
- "chrome": "chrome",
- "headlesschrome": "headless_chrome",
- "ff": "firefox",
- "firefox": "firefox",
- "headlessfirefox": "headless_firefox",
- "ie": "ie",
- "internetexplorer": "ie",
- "edge": "edge",
- "safari": "safari",
- }
-
def __init__(self, log_dir):
+ self.browser_names = {
+ "googlechrome": "chrome",
+ "gc": "chrome",
+ "chrome": "chrome",
+ "headlesschrome": "headless_chrome",
+ "ff": "firefox",
+ "firefox": "firefox",
+ "headlessfirefox": "headless_firefox",
+ "ie": "ie",
+ "internetexplorer": "ie",
+ "edge": "edge",
+ "safari": "safari",
+ }
self.log_dir = log_dir
self.selenium_options = SeleniumOptions()
self.selenium_service = SeleniumService()
@@ -80,10 +77,7 @@ def create_driver(
if service_log_path:
logger.info(f"Browser driver log file created to: {service_log_path}")
self._create_directory(service_log_path)
- if (
- creation_method == self.create_firefox
- or creation_method == self.create_headless_firefox
- ):
+ if creation_method in [self.create_firefox, self.create_headless_firefox]:
return creation_method(
desired_capabilities,
remote_url,
@@ -137,12 +131,10 @@ def _remote_capabilities_resolver(self, set_capabilities, default_capabilities):
def _get_log_method(self, service_cls, service_log_path):
# -- temporary fix to transition selenium to v4.13 from v4.11 and prior
- from inspect import signature
sig = signature(service_cls)
- if 'log_output' in str(sig):
- return {'log_output': service_log_path}
- else:
- return {'log_path': service_log_path}
+ if "log_output" in str(sig):
+ return {"log_output": service_log_path}
+ return {"log_path": service_log_path}
# --
def create_chrome(
@@ -159,7 +151,9 @@ def create_chrome(
options = webdriver.ChromeOptions()
return self._remote(remote_url, options=options)
if not executable_path:
- executable_path = self._get_executable_path(webdriver.chrome.service.Service)
+ executable_path = self._get_executable_path(
+ webdriver.chrome.service.Service
+ )
log_method = self._get_log_method(ChromeService, service_log_path)
if not service:
service = ChromeService(executable_path=executable_path, **log_method)
@@ -179,9 +173,14 @@ def create_headless_chrome(
):
if not options:
options = webdriver.ChromeOptions()
- options.add_argument('--headless=new')
+ options.add_argument("--headless=new")
return self.create_chrome(
- desired_capabilities, remote_url, options, service_log_path, executable_path, service
+ desired_capabilities,
+ remote_url,
+ options,
+ service_log_path,
+ executable_path,
+ service,
)
def _get_executable_path(self, webdriver):
@@ -215,8 +214,12 @@ def create_firefox(
if remote_url:
return self._remote(remote_url, options)
if not executable_path:
- executable_path = self._get_executable_path(webdriver.firefox.service.Service)
- log_method = self._get_log_method(FirefoxService, service_log_path or self._geckodriver_log)
+ executable_path = self._get_executable_path(
+ webdriver.firefox.service.Service
+ )
+ log_method = self._get_log_method(
+ FirefoxService, service_log_path or self._geckodriver_log
+ )
if service is None:
service = FirefoxService(executable_path=executable_path, **log_method)
return webdriver.Firefox(
@@ -263,7 +266,7 @@ def create_headless_firefox(
):
if not options:
options = webdriver.FirefoxOptions()
- options.add_argument('-headless')
+ options.add_argument("-headless")
return self.create_firefox(
desired_capabilities,
remote_url,
@@ -295,7 +298,7 @@ def create_ie(
return webdriver.Ie(
options=options,
service=service,
- #**desired_capabilities,
+ # **desired_capabilities,
)
def _has_options(self, web_driver):
@@ -323,7 +326,7 @@ def create_edge(
return webdriver.Edge(
options=options,
service=service,
- #**desired_capabilities,
+ # **desired_capabilities,
)
def create_safari(
@@ -461,10 +464,10 @@ def _get_index(self, alias_or_index):
except ValueError:
return None
+
class SeleniumService:
- """
+ """ """
- """
def create(self, browser, service):
if not service:
return None
@@ -478,10 +481,13 @@ def create(self, browser, service):
service_parameters = inspect.signature(selenium_service).parameters
for key in attrs:
if key not in service_parameters:
- service_module = '.'.join((selenium_service.__module__, selenium_service.__qualname__))
- raise ValueError(f"{key} is not a member of {service_module} Service class")
- selenium_service_inst = selenium_service(**attrs)
- return selenium_service_inst
+ service_module = ".".join(
+ (selenium_service.__module__, selenium_service.__qualname__)
+ )
+ raise ValueError(
+ f"{key} is not a member of {service_module} Service class"
+ )
+ return selenium_service(**attrs)
def _parse(self, service):
"""The service argument parses slightly different than the options argument. As of
@@ -489,12 +495,14 @@ def _parse(self, service):
instantiation. Thus each item is split instead parsed as done with options.
"""
result = {}
- for item in self._split(service,';'):
+ for item in self._split(service, ";"):
try:
- attr, val = self._split(item, '=')
- result[attr]=ast.literal_eval(val)
- except (ValueError, SyntaxError):
- raise ValueError(f'Unable to parse service: "{item}"')
+ attr, val = self._split(item, "=")
+ result[attr] = ast.literal_eval(val)
+ except (ValueError, SyntaxError) as original_exception:
+ raise ValueError(
+ f'Unable to parse service: "{item}"'
+ ) from original_exception
return result
def _import_service(self, browser):
@@ -514,6 +522,7 @@ def _split(self, service_or_attr, splittok):
split_string.append(service_or_attr[start_position:])
return split_string
+
class SeleniumOptions:
def create(self, browser, options):
if not options:
@@ -525,8 +534,10 @@ def create(self, browser, options):
selenium_options = selenium_options()
for option in options:
for key in option:
- if key == '' and option[key]==[]:
- logger.warn('Empty selenium option found and ignored. Suggested you review options passed to `Open Browser` keyword')
+ if key == "" and option[key] == []:
+ logger.warn(
+ "Empty selenium option found and ignored. Suggested you review options passed to `Open Browser` keyword"
+ )
continue
attr = getattr(selenium_options, key)
if callable(attr):
@@ -575,8 +586,10 @@ def _parse(self, options):
for item in self._split(options):
try:
result.append(self._parse_to_tokens(item))
- except (ValueError, SyntaxError):
- raise ValueError(f'Unable to parse option: "{item}"')
+ except (ValueError, SyntaxError) as original_exception:
+ raise ValueError(
+ f'Unable to parse option: "{item}"'
+ ) from original_exception
return result
def _parse_to_tokens(self, item):
diff --git a/src/SeleniumLibrary/keywords/window.py b/src/SeleniumLibrary/keywords/window.py
index f2b086223..e0393cbe9 100644
--- a/src/SeleniumLibrary/keywords/window.py
+++ b/src/SeleniumLibrary/keywords/window.py
@@ -14,14 +14,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import time
-from typing import Optional, List, Tuple, Union
-from SeleniumLibrary.utils import is_truthy, is_falsy, timestr_to_secs
from selenium.common.exceptions import NoSuchWindowException
-from SeleniumLibrary.base import keyword, LibraryComponent
+from SeleniumLibrary.base import LibraryComponent, keyword
from SeleniumLibrary.locators import WindowManager
-from SeleniumLibrary.utils import plural_or_not
+from SeleniumLibrary.utils import is_falsy, is_truthy, plural_or_not, timestr_to_secs
class WindowKeywords(LibraryComponent):
@@ -32,8 +30,8 @@ def __init__(self, ctx):
@keyword
def switch_window(
self,
- locator: Union[list, str] = "MAIN",
- timeout: Optional[str] = None,
+ locator: list | str = "MAIN",
+ timeout: str | None = None,
browser: str = "CURRENT",
):
"""Switches to browser window matching ``locator``.
@@ -117,17 +115,17 @@ def switch_window(
except NoSuchWindowException:
pass
finally:
- if not isinstance(browser, str) or not browser.upper() == "CURRENT":
+ if not isinstance(browser, str) or browser.upper() != "CURRENT":
self.drivers.switch(browser)
self._window_manager.select(locator, timeout)
@keyword
def close_window(self):
- """Closes currently opened and selected browser window/tab. """
+ """Closes currently opened and selected browser window/tab."""
self.driver.close()
@keyword
- def get_window_handles(self, browser: str = "CURRENT") -> List[str]:
+ def get_window_handles(self, browser: str = "CURRENT") -> list[str]:
"""Returns all child window handles of the selected browser as a list.
Can be used as a list of windows to exclude with `Select Window`.
@@ -139,7 +137,7 @@ def get_window_handles(self, browser: str = "CURRENT") -> List[str]:
return self._window_manager.get_window_handles(browser)
@keyword
- def get_window_identifiers(self, browser: str = "CURRENT") -> List:
+ def get_window_identifiers(self, browser: str = "CURRENT") -> list:
"""Returns and logs id attributes of all windows of the selected browser.
How to select the ``browser`` scope of this keyword, see `Get Locations`."""
@@ -147,7 +145,7 @@ def get_window_identifiers(self, browser: str = "CURRENT") -> List:
return self._log_list(ids)
@keyword
- def get_window_names(self, browser: str = "CURRENT") -> List[str]:
+ def get_window_names(self, browser: str = "CURRENT") -> list[str]:
"""Returns and logs names of all windows of the selected browser.
How to select the ``browser`` scope of this keyword, see `Get Locations`."""
@@ -155,7 +153,7 @@ def get_window_names(self, browser: str = "CURRENT") -> List[str]:
return self._log_list(names)
@keyword
- def get_window_titles(self, browser: str = "CURRENT") -> List[str]:
+ def get_window_titles(self, browser: str = "CURRENT") -> list[str]:
"""Returns and logs titles of all windows of the selected browser.
How to select the ``browser`` scope of this keyword, see `Get Locations`."""
@@ -163,7 +161,7 @@ def get_window_titles(self, browser: str = "CURRENT") -> List[str]:
return self._log_list(titles)
@keyword
- def get_locations(self, browser: str = "CURRENT") -> List[str]:
+ def get_locations(self, browser: str = "CURRENT") -> list[str]:
"""Returns and logs URLs of all windows of the selected browser.
*Browser Scope:*
@@ -192,7 +190,7 @@ def minimize_browser_window(self):
self.driver.minimize_window()
@keyword
- def get_window_size(self, inner: bool = False) -> Tuple[float, float]:
+ def get_window_size(self, inner: bool = False) -> tuple[float, float]:
"""Returns current window width and height as integers.
See also `Set Window Size`.
@@ -239,7 +237,8 @@ def set_window_size(self, width: int, height: int, inner: bool = False):
| `Set Window Size` | 800 | 600 | True |
"""
if is_falsy(inner):
- return self.driver.set_window_size(width, height)
+ self.driver.set_window_size(width, height)
+ return
self.driver.set_window_size(width, height)
inner_width = int(self.driver.execute_script("return window.innerWidth;"))
inner_height = int(self.driver.execute_script("return window.innerHeight;"))
@@ -258,7 +257,7 @@ def set_window_size(self, width: int, height: int, inner: bool = False):
raise AssertionError("Keyword failed setting correct window size.")
@keyword
- def get_window_position(self) -> Tuple[int, int]:
+ def get_window_position(self) -> tuple[int, int]:
"""Returns current window position.
The position is relative to the top left corner of the screen. Returned
diff --git a/src/SeleniumLibrary/locators/customlocator.py b/src/SeleniumLibrary/locators/customlocator.py
index ab967e0e2..96555c7a2 100644
--- a/src/SeleniumLibrary/locators/customlocator.py
+++ b/src/SeleniumLibrary/locators/customlocator.py
@@ -31,7 +31,7 @@ def find(self, criteria, tag, constraints, parent):
element = BuiltIn().run_keyword(
self.finder, parent, criteria, tag, constraints
)
- elif hasattr(self.finder, "__call__"):
+ elif callable(self.finder):
element = self.finder(parent, criteria, tag, constraints)
else:
raise AttributeError(
@@ -41,5 +41,4 @@ def find(self, criteria, tag, constraints, parent):
# Always return an array
if hasattr(element, "__len__") and not isinstance(element, str):
return element
- else:
- return [element]
+ return [element]
diff --git a/src/SeleniumLibrary/locators/elementfinder.py b/src/SeleniumLibrary/locators/elementfinder.py
index e48f63f87..b3749b522 100644
--- a/src/SeleniumLibrary/locators/elementfinder.py
+++ b/src/SeleniumLibrary/locators/elementfinder.py
@@ -14,13 +14,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import re
-from typing import Union
from robot.api import logger
from robot.utils import NormalizedDict
+from selenium.webdriver.common.by import By
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support.event_firing_webdriver import EventFiringWebElement
-from selenium.webdriver.common.by import By
from SeleniumLibrary.base import ContextAware
from SeleniumLibrary.errors import ElementNotFound
@@ -78,7 +77,7 @@ def __init__(self, ctx):
def find(
self,
- locator: Union[str, list],
+ locator: str | list,
tag=None,
first_only=True,
required=True,
@@ -92,7 +91,7 @@ def find(
)
return self._find(locators[-1], tag, first_only, required, element)
- def _split_locator(self, locator: Union[str, list]) -> list:
+ def _split_locator(self, locator: str | list) -> list:
if isinstance(locator, list):
return locator
if not isinstance(locator, str):
@@ -226,10 +225,10 @@ def _find_by_data_locator(self, criteria, tag, constraints, parent):
name, value = criteria.split(":", 1)
if "" in [name, value]:
raise ValueError
- except ValueError:
+ except ValueError as original_exception:
raise ValueError(
f"Provided selector ({criteria}) is malformed. Correct format: name:value."
- )
+ ) from original_exception
local_criteria = f'//*[@data-{name}="{value}"]'
return self._find_by_xpath(local_criteria, tag, constraints, parent)
@@ -257,20 +256,18 @@ def _find_by_default(self, criteria, tag, constraints, parent):
return self._normalize(parent.find_elements(By.XPATH, xpath))
def _get_xpath_constraints(self, constraints):
- xpath_constraints = [
+ return [
self._get_xpath_constraint(name, value)
for name, value in constraints.items()
]
- return xpath_constraints
def _get_xpath_constraint(self, name, value):
if isinstance(value, list):
value = "' or . = '".join(value)
return f"@{name}[. = '{value}']"
- else:
- return f"@{name}='{value}'"
+ return f"@{name}='{value}'"
- def _get_tag_and_constraints(self, tag):
+ def _get_tag_and_constraints(self, tag): # noqa: C901
if tag is None:
return None, {}
tag = tag.lower()
@@ -331,7 +328,7 @@ def _get_locator_separator_index(self, locator):
return min(locator.find("="), locator.find(":"))
def _element_matches(self, element, tag, constraints):
- if not element.tag_name.lower() == tag:
+ if element.tag_name.lower() != tag:
return False
for name in constraints:
if isinstance(constraints[name], list):
diff --git a/src/SeleniumLibrary/locators/windowmanager.py b/src/SeleniumLibrary/locators/windowmanager.py
index a785babbd..8244c8236 100644
--- a/src/SeleniumLibrary/locators/windowmanager.py
+++ b/src/SeleniumLibrary/locators/windowmanager.py
@@ -15,7 +15,7 @@
# limitations under the License.
import time
-from collections import namedtuple
+from typing import NamedTuple
from selenium.common.exceptions import NoSuchWindowException, WebDriverException
@@ -23,7 +23,12 @@
from SeleniumLibrary.errors import WindowNotFound
-WindowInfo = namedtuple("WindowInfo", "handle, id, name, title, url")
+class WindowInfo(NamedTuple):
+ handle: str
+ id: object
+ name: str
+ title: str
+ url: str
class WindowManager(ContextAware):
@@ -40,19 +45,18 @@ def get_window_handles(self, browser):
if isinstance(browser, str) and browser == "ALL":
handles = []
current_index = self.drivers.current_index
- for index, driver in enumerate(self.drivers, 1):
+ for index, _driver in enumerate(self.drivers, 1):
self.drivers.switch(index)
handles.extend(self.driver.window_handles)
self.drivers.switch(current_index)
return handles
- elif isinstance(browser, str) and browser == "CURRENT":
+ if isinstance(browser, str) and browser == "CURRENT":
return self.driver.window_handles
- else:
- current_index = self.drivers.current_index
- self.drivers.switch(browser)
- handles = self.driver.window_handles
- self.drivers.switch(current_index)
- return handles
+ current_index = self.drivers.current_index
+ self.drivers.switch(browser)
+ handles = self.driver.window_handles
+ self.drivers.switch(current_index)
+ return handles
def get_window_infos(self, browser="CURRENT"):
try:
@@ -61,18 +65,17 @@ def get_window_infos(self, browser="CURRENT"):
current_index = None
if isinstance(browser, str) and browser.upper() == "ALL":
infos = []
- for index, driver in enumerate(self.drivers, 1):
+ for index, _driver in enumerate(self.drivers, 1):
self.drivers.switch(index)
infos.extend(self._get_window_infos())
self.drivers.switch(current_index)
return infos
- elif isinstance(browser, str) and browser.upper() == "CURRENT":
+ if isinstance(browser, str) and browser.upper() == "CURRENT":
return self._get_window_infos()
- else:
- self.drivers.switch(browser)
- infos = self._get_window_infos()
- self.drivers.switch(current_index)
- return infos
+ self.drivers.switch(browser)
+ infos = self._get_window_infos()
+ self.drivers.switch(current_index)
+ return infos
def _get_window_infos(self):
infos = []
@@ -196,14 +199,16 @@ def _select_matching(self, matcher, error):
def _get_current_window_info(self):
try:
- id, name = self.driver.execute_script("return [ window.id, window.name ];")
+ window_id, name = self.driver.execute_script(
+ "return [ window.id, window.name ];"
+ )
except WebDriverException:
# The webdriver implementation doesn't support Javascript so we
# can't get window id or name this way.
- id = name = None
+ window_id = name = None
return WindowInfo(
self.driver.current_window_handle,
- id if id is not None else "undefined",
+ window_id if window_id is not None else "undefined",
name or "undefined",
self.driver.title or "undefined",
self.driver.current_url or "undefined",
diff --git a/src/SeleniumLibrary/utils/__init__.py b/src/SeleniumLibrary/utils/__init__.py
index 68ba94e1b..7440fe29d 100644
--- a/src/SeleniumLibrary/utils/__init__.py
+++ b/src/SeleniumLibrary/utils/__init__.py
@@ -17,14 +17,14 @@
from robot.utils import plural_or_not, secs_to_timestr, timestr_to_secs # noqa
from .librarylistener import LibraryListener # noqa
-from .types import (
+from .types import ( # noqa
is_falsy,
is_noney,
is_truthy,
WINDOWS,
_convert_timeout,
_convert_delay,
-) # noqa
+)
def escape_xpath_value(value: str):
diff --git a/src/SeleniumLibrary/utils/events/__init__.py b/src/SeleniumLibrary/utils/events/__init__.py
index edbae3fb5..d1f90519d 100644
--- a/src/SeleniumLibrary/utils/events/__init__.py
+++ b/src/SeleniumLibrary/utils/events/__init__.py
@@ -14,10 +14,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from .scope_event import ScopeStart, ScopeEnd
+from .scope_event import ScopeEnd, ScopeStart
-
-__all__ = ["on", "dispatch", "register_event"]
+__all__ = ["dispatch", "on", "register_event"]
_registered_events = [ScopeStart, ScopeEnd]
_events = []
diff --git a/src/SeleniumLibrary/utils/events/event.py b/src/SeleniumLibrary/utils/events/event.py
index 711ea7af4..ec5381548 100644
--- a/src/SeleniumLibrary/utils/events/event.py
+++ b/src/SeleniumLibrary/utils/events/event.py
@@ -15,8 +15,8 @@
# limitations under the License.
import abc
-from selenium.webdriver.support.event_firing_webdriver import EventFiringWebElement
-from robot.api import logger
+
+import selenium
class Event:
@@ -26,8 +26,4 @@ def trigger(self, *args, **kwargs):
def selenium_major_version():
- import selenium
-
- selenium_version = selenium.__version__
- (major, *sub_versions) = selenium_version.split(".")
- return int(major)
+ return int(selenium.__version__.split(".", 1)[0])
diff --git a/src/SeleniumLibrary/utils/types.py b/src/SeleniumLibrary/utils/types.py
index 04ecc8f40..e12657d53 100644
--- a/src/SeleniumLibrary/utils/types.py
+++ b/src/SeleniumLibrary/utils/types.py
@@ -17,26 +17,25 @@
from datetime import timedelta
from typing import Any, TypeAlias
-from robot.utils import timestr_to_secs
-from robot.utils import is_truthy, is_falsy # noqa
+from robot.utils import is_falsy, is_truthy, timestr_to_secs # noqa
from selenium.webdriver.remote.webelement import WebElement
-
# Need only for unit tests and can be removed when Approval tests fixes:
# https://github.com/approvals/ApprovalTests.Python/issues/41
WINDOWS = os.name == "nt"
-Locator: TypeAlias = WebElement | str | list['Locator']
+Locator: TypeAlias = WebElement | str | list["Locator"]
+
def is_noney(item):
- return item is None or isinstance(item, str) and item.upper() == "NONE"
+ return item is None or (isinstance(item, str) and item.upper() == "NONE")
+
def _convert_delay(delay):
if isinstance(delay, timedelta):
return delay.microseconds // 1000
- else:
- x = timestr_to_secs(delay)
- return int( x * 1000)
+ x = timestr_to_secs(delay)
+ return int(x * 1000)
def _convert_timeout(timeout):
diff --git a/tasks.py b/tasks.py
index 84c093b98..0f578fe37 100644
--- a/tasks.py
+++ b/tasks.py
@@ -186,11 +186,29 @@ def init_labels(ctx, username=None, password=None):
@task
-def lint(ctx):
- """Runs black and flake8 for project Python code."""
- ctx.run("black --config pyproject.toml tasks.py src/ utest/ atest/")
- ctx.run("flake8 --config .flake8 tasks.py src/ utest/ atest/")
+def lint(ctx, fix=False):
+ """Run Ruff lint checkse.
+ Args:
+ fix: Apply safe fixes when True. Defaults to False.
+ """
+ cmd = f"{sys.executable} -m ruff check --config pyproject.toml src/ utest/" # atest/"
+ if fix:
+ cmd = f"{cmd} --fix"
+ ctx.run(cmd)
+
+@task
+def format(ctx, check=False):
+ """Run Ruff formatter.
+
+ Args:
+ check: When True, only check formatting and show diff.
+ When False, apply formatting changes.
+ """
+ cmd = f"{sys.executable} -m ruff format --config pyproject.toml src/ utest/ atest/"
+ if check:
+ cmd = f"{cmd} --check --diff"
+ ctx.run(cmd)
@task
def gen_stub(ctx):
@@ -207,12 +225,12 @@ def atest(ctx, suite=None):
Args:
suite: Select which suite to run.
-
+
Example:
inv utest --suite keywords/test_browsermanagement.py
inv utest --suite keywords/test_selenium_options_parser.py::test_create_chrome_with_options
"""
- command = "python atest/run.py headlesschrome"
+ command = f"{sys.executable} atest/run.py headlesschrome"
if suite:
command = f"{command} --suite {suite}"
ctx.run(command)
diff --git a/utest/run.py b/utest/run.py
index f201c61f2..4f4785dce 100755
--- a/utest/run.py
+++ b/utest/run.py
@@ -1,13 +1,13 @@
#!/usr/bin/env python
import argparse
+import logging
import os
import shutil
import sys
from os.path import join
from pathlib import Path
-from pytest import main as py_main
-
+import pytest
CURDIR = Path(__file__).parent
SRC = join(CURDIR, os.pardir, "src")
@@ -38,9 +38,9 @@ def run_unit_tests(reporter, reporter_args, suite, verbose):
if reporter_args:
py_args.insert(1, f"--approvaltests-add-reporter-args={reporter_args}")
try:
- result = py_main(py_args)
+ result = pytest.main(py_args)
except Exception as error:
- print(f"Suppressed error: {error}")
+ logging.exception(f"Suppressed error: {error}")
result = 254
finally:
sys.path.pop(0)
diff --git a/utest/test/api/approved_files/PluginDocumentation.test_many_plugins.approved.txt b/utest/test/api/approved_files/PluginDocumentation.test_many_plugins.approved.txt
index ce7ebb397..ec9e23125 100644
--- a/utest/test/api/approved_files/PluginDocumentation.test_many_plugins.approved.txt
+++ b/utest/test/api/approved_files/PluginDocumentation.test_many_plugins.approved.txt
@@ -528,18 +528,18 @@ Example project for translation can be found from
[https://github.com/MarketSquare/robotframework-seleniumlibrary-translation-fi | robotframework-seleniumlibrary-translation-fi]
repository.
-= Plugin: my_lib =
+= Plugin: MyLib =
Some dummy documentation.
-= my_lib Heading 1 =
+= MyLib Heading 1 =
This is heading 1 documentation.
-== my_lib Heading 2 ==
+== MyLib Heading 2 ==
This is heading 2 documentation.
-= Plugin: my_lib_args =
+= Plugin: MyLibArgs =
No plugin documentation found.
diff --git a/utest/test/api/my_lib.py b/utest/test/api/my_lib.py
index b5c45c932..3dc65ee95 100644
--- a/utest/test/api/my_lib.py
+++ b/utest/test/api/my_lib.py
@@ -1,14 +1,14 @@
from SeleniumLibrary.base import LibraryComponent, keyword
-class my_lib(LibraryComponent):
+class MyLib(LibraryComponent):
"""Some dummy documentation.
- = my_lib Heading 1 =
+ = MyLib Heading 1 =
This is heading 1 documentation.
- == my_lib Heading 2 ==
+ == MyLib Heading 2 ==
This is heading 2 documentation.
"""
@@ -20,3 +20,6 @@ def foo(self):
@keyword
def bar(self, arg):
self.info(arg)
+
+
+my_lib = MyLib
diff --git a/utest/test/api/my_lib_args.py b/utest/test/api/my_lib_args.py
index e1736ca02..572bd2abc 100644
--- a/utest/test/api/my_lib_args.py
+++ b/utest/test/api/my_lib_args.py
@@ -1,7 +1,7 @@
from SeleniumLibrary.base import LibraryComponent, keyword
-class my_lib_args(LibraryComponent):
+class MyLibArgs(LibraryComponent):
def __init__(self, ctx, arg1, arg2, *args, **kwargs):
LibraryComponent.__init__(self, ctx)
self.arg1 = arg1
@@ -21,3 +21,6 @@ def bar_2(self, arg):
def add_cookie(self, foo, bar):
self.info(foo)
self.info(bar)
+
+
+my_lib_args = MyLibArgs
diff --git a/utest/test/api/my_lib_not_inherit.py b/utest/test/api/my_lib_not_inherit.py
index 37210be63..ec4c37a27 100644
--- a/utest/test/api/my_lib_not_inherit.py
+++ b/utest/test/api/my_lib_not_inherit.py
@@ -1,10 +1,13 @@
from SeleniumLibrary.base import keyword
-class my_lib_not_inherit:
+class MyLibNotInherit:
def __init__(self, ctx):
self.ctx = ctx
@keyword
def bar(self, arg):
self.info(arg)
+
+
+my_lib_not_inherit = MyLibNotInherit
diff --git a/utest/test/api/my_lib_wrong_name.py b/utest/test/api/my_lib_wrong_name.py
index 8d23a5ba3..56eff8293 100644
--- a/utest/test/api/my_lib_wrong_name.py
+++ b/utest/test/api/my_lib_wrong_name.py
@@ -1,7 +1,7 @@
from SeleniumLibrary.base import LibraryComponent, keyword
-class my_lib(LibraryComponent):
+class MyLib(LibraryComponent):
@keyword
def tidii(self, arg):
self.info(arg)
diff --git a/utest/test/api/plugin_tester.py b/utest/test/api/plugin_tester.py
index 1df9b23e6..39480f1b6 100644
--- a/utest/test/api/plugin_tester.py
+++ b/utest/test/api/plugin_tester.py
@@ -1,7 +1,7 @@
from SeleniumLibrary.base import LibraryComponent, keyword
-class plugin_tester(LibraryComponent):
+class PluginTester(LibraryComponent):
def __init__(self, ctx):
LibraryComponent.__init__(self, ctx)
ctx.event_firing_webdriver = "should be last"
@@ -13,3 +13,6 @@ def foo(self):
@keyword
def bar(self, arg):
self.info(arg)
+
+
+plugin_tester = PluginTester
diff --git a/utest/test/api/plugin_with_event_firing_webdriver.py b/utest/test/api/plugin_with_event_firing_webdriver.py
index 4246838e6..d90c34ab7 100644
--- a/utest/test/api/plugin_with_event_firing_webdriver.py
+++ b/utest/test/api/plugin_with_event_firing_webdriver.py
@@ -1,9 +1,8 @@
from SeleniumLibrary.base import LibraryComponent, keyword
-class plugin_with_event_firing_webdriver(LibraryComponent):
-
- """This is example for plugin_with_event_firing_webdriver plugin documentation.
+class PluginWithEventFiringWebdriver(LibraryComponent):
+ """This is example for PluginWithEventFiringWebdriver plugin documentation.
It may contains many chapters and there might be many words
in the documentation. This is really boring example but let
@@ -11,11 +10,11 @@ class plugin_with_event_firing_webdriver(LibraryComponent):
There might be reference to keywords, like `Open Browser`
- == plugin_with_event_firing_webdriver Heading 2 part 1 ==
+ == PluginWithEventFiringWebdriver Heading 2 part 1 ==
This is chapter in heading 2.
- == plugin_with_event_firing_webdriver Heading 2 part 2==
+ == PluginWithEventFiringWebdriver Heading 2 part 2==
This is another chapter in heading 2
"""
@@ -32,3 +31,6 @@ def __init__(self, ctx):
@keyword
def tidii(self):
self.info("foo")
+
+
+plugin_with_event_firing_webdriver = PluginWithEventFiringWebdriver
diff --git a/utest/test/api/test_accessing_keywod_methods.py b/utest/test/api/test_accessing_keywod_methods.py
index 9576a7f4c..8049c676a 100644
--- a/utest/test/api/test_accessing_keywod_methods.py
+++ b/utest/test/api/test_accessing_keywod_methods.py
@@ -1,5 +1,7 @@
import unittest
+import pytest
+
from SeleniumLibrary import SeleniumLibrary
@@ -9,19 +11,19 @@ def setUpClass(cls):
cls.selib = SeleniumLibrary()
def test_kw_with_method_name(self):
- self.assertTrue(self.selib.keywords["add_cookie"])
- self.assertTrue(self.selib.attributes["add_cookie"])
- self.assertTrue(self.selib.keywords["page_should_contain_image"])
- self.assertTrue(self.selib.attributes["page_should_contain_image"])
+ assert self.selib.keywords["add_cookie"]
+ assert self.selib.attributes["add_cookie"]
+ assert self.selib.keywords["page_should_contain_image"]
+ assert self.selib.attributes["page_should_contain_image"]
def test_kw_with_methods_name_do_not_have_kw_name(self):
- with self.assertRaises(KeyError):
+ with pytest.raises(KeyError):
self.selib.keywords["Add Cookie"]
- with self.assertRaises(KeyError):
+ with pytest.raises(KeyError):
self.selib.keywords["Page Should Contain Image"]
def test_kw_with_decorated_name(self):
- self.assertTrue(self.selib.attributes["get_webelement"])
- self.assertTrue(self.selib.keywords["Get WebElement"])
- self.assertTrue(self.selib.attributes["get_webelements"])
- self.assertTrue(self.selib.keywords["Get WebElements"])
+ assert self.selib.attributes["get_webelement"]
+ assert self.selib.keywords["Get WebElement"]
+ assert self.selib.attributes["get_webelements"]
+ assert self.selib.keywords["Get WebElements"]
diff --git a/utest/test/api/test_event_firing_webdriver.py b/utest/test/api/test_event_firing_webdriver.py
index 205eace61..d9c03ef1d 100644
--- a/utest/test/api/test_event_firing_webdriver.py
+++ b/utest/test/api/test_event_firing_webdriver.py
@@ -1,6 +1,7 @@
import os
import unittest
+import pytest
from robot.errors import DataError
from selenium.webdriver.support.events import AbstractEventListener
@@ -19,13 +20,18 @@ def test_import_event_firing_webdriver(self):
def test_no_event_firing_webdriver(self):
sl = SeleniumLibrary()
- self.assertIsNone(sl.event_firing_webdriver)
+ assert sl.event_firing_webdriver is None
def test_import_event_firing_webdriver_error_module(self):
listener = os.path.join(self.root_dir, "MyListenerWrongName.py")
- with self.assertRaises(DataError):
+ with pytest.raises(
+ DataError, match=r"Importing test Selenium lister class '.*' failed."
+ ):
SeleniumLibrary(event_firing_webdriver=listener)
def test_too_many_event_firing_webdriver(self):
- with self.assertRaises(ValueError):
+ with pytest.raises(
+ ValueError,
+ match=r"It is possible to import only one listener but there were 2 listeners.",
+ ):
SeleniumLibrary(event_firing_webdriver=f"{self.listener},{self.listener}")
diff --git a/utest/test/api/test_filepath_unusual_characters.py b/utest/test/api/test_filepath_unusual_characters.py
index fdfc5fa9d..395d1e87a 100644
--- a/utest/test/api/test_filepath_unusual_characters.py
+++ b/utest/test/api/test_filepath_unusual_characters.py
@@ -5,7 +5,6 @@
from approvaltests.reporters.generic_diff_reporter_factory import (
GenericDiffReporterFactory,
)
-from robot.utils import WINDOWS
from SeleniumLibrary.utils.path_formatter import _format_path
@@ -21,7 +20,6 @@ def reporter():
return factory.get_first_working()
-@pytest.mark.skipif(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_normal_file_path(reporter):
results = []
results.append(_format_path("/foo/file.log", 1))
diff --git a/utest/test/api/test_plugin_documentation.py b/utest/test/api/test_plugin_documentation.py
index b03a18fe4..06c5a6e1f 100644
--- a/utest/test/api/test_plugin_documentation.py
+++ b/utest/test/api/test_plugin_documentation.py
@@ -7,7 +7,6 @@
GenericDiffReporterFactory,
)
from approvaltests.reporters.python_native_reporter import PythonNativeReporter
-from robot.utils import WINDOWS
from SeleniumLibrary import SeleniumLibrary
@@ -30,19 +29,16 @@ def setUp(self):
factory.get_first_working(), PythonNativeReporter()
)
- @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_many_plugins(self):
sl = SeleniumLibrary(
plugins=f"{self.plugin_1}, {self.plugin_3};arg1=Text1;arg2=Text2"
)
verify(sl.get_keyword_documentation("__intro__"), self.reporter)
- @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_parse_plugin_init_doc(self):
sl = SeleniumLibrary(plugins=f"{self.plugin_3};arg1=Text1;arg2=Text2")
verify(sl.get_keyword_documentation("__init__"), self.reporter)
- @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_parse_plugin_kw_doc(self):
sl = SeleniumLibrary(plugins=f"{self.plugin_3};arg1=Text1;arg2=Text2")
verify(sl.get_keyword_documentation("execute_javascript"), self.reporter)
diff --git a/utest/test/api/test_plugin_keyword_tags.py b/utest/test/api/test_plugin_keyword_tags.py
index 368f67783..46063f266 100644
--- a/utest/test/api/test_plugin_keyword_tags.py
+++ b/utest/test/api/test_plugin_keyword_tags.py
@@ -2,8 +2,9 @@
import unittest
from SeleniumLibrary import SeleniumLibrary
-from .my_lib import my_lib
-from .my_lib_args import my_lib_args
+
+from .my_lib import MyLib
+from .my_lib_args import MyLibArgs
class PluginKeywordTags(unittest.TestCase):
@@ -16,33 +17,33 @@ def setUpClass(cls):
def test_no_plugin(self):
sl = SeleniumLibrary()
tags = sl.get_keyword_tags("open_browser")
- self.assertFalse(tags)
+ assert not tags
def test_store_plugin_keywords(self):
sl = SeleniumLibrary()
- sl._store_plugin_keywords(my_lib("0"))
- self.assertEqual(sl._plugin_keywords, ["bar", "foo"])
+ sl._store_plugin_keywords(MyLib("0"))
+ assert sl._plugin_keywords == ["bar", "foo"]
def test_store_plugin_keywords_with_args(self):
sl = SeleniumLibrary()
- sl._store_plugin_keywords(my_lib_args("000", "111", "222"))
- self.assertEqual(sl._plugin_keywords, ["add_cookie", "bar_2", "foo_1"])
+ sl._store_plugin_keywords(MyLibArgs("000", "111", "222"))
+ assert sl._plugin_keywords == ["add_cookie", "bar_2", "foo_1"]
def test_tags_in_plugin(self):
sl = SeleniumLibrary(plugins=self.plugin)
tags = sl.get_keyword_tags("foo")
- self.assertEqual(tags, ["plugin"])
+ assert tags == ["plugin"]
tags = sl.get_keyword_tags("open_browser")
- self.assertFalse(tags)
+ assert not tags
def test_tags_in_plugin_args(self):
sl = SeleniumLibrary(plugins=f"{self.plugin_varargs};foo;bar")
tags = sl.get_keyword_tags("foo_1")
- self.assertEqual(tags, ["MyTag", "plugin"])
+ assert tags == ["MyTag", "plugin"]
tags = sl.get_keyword_tags("open_browser")
- self.assertFalse(tags)
+ assert not tags
tags = sl.get_keyword_tags("add_cookie")
- self.assertEqual(tags, ["plugin"])
+ assert tags == ["plugin"]
diff --git a/utest/test/api/test_plugins.py b/utest/test/api/test_plugins.py
index 16f5bd154..317cc6dd5 100644
--- a/utest/test/api/test_plugins.py
+++ b/utest/test/api/test_plugins.py
@@ -1,7 +1,8 @@
-from collections import namedtuple
import os
import unittest
+from typing import NamedTuple
+import pytest
from robot.errors import DataError
from SeleniumLibrary import SeleniumLibrary
@@ -13,7 +14,12 @@ class ExtendingSeleniumLibrary(unittest.TestCase):
def setUpClass(cls):
cls.sl = SeleniumLibrary()
cls.root_dir = os.path.dirname(os.path.abspath(__file__))
- Plugin = namedtuple("Plugin", "plugin, args, kw_args")
+
+ class Plugin(NamedTuple):
+ plugin: str
+ args: list
+ kw_args: dict
+
lib = Plugin(
plugin=os.path.join(cls.root_dir, "my_lib.py"), args=[], kw_args={}
)
@@ -22,75 +28,75 @@ def setUpClass(cls):
def test_no_libraries(self):
for item in [None, "None", ""]:
sl = SeleniumLibrary(plugins=item)
- self.assertEqual(len(sl.get_keyword_names()), 183)
+ assert len(sl.get_keyword_names()) == 183
def test_parse_library(self):
plugin = "path.to.MyLibrary"
plugins = self.sl._string_to_modules(plugin)
- self.assertEqual(len(plugins), 1)
- self.assertEqual(plugins[0].module, plugin)
- self.assertEqual(plugins[0].args, [])
- self.assertEqual(plugins[0].kw_args, {})
+ assert len(plugins) == 1
+ assert plugins[0].module == plugin
+ assert plugins[0].args == []
+ assert plugins[0].kw_args == {}
def test_parse_libraries(self):
plugin = "path.to.MyLibrary,path.to.OtherLibrary"
plugins = self.sl._string_to_modules(plugin)
- self.assertEqual(len(plugins), 2)
- self.assertEqual(plugins[0].module, plugin.split(",")[0])
- self.assertEqual(plugins[0].args, [])
- self.assertEqual(plugins[1].module, plugin.split(",")[1])
- self.assertEqual(plugins[1].args, [])
+ assert len(plugins) == 2
+ assert plugins[0].module == plugin.split(",", maxsplit=1)[0]
+ assert plugins[0].args == []
+ assert plugins[1].module == plugin.split(",")[1]
+ assert plugins[1].args == []
def test_comma_and_space(self):
plugin = "path.to.MyLibrary , path.to.OtherLibrary"
plugins = self.sl._string_to_modules(plugin)
- self.assertEqual(len(plugins), 2)
- self.assertEqual(plugins[0].module, "path.to.MyLibrary")
- self.assertEqual(plugins[0].args, [])
- self.assertEqual(plugins[1].module, "path.to.OtherLibrary")
- self.assertEqual(plugins[1].args, [])
+ assert len(plugins) == 2
+ assert plugins[0].module == "path.to.MyLibrary"
+ assert plugins[0].args == []
+ assert plugins[1].module == "path.to.OtherLibrary"
+ assert plugins[1].args == []
def test_comma_and_space_with_arg(self):
plugin = "path.to.MyLibrary;foo;bar , path.to.OtherLibrary"
plugins = self.sl._string_to_modules(plugin)
- self.assertEqual(len(plugins), 2)
- self.assertEqual(plugins[0].module, "path.to.MyLibrary")
- self.assertEqual(plugins[0].args, ["foo", "bar"])
- self.assertEqual(plugins[1].module, "path.to.OtherLibrary")
- self.assertEqual(plugins[1].args, [])
+ assert len(plugins) == 2
+ assert plugins[0].module == "path.to.MyLibrary"
+ assert plugins[0].args == ["foo", "bar"]
+ assert plugins[1].module == "path.to.OtherLibrary"
+ assert plugins[1].args == []
def test_parse_library_with_args(self):
plugin = "path.to.MyLibrary"
plugin_args = "arg1;arg2"
parsed_plugins = self.sl._string_to_modules(f"{plugin};{plugin_args}")
parsed_plugin = parsed_plugins[0]
- self.assertEqual(len(parsed_plugins), 1)
- self.assertEqual(parsed_plugin.module, plugin)
- self.assertEqual(parsed_plugin.args, [arg for arg in plugin_args.split(";")])
- self.assertEqual(parsed_plugin.kw_args, {})
+ assert len(parsed_plugins) == 1
+ assert parsed_plugin.module == plugin
+ assert parsed_plugin.args == plugin_args.split(";")
+ assert parsed_plugin.kw_args == {}
def test_parse_plugin_with_kw_args(self):
plugin = "PluginWithKwArgs.py"
plugin_args = "kw1=Text1;kw2=Text2"
parsed_plugins = self.sl._string_to_modules(f"{plugin};{plugin_args}")
parsed_plugin = parsed_plugins[0]
- self.assertEqual(len(parsed_plugins), 1)
- self.assertEqual(parsed_plugin.module, plugin)
- self.assertEqual(parsed_plugin.args, [])
- self.assertEqual(parsed_plugin.kw_args, {"kw1": "Text1", "kw2": "Text2"})
+ assert len(parsed_plugins) == 1
+ assert parsed_plugin.module == plugin
+ assert parsed_plugin.args == []
+ assert parsed_plugin.kw_args == {"kw1": "Text1", "kw2": "Text2"}
def test_plugin_does_not_exist(self):
not_here = os.path.join(self.root_dir, "not_here.py")
- with self.assertRaises(DataError):
+ with pytest.raises(DataError):
SeleniumLibrary(plugins=not_here)
- with self.assertRaises(DataError):
+ with pytest.raises(DataError):
SeleniumLibrary(plugins="SeleniumLibrary.NotHere")
def test_plugin_wrong_import_with_path(self):
my_lib = os.path.join(self.root_dir, "my_lib.py")
wrong_name = os.path.join(self.root_dir, "my_lib_wrong_name.py")
- with self.assertRaises(DataError):
+ with pytest.raises(DataError):
SeleniumLibrary(plugins=f"{my_lib}, {wrong_name}")
def test_sl_with_kw_args_plugin(self):
@@ -108,7 +114,7 @@ def test_sl_with_kw_args_plugin(self):
def test_no_library_component_inherit(self):
no_inherit = os.path.join(self.root_dir, "my_lib_not_inherit.py")
- with self.assertRaises(PluginError):
+ with pytest.raises(PluginError):
SeleniumLibrary(plugins=no_inherit)
def test_plugin_as_last_in_init(self):
@@ -117,12 +123,12 @@ def test_plugin_as_last_in_init(self):
sl = SeleniumLibrary(
plugins=plugin_file, event_firing_webdriver=event_firing_wd
)
- self.assertEqual(sl.event_firing_webdriver, "should be last")
+ assert sl.event_firing_webdriver == "should be last"
def test_easier_event_firing_webdriver_from_plugin(self):
plugin_file = os.path.join(
self.root_dir, "plugin_with_event_firing_webdriver.py"
)
sl = SeleniumLibrary(plugins=plugin_file)
- self.assertEqual(sl._plugin_keywords, ["tidii"])
- self.assertEqual(sl.event_firing_webdriver, "event_firing_webdriver")
+ assert sl._plugin_keywords == ["tidii"]
+ assert sl.event_firing_webdriver == "event_firing_webdriver"
diff --git a/utest/test/entry/test_entry_point.py b/utest/test/entry/test_entry_point.py
index fcbc10bbf..2d94a64c0 100644
--- a/utest/test/entry/test_entry_point.py
+++ b/utest/test/entry/test_entry_point.py
@@ -1,6 +1,6 @@
import json
-from pathlib import Path
import sys
+from pathlib import Path
from approvaltests import verify_all
diff --git a/utest/test/keywords/IGNOREDtest_webdrivercreator.py b/utest/test/keywords/IGNOREDtest_webdrivercreator.py
index dd33da50b..c74852517 100644
--- a/utest/test/keywords/IGNOREDtest_webdrivercreator.py
+++ b/utest/test/keywords/IGNOREDtest_webdrivercreator.py
@@ -1,7 +1,7 @@
import os
import pytest
-from mockito import mock, verify, when, unstub, ANY
+from mockito import ANY, mock, unstub, verify, when
from selenium import webdriver
from SeleniumLibrary.keywords import WebDriverCreator
@@ -36,9 +36,8 @@ def test_get_creator_method(creator):
method = creator._get_creator_method("firefox")
assert method
- with pytest.raises(ValueError) as error:
+ with pytest.raises(ValueError, match=r"foobar is not a supported browser\."):
creator._get_creator_method("foobar")
- assert "foobar is not a supported browser." in str(error.value)
def test_parse_capabilities(creator):
@@ -135,7 +134,8 @@ def test_capabilities_resolver_chrome(creator):
def test_chrome(creator):
expected_webdriver = mock()
when(webdriver).Chrome(
- options=None, service=None # service=ANY # service_log_path=None, executable_path="chromedriver"
+ options=None,
+ service=None, # service=ANY # service_log_path=None, executable_path="chromedriver"
).thenReturn(expected_webdriver)
driver = creator.create_chrome({}, None)
assert driver == expected_webdriver
@@ -172,7 +172,7 @@ def test_chrome_remote_no_caps(creator):
def test_chrome_remote_caps(creator):
url = "http://localhost:4444/wd/hub"
expected_webdriver = mock()
- # capabilities = {"browserName": "chrome"}
+ capabilities = {"browserName": "chrome"}
file_detector = mock_file_detector(creator)
when(webdriver).Remote(
command_executor=url,
@@ -205,10 +205,10 @@ def test_chrome_headless(creator):
expected_webdriver = mock()
options = mock()
when(webdriver).ChromeOptions().thenReturn(options)
- service = mock()
when(webdriver).ChromeOptions().thenReturn(options)
when(webdriver).Chrome(
- options=options, service=ANY # service=None # service_log_path=None, executable_path="chromedriver"
+ options=options,
+ service=ANY, # service=None # service_log_path=None, executable_path="chromedriver"
).thenReturn(expected_webdriver)
driver = creator.create_headless_chrome({}, None)
assert options.headless is True
@@ -265,7 +265,7 @@ def test_get_ff_profile_no_path(creator):
assert profile == profile_mock
-def test_get_ff_profile_instance_FirefoxProfile(creator):
+def test_get_ff_profile_instance_FirefoxProfile(creator): # noqa: N802
input_profile = webdriver.FirefoxProfile()
profile = creator._get_ff_profile(input_profile)
assert profile == input_profile
diff --git a/utest/test/keywords/IGNOREtest_webdrivercreator_executable_path.py b/utest/test/keywords/IGNOREtest_webdrivercreator_executable_path.py
index c4f05b547..d51d23c0b 100644
--- a/utest/test/keywords/IGNOREtest_webdrivercreator_executable_path.py
+++ b/utest/test/keywords/IGNOREtest_webdrivercreator_executable_path.py
@@ -1,12 +1,11 @@
import os
import pytest
-from mockito import mock, unstub, when, ANY
+from mockito import ANY, mock, unstub, when
from selenium import webdriver
from SeleniumLibrary.keywords import WebDriverCreator
-
LOG_DIR = "/log/dir"
@@ -24,7 +23,8 @@ def teardown_function():
def test_create_chrome_executable_path_set(creator):
expected_webdriver = mock()
when(webdriver).Chrome(
- options=None, service=ANY, # service_log_path=None, executable_path="/path/to/chromedriver"
+ options=None,
+ service=ANY, # service_log_path=None, executable_path="/path/to/chromedriver"
).thenReturn(expected_webdriver)
driver = creator.create_chrome({}, None, executable_path="/path/to/chromedriver")
assert driver == expected_webdriver
@@ -33,7 +33,8 @@ def test_create_chrome_executable_path_set(creator):
def test_create_chrome_executable_path_not_set(creator):
expected_webdriver = mock()
when(webdriver).Chrome(
- options=None, service=ANY, # service_log_path=None, executable_path="chromedriver"
+ options=None,
+ service=ANY, # service_log_path=None, executable_path="chromedriver"
).thenReturn(expected_webdriver)
when(creator)._get_executable_path(ANY).thenReturn("chromedriver")
driver = creator.create_chrome({}, None, executable_path=None)
@@ -72,7 +73,8 @@ def test_create_heasless_chrome_executable_path_set(creator):
options = mock()
when(webdriver).ChromeOptions().thenReturn(options)
when(webdriver).Chrome(
- options=options, service = ANY # service_log_path=None, executable_path="/path/to/chromedriver"
+ options=options,
+ service=ANY, # service_log_path=None, executable_path="/path/to/chromedriver"
).thenReturn(expected_webdriver)
driver = creator.create_headless_chrome(
{}, None, executable_path="/path/to/chromedriver"
@@ -92,7 +94,7 @@ def test_create_firefox_executable_path_set(creator):
when(webdriver).Firefox(
options=options,
# firefox_profile=profile,
- service = ANY,
+ service=ANY,
# service_log_path=log_file,
# executable_path=executable,
).thenReturn(expected_webdriver)
@@ -247,5 +249,4 @@ def mock_file_detector(creator):
def get_geckodriver_log():
# return os.path.join(LOG_DIR, "geckodriver-1.log")
# print(f"{os.getcwd()}")
- cwd = os.getcwd()
- return cwd
\ No newline at end of file
+ return os.getcwd()
diff --git a/utest/test/keywords/IGNOREtest_webdrivercreator_service_log_path.py b/utest/test/keywords/IGNOREtest_webdrivercreator_service_log_path.py
index eb9fe6c5f..c96c32c49 100644
--- a/utest/test/keywords/IGNOREtest_webdrivercreator_service_log_path.py
+++ b/utest/test/keywords/IGNOREtest_webdrivercreator_service_log_path.py
@@ -1,25 +1,26 @@
import os
-from collections import namedtuple
+from typing import NamedTuple
import pytest
-
-from mockito import mock, when, unstub, ANY
+from mockito import ANY, mock, unstub, when
from selenium import webdriver
-from selenium.webdriver import chrome
-#from selenium.webdriver.chrome.service import Service as ChromeService
-from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome import service as chromeservice
+# from selenium.webdriver.chrome.service import Service as ChromeService
from SeleniumLibrary.keywords import WebDriverCreator
from SeleniumLibrary.utils import WINDOWS
@pytest.fixture(scope="module")
+class Creator(NamedTuple):
+ creator: WebDriverCreator
+ output_dir: str
+
+
def creator():
curr_dir = os.path.dirname(os.path.abspath(__file__))
output_dir = os.path.abspath(os.path.join(curr_dir, "..", "..", "output_dir"))
creator = WebDriverCreator(output_dir)
- Creator = namedtuple("Creator", "creator, output_dir")
return Creator(creator, output_dir)
@@ -57,7 +58,9 @@ def test_log_file_with_index_exist(creator):
def test_create_chrome_with_service_log_path_none(creator):
expected_webdriver = mock()
service = mock()
- when(chromeservice).Service(log_path=None, executable_path="chromedriver").thenReturn(service)
+ when(chromeservice).Service(
+ log_path=None, executable_path="chromedriver"
+ ).thenReturn(service)
# when(chrome).service(log_path=None, executable_path="chromedriver").thenReturn(service)
# service = ChromeService(log_path=None, executable_path="chromedriver")
# service = Service(log_path=None, executable_path="chromedriver")
@@ -65,7 +68,8 @@ def test_create_chrome_with_service_log_path_none(creator):
# when(webdriver).chrome.service().thenReturn(service)
when(webdriver).Chrome(
# options=None, service_log_path=None, executable_path="chromedriver"
- options=None, service=ANY,
+ options=None,
+ service=ANY,
# options=None, service=service,
).thenReturn(expected_webdriver)
driver = creator.creator.create_chrome({}, None, service_log_path=None)
@@ -76,7 +80,8 @@ def test_create_chrome_with_service_log_path_real_path(creator):
log_file = os.path.join(creator.output_dir, "firefox-{index}.log")
expected_webdriver = mock()
when(webdriver).Chrome(
- options=None, service=ANY,
+ options=None,
+ service=ANY,
).thenReturn(expected_webdriver)
driver = creator.creator.create_chrome({}, None, service_log_path=log_file)
assert driver == expected_webdriver
@@ -88,14 +93,15 @@ def test_create_headlesschrome_with_service_log_path_real_path(creator):
options = mock()
when(webdriver).ChromeOptions().thenReturn(options)
when(webdriver).Chrome(
- options=options, service=ANY,
+ options=options,
+ service=ANY,
).thenReturn(expected_webdriver)
driver = creator.creator.create_headless_chrome({}, None, service_log_path=log_file)
assert driver == expected_webdriver
def test_create_firefox_with_service_log_path_none(creator):
- log_file = os.path.join(creator.output_dir, "geckodriver-1.log")
+ # log_file = os.path.join(creator.output_dir, "geckodriver-1.log")
expected_webdriver = mock()
options = mock()
when(webdriver).FirefoxOptions().thenReturn(options)
@@ -162,18 +168,20 @@ def test_create_ie_with_service_log_path_real_path(creator):
log_file = os.path.join(creator.output_dir, "ie-1.log")
expected_webdriver = mock()
when(webdriver).Ie(
- options=None, service=ANY,
+ options=None,
+ service=ANY,
).thenReturn(expected_webdriver)
driver = creator.creator.create_ie({}, None, service_log_path=log_file)
assert driver == expected_webdriver
def test_create_edge_with_service_log_path_real_path(creator):
- executable_path = "msedgedriver"
+ # executable_path = "msedgedriver"
log_file = os.path.join(creator.output_dir, "edge-1.log")
expected_webdriver = mock()
when(webdriver).Edge(
- options=None, service=ANY,
+ options=None,
+ service=ANY,
).thenReturn(expected_webdriver)
driver = creator.creator.create_edge({}, None, service_log_path=log_file)
assert driver == expected_webdriver
@@ -197,4 +205,4 @@ def test_create_edge_with_service_log_path_real_path(creator):
# expected_webdriver
# )
# driver = creator.creator.create_safari({}, None, service_log_path=log_file)
-# assert driver == expected_webdriver
\ No newline at end of file
+# assert driver == expected_webdriver
diff --git a/utest/test/keywords/test_browsermanagement.py b/utest/test/keywords/test_browsermanagement.py
index 9dcc44dfc..5b9e03213 100644
--- a/utest/test/keywords/test_browsermanagement.py
+++ b/utest/test/keywords/test_browsermanagement.py
@@ -1,11 +1,9 @@
import pytest
-from mockito import when, mock, verify, verifyNoUnwantedInteractions, ANY
+from mockito import ANY, mock, verify, verifyNoUnwantedInteractions, when
from selenium import webdriver
-from selenium.webdriver.chrome.service import Service as ChromeService
-from selenium.webdriver.chrome.service import Service
-from SeleniumLibrary.keywords import BrowserManagementKeywords
from SeleniumLibrary import SeleniumLibrary
+from SeleniumLibrary.keywords import BrowserManagementKeywords
def test_set_selenium_timeout_only_affects_open_browsers():
@@ -27,16 +25,16 @@ def test_set_selenium_timeout_only_affects_open_browsers():
def test_action_chain_delay_default():
sl = SeleniumLibrary()
- assert sl.action_chain_delay == 250, f"Delay should have 250"
+ assert sl.action_chain_delay == 250, "Delay should have 250"
def test_set_action_chain_delay_default():
sl = SeleniumLibrary()
sl.set_action_chain_delay("3.0")
- assert sl.action_chain_delay == 3000, f"Delay should have 3000"
+ assert sl.action_chain_delay == 3000, "Delay should have 3000"
sl.set_action_chain_delay("258 milliseconds")
- assert sl.action_chain_delay == 258, f"Delay should have 258"
+ assert sl.action_chain_delay == 258, "Delay should have 258"
def test_get_action_chain_delay_default():
@@ -44,6 +42,7 @@ def test_get_action_chain_delay_default():
sl.set_action_chain_delay("300 milliseconds")
assert sl.get_action_chain_delay() == 0.3
+
def test_selenium_implicit_wait_default():
sl = SeleniumLibrary()
assert sl.implicit_wait == 0.0, "Wait should have 0.0"
@@ -59,10 +58,10 @@ def test_set_selenium_implicit_wait():
def test_selenium_implicit_wait_error():
- with pytest.raises(ValueError):
+ with pytest.raises(ValueError, match=r"Invalid time string 'False'\."):
SeleniumLibrary(implicit_wait="False")
sl = SeleniumLibrary(implicit_wait="3")
- with pytest.raises(ValueError):
+ with pytest.raises(ValueError, match=r"Invalid time string '1 vuosi'\."):
sl.set_selenium_implicit_wait("1 vuosi")
@@ -77,7 +76,9 @@ def test_selenium_implicit_wait_get():
def test_selenium_page_load_timeout_with_default():
sl = SeleniumLibrary()
- assert sl.page_load_timeout == 300.0, "Default page load timeout should be 5 minutes"
+ assert sl.page_load_timeout == 300.0, (
+ "Default page load timeout should be 5 minutes"
+ )
def test_set_selenium_page_load_timeout():
@@ -106,23 +107,20 @@ def test_get_selenium_page_load_timeout():
def test_bad_browser_name():
ctx = mock()
bm = BrowserManagementKeywords(ctx)
- try:
+ with pytest.raises(ValueError, match=r"fireox is not a supported browser\."):
bm._make_driver("fireox")
- raise ValueError("Exception not raised")
- except ValueError as e:
- assert str(e) == "fireox is not a supported browser."
def test_create_webdriver():
ctx = mock()
ctx.event_firing_webdriver = None
bm = BrowserManagementKeywords(ctx)
- FakeWebDriver = mock()
+ fake_webdriver = mock()
driver = mock()
- when(FakeWebDriver).__call__(some_arg=1).thenReturn(driver)
- when(FakeWebDriver).__call__(some_arg=2).thenReturn(driver)
+ when(fake_webdriver).__call__(some_arg=1).thenReturn(driver)
+ when(fake_webdriver).__call__(some_arg=2).thenReturn(driver)
when(ctx).register_driver(driver, "fake1").thenReturn(0)
- webdriver.FakeWebDriver = FakeWebDriver
+ webdriver.FakeWebDriver = fake_webdriver
try:
index = bm.create_webdriver("FakeWebDriver", "fake1", some_arg=1)
verify(ctx).register_driver(driver, "fake1")
@@ -142,7 +140,8 @@ def test_open_browser_speed():
browser = mock()
executable_path = "chromedriver"
when(webdriver).Chrome(
- options=None, service=ANY,
+ options=None,
+ service=ANY,
).thenReturn(browser)
bm = BrowserManagementKeywords(ctx)
when(bm._webdriver_creator)._get_executable_path(ANY).thenReturn(executable_path)
@@ -157,17 +156,17 @@ def test_create_webdriver_speed():
ctx.speed = 0.0
browser = mock()
executable_path = "chromedriver"
- #Original code:
+ # Original code:
# when(webdriver).Chrome(
# options=None, service_log_path=None, executable_path=executable_path
# ).thenReturn(browser)
- #Tried:
+ # Tried:
# service = ChromeService(executable_path="chromedriver", log_path=None)
# when(webdriver).Chrome(
# options=None, service=Service,
# ).thenReturn(browser)
- #Results in ..
+ # Results in ..
# E mockito.invocation.InvocationError:
# E Called but not expected:
# E
@@ -177,11 +176,11 @@ def test_create_webdriver_speed():
# E
# E Chrome(options=None, service=)
- #Tried:
+ # Tried:
# when(webdriver).Chrome(
# options=None, service=None,
# ).thenReturn(browser)
- #Results in ..
+ # Results in ..
# E mockito.invocation.InvocationError:
# E Called but not expected:
# E
@@ -191,7 +190,7 @@ def test_create_webdriver_speed():
# E
# E Chrome(options=None, service=None)
- #Tried:
+ # Tried:
# service = mock()
# when(webdriver.chrome.service).Service(
# executable_path="chromedriver", log_path=None,
@@ -199,10 +198,10 @@ def test_create_webdriver_speed():
# when(webdriver).Chrome(
# options=None, service=service,
# ).thenReturn(browser)
- #Results in ..
+ # Results in ..
# ...
- #Tried:
+ # Tried:
# service = ChromeService(executable_path="chromedriver", log_path=None)
# when(webdriver.chrome.service).Service(
# executable_path="chromedriver", log_path=None,
@@ -210,7 +209,7 @@ def test_create_webdriver_speed():
# when(webdriver).Chrome(
# options=None, service=service,
# ).thenReturn(browser)
- #Results in ..
+ # Results in ..
# E mockito.invocation.InvocationError:
# E Called but not expected:
# E
@@ -219,16 +218,16 @@ def test_create_webdriver_speed():
# E Stubbed invocations are:
# E
# E Chrome(options=None, service=)
- #which does seem closer ..
-
- #Tried:
+ # which does seem closer ..
+
+ # Tried:
# service = Service(executable_path="chromedriver", log_path=None)
# when(webdriver).Chrome(
# options=None, service=service,
# ).thenReturn(browser)
- #Results in ..
+ # Results in ..
- #Tried:
+ # Tried:
# service = mock()
# ## when(Service).__init__(
# when(Chrome).Service(
@@ -237,36 +236,37 @@ def test_create_webdriver_speed():
# when(webdriver).Chrome(
# options=None, service=service,
# ).thenReturn(browser)
- #Results in ..
+ # Results in ..
- #Tried:
+ # Tried:
when(webdriver).Chrome(
- options=None, service=ANY,
+ options=None,
+ service=ANY,
).thenReturn(browser)
- #Results in ..
+ # Results in ..
# .. passed ?? Is this truely correct?
- #Also tried:
+ # Also tried:
# service_log_path = None
# service = ChromeService(executable_path=executable_path, log_path=service_log_path)
# when(webdriver).Chrome(
# options=None, service=service,
# ).thenReturn(browser)
- #Also tried:
+ # Also tried:
# service = ChromeService()
# when(webdriver).Chrome(
# options=None, service=service,
# ).thenReturn(browser)
- #Also tried:
+ # Also tried:
# service = mock(ChromeService)
# when(webdriver).Chrome(
# options=None, service=service,
# ).thenReturn(browser)
- #Also tried:
- #service = mock(Service)
+ # Also tried:
+ # service = mock(Service)
# when(webdriver).Chrome(
# options=None, service=service,
# ).thenReturn(browser)
diff --git a/utest/test/keywords/test_click_modifier.py b/utest/test/keywords/test_click_modifier.py
index 0b651c276..5b3e0560e 100644
--- a/utest/test/keywords/test_click_modifier.py
+++ b/utest/test/keywords/test_click_modifier.py
@@ -40,24 +40,19 @@ def test_parsing_multiple_modifiers(element):
def test_invalid_modifier(element):
- with pytest.raises(ValueError) as error:
+ with pytest.raises(ValueError, match="'FOO' modifier "):
element.parse_modifier("FOO")
- assert "'FOO' modifier " in str(error.value)
- with pytest.raises(ValueError) as error:
+ with pytest.raises(ValueError, match="'FOO' modifier "):
element.parse_modifier("FOO+CTRL")
- assert "'FOO' modifier " in str(error.value)
- with pytest.raises(ValueError) as error:
+ with pytest.raises(ValueError, match="'FOO' modifier "):
element.parse_modifier("CTRL+FOO")
- assert "'FOO' modifier " in str(error.value)
- with pytest.raises(ValueError) as error:
+ with pytest.raises(ValueError, match="'CTRLFOO' modifier "):
element.parse_modifier("CTRLFOO")
- assert "'CTRLFOO' modifier " in str(error.value)
def test_invalid_key_separator(element):
- with pytest.raises(ValueError) as error:
+ with pytest.raises(ValueError, match="'CTRL-CTRL' modifier "):
element.parse_modifier("CTRL-CTRL")
- assert "'CTRL-CTRL' modifier " in str(error.value)
diff --git a/utest/test/keywords/test_cookie.py b/utest/test/keywords/test_cookie.py
index 1fe110efa..52d42a681 100644
--- a/utest/test/keywords/test_cookie.py
+++ b/utest/test/keywords/test_cookie.py
@@ -6,7 +6,6 @@
from SeleniumLibrary.keywords import CookieKeywords
from SeleniumLibrary.keywords.cookie import CookieInformation
-
ALL_ARGS = {
"name": "foo",
"value": "123",
@@ -20,24 +19,24 @@
pytestmark = pytest.mark.usefixtures("unstub")
-@pytest.fixture()
+@pytest.fixture
def driver():
return mock()
-@pytest.fixture()
+@pytest.fixture
def ctx(driver):
ctx = mock()
ctx.driver = driver
return ctx
-@pytest.fixture()
+@pytest.fixture
def default_cookie():
return {"name": "name", "value": "value"}
-@pytest.fixture()
+@pytest.fixture
def cookie(ctx):
return CookieKeywords(ctx)
diff --git a/utest/test/keywords/test_expectedconditions.py b/utest/test/keywords/test_expectedconditions.py
index 3ade2e5fa..d6052e08c 100644
--- a/utest/test/keywords/test_expectedconditions.py
+++ b/utest/test/keywords/test_expectedconditions.py
@@ -20,12 +20,13 @@
# Element\ To\ Be\ Clickable
# Element${SPACE}To${SPACE}Be${SPACE}Clickable
-class ExpectedConditionKeywords(unittest.TestCase):
+
+class TestExpectedConditionKeywords(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.ec_keywords = ExpectedConditionKeywords(None)
- def WorkInProgresstest_parse_condition(self):
+ def workinprogresstest_parse_condition(self):
results = []
results.append(self.ec_keywords._parse_condition("Element To Be Clickable"))
results.append(self.ec_keywords._parse_condition("eLEment TO be ClIcKable"))
diff --git a/utest/test/keywords/test_firefox_profile_parsing.py b/utest/test/keywords/test_firefox_profile_parsing.py
index 3a7e895e2..ad3864d5f 100644
--- a/utest/test/keywords/test_firefox_profile_parsing.py
+++ b/utest/test/keywords/test_firefox_profile_parsing.py
@@ -5,7 +5,6 @@
from approvaltests.reporters.generic_diff_reporter_factory import (
GenericDiffReporterFactory,
)
-from robot.utils import WINDOWS
from selenium import webdriver
from SeleniumLibrary.keywords import WebDriverCreator
@@ -27,7 +26,6 @@ def setUpClass(cls):
def setUp(self):
self.results = []
- @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_single_method(self):
self._parse_result(
self.creator._get_ff_profile('set_preference("key1", "arg1")')
@@ -67,10 +65,9 @@ def _get_preferences_attribute(self, result):
# -- temporary fix to transition selenium to v4.17.2 from v4.16.0 and prior
# from inspect import signature
# sig = signature(result)
- if hasattr(result,'default_preferences'):
+ if hasattr(result, "default_preferences"):
return result.default_preferences
- elif hasattr(result,'_desired_preferences'):
+ if hasattr(result, "_desired_preferences"):
return result._desired_preferences
- else:
- return None
+ return None
# --
diff --git a/utest/test/keywords/test_input_text_file_decorator.py b/utest/test/keywords/test_input_text_file_decorator.py
index cd748e785..a0ec8fa13 100644
--- a/utest/test/keywords/test_input_text_file_decorator.py
+++ b/utest/test/keywords/test_input_text_file_decorator.py
@@ -17,8 +17,8 @@ def tearDown(self):
def test_file_decorator_not_file(self):
when(self.file).choose_file().thenReturn(False)
- self.assertEqual(self.file.is_local_file("some string"), None)
+ assert self.file.is_local_file("some string") is None
def test_file_decodator_is_file_choose_file(self):
when(self.file).choose_file().thenReturn(True)
- self.assertEqual(self.file.is_local_file("some_file"), None)
+ assert self.file.is_local_file("some_file") is None
diff --git a/utest/test/keywords/test_javascript.py b/utest/test/keywords/test_javascript.py
index 1b4b469c5..2e35bae4e 100644
--- a/utest/test/keywords/test_javascript.py
+++ b/utest/test/keywords/test_javascript.py
@@ -5,14 +5,12 @@
from approvaltests.reporters.generic_diff_reporter_factory import (
GenericDiffReporterFactory,
)
-from robot.utils import WINDOWS
from SeleniumLibrary.keywords import JavaScriptKeywords
class JavaScriptKeywordsTest(unittest.TestCase):
@classmethod
- @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def setUpClass(cls):
cls.code_examples = [
(),
@@ -40,13 +38,11 @@ def setUpClass(cls):
factory.load(reporter_json)
cls.reporter = factory.get_first_working()
- @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_get_javascript(self):
code, args = self.js._get_javascript_to_execute(("code", "here"))
result = f"{code} + {args}"
verify(result, self.reporter)
- @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_get_javascript_no_code(self):
code = ("ARGUMENTS", "arg1", "arg1")
try:
@@ -55,21 +51,18 @@ def test_get_javascript_no_code(self):
result = str(error)
verify(result, self.reporter)
- @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_separate_code_and_args(self):
all_results = []
for code in self.code_examples:
all_results.append(self.js_reporter(code))
verify_all("code and args", all_results, reporter=self.reporter)
- @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_indexing(self):
all_results = []
for code in self.code_examples:
all_results.append(self.js._get_marker_index(code))
verify_all("index", all_results, reporter=self.reporter)
- @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_check_marker_error(self):
examples = [
(),
diff --git a/utest/test/keywords/test_keyword_arguments_browsermanagement.py b/utest/test/keywords/test_keyword_arguments_browsermanagement.py
index 0d730878a..6237a89cb 100644
--- a/utest/test/keywords/test_keyword_arguments_browsermanagement.py
+++ b/utest/test/keywords/test_keyword_arguments_browsermanagement.py
@@ -1,6 +1,6 @@
import unittest
-from mockito import mock, unstub, when, verify, ANY
+from mockito import ANY, mock, unstub, verify, when
from SeleniumLibrary.keywords import BrowserManagementKeywords
@@ -25,13 +25,13 @@ def test_open_browser(self):
"firefox", None, None, False, None, None, None, None
).thenReturn(browser)
alias = self.brorser.open_browser(url)
- self.assertEqual(alias, None)
+ assert alias is None
when(self.brorser)._make_driver(
"firefox", None, None, remote_url, None, None, None, None
).thenReturn(browser)
alias = self.brorser.open_browser(url, alias="None", remote_url=remote_url)
- self.assertEqual(alias, None)
+ assert alias is None
def test_same_alias(self):
url = "https://github.com/robotframework"
diff --git a/utest/test/keywords/test_keyword_arguments_element.py b/utest/test/keywords/test_keyword_arguments_element.py
index c35b402ec..d6662e40a 100644
--- a/utest/test/keywords/test_keyword_arguments_element.py
+++ b/utest/test/keywords/test_keyword_arguments_element.py
@@ -1,10 +1,11 @@
import pytest
-from mockito import mock, unstub, when, matchers
-from SeleniumLibrary.keywords import ElementKeywords
+from mockito import matchers, mock, unstub, when
+
import SeleniumLibrary.keywords.element as SUT
+from SeleniumLibrary.keywords import ElementKeywords
-@pytest.fixture(scope="function")
+@pytest.fixture
def element():
ctx = mock()
ctx._browser = mock()
@@ -30,7 +31,6 @@ def test_element_text_should_be(element):
assert "foobar" in str(error.value)
-
def test_action_chain_delay_in_elements(element):
locator = "//div"
webelement = mock()
@@ -40,8 +40,7 @@ def test_action_chain_delay_in_elements(element):
expected_delay_in_ms = 1000
element.ctx.action_chain_delay = expected_delay_in_ms
when(chain_mock).move_to_element(matchers.ANY).thenReturn(mock())
- when(SUT).ActionChains(matchers.ANY, duration=expected_delay_in_ms).thenReturn(chain_mock)
+ when(SUT).ActionChains(matchers.ANY, duration=expected_delay_in_ms).thenReturn(
+ chain_mock
+ )
element.scroll_element_into_view(locator)
-
-
-
diff --git a/utest/test/keywords/test_keyword_arguments_formelement.py b/utest/test/keywords/test_keyword_arguments_formelement.py
index 193ba0dac..322ae6475 100644
--- a/utest/test/keywords/test_keyword_arguments_formelement.py
+++ b/utest/test/keywords/test_keyword_arguments_formelement.py
@@ -3,11 +3,10 @@
from SeleniumLibrary.keywords import FormElementKeywords
-
FALSES = ["False", False, "", None, "NONE"]
-@pytest.fixture(scope="function")
+@pytest.fixture
def form():
ctx = mock()
ctx.driver = mock()
@@ -21,7 +20,7 @@ def teardown_function():
def test_submit_form_false(form):
element = mock()
when(form).find_element("tag:form", tag="form").thenReturn(element)
- for false in FALSES:
+ for _false in FALSES:
form.submit_form()
form.submit_form()
diff --git a/utest/test/keywords/test_keyword_arguments_selectelement.py b/utest/test/keywords/test_keyword_arguments_selectelement.py
index 8e8c78999..bfe671ae0 100644
--- a/utest/test/keywords/test_keyword_arguments_selectelement.py
+++ b/utest/test/keywords/test_keyword_arguments_selectelement.py
@@ -2,7 +2,6 @@
from mockito import mock, unstub, when
-
from SeleniumLibrary.keywords import SelectElementKeywords
diff --git a/utest/test/keywords/test_keyword_arguments_waiting.py b/utest/test/keywords/test_keyword_arguments_waiting.py
index 9809b8314..26ccf28a5 100644
--- a/utest/test/keywords/test_keyword_arguments_waiting.py
+++ b/utest/test/keywords/test_keyword_arguments_waiting.py
@@ -20,7 +20,6 @@ def teardown_module():
def test_wait_for_condition(waiting):
condition = 'return document.getElementById("intro")'
- error = "did not become true"
with pytest.raises(AssertionError) as error:
waiting.wait_for_condition(condition)
assert "did not become true" in str(error.value)
diff --git a/utest/test/keywords/test_press_keys.py b/utest/test/keywords/test_press_keys.py
index d168814dc..ebea52ff6 100644
--- a/utest/test/keywords/test_press_keys.py
+++ b/utest/test/keywords/test_press_keys.py
@@ -1,11 +1,10 @@
-import unittest
import os
+import unittest
from approvaltests.approvals import verify_all
from approvaltests.reporters.generic_diff_reporter_factory import (
GenericDiffReporterFactory,
)
-from robot.utils import WINDOWS
from SeleniumLibrary.keywords import ElementKeywords
@@ -24,7 +23,6 @@ def setUp(self):
factory.load(reporter_json)
self.reporter = factory.get_first_working()
- @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_parse_keys(self):
results = []
results.append(self.element_keywords._parse_keys("A", "B", "C"))
@@ -41,7 +39,6 @@ def test_parse_keys(self):
results.append(self.element_keywords._parse_keys("IS", "ALT", "HERE"))
verify_all("index", results, reporter=self.reporter)
- @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_parse_keys_aliases(self):
results = []
results.append(self.element_keywords._parse_aliases("CTRL"))
@@ -51,7 +48,6 @@ def test_parse_keys_aliases(self):
results.append(self.element_keywords._parse_aliases("END"))
verify_all("Alias testing", results, reporter=self.reporter)
- @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_separate_key(self):
results = []
results.append(self.element_keywords._separate_key("BB"))
@@ -65,7 +61,6 @@ def test_separate_key(self):
results.append(self.element_keywords._separate_key("+++"))
verify_all("Separate key", results, reporter=self.reporter)
- @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_convert_key(self):
results = []
results.append(self.element_keywords._convert_special_keys(["B"]))
diff --git a/utest/test/keywords/test_runonfailure_from_lib.py b/utest/test/keywords/test_runonfailure_from_lib.py
index 8034a4002..530820d3d 100644
--- a/utest/test/keywords/test_runonfailure_from_lib.py
+++ b/utest/test/keywords/test_runonfailure_from_lib.py
@@ -1,6 +1,6 @@
import unittest
-from mockito import when, unstub, verify
+from mockito import unstub, verify, when
from SeleniumLibrary import SeleniumLibrary
diff --git a/utest/test/keywords/test_screen_shot.py b/utest/test/keywords/test_screen_shot.py
index 2ea09cb30..128d98230 100644
--- a/utest/test/keywords/test_screen_shot.py
+++ b/utest/test/keywords/test_screen_shot.py
@@ -1,4 +1,4 @@
-from os.path import dirname, abspath, join
+from os.path import abspath, dirname, join
import pytest
from mockito import mock, unstub
@@ -10,6 +10,7 @@
EMBED = "EMBED"
BASE64 = "BASE64"
+
@pytest.fixture(scope="module")
def screen_shot():
ctx = mock()
diff --git a/utest/test/keywords/test_selenium_options_parser.py b/utest/test/keywords/test_selenium_options_parser.py
index b61fff029..77a3ed9a2 100644
--- a/utest/test/keywords/test_selenium_options_parser.py
+++ b/utest/test/keywords/test_selenium_options_parser.py
@@ -1,14 +1,12 @@
import os
import sys
-import unittest
import pytest
from approvaltests.approvals import verify_all
from approvaltests.reporters.generic_diff_reporter_factory import (
GenericDiffReporterFactory,
)
-from mockito import mock, when, unstub, ANY
-from robot.utils import WINDOWS
+from mockito import ANY, mock, unstub, when
from selenium import webdriver
from SeleniumLibrary.keywords.webdrivertools import SeleniumOptions, WebDriverCreator
@@ -18,6 +16,7 @@
def options():
return SeleniumOptions()
+
@pytest.fixture(scope="module")
def reporter():
path = os.path.dirname(__file__)
@@ -33,7 +32,6 @@ def teardown_function():
unstub()
-@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_parse_options_string(options, reporter):
results = []
results.append(options._parse('method("arg1")'))
@@ -72,7 +70,6 @@ def test_parse_options_string(options, reporter):
verify_all("Selenium options string to dict", results, reporter=reporter)
-@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_index_of_separator(options, reporter):
results = []
results.append(options._get_arument_index('method({"key": "value"})'))
@@ -82,7 +79,6 @@ def test_index_of_separator(options, reporter):
verify_all("Get argument index", results, reporter=reporter)
-@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_parse_complex_object(options, reporter):
results = []
results.append(options._parse_to_tokens('method({"key": "value"})'))
@@ -92,7 +88,6 @@ def test_parse_complex_object(options, reporter):
verify_all("Parse complex Python object", results, reporter=reporter)
-@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_parse_arguemnts(options, reporter):
results = []
results.append(options._parse_arguments(("arg1",), True))
@@ -103,7 +98,6 @@ def test_parse_arguemnts(options, reporter):
verify_all("Parse arguments from complex object", results, reporter=reporter)
-@pytest.mark.skipif(WINDOWS, reason="ApprovalTest do not support different line feeds")
@pytest.mark.skipif(sys.version_info > (3, 11), reason="Errors change with Python 3.12")
def test_parse_options_string_errors(options, reporter):
results = []
@@ -116,7 +110,6 @@ def test_parse_options_string_errors(options, reporter):
verify_all("Selenium options string errors", results, reporter=reporter)
-@pytest.mark.skipif(WINDOWS, reason="ApprovalTest do not support different line feeds")
@pytest.mark.skipif(sys.version_info < (3, 12), reason="Errors change with Python 3.12")
def test_parse_options_string_errors_py3_12(options, reporter):
results = []
@@ -129,7 +122,6 @@ def test_parse_options_string_errors_py3_12(options, reporter):
verify_all("Selenium options string errors", results, reporter=reporter)
-@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_split_options(options, reporter):
results = []
results.append(options._split('method("arg1");method("arg2")'))
@@ -143,7 +135,6 @@ def test_split_options(options, reporter):
verify_all("Selenium options string splitting", results, reporter=reporter)
-@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_options_create(options, reporter):
results = []
options_str = 'add_argument("--disable-dev-shm-usage")'
@@ -175,7 +166,6 @@ def test_options_create(options, reporter):
verify_all("Selenium options", results, reporter=reporter)
-@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_get_options(options, reporter):
options_str = 'add_argument("--proxy-server=66.97.38.58:80")'
sel_options = options.create("chrome", options_str)
@@ -183,7 +173,6 @@ def test_get_options(options, reporter):
verify_all("Selenium options with string.", results, reporter=reporter)
-@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_importer(options, reporter):
results = []
results.append(options._import_options("firefox"))
@@ -202,7 +191,7 @@ def error_formatter(method, arg, full=False):
except Exception as error:
if full:
return f"{arg} {error}"
- return "{} {}".format(arg, error.__str__()[:15])
+ return f"{arg} {error.__str__()[:15]}"
@pytest.fixture(scope="module")
@@ -215,8 +204,7 @@ def creator():
@pytest.fixture(scope="module")
def output_dir():
curr_dir = os.path.dirname(os.path.abspath(__file__))
- output_dir = os.path.abspath(os.path.join(curr_dir, "..", "..", "output_dir"))
- return output_dir
+ return os.path.abspath(os.path.join(curr_dir, "..", "..", "output_dir"))
def test_create_chrome_with_options(creator):
@@ -227,7 +215,8 @@ def test_create_chrome_with_options(creator):
# executable_path=ANY, log_path=ANY,
# ).thenReturn(service)
when(webdriver).Chrome(
- options=options, service=ANY # service_log_path=None, executable_path="chromedriver"
+ options=options,
+ service=ANY, # service_log_path=None, executable_path="chromedriver"
).thenReturn(expected_webdriver)
driver = creator.create_chrome({}, None, options=options)
assert driver == expected_webdriver
@@ -235,13 +224,13 @@ def test_create_chrome_with_options(creator):
def test_create_chrome_with_options_and_remote_url(creator):
url = "http://localhost:4444/wd/hub"
- #caps = webdriver.DesiredCapabilities.CHROME.copy()
+ # caps = webdriver.DesiredCapabilities.CHROME.copy()
options = mock()
expected_webdriver = mock()
file_detector = mock_file_detector(creator)
when(webdriver).Remote(
command_executor=url,
- #desired_capabilities=caps,
+ # desired_capabilities=caps,
# browser_profile=None,
options=options,
file_detector=file_detector,
@@ -254,21 +243,22 @@ def test_create_headless_chrome_with_options(creator):
options = mock()
expected_webdriver = mock()
when(webdriver).Chrome(
- options=options, service=ANY # service_log_path=None, options=options, executable_path="chromedriver"
+ options=options,
+ service=ANY, # service_log_path=None, options=options, executable_path="chromedriver"
).thenReturn(expected_webdriver)
driver = creator.create_headless_chrome({}, None, options=options)
assert driver == expected_webdriver
def test_create_firefox_with_options(creator, output_dir):
- log_file = os.path.join(output_dir, "geckodriver-1.log")
+ # log_file = os.path.join(output_dir, "geckodriver-1.log")
options = mock()
profile = mock()
expected_webdriver = mock()
when(webdriver).FirefoxProfile().thenReturn(profile)
when(webdriver).Firefox(
options=options,
- service=ANY
+ service=ANY,
# firefox_profile=profile,
# executable_path="geckodriver",
# service_log_path=log_file,
@@ -297,14 +287,14 @@ def test_create_firefox_with_options_and_remote_url(creator):
def test_create_headless_firefox_with_options(creator, output_dir):
- log_file = os.path.join(output_dir, "geckodriver-1.log")
+ # log_file = os.path.join(output_dir, "geckodriver-1.log")
options = mock()
profile = mock()
expected_webdriver = mock()
when(webdriver).FirefoxProfile().thenReturn(profile)
when(webdriver).Firefox(
options=options,
- service=ANY
+ service=ANY,
# firefox_profile=profile,
# executable_path="geckodriver",
# service_log_path=log_file,
@@ -317,7 +307,8 @@ def test_create_ie_with_options(creator):
options = mock()
expected_webdriver = mock()
when(webdriver).Ie(
- options=options, service=ANY # service_log_path=None, options=options, executable_path="IEDriverServer.exe"
+ options=options,
+ service=ANY, # service_log_path=None, options=options, executable_path="IEDriverServer.exe"
).thenReturn(expected_webdriver)
driver = creator.create_ie({}, None, options=options)
assert driver == expected_webdriver
@@ -344,7 +335,8 @@ def test_create_ie_with_options_and_log_path(creator):
options = mock()
expected_webdriver = mock()
when(webdriver).Ie(
- options=options, service=ANY # service_log_path=None, executable_path="IEDriverServer.exe"
+ options=options,
+ service=ANY, # service_log_path=None, executable_path="IEDriverServer.exe"
).thenReturn(expected_webdriver)
driver = creator.create_ie({}, None, options=options)
assert driver == expected_webdriver
@@ -377,7 +369,8 @@ def test_create_driver_chrome(creator):
executable_path = "chromedriver"
when(creator)._get_executable_path(ANY).thenReturn(executable_path)
when(webdriver).Chrome(
- options=options, service=ANY # service_log_path=None, options=options, executable_path=executable_path
+ options=options,
+ service=ANY, # service_log_path=None, options=options, executable_path=executable_path
).thenReturn(expected_webdriver)
driver = creator.create_driver(
"Chrome", desired_capabilities={}, remote_url=None, options=str_options
@@ -386,7 +379,7 @@ def test_create_driver_chrome(creator):
def test_create_driver_firefox(creator, output_dir):
- log_file = os.path.join(output_dir, "geckodriver-1.log")
+ # log_file = os.path.join(output_dir, "geckodriver-1.log")
str_options = "add_argument:--disable-dev-shm-usage"
options = mock()
profile = mock()
@@ -397,7 +390,7 @@ def test_create_driver_firefox(creator, output_dir):
when(creator)._get_executable_path(ANY).thenReturn(executable_path)
when(webdriver).Firefox(
options=options,
- service=ANY
+ service=ANY,
# firefox_profile=profile,
# executable_path=executable_path,
# service_log_path=log_file,
diff --git a/utest/test/keywords/test_selenium_service_parser.py b/utest/test/keywords/test_selenium_service_parser.py
index 095a8c2c2..309b2203e 100644
--- a/utest/test/keywords/test_selenium_service_parser.py
+++ b/utest/test/keywords/test_selenium_service_parser.py
@@ -1,23 +1,21 @@
import os
import sys
-import unittest
import pytest
from approvaltests.approvals import verify_all
from approvaltests.reporters.generic_diff_reporter_factory import (
GenericDiffReporterFactory,
)
-from mockito import mock, when, unstub, ANY
-from robot.utils import WINDOWS
-from selenium import webdriver
+from mockito import unstub
-from SeleniumLibrary.keywords.webdrivertools import SeleniumService, WebDriverCreator
+from SeleniumLibrary.keywords.webdrivertools import SeleniumService
@pytest.fixture(scope="module")
def service():
return SeleniumService()
+
@pytest.fixture(scope="module")
def reporter():
path = os.path.dirname(__file__)
@@ -33,30 +31,24 @@ def teardown_function():
unstub()
-@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_parse_service_string(service, reporter):
results = []
results.append(service._parse('attribute="arg1"'))
# results.append(service._parse(" attribute = True ")) # need to resolve issues with spaces in service string.
results.append(service._parse('attribute="arg1";attribute=True'))
- results.append(service._parse('attribute=["arg1","arg2","arg3"] ; attribute=True ; attribute="arg4"'))
results.append(
service._parse(
- 'attribute="C:\\\\path\\to\\\\profile"'
+ 'attribute=["arg1","arg2","arg3"] ; attribute=True ; attribute="arg4"'
)
)
+ results.append(service._parse('attribute="C:\\\\path\\to\\\\profile"'))
results.append(
- service._parse(
- r'attribute="arg1"; attribute="C:\\path\\to\\profile"'
- )
+ service._parse(r'attribute="arg1"; attribute="C:\\path\\to\\profile"')
)
results.append(service._parse("attribute=None"))
verify_all("Selenium service string to dict", results, reporter=reporter)
-# @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
-# @unittest.skipIf(sys.version_info > (3, 11), reason="Errors change with Python 3.12")
-@pytest.mark.skipif(WINDOWS, reason="ApprovalTest do not support different line feeds")
@pytest.mark.skipif(sys.version_info > (3, 11), reason="Errors change with Python 3.12")
def test_parse_service_string_errors(service, reporter):
results = []
@@ -65,11 +57,12 @@ def test_parse_service_string_errors(service, reporter):
results.append(error_formatter(service._parse, "attribute=['arg1'", True))
results.append(error_formatter(service._parse, "attribute=['arg1';'arg2']", True))
results.append(error_formatter(service._parse, "attribute['arg1']", True))
- results.append(error_formatter(service._parse, "attribute=['arg1'] attribute=['arg2']", True))
+ results.append(
+ error_formatter(service._parse, "attribute=['arg1'] attribute=['arg2']", True)
+ )
verify_all("Selenium service string errors", results, reporter=reporter)
-@pytest.mark.skipif(WINDOWS, reason="ApprovalTest do not support different line feeds")
@pytest.mark.skipif(sys.version_info < (3, 12), reason="Errors change with Python 3.12")
def test_parse_service_string_errors_py3_12(service, reporter):
results = []
@@ -78,30 +71,31 @@ def test_parse_service_string_errors_py3_12(service, reporter):
results.append(error_formatter(service._parse, "attribute=['arg1'", True))
results.append(error_formatter(service._parse, "attribute=['arg1';'arg2']", True))
results.append(error_formatter(service._parse, "attribute['arg1']", True))
- results.append(error_formatter(service._parse, "attribute=['arg1'] attribute=['arg2']", True))
+ results.append(
+ error_formatter(service._parse, "attribute=['arg1'] attribute=['arg2']", True)
+ )
verify_all("Selenium service string errors", results, reporter=reporter)
-@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_split_service(service, reporter):
results = []
- results.append(service._split("attribute='arg1'", ';'))
- results.append(service._split("attribute='arg1';attribute='arg2'", ';'))
- results.append(service._split("attribute=['arg1','arg2'];attribute='arg3'", ';'))
- results.append(service._split(" attribute = 'arg1' ; attribute = 'arg2' ", ';'))
+ results.append(service._split("attribute='arg1'", ";"))
+ results.append(service._split("attribute='arg1';attribute='arg2'", ";"))
+ results.append(service._split("attribute=['arg1','arg2'];attribute='arg3'", ";"))
+ results.append(service._split(" attribute = 'arg1' ; attribute = 'arg2' ", ";"))
verify_all("Selenium service string splitting", results, reporter=reporter)
-@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_split_attribute(service, reporter):
results = []
- results.append(service._split("attribute='arg1'", '='))
- results.append(service._split("attribute=['arg1','arg2']", '='))
- results.append(service._split(" attribute = [ 'arg1' , 'arg2' ]", '='))
- verify_all("Selenium service attribute string splitting", results, reporter=reporter)
+ results.append(service._split("attribute='arg1'", "="))
+ results.append(service._split("attribute=['arg1','arg2']", "="))
+ results.append(service._split(" attribute = [ 'arg1' , 'arg2' ]", "="))
+ verify_all(
+ "Selenium service attribute string splitting", results, reporter=reporter
+ )
-@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_service_create(service, reporter):
results = []
service_str = "service_args=['--log-level=DEBUG']"
@@ -119,7 +113,6 @@ def test_service_create(service, reporter):
verify_all("Selenium service", results, reporter=reporter)
-@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_importer(service, reporter):
results = []
results.append(service._import_service("firefox"))
@@ -138,4 +131,4 @@ def error_formatter(method, arg, full=False):
except Exception as error:
if full:
return f"{arg} {error}"
- return "{} {}".format(arg, error.__str__()[:15])
\ No newline at end of file
+ return f"{arg} {error.__str__()[:15]}"
diff --git a/utest/test/keywords/test_tablekeywords.py b/utest/test/keywords/test_tablekeywords.py
index 6e8c1cf32..87275bc31 100644
--- a/utest/test/keywords/test_tablekeywords.py
+++ b/utest/test/keywords/test_tablekeywords.py
@@ -1,6 +1,6 @@
import unittest
-from mockito import mock, when, unstub
+from mockito import mock, unstub, when
from SeleniumLibrary.keywords import TableElementKeywords
diff --git a/utest/test/keywords/test_waiting_stale_element_refereance_exception.py b/utest/test/keywords/test_waiting_stale_element_refereance_exception.py
index 910d9cb6c..3b5b53e1a 100644
--- a/utest/test/keywords/test_waiting_stale_element_refereance_exception.py
+++ b/utest/test/keywords/test_waiting_stale_element_refereance_exception.py
@@ -1,6 +1,6 @@
import pytest
+from mockito import mock, unstub, when
from selenium.common.exceptions import StaleElementReferenceException
-from mockito import mock, when, unstub
from SeleniumLibrary.keywords import WaitingKeywords
diff --git a/utest/test/keywords/test_webdrivercache.py b/utest/test/keywords/test_webdrivercache.py
index f138565f2..900aaefb1 100644
--- a/utest/test/keywords/test_webdrivercache.py
+++ b/utest/test/keywords/test_webdrivercache.py
@@ -1,6 +1,7 @@
import unittest
-from mockito import mock, verify, when, unstub
+import pytest
+from mockito import mock, unstub, verify, when
from robot.utils.connectioncache import NoConnection
from selenium.common.exceptions import TimeoutException, WebDriverException
@@ -13,10 +14,9 @@ def tearDown(self):
def test_no_current_message(self):
cache = WebDriverCache()
- try:
- self.assertRaises(RuntimeError, cache.current.anyMember())
- except RuntimeError as e:
- self.assertEqual(str(e), "No current browser")
+ with pytest.raises(RuntimeError) as e:
+ cache.current.anyMember()
+ assert str(e.value) == "No current browser"
def test_browsers_property(self):
cache = WebDriverCache()
@@ -29,13 +29,13 @@ def test_browsers_property(self):
index2 = cache.register(driver2)
index3 = cache.register(driver3)
- self.assertEqual(len(cache.drivers), 3)
- self.assertEqual(cache.drivers[0], driver1)
- self.assertEqual(cache.drivers[1], driver2)
- self.assertEqual(cache.drivers[2], driver3)
- self.assertEqual(index1, 1)
- self.assertEqual(index2, 2)
- self.assertEqual(index3, 3)
+ assert len(cache.drivers) == 3
+ assert cache.drivers[0] == driver1
+ assert cache.drivers[1] == driver2
+ assert cache.drivers[2] == driver3
+ assert index1 == 1
+ assert index2 == 2
+ assert index3 == 3
def test_get_open_browsers(self):
cache = WebDriverCache()
@@ -49,16 +49,16 @@ def test_get_open_browsers(self):
cache.register(driver3)
drivers = cache.active_drivers
- self.assertEqual(len(drivers), 3)
- self.assertEqual(drivers[0], driver1)
- self.assertEqual(drivers[1], driver2)
- self.assertEqual(drivers[2], driver3)
+ assert len(drivers) == 3
+ assert drivers[0] == driver1
+ assert drivers[1] == driver2
+ assert drivers[2] == driver3
cache.close()
drivers = cache.active_drivers
- self.assertEqual(len(drivers), 2)
- self.assertEqual(drivers[0], driver1)
- self.assertEqual(drivers[1], driver2)
+ assert len(drivers) == 2
+ assert drivers[0] == driver1
+ assert drivers[1] == driver2
def test_close(self):
cache = WebDriverCache()
@@ -96,19 +96,19 @@ def test_resolve_alias_or_index(self):
cache.register(mock())
index = cache.get_index("foo")
- self.assertEqual(index, 1)
+ assert index == 1
index = cache.get_index(1)
- self.assertEqual(index, 1)
+ assert index == 1
index = cache.get_index(3)
- self.assertEqual(index, 3)
+ assert index == 3
index = cache.get_index(None)
- self.assertEqual(index, None)
+ assert index is None
index = cache.get_index("None")
- self.assertEqual(index, None)
+ assert index is None
def test_resolve_alias_or_index_with_none(self):
cache = WebDriverCache()
@@ -117,13 +117,13 @@ def test_resolve_alias_or_index_with_none(self):
cache.register(mock(), "None")
index = cache.get_index("foo")
- self.assertEqual(index, 1)
+ assert index == 1
index = cache.get_index(1)
- self.assertEqual(index, 1)
+ assert index == 1
index = cache.get_index(None)
- self.assertEqual(index, None)
+ assert index is None
def test_resolve_alias_or_index_error(self):
cache = WebDriverCache()
@@ -132,13 +132,13 @@ def test_resolve_alias_or_index_error(self):
cache.register(mock())
index = cache.get_index("bar")
- self.assertEqual(index, None)
+ assert index is None
index = cache.get_index(12)
- self.assertEqual(index, None)
+ assert index is None
index = cache.get_index(-1)
- self.assertEqual(index, None)
+ assert index is None
def test_close_and_same_alias(self):
cache = WebDriverCache()
@@ -147,20 +147,20 @@ def test_close_and_same_alias(self):
cache.register(mock(), "bar")
cache.close()
index = cache.get_index("bar")
- self.assertEqual(index, None)
+ assert index is None
def test_same_alias_new_browser(self):
cache = WebDriverCache()
cache.close()
index = cache.get_index("bar")
- self.assertEqual(index, None)
+ assert index is None
def test_close_all_cache_first_quite_fails(self):
cache = WebDriverCache()
driver = mock()
when(driver).quit().thenRaise(TimeoutException("timeout."))
cache.register(driver, "bar")
- with self.assertRaises(TimeoutException):
+ with pytest.raises(TimeoutException):
cache.close_all()
self.verify_cache(cache)
@@ -173,7 +173,7 @@ def test_close_all_cache_middle_quite_fails(self):
cache.register(driver0, "bar0")
cache.register(driver1, "bar1")
cache.register(driver2, "bar2")
- with self.assertRaises(TimeoutException):
+ with pytest.raises(TimeoutException):
cache.close_all()
self.verify_cache(cache)
@@ -186,7 +186,7 @@ def test_close_all_cache_all_quite_fails(self):
cache.register(driver0, "bar0")
cache.register(driver1, "bar1")
cache.register(driver2, "bar2")
- with self.assertRaises(TimeoutException):
+ with pytest.raises(TimeoutException):
cache.close_all()
self.verify_cache(cache)
@@ -199,7 +199,7 @@ def test_close_all_cache_not_selenium_error(self):
cache.register(driver0, "bar0")
cache.register(driver1, "bar1")
cache.register(driver2, "bar2")
- with self.assertRaises(TimeoutException):
+ with pytest.raises(TimeoutException):
cache.close_all()
self.verify_cache(cache)
@@ -217,10 +217,10 @@ def test_close_quite_fails(self):
driver = mock()
when(driver).quit().thenRaise(TimeoutException("timeout."))
cache.register(driver, "bar")
- with self.assertRaises(TimeoutException):
+ with pytest.raises(TimeoutException):
cache.close()
- self.assertTrue(isinstance(cache.current, NoConnection))
- self.assertTrue(driver in cache._closed)
+ assert isinstance(cache.current, NoConnection)
+ assert driver in cache._closed
def test_close_no_error(self):
cache = WebDriverCache()
@@ -228,10 +228,10 @@ def test_close_no_error(self):
when(driver).quit().thenReturn(None)
cache.register(driver, "bar")
cache.close()
- self.assertTrue(isinstance(cache.current, NoConnection))
- self.assertTrue(driver in cache._closed)
+ assert isinstance(cache.current, NoConnection)
+ assert driver in cache._closed
def verify_cache(self, cache):
- self.assertEqual(cache._connections, [])
- self.assertEqual(cache._aliases, {})
- self.assertTrue(isinstance(cache.current, NoConnection))
+ assert cache._connections == []
+ assert cache._aliases == {}
+ assert isinstance(cache.current, NoConnection)
diff --git a/utest/test/keywords/test_windowmananger_window_info.py b/utest/test/keywords/test_windowmananger_window_info.py
index 16abd144e..f58300c9a 100644
--- a/utest/test/keywords/test_windowmananger_window_info.py
+++ b/utest/test/keywords/test_windowmananger_window_info.py
@@ -1,9 +1,9 @@
import unittest
-from mockito import mock, when, unstub
+from mockito import mock, unstub, when
+from selenium.common.exceptions import WebDriverException
from SeleniumLibrary.locators.windowmanager import WindowManager
-from selenium.common.exceptions import WebDriverException
SCRIPT = "return [ window.id, window.name ];"
HANDLE = "17c3dc18-0443-478b-aec6-ed7e2a5da7e1"
@@ -28,50 +28,48 @@ def mock_window_info(self, id_, name, title, url):
def test_window_info_values_are_strings(self):
self.mock_window_info("id", "name", "title", "url")
info = self.manager._get_current_window_info()
- self.assertEqual(info, (HANDLE, "id", "name", "title", "url"))
+ assert info == (HANDLE, "id", "name", "title", "url")
def test_window_info_values_are_none(self):
self.mock_window_info(None, None, None, None)
info = self.manager._get_current_window_info()
- self.assertEqual(
- info, (HANDLE, "undefined", "undefined", "undefined", "undefined")
- )
+ assert info == (HANDLE, "undefined", "undefined", "undefined", "undefined")
def test_window_info_values_are_empty_strings(self):
self.mock_window_info("", "", "", "")
info = self.manager._get_current_window_info()
- self.assertEqual(info, (HANDLE, "", "undefined", "undefined", "undefined"))
+ assert info == (HANDLE, "", "undefined", "undefined", "undefined")
def test_window_id_is_bool(self):
self.mock_window_info(True, "", "", "")
info = self.manager._get_current_window_info()
- self.assertEqual(info[1], True)
+ assert info[1]
self.mock_window_info(False, "", "", "")
info = self.manager._get_current_window_info()
- self.assertEqual(info[1], False)
+ assert not info[1]
def test_window_id_is_web_element(self):
elem = mock()
self.mock_window_info(*[elem, "", "", ""])
info = self.manager._get_current_window_info()
- self.assertEqual(info[1], elem)
+ assert info[1] == elem
def test_window_id_is_container(self):
self.mock_window_info(*[["1"], "", "", ""])
info = self.manager._get_current_window_info()
- self.assertEqual(info[1], ["1"])
+ assert info[1] == ["1"]
self.mock_window_info(*[{"a": 2}, "", "", ""])
info = self.manager._get_current_window_info()
- self.assertEqual(info[1], {"a": 2})
+ assert info[1] == {"a": 2}
def test_window_id_is_empty_container(self):
self.mock_window_info(*[[], "", "", ""])
info = self.manager._get_current_window_info()
- self.assertEqual(info[1], [])
+ assert info[1] == []
self.mock_window_info(*[{}, "", "", ""])
info = self.manager._get_current_window_info()
- self.assertEqual(info[1], {})
+ assert info[1] == {}
def test_no_javascript_support(self):
when(self.driver).execute_script(SCRIPT).thenRaise(WebDriverException)
@@ -79,4 +77,4 @@ def test_no_javascript_support(self):
self.driver.current_url = "url"
self.driver.current_window_handle = HANDLE
info = self.manager._get_current_window_info()
- self.assertEqual(info, (HANDLE, "undefined", "undefined", "title", "url"))
+ assert info == (HANDLE, "undefined", "undefined", "title", "url")
diff --git a/utest/test/locators/test_elementfinder.py b/utest/test/locators/test_elementfinder.py
index 50472be20..21792ea33 100644
--- a/utest/test/locators/test_elementfinder.py
+++ b/utest/test/locators/test_elementfinder.py
@@ -3,14 +3,15 @@
import pytest
from approvaltests import verify_all
from approvaltests.reporters import GenericDiffReporterFactory
-from mockito import any, mock, verify, when, unstub
+from mockito import any as mockito_any
+from mockito import mock, unstub, verify, when
from selenium.webdriver.common.by import By
from SeleniumLibrary.errors import ElementNotFound
from SeleniumLibrary.locators.elementfinder import ElementFinder
-@pytest.fixture(scope="function")
+@pytest.fixture
def finder():
ctx = mock()
ctx.driver = mock()
@@ -105,7 +106,7 @@ def _verify_parse_locator(locator, prefix, criteria, finder=None):
def test_parent_is_not_webelement(finder):
- with pytest.raises(ValueError):
+ with pytest.raises(ValueError, match=r"^Parent must be Selenium WebElement"):
finder.find("//div", parent="//button")
@@ -155,9 +156,8 @@ def test_find_by_dom__parent_is_webelement(finder):
when(finder)._disallow_webelement_parent(webelement).thenRaise(
ValueError("This method does not allow webelement as parent")
)
- with pytest.raises(ValueError) as error:
+ with pytest.raises(ValueError, match="not allow webelement as parent"):
finder.find("dom=value", parent=webelement)
- assert "not allow webelement as parent" in str(error.value)
def test_find_by_sizzle_parent_is_webelement(finder):
@@ -167,9 +167,8 @@ def test_find_by_sizzle_parent_is_webelement(finder):
when(finder)._disallow_webelement_parent(webelement).thenRaise(
ValueError("This method does not allow webelement as parent")
)
- with pytest.raises(ValueError) as error:
+ with pytest.raises(ValueError, match="not allow webelement as parent"):
finder.find("sizzle=div.class", parent=webelement)
- assert "not allow webelement as parent" in str(error.value)
def test_find_by_link_text_parent_is_webelement(finder):
@@ -224,9 +223,8 @@ def test_find_sc_locator_parent_is_webelement(finder):
when(finder)._disallow_webelement_parent(webelement).thenRaise(
ValueError("This method does not allow webelement as parent")
)
- with pytest.raises(ValueError) as error:
+ with pytest.raises(ValueError, match="not allow webelement as parent"):
finder.find("scLocator=div", parent=webelement)
- assert "not allow webelement as parent" in str(error.value)
def test_find_by_default_parent_is_webelement(finder):
@@ -250,13 +248,13 @@ def test_non_existing_prefix(finder):
def test_find_with_no_tag(finder):
driver = _get_driver(finder)
finder.find("test1", required=False)
- verify(driver).find_elements(By.XPATH, "//*[(@id='test1' or " "@name='test1')]")
+ verify(driver).find_elements(By.XPATH, "//*[(@id='test1' or @name='test1')]")
def test_find_with_explicit_default_strategy(finder):
driver = _get_driver(finder)
finder.find("default=test1", required=False)
- verify(driver).find_elements(By.XPATH, "//*[(@id='test1' or " "@name='test1')]")
+ verify(driver).find_elements(By.XPATH, "//*[(@id='test1' or @name='test1')]")
def test_find_with_explicit_default_strategy_and_equals(finder):
@@ -283,10 +281,13 @@ def test_find_with_data(finder):
finder.find("data:id:my_id", tag="div", required=False)
verify(driver).find_elements(By.XPATH, '//*[@data-id="my_id"]')
+
def test_find_with_data_multiple_colons(finder):
driver = _get_driver(finder)
elements = _make_mock_elements("div", "a", "span", "a")
- when(driver).find_elements(By.XPATH, '//*[@data-automation-id="foo:bar"]').thenReturn(elements)
+ when(driver).find_elements(
+ By.XPATH, '//*[@data-automation-id="foo:bar"]'
+ ).thenReturn(elements)
result = finder.find("data:automation-id:foo:bar", first_only=False)
assert result == elements
@@ -655,7 +656,7 @@ def test_find_returns_bad_values(finder):
for bad_value in (None, {"": None}):
for locator_strategy in locator_strategies:
when_find_func = getattr(when(driver), func_name)
- when_find_func(locator_strategy, any()).thenReturn(bad_value)
+ when_find_func(locator_strategy, mockito_any()).thenReturn(bad_value)
for locator in (
"identifier=it",
"id=it",
diff --git a/utest/test/locators/test_windowmanager.py b/utest/test/locators/test_windowmanager.py
index f40770ae4..393faad60 100644
--- a/utest/test/locators/test_windowmanager.py
+++ b/utest/test/locators/test_windowmanager.py
@@ -1,6 +1,7 @@
import unittest
import uuid
+import pytest
from mockito import mock
from SeleniumLibrary.errors import WindowNotFound
@@ -10,11 +11,11 @@
class WindowManagerTests(unittest.TestCase):
def test_select_with_invalid_prefix(self):
manager = WindowManagerWithMockBrowser()
- with self.assertRaises(WindowNotFound) as context:
+ with pytest.raises(WindowNotFound) as context:
manager.select("something=test1")
- self.assertEqual(
- str(context.exception),
- "No window matching handle, name, title or URL 'something=test1' found.",
+ assert (
+ str(context.value)
+ == "No window matching handle, name, title or URL 'something=test1' found."
)
def test_select_by_title(self):
@@ -24,7 +25,7 @@ def test_select_by_title(self):
{"name": "win3", "title": "Title 3", "url": "http://localhost/page3.html"},
)
manager.select("title=Title 2")
- self.assertEqual(manager.driver.current_window.name, "win2")
+ assert manager.driver.current_window.name == "win2"
def test_select_by_title_with_multiple_matches(self):
manager = WindowManagerWithMockBrowser(
@@ -41,7 +42,7 @@ def test_select_by_title_with_multiple_matches(self):
},
)
manager.select("title=Title 2")
- self.assertEqual(manager.driver.current_window.name, "win2a")
+ assert manager.driver.current_window.name == "win2a"
def test_select_by_title_no_match(self):
manager = WindowManagerWithMockBrowser(
@@ -49,11 +50,9 @@ def test_select_by_title_no_match(self):
{"name": "win2", "title": "Title 2", "url": "http://localhost/page2.html"},
{"name": "win3", "title": "Title 3", "url": "http://localhost/page3.html"},
)
- with self.assertRaises(WindowNotFound) as context:
+ with pytest.raises(WindowNotFound) as context:
manager.select("title=Title -1")
- self.assertEqual(
- str(context.exception), "Unable to locate window with title 'Title -1'."
- )
+ assert str(context.value) == "Unable to locate window with title 'Title -1'."
def test_select_by_name(self):
manager = WindowManagerWithMockBrowser(
@@ -62,7 +61,7 @@ def test_select_by_name(self):
{"name": "win3", "title": "Title 3", "url": "http://localhost/page3.html"},
)
manager.select("name=win2")
- self.assertEqual(manager.driver.current_window.name, "win2")
+ assert manager.driver.current_window.name == "win2"
def test_select_by_name_no_match(self):
manager = WindowManagerWithMockBrowser(
@@ -70,11 +69,9 @@ def test_select_by_name_no_match(self):
{"name": "win2", "title": "Title 2", "url": "http://localhost/page2.html"},
{"name": "win3", "title": "Title 3", "url": "http://localhost/page3.html"},
)
- with self.assertRaises(WindowNotFound) as context:
+ with pytest.raises(WindowNotFound) as context:
manager.select("name=win-1")
- self.assertEqual(
- str(context.exception), "Unable to locate window with name 'win-1'."
- )
+ assert str(context.value) == "Unable to locate window with name 'win-1'."
def test_select_by_url(self):
manager = WindowManagerWithMockBrowser(
@@ -83,7 +80,7 @@ def test_select_by_url(self):
{"name": "win3", "title": "Title 3", "url": "http://localhost/page3.html"},
)
manager.select("url=http://localhost/page2.html")
- self.assertEqual(manager.driver.current_window.name, "win2")
+ assert manager.driver.current_window.name == "win2"
def test_select_by_url_with_multiple_matches(self):
manager = WindowManagerWithMockBrowser(
@@ -100,7 +97,7 @@ def test_select_by_url_with_multiple_matches(self):
},
)
manager.select("url=http://localhost/page2.html")
- self.assertEqual(manager.driver.current_window.name, "win2a")
+ assert manager.driver.current_window.name == "win2a"
def test_select_by_url_no_match(self):
manager = WindowManagerWithMockBrowser(
@@ -108,11 +105,11 @@ def test_select_by_url_no_match(self):
{"name": "win2", "title": "Title 2", "url": "http://localhost/page2.html"},
{"name": "win3", "title": "Title 3", "url": "http://localhost/page3.html"},
)
- with self.assertRaises(WindowNotFound) as context:
+ with pytest.raises(WindowNotFound) as context:
manager.select("url=http://localhost/page-1.html")
- self.assertEqual(
- str(context.exception),
- "Unable to locate window with URL 'http://localhost/page-1.html'.",
+ assert (
+ str(context.value)
+ == "Unable to locate window with URL 'http://localhost/page-1.html'."
)
def test_select_main_window(self):
@@ -122,11 +119,11 @@ def test_select_main_window(self):
{"name": "win3", "title": "Title 3", "url": "http://localhost/page3.html"},
)
manager.select("name=win2")
- self.assertEqual(manager.driver.current_window.name, "win2")
+ assert manager.driver.current_window.name == "win2"
manager.select("main")
- self.assertEqual(manager.driver.current_window.name, "win1")
+ assert manager.driver.current_window.name == "win1"
manager.select("MAIN")
- self.assertEqual(manager.driver.current_window.name, "win1")
+ assert manager.driver.current_window.name == "win1"
def test_select_by_default_with_name(self):
manager = WindowManagerWithMockBrowser(
@@ -135,7 +132,7 @@ def test_select_by_default_with_name(self):
{"name": "win3", "title": "Title 3", "url": "http://localhost/page3.html"},
)
manager.select("win2")
- self.assertEqual(manager.driver.current_window.name, "win2")
+ assert manager.driver.current_window.name == "win2"
def test_select_by_default_with_title(self):
manager = WindowManagerWithMockBrowser(
@@ -144,7 +141,7 @@ def test_select_by_default_with_title(self):
{"name": "win3", "title": "Title 3", "url": "http://localhost/page3.html"},
)
manager.select("Title 2")
- self.assertEqual(manager.driver.current_window.name, "win2")
+ assert manager.driver.current_window.name == "win2"
def test_select_by_default_no_match(self):
manager = WindowManagerWithMockBrowser(
@@ -152,11 +149,11 @@ def test_select_by_default_no_match(self):
{"name": "win2", "title": "Title 2", "url": "http://localhost/page2.html"},
{"name": "win3", "title": "Title 3", "url": "http://localhost/page3.html"},
)
- with self.assertRaises(WindowNotFound) as context:
+ with pytest.raises(WindowNotFound) as context:
manager.select("foobar")
- self.assertEqual(
- str(context.exception),
- "No window matching handle, name, title or URL 'foobar' found.",
+ assert (
+ str(context.value)
+ == "No window matching handle, name, title or URL 'foobar' found."
)
def test_prefix_is_case_sensitive(self):
@@ -166,12 +163,12 @@ def test_prefix_is_case_sensitive(self):
{"name": "win3", "title": "Title 3", "url": "http://localhost/page3.html"},
)
manager.select("name=win2")
- self.assertEqual(manager.driver.current_window.name, "win2")
- with self.assertRaises(WindowNotFound) as context:
+ assert manager.driver.current_window.name == "win2"
+ with pytest.raises(WindowNotFound) as context:
manager.select("nAmE=win2")
- self.assertEqual(
- str(context.exception),
- "No window matching handle, name, title or URL 'nAmE=win2' found.",
+ assert (
+ str(context.value)
+ == "No window matching handle, name, title or URL 'nAmE=win2' found."
)
def test_get_window_infos(self):
@@ -180,21 +177,26 @@ def test_get_window_infos(self):
{"id": "id2", "name": "win2", "title": "Title 2", "url": "http://url.2"},
{"name": "win3", "title": "Title 3", "url": "http://url.3"},
)
- self.assertEqual(
- [info.id for info in manager.get_window_infos()],
- ["id1", "id2", "undefined"],
- )
- self.assertEqual(
- [info.name for info in manager.get_window_infos()], ["win1", "win2", "win3"]
- )
- self.assertEqual(
- [info.title for info in manager.get_window_infos()],
- ["Title 1", "Title 2", "Title 3"],
- )
- self.assertEqual(
- [info.url for info in manager.get_window_infos()],
- ["http://url.1", "http://url.2", "http://url.3"],
- )
+ assert [info.id for info in manager.get_window_infos()] == [
+ "id1",
+ "id2",
+ "undefined",
+ ]
+ assert [info.name for info in manager.get_window_infos()] == [
+ "win1",
+ "win2",
+ "win3",
+ ]
+ assert [info.title for info in manager.get_window_infos()] == [
+ "Title 1",
+ "Title 2",
+ "Title 3",
+ ]
+ assert [info.url for info in manager.get_window_infos()] == [
+ "http://url.1",
+ "http://url.2",
+ "http://url.3",
+ ]
class WindowManagerWithMockBrowser(WindowManager):
@@ -238,6 +240,7 @@ def execute_script(script):
handle_ = driver.session_id
if handle_ in driver.window_handles:
return window_infos[handle_][:2]
+ return None
driver.execute_script = execute_script
return driver
diff --git a/utest/test/robotframework_seleniumlibrary_translation_fi/__init__.py b/utest/test/robotframework_seleniumlibrary_translation_fi/__init__.py
index 369b7c953..55f6e3a2d 100644
--- a/utest/test/robotframework_seleniumlibrary_translation_fi/__init__.py
+++ b/utest/test/robotframework_seleniumlibrary_translation_fi/__init__.py
@@ -3,7 +3,4 @@
def get_language() -> dict:
curr_dir = Path(__file__).parent.absolute()
- return {
- "language": "fi",
- "path": curr_dir / "translate.json"
- }
+ return {"language": "fi", "path": curr_dir / "translate.json"}
diff --git a/utest/test/robotframework_seleniumlibrary_translation_list/__init__.py b/utest/test/robotframework_seleniumlibrary_translation_list/__init__.py
index 4ccfe3f24..a3758c18a 100644
--- a/utest/test/robotframework_seleniumlibrary_translation_list/__init__.py
+++ b/utest/test/robotframework_seleniumlibrary_translation_list/__init__.py
@@ -4,12 +4,6 @@
def get_language() -> list:
curr_dir = Path(__file__).parent.absolute()
return [
- {
- "language": "eng",
- "path": curr_dir / "translate1.json"
- },
- {
- "language": "swe",
- "path": curr_dir / "translate2.json"
- }
- ]
\ No newline at end of file
+ {"language": "eng", "path": curr_dir / "translate1.json"},
+ {"language": "swe", "path": curr_dir / "translate2.json"},
+ ]
diff --git a/utest/test/translation/__init__.py b/utest/test/translation/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/utest/test/translation/test_translation.py b/utest/test/translation/test_translation.py
index 0281189dc..18df6ea8d 100644
--- a/utest/test/translation/test_translation.py
+++ b/utest/test/translation/test_translation.py
@@ -1,12 +1,12 @@
-from pathlib import Path
import sys
+from pathlib import Path
import pytest
from SeleniumLibrary import SeleniumLibrary
-@pytest.fixture()
+@pytest.fixture
def sl() -> SeleniumLibrary:
sys.path.append(str(Path(__file__).parent.parent.absolute()))
return SeleniumLibrary(language="FI")
diff --git a/utest/test/utils/test_package.py b/utest/test/utils/test_package.py
index 2043421f7..8fe174a84 100644
--- a/utest/test/utils/test_package.py
+++ b/utest/test/utils/test_package.py
@@ -5,13 +5,13 @@
class UtilsPackageTests(unittest.TestCase):
def test_escape_xpath_value_with_apos(self):
- self.assertEqual(escape_xpath_value("test '1'"), "\"test '1'\"")
+ assert escape_xpath_value("test '1'") == "\"test '1'\""
def test_escape_xpath_value_with_quote(self):
- self.assertEqual(escape_xpath_value('test "1"'), "'test \"1\"'")
+ assert escape_xpath_value('test "1"') == "'test \"1\"'"
def test_escape_xpath_value_with_quote_and_apos(self):
- self.assertEqual(
- escape_xpath_value("test \"1\" and '2'"),
- "concat('test \"1\" and ', \"'\", '2', \"'\", '')",
+ assert (
+ escape_xpath_value("test \"1\" and '2'")
+ == "concat('test \"1\" and ', \"'\", '2', \"'\", '')"
)
diff --git a/utest/test/utils/test_types.py b/utest/test/utils/test_types.py
index 5dfca9e00..7a093ca53 100644
--- a/utest/test/utils/test_types.py
+++ b/utest/test/utils/test_types.py
@@ -6,5 +6,5 @@
def test_is_noney():
for item in [None, "None", "NONE", "none"]:
assert is_noney(item)
- for item in TRUTHY + [False, 0, "False", "", [], {}, ()]:
+ for item in [*TRUTHY, False, 0, "False", "", [], {}, ()]:
assert is_noney(item) is False
diff --git a/utest/test/utils/test_xpath_escape.py b/utest/test/utils/test_xpath_escape.py
index 5f1defae7..1eda8f15c 100644
--- a/utest/test/utils/test_xpath_escape.py
+++ b/utest/test/utils/test_xpath_escape.py
@@ -5,7 +5,6 @@
from approvaltests.reporters.generic_diff_reporter_factory import (
GenericDiffReporterFactory,
)
-from robot.utils import WINDOWS
from SeleniumLibrary.utils import escape_xpath_value
@@ -21,7 +20,6 @@ def reporter():
return factory.get_first_working()
-@pytest.mark.skipif(WINDOWS, reason="ApprovalTest do not support different line feeds")
def test_string(reporter):
results = []
results.append(escape_xpath_value("tidii"))