From f513902b9c1b43e40e38e727c47323e69d84a1b5 Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Sun, 23 Mar 2025 21:03:37 +0530 Subject: [PATCH 01/29] refactored conftest.py --- py/conftest.py | 342 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 224 insertions(+), 118 deletions(-) diff --git a/py/conftest.py b/py/conftest.py index c18e8fcf5c0e5..bd860ab591e26 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -18,6 +18,7 @@ import os import platform from pathlib import Path +from dataclasses import dataclass import pytest @@ -100,49 +101,219 @@ def pytest_generate_tests(metafunc): metafunc.parametrize("driver", metafunc.config.option.drivers, indirect=True) -def get_driver_class(driver_option): - """Generate the driver class name from the lowercase driver option.""" - if driver_option == "webkitgtk": - driver_class = "WebKitGTK" - elif driver_option == "wpewebkit": - driver_class = "WPEWebKit" - else: - driver_class = driver_option.capitalize() - return driver_class +driver_instance = None +selenium_driver = None + + +class ContainerProtocol: + def __contains__(self, name): + if name.lower() in self.__dict__: + return True + return False + + +@dataclass +class SupportedDrivers(ContainerProtocol): + chrome: str = "Chrome" + firefox: str = "Firefox" + safari: str = "Safari" + edge: str = "Edge" + ie: str = "Ie" + webkitgtk: str = "WebKitGTK" + wpewebkit: str = "WPEWebKit" + remote: str = "Remote" + + +@dataclass +class SupportedOptions(ContainerProtocol): + chrome: str = "ChromeOptions" + firefox: str = "FirefoxOptions" + edge: str = "EdgeOptions" + safari: str = "SafariOptions" + ie: str = "IeOptions" + remote: str = "FirefoxOptions" + webkitgtk: str = "WebKitGTKOptions" + wpewebkit: str = "WPEWebKitOptions" + + +@dataclass +class SupportedBidiDrivers(ContainerProtocol): + chrome: str = "Chrome" + firefox: str = "Firefox" + edge: str = "Edge" + remote: str = "Remote" + + +class Driver: + def __init__(self, driver_class, request): + self.driver_class = driver_class + self._request = request + self._driver = None + self._platform = None + self._service = None + self.kwargs = {} + self.options = driver_class + self.headless = driver_class + self.bidi = request.config.option.bidi + + @property + def supported_drivers(self): + return SupportedDrivers() + + @property + def supported_options(self): + return SupportedOptions() + + @property + def supported_bidi_drivers(self): + return SupportedBidiDrivers() + + @property + def driver_class(self): + return self._driver_class + + @driver_class.setter + def driver_class(self, cls_name): + if cls_name.lower() not in self.supported_drivers: + raise AttributeError(f"Invalid driver class {cls_name.lower()}") + self._driver_class = getattr(self.supported_drivers, cls_name.lower()) + + @property + def exe_platform(self): + self._platform = platform.system() + return self._platform + + @property + def browser_path(self): + if self._request.config.option.binary: + return self._request.config.option.binary + return None + @property + def browser_args(self): + if self._request.config.option.args: + return self._request.config.option.args + return None -driver_instance = None + @property + def driver_path(self): + if self._request.config.option.executable: + return self._request.config.option.executable + return None + + @property + def headless(self): + self._headless = self._request.config.option.headless + if self._headless: + return True + return False + + @headless.setter + def headless(self, driver_class): + if self.headless: + if driver_class.lower() == "chrome" or driver_class.lower() == "edge": + self._options.add_argument("--headless=new") + if driver_class.lower() == "firefox": + self._options.add_argument("-headless") + + @property + def bidi(self): + return self._bidi + + @bidi.setter + def bidi(self, value): + self._bidi = value + if self._bidi: + self._options.web_socket_url = True + self._options.unhandled_prompt_behavior = "ignore" + + @property + def options(self): + return self._options + + @options.setter + def options(self, cls_name): + if cls_name.lower() not in self.supported_options: + raise AttributeError(f"Invalid Options class {cls_name.lower()}") + self._options = getattr(webdriver, getattr(self.supported_options, cls_name.lower()))() + if self.driver_class == self.supported_drivers.firefox: + # There are issues with window size/position when running Firefox + # under Wayland, so we use XWayland instead. + os.environ["MOZ_ENABLE_WAYLAND"] = "0" + if self.driver_class == self.supported_drivers.remote: + self._options.set_capability("moz:firefoxOptions", {}) + self._options.enable_downloads = True + os.environ["MOZ_ENABLE_WAYLAND"] = "0" + if self.driver_class == self.supported_drivers.webkitgtk: + self._options.overlay_scrollbars_enabled = False + + @property + def service(self): + executable = self.driver_path + if executable: + module = getattr(webdriver, self.driver_class.lower()) + self._service = module.service.Service(executable_path=executable) + return self._service + return None + + @property + def driver(self): + self._driver = self._initialize_driver() + return self._driver + + @property + def is_platform_valid(self): + if self.driver_class.lower() == "safari" and self.exe_platform != "Darwin": + return False + if self.driver_class.lower() == "ie" and self.exe_platform != "Windows": + return False + if "webkit" in self.driver_class.lower() and self.exe_platform == "Windows": + return False + return True + + def _initialize_driver(self): + if self.options is not None: + self.kwargs["options"] = self.options + if self.driver_path is not None: + self.kwargs["service"] = self.service + return getattr(webdriver, self.driver_class)(**self.kwargs) + + @property + def stop_driver(self): + def fin(): + global driver_instance + if self._driver is not None: + self._driver.quit() + self._driver = None + driver_instance = None + + return fin @pytest.fixture(scope="function") def driver(request): - kwargs = {} - driver_option = getattr(request, "param", "Chrome") + global driver_instance + global selenium_driver + driver_class = getattr(request, "param", "Chrome").lower() + + if selenium_driver is None: + selenium_driver = Driver(driver_class, request) - # browser can be changed with `--driver=firefox` as an argument or to addopts in pytest.ini - driver_class = get_driver_class(driver_option) + # skip tests if not available on the platform + if not selenium_driver.is_platform_valid: + pytest.skip(f"{driver_class} tests can only run on {selenium_driver.exe_platform}") # skip tests in the 'remote' directory if run with a local driver - if request.node.path.parts[-2] == "remote" and driver_class != "Remote": - pytest.skip(f"Remote tests can't be run with driver '{driver_option.lower()}'") - - # skip tests that can't run on certain platforms - _platform = platform.system() - if driver_class == "Safari" and _platform != "Darwin": - pytest.skip("Safari tests can only run on an Apple OS") - if (driver_class == "Ie") and _platform != "Windows": - pytest.skip("IE and EdgeHTML Tests can only run on Windows") - if "WebKit" in driver_class and _platform == "Windows": - pytest.skip("WebKit tests cannot be run on Windows") + if request.node.path.parts[-2] == "remote" and selenium_driver.driver_class != "Remote": + pytest.skip(f"Remote tests can't be run with driver '{selenium_driver.driver_class}'") # skip tests for drivers that don't support BiDi when --bidi is enabled - if request.config.option.bidi: - if driver_class in ("Ie", "Safari", "WebKitGTK", "WPEWebKit"): + if selenium_driver.bidi: + if driver_class.lower() not in selenium_driver.supported_bidi_drivers: pytest.skip(f"{driver_class} does not support BiDi") # conditionally mark tests as expected to fail based on driver marker = request.node.get_closest_marker(f"xfail_{driver_class.lower()}") - if marker is not None: if "run" in marker.kwargs: if marker.kwargs["run"] is False: @@ -153,104 +324,23 @@ def driver(request): marker.kwargs.pop("raises") pytest.xfail(**marker.kwargs) - def fin(): - global driver_instance - if driver_instance is not None: - driver_instance.quit() - driver_instance = None - - request.addfinalizer(fin) - - driver_path = request.config.option.executable - options = None + request.addfinalizer(selenium_driver.stop_driver) - global driver_instance if driver_instance is None: - if driver_class == "Firefox": - options = get_options(driver_class, request.config) - if platform.system() == "Linux": - # There are issues with window size/position when running Firefox - # under Wayland, so we use XWayland instead. - os.environ["MOZ_ENABLE_WAYLAND"] = "0" - if driver_class == "Chrome": - options = get_options(driver_class, request.config) - if driver_class == "Edge": - options = get_options(driver_class, request.config) - if driver_class == "WebKitGTK": - options = get_options(driver_class, request.config) - if driver_class == "WPEWebKit": - options = get_options(driver_class, request.config) - if driver_class == "Remote": - options = get_options("Firefox", request.config) or webdriver.FirefoxOptions() - options.set_capability("moz:firefoxOptions", {}) - options.enable_downloads = True - if driver_path is not None: - kwargs["service"] = get_service(driver_class, driver_path) - if options is not None: - kwargs["options"] = options - - driver_instance = getattr(webdriver, driver_class)(**kwargs) + driver_instance = selenium_driver.driver yield driver_instance # Close the browser after BiDi tests. Those make event subscriptions # and doesn't seems to be stable enough, causing the flakiness of the # subsequent tests. # Remove this when BiDi implementation and API is stable. - if request.config.option.bidi: - - def fin(): - global driver_instance - if driver_instance is not None: - driver_instance.quit() - driver_instance = None - - request.addfinalizer(fin) + if selenium_driver.bidi: + request.addfinalizer(selenium_driver.stop_driver) if request.node.get_closest_marker("no_driver_after_test"): driver_instance = None -def get_options(driver_class, config): - browser_path = config.option.binary - browser_args = config.option.args - headless = config.option.headless - bidi = config.option.bidi - - options = getattr(webdriver, f"{driver_class}Options")() - - if browser_path or browser_args: - if driver_class == "WebKitGTK": - options.overlay_scrollbars_enabled = False - if browser_path is not None: - options.binary_location = browser_path.strip("'") - if browser_args is not None: - for arg in browser_args.split(): - options.add_argument(arg) - - if headless: - if driver_class == "Chrome" or driver_class == "Edge": - options.add_argument("--headless") - if driver_class == "Firefox": - options.add_argument("-headless") - - if bidi: - options.web_socket_url = True - options.unhandled_prompt_behavior = "ignore" - - return options - - -def get_service(driver_class, executable): - # Let the default behaviour be used if we don't set the driver executable - if not executable: - return None - - module = getattr(webdriver, driver_class.lower()) - service = module.service.Service(executable_path=executable) - - return service - - @pytest.fixture(scope="session", autouse=True) def stop_driver(request): def fin(): @@ -333,12 +423,24 @@ def driver_executable(request): return request.config.option.executable +@pytest.fixture(scope="function") +def clean_service(request): + _supported_drivers = SupportedDrivers() + try: + driver_class = getattr(_supported_drivers, request.config.option.drivers[0].lower()) + except (AttributeError, TypeError): + raise Exception("This test requires a --driver to be specified.") + selenium_driver = Driver(driver_class, request) + yield selenium_driver.service + + @pytest.fixture(scope="function") def clean_driver(request): + _supported_drivers = SupportedDrivers() try: - driver_class = get_driver_class(request.config.option.drivers[0]) + driver_class = getattr(_supported_drivers, request.config.option.drivers[0].lower()) except (AttributeError, TypeError): - raise Exception("This test requires a --driver to be specified") + raise Exception("This test requires a --driver to be specified.") driver_reference = getattr(webdriver, driver_class) yield driver_reference if request.node.get_closest_marker("no_driver_after_test"): @@ -359,13 +461,17 @@ def clean_options(request): @pytest.fixture def firefox_options(request): + _supported_drivers = SupportedDrivers() try: - driver_option = request.config.option.drivers[0] + driver_class = request.config.option.drivers[0] except (AttributeError, TypeError): raise Exception("This test requires a --driver to be specified") + # skip tests in the 'remote' directory if run with a local driver - if request.node.path.parts[-2] == "remote" and get_driver_class(driver_option) != "Remote": - pytest.skip(f"Remote tests can't be run with driver '{driver_option}'") + _driver_class = getattr(_supported_drivers, driver_class.lower()) + if request.node.path.parts[-2] == "remote" and _driver_class != "Remote": + pytest.skip(f"Remote tests can't be run with driver '{_driver_class}'") + options = webdriver.FirefoxOptions() if request.config.option.headless: options.add_argument("-headless") From e6afd87e1eec7a59946cd3e19557fc6166acd1f9 Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Tue, 25 Mar 2025 21:53:22 +0530 Subject: [PATCH 02/29] fixed driver_class bugs --- py/conftest.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/py/conftest.py b/py/conftest.py index bd860ab591e26..2e94cf9bf04ae 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -329,6 +329,8 @@ def driver(request): if driver_instance is None: driver_instance = selenium_driver.driver + driver_instance = selenium_driver.driver + yield driver_instance # Close the browser after BiDi tests. Those make event subscriptions # and doesn't seems to be stable enough, causing the flakiness of the From 5913a55e30a608c41de9573b92eb46a233c5b722 Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Wed, 26 Mar 2025 21:53:57 +0530 Subject: [PATCH 03/29] fixing teardown --- py/conftest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/py/conftest.py b/py/conftest.py index 2e94cf9bf04ae..b0143a058df3e 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -329,8 +329,6 @@ def driver(request): if driver_instance is None: driver_instance = selenium_driver.driver - driver_instance = selenium_driver.driver - yield driver_instance # Close the browser after BiDi tests. Those make event subscriptions # and doesn't seems to be stable enough, causing the flakiness of the @@ -342,6 +340,8 @@ def driver(request): if request.node.get_closest_marker("no_driver_after_test"): driver_instance = None + driver_instance.quit() + @pytest.fixture(scope="session", autouse=True) def stop_driver(request): From a376f5ec890f79c2cabc5469b3936eb73e678c8e Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Sun, 30 Mar 2025 22:45:03 +0530 Subject: [PATCH 04/29] fixed all review comments --- py/conftest.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/py/conftest.py b/py/conftest.py index b0143a058df3e..bd860ab591e26 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -340,8 +340,6 @@ def driver(request): if request.node.get_closest_marker("no_driver_after_test"): driver_instance = None - driver_instance.quit() - @pytest.fixture(scope="session", autouse=True) def stop_driver(request): From d6dbc35263ea72cb8e4dc5dd6c6985395bf211b9 Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Tue, 1 Apr 2025 23:46:57 +0530 Subject: [PATCH 05/29] fixed bugs --- py/conftest.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/py/conftest.py b/py/conftest.py index bd860ab591e26..12355876c34d9 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -145,6 +145,9 @@ class SupportedBidiDrivers(ContainerProtocol): class Driver: + _supported_drivers = SupportedDrivers() + _supported_options = SupportedOptions() + def __init__(self, driver_class, request): self.driver_class = driver_class self._request = request @@ -178,6 +181,16 @@ def driver_class(self, cls_name): raise AttributeError(f"Invalid driver class {cls_name.lower()}") self._driver_class = getattr(self.supported_drivers, cls_name.lower()) + @property + def driver_class(self): + return self._driver_class + + @driver_class.setter + def driver_class(self, cls_name): + if cls_name.lower() not in self._supported_drivers: + raise AttributeError(f"Invalid driver class {cls_name.lower()}") + self._driver_class = getattr(self._supported_drivers, cls_name.lower()) + @property def exe_platform(self): self._platform = platform.system() From fe51fd7bcd690db46e857c89e54795d268ede1dd Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Sat, 19 Apr 2025 18:39:06 +0530 Subject: [PATCH 06/29] fixed bidi_network_tests --- py/conftest.py | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/py/conftest.py b/py/conftest.py index 12355876c34d9..bb0d28eb8422d 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -145,9 +145,6 @@ class SupportedBidiDrivers(ContainerProtocol): class Driver: - _supported_drivers = SupportedDrivers() - _supported_options = SupportedOptions() - def __init__(self, driver_class, request): self.driver_class = driver_class self._request = request @@ -187,9 +184,9 @@ def driver_class(self): @driver_class.setter def driver_class(self, cls_name): - if cls_name.lower() not in self._supported_drivers: + if cls_name.lower() not in self.supported_drivers: raise AttributeError(f"Invalid driver class {cls_name.lower()}") - self._driver_class = getattr(self._supported_drivers, cls_name.lower()) + self._driver_class = getattr(self.supported_drivers, cls_name.lower()) @property def exe_platform(self): @@ -325,6 +322,11 @@ def driver(request): if driver_class.lower() not in selenium_driver.supported_bidi_drivers: pytest.skip(f"{driver_class} does not support BiDi") + # skip tests for drivers that don't support BiDi when --bidi is enabled + if selenium_driver.bidi: + if driver_class.lower() not in selenium_driver.supported_bidi_drivers: + pytest.skip(f"{driver_class} does not support BiDi") + # conditionally mark tests as expected to fail based on driver marker = request.node.get_closest_marker(f"xfail_{driver_class.lower()}") if marker is not None: @@ -353,6 +355,16 @@ def driver(request): if request.node.get_closest_marker("no_driver_after_test"): driver_instance = None + # Close the browser after BiDi tests. Those make event subscriptions + # and doesn't seems to be stable enough, causing the flakiness of the + # subsequent tests. + # Remove this when BiDi implementation and API is stable. + if selenium_driver.bidi: + request.addfinalizer(selenium_driver.stop_driver) + + if request.node.get_closest_marker("no_driver_after_test"): + driver_instance = None + @pytest.fixture(scope="session", autouse=True) def stop_driver(request): From 33a673c55d4e027ff9447b0de7e08457bee0746c Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Sat, 19 Apr 2025 20:41:38 +0530 Subject: [PATCH 07/29] added property to check for valid platform --- py/conftest.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/py/conftest.py b/py/conftest.py index bb0d28eb8422d..583a1361cb5aa 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -322,11 +322,6 @@ def driver(request): if driver_class.lower() not in selenium_driver.supported_bidi_drivers: pytest.skip(f"{driver_class} does not support BiDi") - # skip tests for drivers that don't support BiDi when --bidi is enabled - if selenium_driver.bidi: - if driver_class.lower() not in selenium_driver.supported_bidi_drivers: - pytest.skip(f"{driver_class} does not support BiDi") - # conditionally mark tests as expected to fail based on driver marker = request.node.get_closest_marker(f"xfail_{driver_class.lower()}") if marker is not None: From cf68e36d5ef5b38b0e283604a5db41ee3f02303a Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Tue, 22 Apr 2025 05:34:09 +0530 Subject: [PATCH 08/29] fixted linting issue --- py/conftest.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/py/conftest.py b/py/conftest.py index 583a1361cb5aa..b3be3504632bb 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -419,6 +419,43 @@ def server(request): server.start() yield server server.stop() + _socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + url = f"http://{_host}:{_port}/status" + try: + _socket.connect((_host, _port)) + print( + "The remote driver server is already running or something else" + "is using port {}, continuing...".format(_port) + ) + except Exception: + remote_env = os.environ.copy() + if platform.system() == "Linux": + # There are issues with window size/position when running Firefox + # under Wayland, so we use XWayland instead. + remote_env["MOZ_ENABLE_WAYLAND"] = "0" + print("Starting the Selenium server") + process = subprocess.Popen( + [ + "java", + "-jar", + _path, + "standalone", + "--port", + "4444", + "--selenium-manager", + "true", + "--enable-managed-downloads", + "true", + ], + env=remote_env, + ) + print(f"Selenium server running as process: {process.pid}") + assert wait_for_server(url, 10), f"Timed out waiting for Selenium server at {url}" + print("Selenium server is ready") + yield process + process.terminate() + process.wait() + print("Selenium server has been terminated") @pytest.fixture(autouse=True, scope="session") From 32efe4da9752af2c81dd87b44da2e7939b9f323c Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Tue, 22 Apr 2025 21:48:46 +0530 Subject: [PATCH 09/29] fixed lynting issue --- py/conftest.py | 1 + 1 file changed, 1 insertion(+) diff --git a/py/conftest.py b/py/conftest.py index b3be3504632bb..4c6427f602e80 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -27,6 +27,7 @@ from test.selenium.webdriver.common.network import get_lan_ip from test.selenium.webdriver.common.webserver import SimpleWebServer + drivers = ( "chrome", "edge", From e546760aa8cf7f42548d1ff826a24563847680a2 Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Thu, 1 May 2025 08:02:56 +0530 Subject: [PATCH 10/29] fixed linting issues --- py/conftest.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/py/conftest.py b/py/conftest.py index 4c6427f602e80..1889dfc10cefa 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -528,7 +528,11 @@ def firefox_options(request): # skip tests in the 'remote' directory if run with a local driver _driver_class = getattr(_supported_drivers, driver_class.lower()) if request.node.path.parts[-2] == "remote" and _driver_class != "Remote": +<<<<<<< HEAD pytest.skip(f"Remote tests can't be run with driver '{_driver_class}'") +======= + pytest.skip(f"Remote tests can't be run with driver '{selenium_driver.driver_class}'") +>>>>>>> 35c2a28003 (fixed linting issues) options = webdriver.FirefoxOptions() if request.config.option.headless: From 6b2b60dcc4156d39cae75c23e36fabb9c7ca0235 Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Thu, 1 May 2025 08:06:18 +0530 Subject: [PATCH 11/29] fixed linting issues --- py/conftest.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/py/conftest.py b/py/conftest.py index 1889dfc10cefa..4c6427f602e80 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -528,11 +528,7 @@ def firefox_options(request): # skip tests in the 'remote' directory if run with a local driver _driver_class = getattr(_supported_drivers, driver_class.lower()) if request.node.path.parts[-2] == "remote" and _driver_class != "Remote": -<<<<<<< HEAD pytest.skip(f"Remote tests can't be run with driver '{_driver_class}'") -======= - pytest.skip(f"Remote tests can't be run with driver '{selenium_driver.driver_class}'") ->>>>>>> 35c2a28003 (fixed linting issues) options = webdriver.FirefoxOptions() if request.config.option.headless: From c4facc9afae15a48dc7a3306c0e03d72b9867188 Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Thu, 1 May 2025 09:19:26 +0530 Subject: [PATCH 12/29] fixed merge conflicts and cleaned up --- py/conftest.py | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/py/conftest.py b/py/conftest.py index 4c6427f602e80..583a1361cb5aa 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -27,7 +27,6 @@ from test.selenium.webdriver.common.network import get_lan_ip from test.selenium.webdriver.common.webserver import SimpleWebServer - drivers = ( "chrome", "edge", @@ -420,43 +419,6 @@ def server(request): server.start() yield server server.stop() - _socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - url = f"http://{_host}:{_port}/status" - try: - _socket.connect((_host, _port)) - print( - "The remote driver server is already running or something else" - "is using port {}, continuing...".format(_port) - ) - except Exception: - remote_env = os.environ.copy() - if platform.system() == "Linux": - # There are issues with window size/position when running Firefox - # under Wayland, so we use XWayland instead. - remote_env["MOZ_ENABLE_WAYLAND"] = "0" - print("Starting the Selenium server") - process = subprocess.Popen( - [ - "java", - "-jar", - _path, - "standalone", - "--port", - "4444", - "--selenium-manager", - "true", - "--enable-managed-downloads", - "true", - ], - env=remote_env, - ) - print(f"Selenium server running as process: {process.pid}") - assert wait_for_server(url, 10), f"Timed out waiting for Selenium server at {url}" - print("Selenium server is ready") - yield process - process.terminate() - process.wait() - print("Selenium server has been terminated") @pytest.fixture(autouse=True, scope="session") From 13ca869f6470fa982e21fd48bd189ca92deac384 Mon Sep 17 00:00:00 2001 From: Sandeep Suryaprasad Date: Sat, 3 May 2025 14:40:32 +0530 Subject: [PATCH 13/29] fixed browser args bugs --- py/conftest.py | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/py/conftest.py b/py/conftest.py index 583a1361cb5aa..fe35638afa846 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -153,7 +153,7 @@ def __init__(self, driver_class, request): self._service = None self.kwargs = {} self.options = driver_class - self.headless = driver_class + self.headless = request.config.option.headless self.bidi = request.config.option.bidi @property @@ -213,17 +213,17 @@ def driver_path(self): @property def headless(self): - self._headless = self._request.config.option.headless if self._headless: return True return False @headless.setter - def headless(self, driver_class): - if self.headless: - if driver_class.lower() == "chrome" or driver_class.lower() == "edge": + def headless(self, value): + self._headless = value + if self._headless: + if self.driver_class.lower() == "chrome" or self.driver_class.lower() == "edge": self._options.add_argument("--headless=new") - if driver_class.lower() == "firefox": + if self.driver_class.lower() == "firefox": self._options.add_argument("-headless") @property @@ -245,17 +245,29 @@ def options(self): def options(self, cls_name): if cls_name.lower() not in self.supported_options: raise AttributeError(f"Invalid Options class {cls_name.lower()}") - self._options = getattr(webdriver, getattr(self.supported_options, cls_name.lower()))() + if self.driver_class == self.supported_drivers.firefox: - # There are issues with window size/position when running Firefox - # under Wayland, so we use XWayland instead. - os.environ["MOZ_ENABLE_WAYLAND"] = "0" - if self.driver_class == self.supported_drivers.remote: + self._options = getattr(webdriver, self.supported_options.firefox)() + if self.exe_platform == "Linux": + # There are issues with window size/position when running Firefox + # under Wayland, so we use XWayland instead. + os.environ["MOZ_ENABLE_WAYLAND"] = "0" + elif self.driver_class == self.supported_drivers.remote: + self._options = getattr(webdriver, self.supported_options.firefox)() self._options.set_capability("moz:firefoxOptions", {}) self._options.enable_downloads = True - os.environ["MOZ_ENABLE_WAYLAND"] = "0" - if self.driver_class == self.supported_drivers.webkitgtk: - self._options.overlay_scrollbars_enabled = False + else: + opts_cls = getattr(self.supported_options, cls_name.lower()) + self._options = getattr(webdriver, opts_cls)() + + if self.browser_path or self.browser_args: + if self.driver_class == self.supported_drivers.webkitgtk: + self._options.overlay_scrollbars_enabled = False + if self.browser_path is not None: + self._options.binary_location = browser_path.strip("'") + if self.browser_args is not None: + for arg in self.browser_args.split(): + self._options.add_argument(arg) @property def service(self): From a441d6d6d6c9922c2e78eb18b0c16e1fe0f25229 Mon Sep 17 00:00:00 2001 From: Sandeep Suryaprasad Date: Sat, 3 May 2025 15:10:09 +0530 Subject: [PATCH 14/29] fixed linting issue --- py/conftest.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/py/conftest.py b/py/conftest.py index fe35638afa846..2cfa96d294a2a 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -149,7 +149,6 @@ def __init__(self, driver_class, request): self.driver_class = driver_class self._request = request self._driver = None - self._platform = None self._service = None self.kwargs = {} self.options = driver_class @@ -190,8 +189,7 @@ def driver_class(self, cls_name): @property def exe_platform(self): - self._platform = platform.system() - return self._platform + return platform.system() @property def browser_path(self): @@ -264,7 +262,7 @@ def options(self, cls_name): if self.driver_class == self.supported_drivers.webkitgtk: self._options.overlay_scrollbars_enabled = False if self.browser_path is not None: - self._options.binary_location = browser_path.strip("'") + self._options.binary_location = self.browser_path.strip("'") if self.browser_args is not None: for arg in self.browser_args.split(): self._options.add_argument(arg) From b1b9318a0d89a9df94f95566a6b3256f839658b5 Mon Sep 17 00:00:00 2001 From: Sandeep Suryaprasad Date: Sat, 3 May 2025 15:21:56 +0530 Subject: [PATCH 15/29] testing --- py/conftest.py | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/py/conftest.py b/py/conftest.py index 2cfa96d294a2a..8f36df9fd06ee 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -152,8 +152,6 @@ def __init__(self, driver_class, request): self._service = None self.kwargs = {} self.options = driver_class - self.headless = request.config.option.headless - self.bidi = request.config.option.bidi @property def supported_drivers(self): @@ -211,29 +209,15 @@ def driver_path(self): @property def headless(self): - if self._headless: + if self._request.config.option.headless: return True return False - @headless.setter - def headless(self, value): - self._headless = value - if self._headless: - if self.driver_class.lower() == "chrome" or self.driver_class.lower() == "edge": - self._options.add_argument("--headless=new") - if self.driver_class.lower() == "firefox": - self._options.add_argument("-headless") - @property def bidi(self): - return self._bidi - - @bidi.setter - def bidi(self, value): - self._bidi = value - if self._bidi: - self._options.web_socket_url = True - self._options.unhandled_prompt_behavior = "ignore" + if self._request.config.option.bidi: + return True + return False @property def options(self): @@ -267,6 +251,16 @@ def options(self, cls_name): for arg in self.browser_args.split(): self._options.add_argument(arg) + if self.headless: + if self.driver_class.lower() == "chrome" or self.driver_class.lower() == "edge": + self._options.add_argument("--headless=new") + if self.driver_class.lower() == "firefox": + self._options.add_argument("-headless") + + if self.bidi: + self._options.web_socket_url = True + self._options.unhandled_prompt_behavior = "ignore" + @property def service(self): executable = self.driver_path From b7acddfacbca0e4ef821452abca0406d30de3672 Mon Sep 17 00:00:00 2001 From: Sandeep Suryaprasad Date: Sat, 3 May 2025 17:01:56 +0530 Subject: [PATCH 16/29] testing --- py/conftest.py | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/py/conftest.py b/py/conftest.py index 8f36df9fd06ee..b1c825d220e49 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -175,16 +175,6 @@ def driver_class(self, cls_name): raise AttributeError(f"Invalid driver class {cls_name.lower()}") self._driver_class = getattr(self.supported_drivers, cls_name.lower()) - @property - def driver_class(self): - return self._driver_class - - @driver_class.setter - def driver_class(self, cls_name): - if cls_name.lower() not in self.supported_drivers: - raise AttributeError(f"Invalid driver class {cls_name.lower()}") - self._driver_class = getattr(self.supported_drivers, cls_name.lower()) - @property def exe_platform(self): return platform.system() @@ -252,9 +242,9 @@ def options(self, cls_name): self._options.add_argument(arg) if self.headless: - if self.driver_class.lower() == "chrome" or self.driver_class.lower() == "edge": + if cls_name.lower() == "chrome" or cls_name.lower() == "edge": self._options.add_argument("--headless=new") - if self.driver_class.lower() == "firefox": + if cls_name.lower() == "firefox": self._options.add_argument("-headless") if self.bidi: From e601205dcca91c442e4697e790b0fd7d7fd5239f Mon Sep 17 00:00:00 2001 From: Sandeep Suryaprasad Date: Sat, 3 May 2025 18:24:00 +0530 Subject: [PATCH 17/29] testing --- py/conftest.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/py/conftest.py b/py/conftest.py index b1c825d220e49..ae059c24d36d9 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -150,7 +150,6 @@ def __init__(self, driver_class, request): self._request = request self._driver = None self._service = None - self.kwargs = {} self.options = driver_class @property @@ -276,11 +275,12 @@ def is_platform_valid(self): return True def _initialize_driver(self): + kwargs = {} if self.options is not None: - self.kwargs["options"] = self.options + kwargs["options"] = self.options if self.driver_path is not None: - self.kwargs["service"] = self.service - return getattr(webdriver, self.driver_class)(**self.kwargs) + kwargs["service"] = self.service + return getattr(webdriver, self.driver_class)(**kwargs) @property def stop_driver(self): From ef3d97941fd057d7255ab8e7bc86be2b9f0c3fff Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Sat, 17 May 2025 21:32:34 +0530 Subject: [PATCH 18/29] testing --- py/conftest.py | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/py/conftest.py b/py/conftest.py index ae059c24d36d9..54c09e16b0778 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -17,8 +17,8 @@ import os import platform -from pathlib import Path from dataclasses import dataclass +from pathlib import Path import pytest @@ -437,17 +437,6 @@ def driver_executable(request): return request.config.option.executable -@pytest.fixture(scope="function") -def clean_service(request): - _supported_drivers = SupportedDrivers() - try: - driver_class = getattr(_supported_drivers, request.config.option.drivers[0].lower()) - except (AttributeError, TypeError): - raise Exception("This test requires a --driver to be specified.") - selenium_driver = Driver(driver_class, request) - yield selenium_driver.service - - @pytest.fixture(scope="function") def clean_driver(request): _supported_drivers = SupportedDrivers() @@ -463,14 +452,16 @@ def clean_driver(request): @pytest.fixture(scope="function") def clean_service(request): - driver_class = get_driver_class(request.config.option.drivers[0]) - yield get_service(driver_class, request.config.option.executable) + driver_class = request.config.option.drivers[0].lower() + selenium_driver = Driver(driver_class, request) + yield selenium_driver.service @pytest.fixture(scope="function") def clean_options(request): - driver_class = get_driver_class(request.config.option.drivers[0]) - yield get_options(driver_class, request.config) + driver_class = request.config.option.drivers[0].lower() + selenium_driver = Driver(driver_class, request) + yield selenium_driver.options @pytest.fixture From 300728f2822598a9c2496ddc09b970527402018b Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Sun, 18 May 2025 20:30:15 +0530 Subject: [PATCH 19/29] removed duplicate code after yield in driver fixture --- py/conftest.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/py/conftest.py b/py/conftest.py index 54c09e16b0778..00a2106e2c5c7 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -344,16 +344,6 @@ def driver(request): if request.node.get_closest_marker("no_driver_after_test"): driver_instance = None - # Close the browser after BiDi tests. Those make event subscriptions - # and doesn't seems to be stable enough, causing the flakiness of the - # subsequent tests. - # Remove this when BiDi implementation and API is stable. - if selenium_driver.bidi: - request.addfinalizer(selenium_driver.stop_driver) - - if request.node.get_closest_marker("no_driver_after_test"): - driver_instance = None - @pytest.fixture(scope="session", autouse=True) def stop_driver(request): From c4a8525568fb99bccaa869690cb5801edbe83d7f Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Sun, 25 May 2025 18:44:53 +0530 Subject: [PATCH 20/29] moved headless and bidi option to a separate setter methods --- py/conftest.py | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/py/conftest.py b/py/conftest.py index 00a2106e2c5c7..51621843c2eef 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -151,6 +151,8 @@ def __init__(self, driver_class, request): self._driver = None self._service = None self.options = driver_class + self.headless = driver_class + self.bidi = driver_class @property def supported_drivers(self): @@ -198,15 +200,27 @@ def driver_path(self): @property def headless(self): - if self._request.config.option.headless: - return True - return False + return self._headless + + @headless.setter + def headless(self, cls_name): + self._headless = self._request.config.option.headless + if self._headless: + if cls_name.lower() == "chrome" or cls_name.lower() == "edge": + self._options.add_argument("--headless=new") + if cls_name.lower() == "firefox": + self._options.add_argument("-headless") @property def bidi(self): - if self._request.config.option.bidi: - return True - return False + return self._bidi + + @bidi.setter + def bidi(self, cls_name): + self._bidi = self._request.config.option.bidi + if self._bidi: + self._options.web_socket_url = True + self._options.unhandled_prompt_behavior = "ignore" @property def options(self): @@ -240,16 +254,6 @@ def options(self, cls_name): for arg in self.browser_args.split(): self._options.add_argument(arg) - if self.headless: - if cls_name.lower() == "chrome" or cls_name.lower() == "edge": - self._options.add_argument("--headless=new") - if cls_name.lower() == "firefox": - self._options.add_argument("-headless") - - if self.bidi: - self._options.web_socket_url = True - self._options.unhandled_prompt_behavior = "ignore" - @property def service(self): executable = self.driver_path From fc26b47e002faad4fab91f543428a73c6647dde0 Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Fri, 30 May 2025 22:53:03 +0530 Subject: [PATCH 21/29] added new property to skip remote tests --- py/conftest.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/py/conftest.py b/py/conftest.py index 51621843c2eef..b1409863363a9 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -286,6 +286,12 @@ def _initialize_driver(self): kwargs["service"] = self.service return getattr(webdriver, self.driver_class)(**kwargs) + @property + def skip_remote_tests(self): + if self._request.node.path.parts[-2] == "remote" and self.driver_class != "Remote": + return True + return False + @property def stop_driver(self): def fin(): @@ -312,7 +318,7 @@ def driver(request): pytest.skip(f"{driver_class} tests can only run on {selenium_driver.exe_platform}") # skip tests in the 'remote' directory if run with a local driver - if request.node.path.parts[-2] == "remote" and selenium_driver.driver_class != "Remote": + if selenium_driver.skip_remote_tests: pytest.skip(f"Remote tests can't be run with driver '{selenium_driver.driver_class}'") # skip tests for drivers that don't support BiDi when --bidi is enabled @@ -460,16 +466,15 @@ def clean_options(request): @pytest.fixture def firefox_options(request): - _supported_drivers = SupportedDrivers() try: driver_class = request.config.option.drivers[0] except (AttributeError, TypeError): raise Exception("This test requires a --driver to be specified") # skip tests in the 'remote' directory if run with a local driver - _driver_class = getattr(_supported_drivers, driver_class.lower()) - if request.node.path.parts[-2] == "remote" and _driver_class != "Remote": - pytest.skip(f"Remote tests can't be run with driver '{_driver_class}'") + selenium_driver = Driver(driver_class, request) + if selenium_driver.skip_remote_tests: + pytest.skip(f"Remote tests can't be run with driver '{driver_class}'") options = webdriver.FirefoxOptions() if request.config.option.headless: From c36b3c5c7c12e5170262a38dbeaa613db27ad27d Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Fri, 30 May 2025 23:28:45 +0530 Subject: [PATCH 22/29] changed headless flag --- py/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/conftest.py b/py/conftest.py index b1409863363a9..b5291cf7cecd3 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -207,7 +207,7 @@ def headless(self, cls_name): self._headless = self._request.config.option.headless if self._headless: if cls_name.lower() == "chrome" or cls_name.lower() == "edge": - self._options.add_argument("--headless=new") + self._options.add_argument("--headless") if cls_name.lower() == "firefox": self._options.add_argument("-headless") From 01a6884f37cb0402a839bf06c2dbad6b78a9757a Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Fri, 30 May 2025 23:42:50 +0530 Subject: [PATCH 23/29] added change to accomodate changes in PR-15794 --- py/conftest.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/py/conftest.py b/py/conftest.py index b5291cf7cecd3..48180285fdb41 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -485,21 +485,21 @@ def firefox_options(request): @pytest.fixture def chromium_options(request): try: - driver_option = request.config.option.drivers[0].lower() + driver_class = request.config.option.drivers[0].lower() except (AttributeError, TypeError): raise Exception("This test requires a --driver to be specified") - # Skip if not Chrome or Edge - if driver_option not in ("chrome", "edge"): - pytest.skip(f"This test requires Chrome or Edge, got {driver_option}") + if driver_class not in ("chrome", "edge"): + pytest.skip(f"This test requires Chrome or Edge, got {driver_class}") + selenium_driver = Driver(driver_class, request) # skip tests in the 'remote' directory if run with a local driver - if request.node.path.parts[-2] == "remote" and get_driver_class(driver_option) != "Remote": - pytest.skip(f"Remote tests can't be run with driver '{driver_option}'") + if selenium_driver.skip_remote_tests: + pytest.skip(f"Remote tests can't be run with driver '{driver_class}'") - if driver_option == "chrome": + if driver_class == "chrome": options = webdriver.ChromeOptions() - elif driver_option == "edge": + elif driver_class == "edge": options = webdriver.EdgeOptions() if request.config.option.headless: From b5def48992d9136d605e0e64820f3c60d38e53c4 Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Sat, 31 May 2025 00:39:50 +0530 Subject: [PATCH 24/29] fixed formatting issue --- py/conftest.py | 1 + 1 file changed, 1 insertion(+) diff --git a/py/conftest.py b/py/conftest.py index 48180285fdb41..631bff3d9a400 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -488,6 +488,7 @@ def chromium_options(request): driver_class = request.config.option.drivers[0].lower() except (AttributeError, TypeError): raise Exception("This test requires a --driver to be specified") + # Skip if not Chrome or Edge if driver_class not in ("chrome", "edge"): pytest.skip(f"This test requires Chrome or Edge, got {driver_class}") From f8e44476f0c00333b5cdb39a595c93fb00403d7c Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Sat, 31 May 2025 09:02:50 +0530 Subject: [PATCH 25/29] fixed formatting --- py/conftest.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/py/conftest.py b/py/conftest.py index 631bff3d9a400..641732f0571a6 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -288,7 +288,10 @@ def _initialize_driver(self): @property def skip_remote_tests(self): - if self._request.node.path.parts[-2] == "remote" and self.driver_class != "Remote": + if ( + self._request.node.path.parts[-2] == "remote" + and self.driver_class != "Remote" + ): return True return False @@ -315,11 +318,15 @@ def driver(request): # skip tests if not available on the platform if not selenium_driver.is_platform_valid: - pytest.skip(f"{driver_class} tests can only run on {selenium_driver.exe_platform}") + pytest.skip( + f"{driver_class} tests can only run on {selenium_driver.exe_platform}" + ) # skip tests in the 'remote' directory if run with a local driver if selenium_driver.skip_remote_tests: - pytest.skip(f"Remote tests can't be run with driver '{selenium_driver.driver_class}'") + pytest.skip( + f"Remote tests can't be run with driver '{selenium_driver.driver_class}'" + ) # skip tests for drivers that don't support BiDi when --bidi is enabled if selenium_driver.bidi: @@ -441,7 +448,9 @@ def driver_executable(request): def clean_driver(request): _supported_drivers = SupportedDrivers() try: - driver_class = getattr(_supported_drivers, request.config.option.drivers[0].lower()) + driver_class = getattr( + _supported_drivers, request.config.option.drivers[0].lower() + ) except (AttributeError, TypeError): raise Exception("This test requires a --driver to be specified.") driver_reference = getattr(webdriver, driver_class) From c88c158a7e75c0333e61b94ef8dfdd05fcd061e4 Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Sat, 31 May 2025 15:35:40 +0530 Subject: [PATCH 26/29] added new cls method which returns clean options --- py/conftest.py | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/py/conftest.py b/py/conftest.py index 641732f0571a6..45b4a5e07843d 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -154,6 +154,10 @@ def __init__(self, driver_class, request): self.headless = driver_class self.bidi = driver_class + @classmethod + def clean_options(cls, driver_class, request): + return cls(driver_class, request).options + @property def supported_drivers(self): return SupportedDrivers() @@ -468,9 +472,7 @@ def clean_service(request): @pytest.fixture(scope="function") def clean_options(request): - driver_class = request.config.option.drivers[0].lower() - selenium_driver = Driver(driver_class, request) - yield selenium_driver.options + yield Driver.clean_options(driver_class, request) @pytest.fixture @@ -485,9 +487,8 @@ def firefox_options(request): if selenium_driver.skip_remote_tests: pytest.skip(f"Remote tests can't be run with driver '{driver_class}'") - options = webdriver.FirefoxOptions() - if request.config.option.headless: - options.add_argument("-headless") + options = Driver.clean_options("firefox", request) + return options @@ -507,12 +508,8 @@ def chromium_options(request): if selenium_driver.skip_remote_tests: pytest.skip(f"Remote tests can't be run with driver '{driver_class}'") - if driver_class == "chrome": - options = webdriver.ChromeOptions() - elif driver_class == "edge": - options = webdriver.EdgeOptions() - - if request.config.option.headless: - options.add_argument("--headless") + if driver_class in ("chrome", "edge"): + options = Driver.clean_options(driver_class, request) return options + From 05f976d67b96a6a06a1eaaa3f02a267f02004106 Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Sat, 31 May 2025 15:41:51 +0530 Subject: [PATCH 27/29] fixed linting issue --- py/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/conftest.py b/py/conftest.py index 45b4a5e07843d..7310608214d46 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -472,6 +472,7 @@ def clean_service(request): @pytest.fixture(scope="function") def clean_options(request): + driver_class = request.config.option.drivers[0].lower() yield Driver.clean_options(driver_class, request) @@ -512,4 +513,3 @@ def chromium_options(request): options = Driver.clean_options(driver_class, request) return options - From 39acd60b175e8e8af956ef9b8ef5674b1fc50003 Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Sat, 31 May 2025 16:04:35 +0530 Subject: [PATCH 28/29] testing --- py/conftest.py | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/py/conftest.py b/py/conftest.py index 7310608214d46..1de8303d11186 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -290,15 +290,6 @@ def _initialize_driver(self): kwargs["service"] = self.service return getattr(webdriver, self.driver_class)(**kwargs) - @property - def skip_remote_tests(self): - if ( - self._request.node.path.parts[-2] == "remote" - and self.driver_class != "Remote" - ): - return True - return False - @property def stop_driver(self): def fin(): @@ -327,7 +318,7 @@ def driver(request): ) # skip tests in the 'remote' directory if run with a local driver - if selenium_driver.skip_remote_tests: + if request.node.path.parts[-2] == "remote" and selenium_driver.driver_class != "Remote": pytest.skip( f"Remote tests can't be run with driver '{selenium_driver.driver_class}'" ) @@ -478,14 +469,14 @@ def clean_options(request): @pytest.fixture def firefox_options(request): + _supported_drivers = SupportedDrivers() try: - driver_class = request.config.option.drivers[0] + driver_class = request.config.option.drivers[0].lower() except (AttributeError, TypeError): raise Exception("This test requires a --driver to be specified") # skip tests in the 'remote' directory if run with a local driver - selenium_driver = Driver(driver_class, request) - if selenium_driver.skip_remote_tests: + if request.node.path.parts[-2] == "remote" and getattr(_supported_drivers, driver_class) != "Remote": pytest.skip(f"Remote tests can't be run with driver '{driver_class}'") options = Driver.clean_options("firefox", request) @@ -495,6 +486,7 @@ def firefox_options(request): @pytest.fixture def chromium_options(request): + _supported_drivers = SupportedDrivers() try: driver_class = request.config.option.drivers[0].lower() except (AttributeError, TypeError): @@ -504,9 +496,8 @@ def chromium_options(request): if driver_class not in ("chrome", "edge"): pytest.skip(f"This test requires Chrome or Edge, got {driver_class}") - selenium_driver = Driver(driver_class, request) # skip tests in the 'remote' directory if run with a local driver - if selenium_driver.skip_remote_tests: + if request.node.path.parts[-2] == "remote" and getattr(_supported_drivers, driver_class) != "Remote": pytest.skip(f"Remote tests can't be run with driver '{driver_class}'") if driver_class in ("chrome", "edge"): From 896d0f3328025e7cbfb40be479fd4459185b974d Mon Sep 17 00:00:00 2001 From: sandeepsuryaprasad Date: Sat, 31 May 2025 21:07:57 +0530 Subject: [PATCH 29/29] formatted using ruff --- py/conftest.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/py/conftest.py b/py/conftest.py index 1de8303d11186..fd1b28d6bebc9 100644 --- a/py/conftest.py +++ b/py/conftest.py @@ -313,15 +313,11 @@ def driver(request): # skip tests if not available on the platform if not selenium_driver.is_platform_valid: - pytest.skip( - f"{driver_class} tests can only run on {selenium_driver.exe_platform}" - ) + pytest.skip(f"{driver_class} tests can only run on {selenium_driver.exe_platform}") # skip tests in the 'remote' directory if run with a local driver if request.node.path.parts[-2] == "remote" and selenium_driver.driver_class != "Remote": - pytest.skip( - f"Remote tests can't be run with driver '{selenium_driver.driver_class}'" - ) + pytest.skip(f"Remote tests can't be run with driver '{selenium_driver.driver_class}'") # skip tests for drivers that don't support BiDi when --bidi is enabled if selenium_driver.bidi: @@ -443,9 +439,7 @@ def driver_executable(request): def clean_driver(request): _supported_drivers = SupportedDrivers() try: - driver_class = getattr( - _supported_drivers, request.config.option.drivers[0].lower() - ) + driver_class = getattr(_supported_drivers, request.config.option.drivers[0].lower()) except (AttributeError, TypeError): raise Exception("This test requires a --driver to be specified.") driver_reference = getattr(webdriver, driver_class)