From f883bdd4c80d60ddd2ad63b6129b5ced92ad6f69 Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Sun, 23 Feb 2025 11:48:19 -0500 Subject: [PATCH 01/37] Removed verbose argument from robotstatuschecker --- atest/run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atest/run.py b/atest/run.py index 3e7960a15..d386ea7db 100755 --- a/atest/run.py +++ b/atest/run.py @@ -251,7 +251,7 @@ def process_output(browser): print("Verifying results...") options = [] output = os.path.join(RESULTS_DIR, "output.xml") - robotstatuschecker.process_output(output, verbose=False) + robotstatuschecker.process_output(output) options.extend([opt.format(browser=browser) for opt in REBOT_OPTIONS]) try: rebot_cli(options + [output]) From d1b21d309b4e43e40e53a482258435f042a2a8ee Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Sun, 23 Feb 2025 11:48:54 -0500 Subject: [PATCH 02/37] Relaxed click version requirement --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 616d9719e..502fafc26 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ selenium >= 4.3.0 robotframework >= 4.1.3 robotframework-pythonlibcore >= 4.4.1 -click >= 8.1.7 +click >= 8.0 From fbd15da49b60e5b1e17cadadfc787c503205b782 Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Sun, 23 Feb 2025 11:51:07 -0500 Subject: [PATCH 03/37] Updated older RETURN syntax to newer one --- atest/acceptance/locators/custom.robot | 2 +- atest/acceptance/resource.robot | 2 +- src/SeleniumLibrary/__init__.py | 2 +- .../PluginDocumentation.test_many_plugins.approved.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/atest/acceptance/locators/custom.robot b/atest/acceptance/locators/custom.robot index 56841038f..af1b87fdf 100644 --- a/atest/acceptance/locators/custom.robot +++ b/atest/acceptance/locators/custom.robot @@ -55,4 +55,4 @@ Teardown Custom Locator Custom Locator Strategy [Arguments] ${browser} ${locator} ${tag} ${constraints} ${element}= Execute Javascript return window.document.getElementById('${locator}') || []; - [Return] ${element} + RETURN ${element} diff --git a/atest/acceptance/resource.robot b/atest/acceptance/resource.robot index 7b429d0ff..b965d3611 100644 --- a/atest/acceptance/resource.robot +++ b/atest/acceptance/resource.robot @@ -24,7 +24,7 @@ Open Browser To Start Page Without Testing Default Options ... desired_capabilities=${DESIRED_CAPABILITIES} alias=${alias} ${orig speed} = Set Selenium Speed ${SPEED} ${orig timeout} = Set Selenium Timeout 10 seconds - [Return] ${orig speed} 5 seconds + RETURN ${orig speed} 5 seconds Cannot Be Executed In IE [Documentation] Cannot Be Executed In IE diff --git a/src/SeleniumLibrary/__init__.py b/src/SeleniumLibrary/__init__.py index 1228fb94e..5290a567a 100644 --- a/src/SeleniumLibrary/__init__.py +++ b/src/SeleniumLibrary/__init__.py @@ -238,7 +238,7 @@ class SeleniumLibrary(DynamicCore): | Custom Locator Strategy | [Arguments] | ${browser} | ${locator} | ${tag} | ${constraints} | | | ${element}= | Execute Javascript | return window.document.getElementById('${locator}'); | - | | [Return] | ${element} | + | | RETURN | ${element} | This keyword is a reimplementation of the basic functionality of the ``id`` locator where ``${browser}`` is a reference to a WebDriver 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 447445852..1a204d3bb 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 @@ -177,7 +177,7 @@ a WebElement that should be acted on: | Custom Locator Strategy | [Arguments] | ${browser} | ${locator} | ${tag} | ${constraints} | | | ${element}= | Execute Javascript | return window.document.getElementById('${locator}'); | -| | [Return] | ${element} | +| | RETURN | ${element} | This keyword is a reimplementation of the basic functionality of the ``id`` locator where ``${browser}`` is a reference to a WebDriver From 33bd5efa1aeb60f0ca6cf9a7bff93f75d4a41511 Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Sun, 23 Feb 2025 13:54:52 -0500 Subject: [PATCH 04/37] Quick update to upload-artifacts v4 --- .github/workflows/CI.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index dea36b146..41fa78502 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -87,8 +87,9 @@ jobs: # sudo chmod u+x ./selenium-server-standalone.jar # xvfb-run --auto-servernum python atest/run.py --zip headlesschrome --grid True - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 if: failure() with: name: SeleniumLibrary Test results path: atest/zip_results + overwrite: true \ No newline at end of file From a6874407f8d3a11025d4800e1c979b29341267a6 Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Wed, 26 Feb 2025 19:37:35 -0500 Subject: [PATCH 05/37] Release notes for 6.7.1 --- docs/SeleniumLibrary-6.7.1.rst | 72 ++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 docs/SeleniumLibrary-6.7.1.rst diff --git a/docs/SeleniumLibrary-6.7.1.rst b/docs/SeleniumLibrary-6.7.1.rst new file mode 100644 index 000000000..31c557f0a --- /dev/null +++ b/docs/SeleniumLibrary-6.7.1.rst @@ -0,0 +1,72 @@ +===================== +SeleniumLibrary 6.7.1 +===================== + + +.. default-role:: code + + +SeleniumLibrary_ is a web testing library for `Robot Framework`_ that utilizes +the Selenium_ tool internally. SeleniumLibrary 6.7.1 is a new release with +one minor change - downgrade the requirements on the click dependency. + +If you have pip_ installed, just run + +:: + + pip install --upgrade robotframework-seleniumlibrary + +to install the latest available release or use + +:: + + pip install robotframework-seleniumlibrary==6.7.1 + +to install exactly this version. Alternatively you can download the source +distribution from PyPI_ and install it manually. + +SeleniumLibrary 6.7.1 was released on Wednesday February 26, 2025. SeleniumLibrary supports +Python 3.8 through 3.13, Selenium 4.24.0 through 4.27.1 and +Robot Framework 6.1.1 and 7.1.1. + +.. _Robot Framework: http://robotframework.org +.. _SeleniumLibrary: https://github.com/robotframework/SeleniumLibrary +.. _Selenium: http://seleniumhq.org +.. _pip: http://pip-installer.org +.. _PyPI: https://pypi.python.org/pypi/robotframework-seleniumlibrary +.. _issue tracker: https://github.com/robotframework/SeleniumLibrary/issues?q=milestone%3Av6.7.1 + + +.. contents:: + :depth: 2 + :local: + +Changes +======= + +- Downgrade the requirement on click to `click>=8.0`. (`#1932`_) + +Acknowledgements +================ + +I want to thank Oliver Boehmer for raising up this issue and Pekka Klärck and Tatu Aalto for +consultation and review. (`#1932`_) + +Full list of fixes and enhancements +=================================== + +.. list-table:: + :header-rows: 1 + + * - ID + - Type + - Priority + - Summary + * - `#1932`_ + - --- + - medium + - Downgrade requirements on click to `click>=8.0` + +Altogether 1 issue. View on the `issue tracker `__. + +.. _#1932: https://github.com/robotframework/SeleniumLibrary/issues/1932 From 7af16cec8b78d77b623df06942e46716d580e4bd Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Wed, 26 Feb 2025 19:38:11 -0500 Subject: [PATCH 06/37] Updated version to 6.7.1 --- src/SeleniumLibrary/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SeleniumLibrary/__init__.py b/src/SeleniumLibrary/__init__.py index 5290a567a..0187df611 100644 --- a/src/SeleniumLibrary/__init__.py +++ b/src/SeleniumLibrary/__init__.py @@ -55,7 +55,7 @@ from SeleniumLibrary.utils import LibraryListener, is_truthy, _convert_timeout, _convert_delay -__version__ = "6.7.0" +__version__ = "6.7.1" class SeleniumLibrary(DynamicCore): From bbb50d51b407597ea33bca2118e1ef7b93a5fe34 Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Wed, 26 Feb 2025 19:39:30 -0500 Subject: [PATCH 07/37] Generated docs for version 6.7.1 --- docs/SeleniumLibrary.html | 2187 +++++++------------------------------ 1 file changed, 367 insertions(+), 1820 deletions(-) diff --git a/docs/SeleniumLibrary.html b/docs/SeleniumLibrary.html index 2bd5eac76..4d6abc3b6 100644 --- a/docs/SeleniumLibrary.html +++ b/docs/SeleniumLibrary.html @@ -7,1194 +7,11 @@ - - - - - - - - - - + - - - + +

Opening library documentation failed

  • Verify that you have JavaScript enabled in your browser.
  • -
  • Make sure you are using a modern enough browser. If using Internet Explorer, version 11 is required.
  • -
  • Check are there messages in your browser's JavaScript error log. Please report the problem if you suspect you have encountered a bug.
  • +
  • + Make sure you are using a modern enough browser. If using + Internet Explorer, version 11 is required. +
  • +
  • + Check are there messages in your browser's + JavaScript error log. Please report the problem if you suspect + you have encountered a bug. +
- - - + + + + +
+ - + + + + + + - + - - - + + - + + - - - - - + {{#if usages.length}} +
+

{{t "usages"}}

+
    + {{#each usages}} +
  • {{this}}
  • + {{/each}} +
+
+ {{/if}} + + + + + From 15ce0966638cb3a2e7e22fa4cc7fd129030252d8 Mon Sep 17 00:00:00 2001 From: Corey Goldberg <1113081+cgoldberg@users.noreply.github.com> Date: Fri, 23 May 2025 10:50:47 -0400 Subject: [PATCH 08/37] Update README.rst 'Browser drivers' section --- README.rst | 37 ++++--------------------------------- 1 file changed, 4 insertions(+), 33 deletions(-) diff --git a/README.rst b/README.rst index efd83b3c4..1f4346024 100644 --- a/README.rst +++ b/README.rst @@ -44,8 +44,7 @@ The recommended installation method is using pip_:: pip install --upgrade robotframework-seleniumlibrary Running this command installs also the latest Selenium and Robot Framework -versions, but you still need to install `browser drivers`_ separately. -The ``--upgrade`` option can be omitted when installing the library for the +versions. The ``--upgrade`` option can be omitted when installing the library for the first time. It is possible to install directly from the GitHub_ repository. To install @@ -64,39 +63,11 @@ using ``pip`` see `its own documentation `__. Browser drivers --------------- -After installing the library, you still need to install browser and -operating system specific browser drivers for all those browsers you -want to use in tests. These are the exact same drivers you need to use with -Selenium also when not using SeleniumLibrary. More information about -drivers can be found from `Selenium documentation`__. - -The general approach to install a browser driver is downloading a right -driver, such as ``chromedriver`` for Chrome, and placing it into -a directory that is in PATH__. Drivers for different browsers -can be found via Selenium documentation or by using your favorite -search engine with a search term like ``selenium chrome browser driver``. -New browser driver versions are released to support features in -new browsers, fix bug, or otherwise, and you need to keep an eye on them -to know when to update drivers you use. - -Alternatively, you can use a tool called WebdriverManager__ which can -find the latest version or when required, any version of appropriate -webdrivers for you and then download and link/copy it into right -location. Tool can run on all major operating systems and supports -downloading of Chrome, Firefox, Opera & Edge webdrivers. - -Here's an example: - -.. code:: bash - - pip install webdrivermanager - webdrivermanager firefox chrome --linkpath /usr/local/bin - - +Browsers and drivers are installed and managed automatically by `Selenium Manager`__. +For more information, see the `Selenium documentation`__. +__ https://www.selenium.dev/documentation/selenium_manager __ https://seleniumhq.github.io/selenium/docs/api/py/index.html#drivers -__ https://en.wikipedia.org/wiki/PATH_(variable) -__ https://github.com/omenia/webdrivermanager Usage ----- From 1a6a2ba1e8f056767d521a97168927a6e651ef89 Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Sat, 24 May 2025 16:08:31 -0400 Subject: [PATCH 09/37] Initial commit of screenshot return base64 string --- src/SeleniumLibrary/keywords/screenshot.py | 40 +++++++++++++--------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/src/SeleniumLibrary/keywords/screenshot.py b/src/SeleniumLibrary/keywords/screenshot.py index 8cd8dc299..68ab37db2 100644 --- a/src/SeleniumLibrary/keywords/screenshot.py +++ b/src/SeleniumLibrary/keywords/screenshot.py @@ -27,6 +27,8 @@ DEFAULT_FILENAME_PAGE = "selenium-screenshot-{index}.png" DEFAULT_FILENAME_ELEMENT = "selenium-element-screenshot-{index}.png" EMBED = "EMBED" +BASE64 = "BASE64" +EMBEDDED_OPTIONS = [EMBED, BASE64] DEFAULT_FILENAME_PDF = "selenium-page-{index}.pdf" @@ -111,8 +113,9 @@ 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 - if self._decide_embedded(filename): - return self._capture_page_screen_to_log() + is_embedded, method = self._decide_embedded(filename) + if is_embedded: + return self._capture_page_screen_to_log(method) return self._capture_page_screenshot_to_file(filename) def _capture_page_screenshot_to_file(self, filename): @@ -123,9 +126,11 @@ def _capture_page_screenshot_to_file(self, filename): self._embed_to_log_as_file(path, 800) return path - def _capture_page_screen_to_log(self): + def _capture_page_screen_to_log(self, return_val): screenshot_as_base64 = self.driver.get_screenshot_as_base64() - self._embed_to_log_as_base64(screenshot_as_base64, 800) + base64_str = self._embed_to_log_as_base64(screenshot_as_base64, 800) + if return_val == BASE64: + return_val base64_str return EMBED @keyword @@ -159,8 +164,9 @@ def capture_element_screenshot( ) return element = self.find_element(locator, required=True) - if self._decide_embedded(filename): - return self._capture_element_screen_to_log(element) + is_embedded, method = self._decide_embedded(filename) + if is_embedded: + return self._capture_element_screen_to_log(element, method) return self._capture_element_screenshot_to_file(element, filename) def _capture_element_screenshot_to_file(self, element, filename): @@ -171,8 +177,10 @@ def _capture_element_screenshot_to_file(self, element, filename): self._embed_to_log_as_file(path, 400) return path - def _capture_element_screen_to_log(self, element): - self._embed_to_log_as_base64(element.screenshot_as_base64, 400) + def _capture_element_screen_to_log(self, element, return_val): + base64_str = self._embed_to_log_as_base64(element.screenshot_as_base64, 400) + if return_val == BASE64: + return base64_str return EMBED @property @@ -184,20 +192,20 @@ def _screenshot_root_directory(self, value): self.ctx.screenshot_root_directory = value def _decide_embedded(self, filename): - filename = filename.lower() + filename = filename.upper() if ( filename == DEFAULT_FILENAME_PAGE - and self._screenshot_root_directory == EMBED + and self._screenshot_root_directory in EMBEDDED_OPTIONS ): - return True + return True, self._screenshot_root_directory if ( filename == DEFAULT_FILENAME_ELEMENT - and self._screenshot_root_directory == EMBED + and self._screenshot_root_directory in EMBEDDED_OPTIONS ): - return True - if filename == EMBED.lower(): - return True - return False + return True, self._screenshot_root_directory + if filename in EMBEDDED_OPTIONS: + return True, self._screenshot_root_directory + return False, None def _get_screenshot_path(self, filename): if self._screenshot_root_directory != EMBED: From 0f5cf9c2318a7e437a463b7093940e4efee3112e Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Sat, 24 May 2025 19:51:26 -0400 Subject: [PATCH 10/37] Updated tests and fixed a couple issues - Updated unit test to look for a tuple - Fixed issue with code on return statement - Fixed issue with unit tests --- src/SeleniumLibrary/keywords/screenshot.py | 6 +++--- utest/test/keywords/test_screen_shot.py | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/SeleniumLibrary/keywords/screenshot.py b/src/SeleniumLibrary/keywords/screenshot.py index 68ab37db2..0289287d4 100644 --- a/src/SeleniumLibrary/keywords/screenshot.py +++ b/src/SeleniumLibrary/keywords/screenshot.py @@ -130,7 +130,7 @@ def _capture_page_screen_to_log(self, return_val): screenshot_as_base64 = self.driver.get_screenshot_as_base64() base64_str = self._embed_to_log_as_base64(screenshot_as_base64, 800) if return_val == BASE64: - return_val base64_str + return base64_str return EMBED @keyword @@ -194,12 +194,12 @@ def _screenshot_root_directory(self, value): def _decide_embedded(self, filename): filename = filename.upper() if ( - filename == DEFAULT_FILENAME_PAGE + filename == DEFAULT_FILENAME_PAGE.upper() and self._screenshot_root_directory in EMBEDDED_OPTIONS ): return True, self._screenshot_root_directory if ( - filename == DEFAULT_FILENAME_ELEMENT + filename == DEFAULT_FILENAME_ELEMENT.upper() and self._screenshot_root_directory in EMBEDDED_OPTIONS ): return True, self._screenshot_root_directory diff --git a/utest/test/keywords/test_screen_shot.py b/utest/test/keywords/test_screen_shot.py index a5cac9248..56b98258f 100644 --- a/utest/test/keywords/test_screen_shot.py +++ b/utest/test/keywords/test_screen_shot.py @@ -22,24 +22,24 @@ def teardown_function(): def test_defaults(screen_shot): - assert screen_shot._decide_embedded(SCREENSHOT_FILE_NAME) is False - assert screen_shot._decide_embedded(ELEMENT_FILE_NAME) is False + assert screen_shot._decide_embedded(SCREENSHOT_FILE_NAME) == (False, None) + assert screen_shot._decide_embedded(ELEMENT_FILE_NAME) == (False, None) def test_screen_shotdir_embeded(screen_shot): screen_shot.ctx.screenshot_root_directory = EMBED - assert screen_shot._decide_embedded(SCREENSHOT_FILE_NAME) is True - assert screen_shot._decide_embedded(SCREENSHOT_FILE_NAME.upper()) is True - assert screen_shot._decide_embedded(ELEMENT_FILE_NAME) is True - assert screen_shot._decide_embedded(ELEMENT_FILE_NAME.upper()) is True - assert screen_shot._decide_embedded("other.psn") is False + assert screen_shot._decide_embedded(SCREENSHOT_FILE_NAME) == (True, EMBED) + assert screen_shot._decide_embedded(SCREENSHOT_FILE_NAME.upper()) == (True, EMBED) + assert screen_shot._decide_embedded(ELEMENT_FILE_NAME) == (True, EMBED) + assert screen_shot._decide_embedded(ELEMENT_FILE_NAME.upper()) == (True, EMBED) + assert screen_shot._decide_embedded("other.psn") == (False, None) def test_file_name_embeded(screen_shot): - assert screen_shot._decide_embedded(EMBED) is True - assert screen_shot._decide_embedded("other.psn") is False + assert screen_shot._decide_embedded(EMBED) == (True, EMBED) + assert screen_shot._decide_embedded("other.psn") == (False, None) screen_shot.ctx.screenshot_root_directory = EMBED - assert screen_shot._decide_embedded(EMBED) is True + assert screen_shot._decide_embedded(EMBED) == (True, EMBED) def test_screenshot_path_embedded(screen_shot): From c87bb4544691d6f4ec6b56f26c3d70c32758b6f4 Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Sun, 25 May 2025 08:17:22 -0400 Subject: [PATCH 11/37] Added BASE64 to set screenshot directory keyword Forgot to add in the setting of the screenshot directory to handle BASE64 when not in all caps. --- src/SeleniumLibrary/keywords/screenshot.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/SeleniumLibrary/keywords/screenshot.py b/src/SeleniumLibrary/keywords/screenshot.py index 0289287d4..dc3812e7a 100644 --- a/src/SeleniumLibrary/keywords/screenshot.py +++ b/src/SeleniumLibrary/keywords/screenshot.py @@ -61,6 +61,8 @@ def set_screenshot_directory(self, path: Union[None, str]) -> str: path = None elif path.upper() == EMBED: path = EMBED + elif path.upper() == BASE64: + path = BASE64 else: path = os.path.abspath(path) self._create_directory(path) From b16e05e2c43f704ad7080fc6a622ff9179c4d46a Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Sun, 25 May 2025 08:19:09 -0400 Subject: [PATCH 12/37] Added unit tests to check for BASE64 and proper handling There is a still an error when the library is initialized with something like `bASe64`. It is not setting it. From the code this looks like the unintended behavior. But then I don't understand why theother test case works when `EmBed` is given. This too should fail as per my reading of the code. Going to trace through a bit more to see why that isn't failing and what I may be missing. --- utest/test/keywords/test_screen_shot.py | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/utest/test/keywords/test_screen_shot.py b/utest/test/keywords/test_screen_shot.py index 56b98258f..2ea09cb30 100644 --- a/utest/test/keywords/test_screen_shot.py +++ b/utest/test/keywords/test_screen_shot.py @@ -8,7 +8,7 @@ SCREENSHOT_FILE_NAME = "selenium-screenshot-{index}.png" ELEMENT_FILE_NAME = "selenium-element-screenshot-{index}.png" EMBED = "EMBED" - +BASE64 = "BASE64" @pytest.fixture(scope="module") def screen_shot(): @@ -35,11 +35,21 @@ def test_screen_shotdir_embeded(screen_shot): assert screen_shot._decide_embedded("other.psn") == (False, None) +def test_screen_shotdir_return_base64(screen_shot): + screen_shot.ctx.screenshot_root_directory = BASE64 + assert screen_shot._decide_embedded(SCREENSHOT_FILE_NAME) == (True, BASE64) + assert screen_shot._decide_embedded(SCREENSHOT_FILE_NAME.upper()) == (True, BASE64) + assert screen_shot._decide_embedded(ELEMENT_FILE_NAME) == (True, BASE64) + assert screen_shot._decide_embedded(ELEMENT_FILE_NAME.upper()) == (True, BASE64) + assert screen_shot._decide_embedded("other.psn") == (False, None) + + def test_file_name_embeded(screen_shot): - assert screen_shot._decide_embedded(EMBED) == (True, EMBED) assert screen_shot._decide_embedded("other.psn") == (False, None) screen_shot.ctx.screenshot_root_directory = EMBED assert screen_shot._decide_embedded(EMBED) == (True, EMBED) + screen_shot.ctx.screenshot_root_directory = BASE64 + assert screen_shot._decide_embedded(BASE64) == (True, BASE64) def test_screenshot_path_embedded(screen_shot): @@ -56,6 +66,12 @@ def test_sl_init_embed(): sl = SeleniumLibrary(screenshot_root_directory=EMBED) assert sl.screenshot_root_directory == EMBED + sl = SeleniumLibrary(screenshot_root_directory="bAsE64") + assert sl.screenshot_root_directory == BASE64 + + sl = SeleniumLibrary(screenshot_root_directory=BASE64) + assert sl.screenshot_root_directory == BASE64 + def test_sl_init_not_embed(): sl = SeleniumLibrary(screenshot_root_directory=None) @@ -76,6 +92,9 @@ def test_sl_set_screenshot_directory(): sl.set_screenshot_directory(EMBED) assert sl.screenshot_root_directory == EMBED + sl.set_screenshot_directory(BASE64) + assert sl.screenshot_root_directory == BASE64 + sl.set_screenshot_directory("EEmBedD") assert "EEmBedD" in sl.screenshot_root_directory assert len("EEmBedD") < len(sl.screenshot_root_directory) From a8e823402cd7d25008350869fe3f7425e18b5d4b Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Sun, 25 May 2025 20:15:55 -0400 Subject: [PATCH 13/37] Resolved issue with setting BASE64 on library initialization --- src/SeleniumLibrary/__init__.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/SeleniumLibrary/__init__.py b/src/SeleniumLibrary/__init__.py index 0187df611..82ee75e5d 100644 --- a/src/SeleniumLibrary/__init__.py +++ b/src/SeleniumLibrary/__init__.py @@ -50,7 +50,7 @@ WebDriverCache, WindowKeywords, ) -from SeleniumLibrary.keywords.screenshot import EMBED +from SeleniumLibrary.keywords.screenshot import EMBED, BASE64 from SeleniumLibrary.locators import ElementFinder from SeleniumLibrary.utils import LibraryListener, is_truthy, _convert_timeout, _convert_delay @@ -614,8 +614,8 @@ def __init__( - ``run_on_failure``: Default action for the `run-on-failure functionality`. - ``screenshot_root_directory``: - Path to folder where possible screenshots are created or EMBED. - See `Set Screenshot Directory` keyword for further details about EMBED. + Path to folder where possible screenshots are created or EMBED or BASE64. + See `Set Screenshot Directory` keyword for further details about EMBED and BASE64. If not given, the directory where the log file is written is used. - ``plugins``: Allows extending the SeleniumLibrary with external Python classes. @@ -846,6 +846,8 @@ def _resolve_screenshot_root_directory(self): if is_string(screenshot_root_directory): if screenshot_root_directory.upper() == EMBED: self.screenshot_root_directory = EMBED + if screenshot_root_directory.upper() == BASE64: + self.screenshot_root_directory = BASE64 @staticmethod def _get_translation(language: Union[str, None]) -> Union[Path, None]: From 6858c22ba183eb2e1fc19c76dd6112b47d7d6d4a Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Sun, 25 May 2025 21:56:44 -0400 Subject: [PATCH 14/37] Added keyword documentation for BASE64 option for screenshots --- src/SeleniumLibrary/keywords/screenshot.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/SeleniumLibrary/keywords/screenshot.py b/src/SeleniumLibrary/keywords/screenshot.py index dc3812e7a..11308af85 100644 --- a/src/SeleniumLibrary/keywords/screenshot.py +++ b/src/SeleniumLibrary/keywords/screenshot.py @@ -83,7 +83,14 @@ def capture_page_screenshot(self, filename: str = DEFAULT_FILENAME_PAGE) -> str: If ``filename`` equals to EMBED (case insensitive), then screenshot is embedded as Base64 image to the log.html. In this case file is not - created in the filesystem. + created in the filesystem. If ``filename`` equals to BASE64 (case + insensitive), then the base64 string is returned and the screenshot + is embedded to the log. This allows one to reuse the image elsewhere + in the report. + + Example: + | ${ss}= | `Capture Page Screenshot` | BASE64 | + | Set Test Message | *HTML*Test Success

| Starting from SeleniumLibrary 1.8, if ``filename`` contains marker ``{index}``, it will be automatically replaced with an unique running @@ -93,9 +100,10 @@ def capture_page_screenshot(self, filename: str = DEFAULT_FILENAME_PAGE) -> str: format string syntax]. An absolute path to the created screenshot file is returned or if - ``filename`` equals to EMBED, word `EMBED` is returned. + ``filename`` equals to EMBED, word `EMBED` is returned. If ``filename`` + equals to BASE64, the base64 string containing the screenshot is returned. - Support for EMBED is new in SeleniumLibrary 4.2 + Support for BASE64 is new in SeleniumLibrary 6.8 Examples: | `Capture Page Screenshot` | | @@ -147,18 +155,24 @@ def capture_element_screenshot( See the `Locating elements` section for details about the locator syntax. - An absolute path to the created element screenshot is returned. + An absolute path to the created element screenshot is returned. If the ``filename`` + equals to BASE64 (case insensitive), then the base64 string is returned in addition + to the screenshot embedded to the log. See ``Capture Page Screenshot`` for more + information. Support for capturing the screenshot from an element has limited support among browser vendors. Please check the browser vendor driver documentation does the browser support capturing a screenshot from an element. New in SeleniumLibrary 3.3. Support for EMBED is new in SeleniumLibrary 4.2. + Support for BASE64 is new in SeleniumLibrary 6.8. Examples: | `Capture Element Screenshot` | id:image_id | | | `Capture Element Screenshot` | id:image_id | ${OUTPUTDIR}/id_image_id-1.png | | `Capture Element Screenshot` | id:image_id | EMBED | + | ${ess}= | `Capture Element Screenshot` | id:image_id | BASE64 | + """ if not self.drivers.current: self.info( From 7c04d02c8fe5c66a0d3f685229de20ec8273de81 Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Sun, 15 Jun 2025 12:50:31 -0400 Subject: [PATCH 15/37] Updating selenium and robotframework versions we test against --- .github/workflows/CI.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 41fa78502..77891d523 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -10,8 +10,8 @@ jobs: strategy: matrix: python-version: [3.8, 3.13.0] # pypy-3.9 - rf-version: [6.1.1, 7.1.1] - selenium-version: [4.24.0, 4.25.0, 4.26.1, 4.27.1] + rf-version: [6.1.1, 7.2.2 7.3] + selenium-version: [4.32.0 4.33.0] browser: [firefox, chrome, headlesschrome] #edge steps: From 42399b688969dfdec2051ab988172458ac93460d Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Sun, 15 Jun 2025 13:05:10 -0400 Subject: [PATCH 16/37] Fixed required version syntax --- .github/workflows/CI.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 77891d523..ac98f2065 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -10,8 +10,8 @@ jobs: strategy: matrix: python-version: [3.8, 3.13.0] # pypy-3.9 - rf-version: [6.1.1, 7.2.2 7.3] - selenium-version: [4.32.0 4.33.0] + rf-version: [6.1.1, 7.2.2, 7.3] + selenium-version: [4.32.0, 4.33.0] browser: [firefox, chrome, headlesschrome] #edge steps: From 0f550e035c172a732ab5f6106dac0f0b53defd06 Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Sun, 15 Jun 2025 14:11:31 -0400 Subject: [PATCH 17/37] Bump lower Python version tested to 3.9 --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index ac98f2065..a4e12bbc6 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -9,7 +9,7 @@ jobs: continue-on-error: true strategy: matrix: - python-version: [3.8, 3.13.0] # pypy-3.9 + python-version: [3.9, 3.13.0] # pypy-3.9 rf-version: [6.1.1, 7.2.2, 7.3] selenium-version: [4.32.0, 4.33.0] browser: [firefox, chrome, headlesschrome] #edge From 33135cf653db990ff7ed97d567c6a6e2d5b06fb2 Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Wed, 18 Jun 2025 06:17:38 -0400 Subject: [PATCH 18/37] Updated expected error messages on a couple tests --- atest/acceptance/keywords/expected_conditions.robot | 2 +- atest/acceptance/keywords/run_on_failure.robot | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/atest/acceptance/keywords/expected_conditions.robot b/atest/acceptance/keywords/expected_conditions.robot index 4fa40dbfe..0df219177 100644 --- a/atest/acceptance/keywords/expected_conditions.robot +++ b/atest/acceptance/keywords/expected_conditions.robot @@ -10,7 +10,7 @@ Wait For Expected Conditions One Argument Title Should Be Delayed Wait For Expected Condition Times out within set timeout - [Documentation] FAIL REGEXP: TimeoutException: Message: Expected Condition not met within set timeout of 0.3* + [Documentation] FAIL STARTS: TimeoutException: Message: Expected Condition not met within set timeout of 0.3 Title Should Be Original Click Element link=delayed change title Wait For Expected Condition title_is Delayed timeout=0.3 diff --git a/atest/acceptance/keywords/run_on_failure.robot b/atest/acceptance/keywords/run_on_failure.robot index 761d4feca..6843aaf86 100644 --- a/atest/acceptance/keywords/run_on_failure.robot +++ b/atest/acceptance/keywords/run_on_failure.robot @@ -67,7 +67,7 @@ Run on Failure Returns Previous Value Should Be Equal ${old} Log Title Run On Failure also fails - [Documentation] LOG 2.1 WARN Keyword 'Failure During Run On failure' could not be run on failure: Expected error. + [Documentation] LOG 2.1.2 WARN Keyword 'Failure During Run On failure' could not be run on failure: Expected error. Register Keyword to Run on Failure Failure During Run On failure Run Keyword And Expect Error ... ${FAILURE MESSAGE} From 38e784d7a2edaf9f65372d0290310500ae543e48 Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Wed, 18 Jun 2025 07:32:39 -0400 Subject: [PATCH 19/37] Trying out key value pairs on python version for more expressive matrix --- .github/workflows/CI.yml | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index a4e12bbc6..a33d175bd 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -9,17 +9,18 @@ jobs: continue-on-error: true strategy: matrix: - python-version: [3.9, 3.13.0] # pypy-3.9 + # python-version: [3.9, 3.13.0] # pypy-3.9 + python-version: [{earliest: 3.9}, {latest: 3.13.0}] # pypy-3.9 rf-version: [6.1.1, 7.2.2, 7.3] selenium-version: [4.32.0, 4.33.0] browser: [firefox, chrome, headlesschrome] #edge steps: - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} with Robot Framework ${{ matrix.rf-version }} + - name: Set up Python ${{ matrix.python-version.* }} with Robot Framework ${{ matrix.rf-version }} uses: actions/setup-python@v5 with: - python-version: ${{ matrix.python-version }} + python-version: ${{ matrix.python-version.* }} - name: Setup Chrome uses: browser-actions/setup-chrome@latest with: @@ -41,12 +42,12 @@ jobs: export DISPLAY=:99.0 Xvfb -ac :99 -screen 0 1280x1024x16 > /dev/null 2>&1 & - name: Install dependencies - if: matrix.python-version != 'pypy-3.7' + if: matrix.python-version.* != 'pypy-3.7' run: | python -m pip install --upgrade pip pip install -r requirements-dev.txt - name: Install dependencies for pypy - if: matrix.python-version == 'pypy-3.9' + if: matrix.python-version.* == 'pypy-3.9' run: | python -m pip install --upgrade pip pip install -r requirements.txt @@ -64,19 +65,24 @@ jobs: echo "$SELENIUM_MANAGER_EXE" echo "WEBDRIVERPATH=$($SELENIUM_MANAGER_EXE --browser chrome --debug | awk '/INFO[[:space:]]Driver path:/ {print $NF;exit}')" >> "$GITHUB_ENV" echo "$WEBDRIVERPATH" - - name: Generate stub file for ${{ matrix.python-version }} - if: matrix.python-version != 'pypy-3.9' + - name: Generate stub file for ${{ matrix.python-version.* }} + if: matrix.python-version.* != 'pypy-3.9' run: | invoke gen-stub # Temporarily ignoring pypy execution - name: Run tests with headless Chrome and with PyPy - if: startsWith( matrix.python-version, 'pypy') == true + if: startsWith( matrix.python-version.*, 'pypy') == true run: | xvfb-run --auto-servernum python atest/run.py --nounit --zip headlesschrome - - name: Run tests with ${{ matrix.browser }} if CPython - if: startsWith( matrix.python-version, 'pypy') == false + # - name: Run tests with ${{ matrix.browser }} if CPython + # if: startsWith( matrix.python-version, 'pypy') == false + # run: | + # xvfb-run --auto-servernum python atest/run.py --zip ${{ matrix.browser }} + + - name: Run tests with latest python + if: matrix.python-version == ${{ matrix.python.version.latest }} run: | xvfb-run --auto-servernum python atest/run.py --zip ${{ matrix.browser }} From 3f135fb350b36bd4fe9f2a8f94323d347d787dbc Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Wed, 18 Jun 2025 07:47:56 -0400 Subject: [PATCH 20/37] Limit test matrix to latest python version and latest rf version Also reveted back from expressive matrix options as I need to learn how to use key-value pairs within gh actions. --- .github/workflows/CI.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index a33d175bd..c69baffd3 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -9,18 +9,18 @@ jobs: continue-on-error: true strategy: matrix: - # python-version: [3.9, 3.13.0] # pypy-3.9 - python-version: [{earliest: 3.9}, {latest: 3.13.0}] # pypy-3.9 - rf-version: [6.1.1, 7.2.2, 7.3] + python-version: [3.9, 3.13.0] # pypy-3.9 + # python-version: [{earliest: 3.9}, {latest: 3.13.0}] # pypy-3.9 + rf-version: [6.1.1, 7.2.2, 7.3.1] selenium-version: [4.32.0, 4.33.0] browser: [firefox, chrome, headlesschrome] #edge steps: - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version.* }} with Robot Framework ${{ matrix.rf-version }} + - name: Set up Python ${{ matrix.python-version }} with Robot Framework ${{ matrix.rf-version }} uses: actions/setup-python@v5 with: - python-version: ${{ matrix.python-version.* }} + python-version: ${{ matrix.python-version }} - name: Setup Chrome uses: browser-actions/setup-chrome@latest with: @@ -42,12 +42,12 @@ jobs: export DISPLAY=:99.0 Xvfb -ac :99 -screen 0 1280x1024x16 > /dev/null 2>&1 & - name: Install dependencies - if: matrix.python-version.* != 'pypy-3.7' + if: matrix.python-version != 'pypy-3.7' run: | python -m pip install --upgrade pip pip install -r requirements-dev.txt - name: Install dependencies for pypy - if: matrix.python-version.* == 'pypy-3.9' + if: matrix.python-version == 'pypy-3.9' run: | python -m pip install --upgrade pip pip install -r requirements.txt @@ -65,14 +65,14 @@ jobs: echo "$SELENIUM_MANAGER_EXE" echo "WEBDRIVERPATH=$($SELENIUM_MANAGER_EXE --browser chrome --debug | awk '/INFO[[:space:]]Driver path:/ {print $NF;exit}')" >> "$GITHUB_ENV" echo "$WEBDRIVERPATH" - - name: Generate stub file for ${{ matrix.python-version.* }} - if: matrix.python-version.* != 'pypy-3.9' + - name: Generate stub file for ${{ matrix.python-version }} + if: matrix.python-version != 'pypy-3.9' run: | invoke gen-stub # Temporarily ignoring pypy execution - name: Run tests with headless Chrome and with PyPy - if: startsWith( matrix.python-version.*, 'pypy') == true + if: startsWith( matrix.python-version, 'pypy') == true run: | xvfb-run --auto-servernum python atest/run.py --nounit --zip headlesschrome @@ -81,8 +81,8 @@ jobs: # run: | # xvfb-run --auto-servernum python atest/run.py --zip ${{ matrix.browser }} - - name: Run tests with latest python - if: matrix.python-version == ${{ matrix.python.version.latest }} + - name: Run tests with latest python and latest robot framework + if: matrix.python-version == '3.13.0' && matrix.rf-version == '7.3.1' run: | xvfb-run --auto-servernum python atest/run.py --zip ${{ matrix.browser }} From b54e4bab7f5be8a240bbd7c5e962a3ccf7c72b93 Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Wed, 18 Jun 2025 08:27:23 -0400 Subject: [PATCH 21/37] Uniquely name the artifacts --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index c69baffd3..5f414184e 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -96,6 +96,6 @@ jobs: - uses: actions/upload-artifact@v4 if: failure() with: - name: SeleniumLibrary Test results + name: sl_$${{ matrix.python-version }}_$${{ matrix.rf-version }}_$${{ matrix.selenium-version }}_$${{ matrix.browser }} path: atest/zip_results overwrite: true \ No newline at end of file From 4f947454b113fdc89ff008192965f7f4fb35721e Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Wed, 18 Jun 2025 17:00:26 -0400 Subject: [PATCH 22/37] Try slight delay in mouse over test --- atest/acceptance/keywords/mouse.robot | 1 + 1 file changed, 1 insertion(+) diff --git a/atest/acceptance/keywords/mouse.robot b/atest/acceptance/keywords/mouse.robot index 2c25035e0..52b8ea1df 100644 --- a/atest/acceptance/keywords/mouse.robot +++ b/atest/acceptance/keywords/mouse.robot @@ -8,6 +8,7 @@ Resource ../resource.robot Mouse Over [Tags] Known Issue Safari Mouse Over el_for_mouseover + Sleep 0.1secs Textfield Value Should Be el_for_mouseover mouseover el_for_mouseover Run Keyword And Expect Error ... Element with locator 'not_there' not found. From 46351bf926c7b5a7fdc66dfd3917d7e97a228ef9 Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Wed, 18 Jun 2025 19:53:45 -0400 Subject: [PATCH 23/37] Try slight delay in mouse over error test --- atest/acceptance/keywords/mouse.robot | 1 + 1 file changed, 1 insertion(+) diff --git a/atest/acceptance/keywords/mouse.robot b/atest/acceptance/keywords/mouse.robot index 52b8ea1df..5aff5c109 100644 --- a/atest/acceptance/keywords/mouse.robot +++ b/atest/acceptance/keywords/mouse.robot @@ -17,6 +17,7 @@ Mouse Over Mouse Over Error [Tags] Known Issue Safari Mouse Over el_for_mouseover + Sleep 0.1secs Textfield Value Should Be el_for_mouseover mouseover el_for_mouseover Run Keyword And Expect Error ... Element with locator '鱼在天空中飞翔' not found. From 30df9442dcb2bec59f1a50343d0d6623bad1c1a1 Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Wed, 18 Jun 2025 20:38:08 -0400 Subject: [PATCH 24/37] Try slowing down tests a bit --- atest/acceptance/keywords/textfields.robot | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/atest/acceptance/keywords/textfields.robot b/atest/acceptance/keywords/textfields.robot index 1fa6f4522..a5c879874 100644 --- a/atest/acceptance/keywords/textfields.robot +++ b/atest/acceptance/keywords/textfields.robot @@ -1,5 +1,5 @@ *** Settings *** -Test Setup Go To Page "forms/prefilled_email_form.html" +Test Setup Text Fields Test Suite Setup Resource ../resource.robot Force Tags Known Issue Internet Explorer @@ -75,3 +75,8 @@ Press Key Attempt Clear Element Text On Non-Editable Field Run Keyword And Expect Error * Clear Element Text can_send_email + +*** Keywords *** +Text Fields Test Suite Setup + Go To Page "forms/prefilled_email_form.html" + Set Selenium Speed 0.1secs \ No newline at end of file From 6780fbb94676dbec13a2822a225dd67f07f3b3c5 Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Wed, 18 Jun 2025 20:59:27 -0400 Subject: [PATCH 25/37] Trying RF verion 7.2.2 --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 5f414184e..318d65aee 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -82,7 +82,7 @@ jobs: # xvfb-run --auto-servernum python atest/run.py --zip ${{ matrix.browser }} - name: Run tests with latest python and latest robot framework - if: matrix.python-version == '3.13.0' && matrix.rf-version == '7.3.1' + if: matrix.python-version == '3.13.0' && matrix.rf-version == '7.2.2' run: | xvfb-run --auto-servernum python atest/run.py --zip ${{ matrix.browser }} From 86ac810bf81df0530bd4f05c8cd50546f9d779ee Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Wed, 18 Jun 2025 21:12:43 -0400 Subject: [PATCH 26/37] Put back in previous selenium versions --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 318d65aee..b0a966083 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -12,7 +12,7 @@ jobs: python-version: [3.9, 3.13.0] # pypy-3.9 # python-version: [{earliest: 3.9}, {latest: 3.13.0}] # pypy-3.9 rf-version: [6.1.1, 7.2.2, 7.3.1] - selenium-version: [4.32.0, 4.33.0] + selenium-version: [4.28.1, 4.29.0, 4.30.0, 4.31.0, 4.32.0, 4.33.0] browser: [firefox, chrome, headlesschrome] #edge steps: From f493acb1248c25ccbf6a49effcf5206003887c51 Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Thu, 19 Jun 2025 09:05:48 -0400 Subject: [PATCH 27/37] Added install chromedriver along side of chrome --- .github/workflows/CI.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index b0a966083..4e139279e 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -25,6 +25,8 @@ jobs: uses: browser-actions/setup-chrome@latest with: chrome-version: latest + install-dependencies: true + install-chromedriver: true id: setup-chrome - run: | echo Installed chromium version: ${{ steps.setup-chrome.outputs.chrome-version }} From 52faa8612baf8fc6b6aa8e50ec36f7bfd116b5c7 Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Thu, 19 Jun 2025 09:22:13 -0400 Subject: [PATCH 28/37] Trying Chrome version 138 Also reduce test matrix for now and set setup-chrome action to v1 (as compared to @latest) --- .github/workflows/CI.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 4e139279e..7f0d70143 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -9,11 +9,11 @@ jobs: continue-on-error: true strategy: matrix: - python-version: [3.9, 3.13.0] # pypy-3.9 + python-version: [3.13.0] # 3.9 pypy-3.9 # python-version: [{earliest: 3.9}, {latest: 3.13.0}] # pypy-3.9 - rf-version: [6.1.1, 7.2.2, 7.3.1] + rf-version: [7.2.2] # 6.1.1, 7.3.1 selenium-version: [4.28.1, 4.29.0, 4.30.0, 4.31.0, 4.32.0, 4.33.0] - browser: [firefox, chrome, headlesschrome] #edge + browser: [chrome] # firefox, chrome, headlesschrome, edge steps: - uses: actions/checkout@v4 @@ -22,9 +22,9 @@ jobs: with: python-version: ${{ matrix.python-version }} - name: Setup Chrome - uses: browser-actions/setup-chrome@latest + uses: browser-actions/setup-chrome@v1 with: - chrome-version: latest + chrome-version: 138 install-dependencies: true install-chromedriver: true id: setup-chrome From db74c43c500b04f03c9c7063fcc985aede4e5690 Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Thu, 19 Jun 2025 09:33:14 -0400 Subject: [PATCH 29/37] Trying chrome version 137 .. Looks like the system has Chrome 1.37 already installed. This will setup chrome 137 somewhere but more importantly add the driver. Realizing I may need to rework how we setup the machine .. --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 7f0d70143..9d59ac27f 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -24,7 +24,7 @@ jobs: - name: Setup Chrome uses: browser-actions/setup-chrome@v1 with: - chrome-version: 138 + chrome-version: 137 install-dependencies: true install-chromedriver: true id: setup-chrome From eeec4b5f03a3986bced4af2d17d04c4acaa76f90 Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Sun, 3 Aug 2025 09:02:23 -0400 Subject: [PATCH 30/37] Turn off Chrome password leak detector --- atest/acceptance/keywords/textfields.robot | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/atest/acceptance/keywords/textfields.robot b/atest/acceptance/keywords/textfields.robot index a5c879874..6c3a41a3e 100644 --- a/atest/acceptance/keywords/textfields.robot +++ b/atest/acceptance/keywords/textfields.robot @@ -1,5 +1,6 @@ *** Settings *** -Test Setup Text Fields Test Suite Setup +Suite Setup Open Browser To Start Page Disabling Chrome Leaked Password Detection +Test Setup Go To Page "forms/prefilled_email_form.html" Resource ../resource.robot Force Tags Known Issue Internet Explorer @@ -77,6 +78,8 @@ Attempt Clear Element Text On Non-Editable Field Run Keyword And Expect Error * Clear Element Text can_send_email *** Keywords *** -Text Fields Test Suite Setup - Go To Page "forms/prefilled_email_form.html" - Set Selenium Speed 0.1secs \ No newline at end of file + +Open Browser To Start Page Disabling Chrome Leaked Password Detection + [Arguments] ${alias}=${None} + Open Browser ${FRONT PAGE} ${BROWSER} remote_url=${REMOTE_URL} + ... options=add_experimental_option("prefs", {"profile.password_manager_leak_detection": False}) alias=${alias} \ No newline at end of file From 8c9307b35cba6f9c0808b0c4f5599ac72c3de3f0 Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Sun, 3 Aug 2025 09:02:55 -0400 Subject: [PATCH 31/37] Tweak some timing on the alert tests --- atest/acceptance/keywords/alerts.robot | 1 + 1 file changed, 1 insertion(+) diff --git a/atest/acceptance/keywords/alerts.robot b/atest/acceptance/keywords/alerts.robot index bd6f0ecaf..01c6c9bdf 100644 --- a/atest/acceptance/keywords/alerts.robot +++ b/atest/acceptance/keywords/alerts.robot @@ -43,6 +43,7 @@ Handle Alert returns message Handle Alert with custom timeout Click Button Slow alert + Sleep 0.1s Handle Alert timeout=1s Click Button Slow alert Run Keyword And Expect Error From a8468c2579b5d5fc292e0e9c011a0d8b4bf876e3 Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Sun, 3 Aug 2025 09:42:05 -0400 Subject: [PATCH 32/37] Trying to get v138 chromedriver .. --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 9d59ac27f..7f0d70143 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -24,7 +24,7 @@ jobs: - name: Setup Chrome uses: browser-actions/setup-chrome@v1 with: - chrome-version: 137 + chrome-version: 138 install-dependencies: true install-chromedriver: true id: setup-chrome From 467edb7b4041c5e9e3bf2bf4ddf7dbd96968a8d0 Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Sun, 3 Aug 2025 10:56:52 -0400 Subject: [PATCH 33/37] Expanding out the version text matrix verifying we are still good across many versions --- .github/workflows/CI.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 7f0d70143..df25eef2e 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -9,9 +9,9 @@ jobs: continue-on-error: true strategy: matrix: - python-version: [3.13.0] # 3.9 pypy-3.9 + python-version: [3.9.23, 3.13.5] # pypy-3.9 # python-version: [{earliest: 3.9}, {latest: 3.13.0}] # pypy-3.9 - rf-version: [7.2.2] # 6.1.1, 7.3.1 + rf-version: [6.1.1, 7.3.2] selenium-version: [4.28.1, 4.29.0, 4.30.0, 4.31.0, 4.32.0, 4.33.0] browser: [chrome] # firefox, chrome, headlesschrome, edge From b1dd105dbefc34bf3afdd5494056ea6d66c288ec Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Sun, 3 Aug 2025 11:16:58 -0400 Subject: [PATCH 34/37] Add latest selenium version 4.34.2 into test matrix --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index df25eef2e..c7ea56b17 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -12,7 +12,7 @@ jobs: python-version: [3.9.23, 3.13.5] # pypy-3.9 # python-version: [{earliest: 3.9}, {latest: 3.13.0}] # pypy-3.9 rf-version: [6.1.1, 7.3.2] - selenium-version: [4.28.1, 4.29.0, 4.30.0, 4.31.0, 4.32.0, 4.33.0] + selenium-version: [4.28.1, 4.29.0, 4.30.0, 4.31.0, 4.32.0, 4.33.0, 4.34.2] browser: [chrome] # firefox, chrome, headlesschrome, edge steps: From 573b36dfd1820fe6c365685240962477369948da Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Sun, 3 Aug 2025 14:32:04 -0400 Subject: [PATCH 35/37] Removed sleep and extended expected timeout. Previously the timeout was 1 sec and the alert was delayed 500ms. With a normal execution it seems that that 500ms diference is just not long enough to reasonably expect the alert to appear. In reviewing this test it was shown any delay was useful and the needed time for an alert to triggered and then recognized would need more than 500ms. --- atest/acceptance/keywords/alerts.robot | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/atest/acceptance/keywords/alerts.robot b/atest/acceptance/keywords/alerts.robot index 01c6c9bdf..fb18fdee5 100644 --- a/atest/acceptance/keywords/alerts.robot +++ b/atest/acceptance/keywords/alerts.robot @@ -43,8 +43,7 @@ Handle Alert returns message Handle Alert with custom timeout Click Button Slow alert - Sleep 0.1s - Handle Alert timeout=1s + Handle Alert timeout=2s Click Button Slow alert Run Keyword And Expect Error ... Alert not found in 1 millisecond. From 3c8ffe3a883564fac400f123e4ac323c52b8fc19 Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Sun, 3 Aug 2025 19:35:33 -0400 Subject: [PATCH 36/37] Corrected expected plugin doc with changes to screenshot embed --- ...luginDocumentation.test_parse_plugin_init_doc.approved.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utest/test/api/approved_files/PluginDocumentation.test_parse_plugin_init_doc.approved.txt b/utest/test/api/approved_files/PluginDocumentation.test_parse_plugin_init_doc.approved.txt index 935242b1e..3d734ab87 100644 --- a/utest/test/api/approved_files/PluginDocumentation.test_parse_plugin_init_doc.approved.txt +++ b/utest/test/api/approved_files/PluginDocumentation.test_parse_plugin_init_doc.approved.txt @@ -7,8 +7,8 @@ SeleniumLibrary can be imported with several optional arguments. - ``run_on_failure``: Default action for the `run-on-failure functionality`. - ``screenshot_root_directory``: - Path to folder where possible screenshots are created or EMBED. - See `Set Screenshot Directory` keyword for further details about EMBED. + Path to folder where possible screenshots are created or EMBED or BASE64. + See `Set Screenshot Directory` keyword for further details about EMBED and BASE64. If not given, the directory where the log file is written is used. - ``plugins``: Allows extending the SeleniumLibrary with external Python classes. From e361743a90f5c423bf78aef214153be03c84e3b7 Mon Sep 17 00:00:00 2001 From: Ed Manlove Date: Sun, 3 Aug 2025 19:37:05 -0400 Subject: [PATCH 37/37] Removed and replaced deprecated is_string method --- src/SeleniumLibrary/__init__.py | 3 +-- src/SeleniumLibrary/keywords/window.py | 4 ++-- src/SeleniumLibrary/locators/windowmanager.py | 11 +++++------ src/SeleniumLibrary/utils/__init__.py | 1 - src/SeleniumLibrary/utils/types.py | 4 ++-- 5 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/SeleniumLibrary/__init__.py b/src/SeleniumLibrary/__init__.py index 82ee75e5d..3994c1ccc 100644 --- a/src/SeleniumLibrary/__init__.py +++ b/src/SeleniumLibrary/__init__.py @@ -24,7 +24,6 @@ from robot.api import logger from robot.errors import DataError from robot.libraries.BuiltIn import BuiltIn -from robot.utils import is_string from robot.utils.importer import Importer from robotlibcore import DynamicCore @@ -843,7 +842,7 @@ def _store_plugin_keywords(self, plugin): def _resolve_screenshot_root_directory(self): screenshot_root_directory = self.screenshot_root_directory - if is_string(screenshot_root_directory): + if isinstance(screenshot_root_directory, str): if screenshot_root_directory.upper() == EMBED: self.screenshot_root_directory = EMBED if screenshot_root_directory.upper() == BASE64: diff --git a/src/SeleniumLibrary/keywords/window.py b/src/SeleniumLibrary/keywords/window.py index 01feee1fe..f2b086223 100644 --- a/src/SeleniumLibrary/keywords/window.py +++ b/src/SeleniumLibrary/keywords/window.py @@ -21,7 +21,7 @@ from SeleniumLibrary.base import keyword, LibraryComponent from SeleniumLibrary.locators import WindowManager -from SeleniumLibrary.utils import plural_or_not, is_string +from SeleniumLibrary.utils import plural_or_not class WindowKeywords(LibraryComponent): @@ -117,7 +117,7 @@ def switch_window( except NoSuchWindowException: pass finally: - if not is_string(browser) or not browser.upper() == "CURRENT": + if not isinstance(browser, str) or not browser.upper() == "CURRENT": self.drivers.switch(browser) self._window_manager.select(locator, timeout) diff --git a/src/SeleniumLibrary/locators/windowmanager.py b/src/SeleniumLibrary/locators/windowmanager.py index 1dcff9330..a785babbd 100644 --- a/src/SeleniumLibrary/locators/windowmanager.py +++ b/src/SeleniumLibrary/locators/windowmanager.py @@ -21,7 +21,6 @@ from SeleniumLibrary.base import ContextAware from SeleniumLibrary.errors import WindowNotFound -from SeleniumLibrary.utils import is_string WindowInfo = namedtuple("WindowInfo", "handle, id, name, title, url") @@ -38,7 +37,7 @@ def __init__(self, ctx): } def get_window_handles(self, browser): - if is_string(browser) and browser == "ALL": + if isinstance(browser, str) and browser == "ALL": handles = [] current_index = self.drivers.current_index for index, driver in enumerate(self.drivers, 1): @@ -46,7 +45,7 @@ def get_window_handles(self, browser): handles.extend(self.driver.window_handles) self.drivers.switch(current_index) return handles - elif is_string(browser) and browser == "CURRENT": + elif isinstance(browser, str) and browser == "CURRENT": return self.driver.window_handles else: current_index = self.drivers.current_index @@ -60,14 +59,14 @@ def get_window_infos(self, browser="CURRENT"): current_index = self.drivers.current_index except AttributeError: current_index = None - if is_string(browser) and browser.upper() == "ALL": + if isinstance(browser, str) and browser.upper() == "ALL": infos = [] 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 is_string(browser) and browser.upper() == "CURRENT": + elif isinstance(browser, str) and browser.upper() == "CURRENT": return self._get_window_infos() else: self.drivers.switch(browser) @@ -100,7 +99,7 @@ def select(self, locator, timeout=0): time.sleep(0.1) def _select(self, locator): - if not is_string(locator): + if not isinstance(locator, str): self._select_by_excludes(locator) elif locator.upper() == "CURRENT": pass diff --git a/src/SeleniumLibrary/utils/__init__.py b/src/SeleniumLibrary/utils/__init__.py index ccc4df2c6..68ba94e1b 100644 --- a/src/SeleniumLibrary/utils/__init__.py +++ b/src/SeleniumLibrary/utils/__init__.py @@ -20,7 +20,6 @@ from .types import ( is_falsy, is_noney, - is_string, is_truthy, WINDOWS, _convert_timeout, diff --git a/src/SeleniumLibrary/utils/types.py b/src/SeleniumLibrary/utils/types.py index 82a94ada5..181b0bf50 100644 --- a/src/SeleniumLibrary/utils/types.py +++ b/src/SeleniumLibrary/utils/types.py @@ -17,7 +17,7 @@ from datetime import timedelta from typing import Any -from robot.utils import is_string, timestr_to_secs +from robot.utils import timestr_to_secs from robot.utils import is_truthy, is_falsy # noqa # Need only for unit tests and can be removed when Approval tests fixes: @@ -26,7 +26,7 @@ def is_noney(item): - return item is None or is_string(item) and item.upper() == "NONE" + return item is None or isinstance(item, str) and item.upper() == "NONE" def _convert_delay(delay): if isinstance(delay, timedelta): pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy