diff --git a/.flake8 b/.flake8 deleted file mode 100644 index 6959f26dc..000000000 --- a/.flake8 +++ /dev/null @@ -1,4 +0,0 @@ -[flake8] -exclude = - __pycache__, -ignore = E501 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..f7d2b9c6a --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.approved.txt text eol=lf \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..26490b671 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "monthly" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" \ No newline at end of file diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 8db0eff25..4045e3ba0 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -1,6 +1,6 @@ name: SeleniumLibrary CI -on: [push, pull_request] +on: workflow_dispatch jobs: build: @@ -9,21 +9,24 @@ jobs: continue-on-error: true strategy: matrix: - python-version: [3.8, 3.11] # 3.12, pypy-3.9 - rf-version: [5.0.1, 6.1.1, 7.0] - selenium-version: [4.20.0, 4.21.0] - browser: [firefox, chrome, headlesschrome] #edge + python-version: [3.10.16, 3.13.5, 3.14.4, pypy-3.10] + # python-version: [{earliest: 3.10}, {latest: 3.14.0-rc.3}, {pypy: pypy-3.10}] + rf-version: [6.1.1, 7.4.2] + selenium-version: [4.29.0, 4.30.0, 4.31.0, 4.32.0, 4.33.0, 4.34.2, 4.43.0] + browser: [chrome] # firefox, chrome, headlesschrome, edge steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Python ${{ matrix.python-version }} with Robot Framework ${{ matrix.rf-version }} - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} - name: Setup Chrome - uses: browser-actions/setup-chrome@latest + uses: browser-actions/setup-chrome@v2 with: - chrome-version: latest + chrome-version: 138 + install-dependencies: true + install-chromedriver: true id: setup-chrome - run: | echo Installed chromium version: ${{ steps.setup-chrome.outputs.chrome-version }} @@ -41,12 +44,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.10' 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.10' run: | python -m pip install --upgrade pip pip install -r requirements.txt @@ -60,16 +63,12 @@ jobs: pip install -U --pre robotframework==${{ matrix.rf-version }} - name: Install drivers via selenium-manager run: | - if [[ ${{ matrix.selenium-version }} == '4.20.0' || ${{ matrix.selenium-version }} == '4.21.0' ]]; then - SELENIUM_MANAGER_EXE=$(python -c 'from selenium.webdriver.common.selenium_manager import SeleniumManager; sm=SeleniumManager(); print(f"{str(sm._get_binary())}")') - else - SELENIUM_MANAGER_EXE=$(python -c 'from selenium.webdriver.common.selenium_manager import SeleniumManager; sm=SeleniumManager(); print(f"{str(sm.get_binary())}")') - fi + SELENIUM_MANAGER_EXE=$(python -c 'from selenium.webdriver.common.selenium_manager import SeleniumManager; sm=SeleniumManager(); print(f"{str(sm._get_binary())}")') 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' + if: matrix.python-version != 'pypy-3.10' run: | invoke gen-stub @@ -79,20 +78,26 @@ jobs: 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 and latest robot framework + if: matrix.python-version == '3.14.4' && matrix.rf-version == '7.4.1' run: | xvfb-run --auto-servernum python atest/run.py --zip ${{ matrix.browser }} # - name: Run tests with Selenium Grid - # if: matrix.python-version == '3.11' && matrix.rf-version == '3.2.2' && matrix.python-version != 'pypy-3.9' + # if: matrix.python-version == '3.11' && matrix.rf-version == '3.2.2' && matrix.python-version != 'pypy-3.10' # run: | # wget --no-verbose --output-document=./selenium-server-standalone.jar http://selenium-release.storage.googleapis.com/3.141/selenium-server-standalone-3.141.59.jar # sudo chmod u+x ./selenium-server-standalone.jar # xvfb-run --auto-servernum python atest/run.py --zip headlesschrome --grid True - - uses: actions/upload-artifact@v1 + - uses: actions/upload-artifact@v7 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 diff --git a/.github/workflows/Select.yml b/.github/workflows/Select.yml new file mode 100644 index 000000000..1bdb7c02e --- /dev/null +++ b/.github/workflows/Select.yml @@ -0,0 +1,119 @@ +name: Selected Test Configuration Matrix + +on: [push, pull_request] + +jobs: + test_config: + runs-on: ubuntu-latest + continue-on-error: true + strategy: + matrix: + config: + - description: latest + python-version: 3.14.4 + rf-version: 7.4.2 + selenium-version: 4.44.0 + browser: chrome + - description: previous + python-version: 3.12.12 + rf-version: 7.3.2 + selenium-version: 4.40.0 + browser: chrome + - description: older_rf_version + python-version: 3.11.14 + rf-version: 6.1.1 + selenium-version: 4.37.0 + browser: chrome + - description: latest_firefox + python-version: 3.14.4 + rf-version: 7.4.1 + selenium-version: 4.39.0 + browser: firefox + steps: + - uses: actions/checkout@v6 + - name: Configuration Description + run: | + echo "${{ matrix.config.description }} configuration" + echo "Testing with RF v${{ matrix.config.rf-version }}, Selenium v${{ matrix.config.selenium-version}}, Python v${{ matrix.config.python-version }} under ${{ matrix.config.browser }}" + - name: Set up Python ${{ matrix.config.python-version }} + uses: actions/setup-python@v6 + with: + python-version: ${{ matrix.config.python-version }} + - name: Setup ${{ matrix.config.browser }} browser + uses: browser-actions/setup-chrome@v2 + with: + chrome-version: latest + install-dependencies: true + id: setup-chrome + - run: | + echo Installed chromium version: ${{ steps.setup-chrome.outputs.chrome-version }} + ${{ steps.setup-chrome.outputs.chrome-path }} --version + - name: Setup firefox + id: setup-firefox + uses: browser-actions/setup-firefox@v1 + with: + firefox-version: latest + - run: | + echo Installed firefox versions: ${{ steps.setup-firefox.outputs.firefox-version }} + ${{ steps.setup-firefox.outputs.firefox-path }} --version + - name: Start xvfb + run: | + export DISPLAY=:99.0 + Xvfb -ac :99 -screen 0 1280x1024x16 > /dev/null 2>&1 & + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements-dev.txt + - name: Install Seleninum v${{ matrix.config.selenium-version }} + run: | + pip install --upgrade selenium==${{ matrix.config.selenium-version }} + - name: Install RF ${{ matrix.config.rf-version }} + run: | + pip install -U --pre robotframework==${{ matrix.config.rf-version }} + + - name: Run tests under specified config + run: | + xvfb-run --auto-servernum python atest/run.py --zip ${{ matrix.config.browser }} + + - uses: actions/upload-artifact@v7 + if: failure() + with: + name: sl_${{ matrix.config.python-version }}_${{ matrix.config.rf-version }}_${{ matrix.config.selenium-version }}_${{ matrix.config.browser }} + path: atest/zip_results + overwrite: true + ruff: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v6 + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.14.4" + + - name: Install dev dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements-dev.txt + + - name: Ruff format check + id: format + continue-on-error: true + run: | + python -m invoke formatter --check + + - name: Ruff lint + id: lint + continue-on-error: true + run: | + python -m invoke lint + + - name: Fail if any Ruff step failed + if: always() + run: | + echo "format outcome: ${{ steps.format.outcome }}" + echo "lint outcome: ${{ steps.lint.outcome }}" + if [ "${{ steps.format.outcome }}" != "success" ] || [ "${{ steps.lint.outcome }}" != "success" ]; then + exit 1 + fi \ No newline at end of file diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index ffb9d6ff8..677200817 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -118,21 +118,23 @@ needed in internal code. When docstrings are added, they should follow `PEP-257`_. See `Documentation`_ section below for more details about documentation syntax, generating docs, etc. -The code should be formatted with `Black`_ and errors found by `flake8`_ -should be fixed. Black and flake8 can be run by using -command:: +The code should be formatted and linted with `Ruff`_. See Development commands below for more details. - inv lint +Development commands +~~~~~~~~~~~~~~~~~~~~ -By default flake8 ignores line length error E501, but it does not ignore -warning W503. In practice Black formats list access like this:: +Use `invoke`_ tasks for common local checks and test runs:: - list[1 : 2] + inv formatter --check # Check formatting with Ruff + inv formatter # Format source files with Ruff + inv lint # Run Ruff lint checks + inv lint --fix # Apply safe Ruff lint fixes + inv utest # Run unit tests + inv atest # Run acceptance tests (headlesschrome) -But flake8 will display an warning about it. This should be manually -fixed to look like:: - - list[1:2] +Run these before opening a pull request so local results are close to CI. +Use the project virtual environment and pinned dependencies from +``requirements-dev.txt`` for consistent results across local runs and CI. Documentation ------------- @@ -160,7 +162,7 @@ individual keywords. Keyword documentation can be easily created using `invoke`_ task:: - inv keyword_documentation + inv kw-docs Resulting docs should be verified before the code is committed. @@ -245,5 +247,4 @@ the same code as your changes. In that case you should .. _utest/README.rst: https://github.com/robotframework/SeleniumLibrary/blob/master/utest/README.rst .. _sync your fork: https://help.github.com/articles/syncing-a-fork/ .. _resolve conflicts: https://help.github.com/articles/resolving-a-merge-conflict-from-the-command-line -.. _Black: https://github.com/psf/black -.. _flake8: https://github.com/PyCQA/flake8 \ No newline at end of file +.. _Ruff: https://github.com/astral-sh/ruff \ No newline at end of file diff --git a/README.rst b/README.rst index 85819fcab..2ec34f134 100644 --- a/README.rst +++ b/README.rst @@ -10,7 +10,7 @@ SeleniumLibrary_ is a web testing library for `Robot Framework`_ that utilizes the Selenium_ tool internally. The project is hosted on GitHub_ and downloads can be found from PyPI_. -SeleniumLibrary currently works with Selenium 4. It supports Python 3.8 through 3.11. +SeleniumLibrary currently works with Selenium 4. It supports Python 3.10 through 3.13. In addition to the normal Python_ interpreter, it works also with PyPy_. @@ -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 ----- diff --git a/atest/acceptance/1-plugin/OpenBrowserExample.py b/atest/acceptance/1-plugin/OpenBrowserExample.py index 2cb006f24..ab04db3bf 100644 --- a/atest/acceptance/1-plugin/OpenBrowserExample.py +++ b/atest/acceptance/1-plugin/OpenBrowserExample.py @@ -121,7 +121,12 @@ def create_driver( ) def create_seleniumwire( - self, desired_capabilities, remote_url, options=None, service_log_path=None, service=None, + self, + desired_capabilities, + remote_url, + options=None, + service_log_path=None, + service=None, ): logger.info(self.extra_dictionary) return webdriver.Chrome() diff --git a/atest/acceptance/2-event_firing_webdriver/event_firing_webdriver.robot b/atest/acceptance/2-event_firing_webdriver/event_firing_webdriver.robot index 5e9a07e6d..d4877f042 100644 --- a/atest/acceptance/2-event_firing_webdriver/event_firing_webdriver.robot +++ b/atest/acceptance/2-event_firing_webdriver/event_firing_webdriver.robot @@ -10,7 +10,7 @@ ${event_firing_or_none} ${NONE} *** Test Cases *** Open Browser To Start Page - [Tags] NoGrid + [Tags] NoGrid SKIP_ON_WINDOWS [Documentation] ... LOG 1:30 DEBUG Wrapping driver to event_firing_webdriver. ... LOG 1:32 INFO Got driver also from SeleniumLibrary. diff --git a/atest/acceptance/create_webdriver.robot b/atest/acceptance/create_webdriver.robot index 9f3796ddf..d87c80086 100644 --- a/atest/acceptance/create_webdriver.robot +++ b/atest/acceptance/create_webdriver.robot @@ -8,7 +8,7 @@ Create Webdriver Creates Functioning WebDriver [Documentation] ... LOG 1:1 INFO REGEXP: Creating an instance of the \\w+ WebDriver. ... LOG 1:18 DEBUG REGEXP: Created \\w+ WebDriver instance with session id (\\w|-)+. - [Tags] Known Issue Internet Explorer Known Issue Safari + [Tags] Known Issue Internet Explorer Known Issue Safari SKIP_ON_WINDOWS [Setup] Set Driver Variables Create Webdriver ${DRIVER_NAME} kwargs=${KWARGS} Go To ${FRONT_PAGE} diff --git a/atest/acceptance/entry_point.robot b/atest/acceptance/entry_point.robot index a92c3740a..631d1a553 100644 --- a/atest/acceptance/entry_point.robot +++ b/atest/acceptance/entry_point.robot @@ -7,7 +7,7 @@ Entry Point Version ${process} = Run Process ... python -m SeleniumLibrary.entry --version ... shell=True - ... cwd=${EXECDIR}/src + ... cwd=${EXECDIR}${/}src Log ${process.stdout} Log ${process.stderr} Should Be Equal As Integers ${process.rc} 0 @@ -17,18 +17,18 @@ Entry Point Version Entry Point Translation ${process} = Run Process - ... python -m SeleniumLibrary.entry translation ${OUTPUT_DIR}/translation.json + ... python -m SeleniumLibrary.entry translation ${OUTPUT_DIR}${/}translation.json ... shell=True - ... cwd=${EXECDIR}/src + ... cwd=${EXECDIR}${/}src Log ${process.stdout} Log ${process.stderr} Should Be Equal As Integers ${process.rc} 0 Should Be Empty ${process.stderr} - Should Be Equal ${process.stdout} Translation file created in ${OUTPUT_DIR}/translation.json + Should Be Equal ${process.stdout} Translation file created in ${OUTPUT_DIR}${/}translation.json ${process} = Run Process - ... python -m SeleniumLibrary.entry translation --compare ${OUTPUT_DIR}/translation.json + ... python -m SeleniumLibrary.entry translation --compare ${OUTPUT_DIR}${/}translation.json ... shell=True - ... cwd=${EXECDIR}/src + ... cwd=${EXECDIR}${/}src Log ${process.stdout} Log ${process.stderr} Should Be Equal As Integers ${process.rc} 0 diff --git a/atest/acceptance/keywords/alerts.robot b/atest/acceptance/keywords/alerts.robot index bd6f0ecaf..fb18fdee5 100644 --- a/atest/acceptance/keywords/alerts.robot +++ b/atest/acceptance/keywords/alerts.robot @@ -43,7 +43,7 @@ Handle Alert returns message Handle Alert with custom timeout Click Button Slow alert - Handle Alert timeout=1s + Handle Alert timeout=2s Click Button Slow alert Run Keyword And Expect Error ... Alert not found in 1 millisecond. diff --git a/atest/acceptance/keywords/async_javascript.robot b/atest/acceptance/keywords/async_javascript.robot index 7fc72b198..646e3dd16 100644 --- a/atest/acceptance/keywords/async_javascript.robot +++ b/atest/acceptance/keywords/async_javascript.robot @@ -88,6 +88,7 @@ Should Timeout If Script Does Not Invoke Callback With Long Timeout ... var callback = arguments[arguments.length - 1]; window.setTimeout(callback, 1500); Should Detect Page Loads While Waiting On An Async Script And Return An Error + [Tags] Triage Set Selenium Timeout 0.5 seconds ${status} ${error} Run Keyword And Ignore Error Execute Async Javascript ... window.location = 'javascript/dynamic'; diff --git a/atest/acceptance/keywords/cookies.robot b/atest/acceptance/keywords/cookies.robot index 81e22c453..36ab343c2 100644 --- a/atest/acceptance/keywords/cookies.robot +++ b/atest/acceptance/keywords/cookies.robot @@ -9,8 +9,11 @@ Library DateTime *** Test Cases *** Get Cookies ${cookies}= Get Cookies + Should Contain ${cookies} test=seleniumlibrary + Should Contain ${cookies} another=value + Should Contain ${cookies} far_future=timemachine Should Match Regexp ${cookies} - ... ^(test=seleniumlibrary; another=value)|(another=value; test=seleniumlibrary)$ + ... ^(?:test=seleniumlibrary|another=value|far_future=timemachine)(?:; (?:test=seleniumlibrary|another=value|far_future=timemachine)){2}$ Get Cookies As Dict ${cookies}= Get Cookies as_dict=True @@ -36,15 +39,21 @@ Add Cookie When Secure Is False Should Be Equal ${cookie.secure} ${False} Add Cookie When Expiry Is Epoch - Add Cookie Cookie1 value1 expiry=1730205247 + # To convert epoch to formatted string + # from time import strftime, localtime + # strftime('%Y-%m-%d %H:%M:%S', localtime(1793247900)) + # To update time each September (as Chrome limits cookies to one year expiry date) use + # import datetime + # print (datetime.datetime.strptime("2027-10-29 12:25:00", "%Y-%m-%d %I:%M:%S").timestamp()) + Add Cookie Cookie1 value1 expiry=1793247900 ${cookie} = Get Cookie Cookie1 - ${expiry} = Convert Date ${1730205247} exclude_millis=True + ${expiry} = Convert Date ${1793247900} exclude_millis=True Should Be Equal As Strings ${cookie.expiry} ${expiry} Add Cookie When Expiry Is Human Readable Data&Time - Add Cookie Cookie12 value12 expiry=2024-10-29 19:36:51 + Add Cookie Cookie12 value12 expiry=2026-10-29 12:25:00 ${cookie} = Get Cookie Cookie12 - Should Be Equal As Strings ${cookie.expiry} 2024-10-29 19:36:51 + Should Be Equal As Strings ${cookie.expiry} 2026-10-29 12:25:00 Delete Cookie [Tags] Known Issue Safari @@ -114,12 +123,15 @@ Test Get Cookie Keyword Logging ... domain=localhost ... secure=False ... httpOnly=False - ... expiry=2024-09-15 *:22:33 + ... expiry=2026-09-01 *:25:00 ... extra={'sameSite': 'Lax'} ${cookie} = Get Cookie far_future *** Keywords *** Add Cookies + # To update time each September (as Chrome limits cookies to one year expiry date) use + # import datetime + # print (datetime.datetime.strptime("2027-09-01 12:25:00", "%Y-%m-%d %I:%M:%S").timestamp()) Delete All Cookies Add Cookie test seleniumlibrary ${now} = Get Current Date @@ -127,4 +139,4 @@ Add Cookies ${tomorrow_thistime_datetime} = Convert Date ${tomorrow_thistime} datetime Set Suite Variable ${tomorrow_thistime_datetime} Add Cookie another value expiry=${tomorrow_thistime} - Add Cookie far_future timemachine expiry=1726399353 # 2024-09-15 11:22:33 + Add Cookie far_future timemachine expiry=1788240300 # 2026-09-01 12:25:00 diff --git a/atest/acceptance/keywords/draganddropframe.robot b/atest/acceptance/keywords/draganddropframe.robot new file mode 100644 index 000000000..089915b96 --- /dev/null +++ b/atest/acceptance/keywords/draganddropframe.robot @@ -0,0 +1,81 @@ +*** Settings *** +Documentation Tests for the custom Drag And Drop Across Frames keyword +... in cross-frame drag-and-drop scenarios. +Resource ../resource.robot +Test Setup Go To Page "frames/draganddrop.html" + +*** Test Cases *** +Drag And Drop Across Frames Works From Default Content + [Tags] Known Issue Firefox + [Documentation] Verifies drag-and-drop from default content to a target inside an iframe. + Wait Until Page Contains Element id=defaultSource 10s + Drag And Drop Across Frames id=defaultSource id=target id=targetFrame + Select Frame id=targetFrame + Element Should Contain id=target Dropped Successfully! + Unselect Frame + +Drag And Drop Across Frames Works From Source Frame + [Tags] Known Issue Firefox + [Documentation] Verifies drag-and-drop from a source iframe to a target iframe. + Wait Until Page Contains Element id=sourceFrame 10s + Select Frame id=sourceFrame + Wait Until Page Contains Element id=frameSource 10s + Unselect Frame + Drag And Drop Across Frames id=frameSource id=target id=targetFrame id=sourceFrame + Select Frame id=targetFrame + Element Should Contain id=target Dropped Successfully! + Unselect Frame + +Drag And Drop Across Frames Returns To Default Content + [Documentation] Verifies that the keyword returns to default content after execution. + Wait Until Page Contains Element id=defaultSource 10s + Drag And Drop Across Frames id=defaultSource id=target id=targetFrame + Page Should Not Contain Element id=target + +Drag And Drop Across Frames Hides Default Source Element + [Tags] Known Issue Firefox + [Documentation] Verifies that the default source element becomes hidden after a successful drop. + Wait Until Page Contains Element id=defaultSource 10s + Drag And Drop Across Frames id=defaultSource id=target id=targetFrame + Element Should Not Be Visible id=defaultSource + +Drag And Drop Across Frames Hides Frame Source Element + [Tags] Known Issue Firefox + [Documentation] Verifies that the frame source element becomes hidden after a successful drop. + Wait Until Page Contains Element id=sourceFrame 10s + Drag And Drop Across Frames id=frameSource id=target id=targetFrame id=sourceFrame + Select Frame id=sourceFrame + Element Should Not Be Visible id=frameSource + Unselect Frame + +Drag And Drop Across Frames Fails With Invalid Target Frame + [Documentation] Verifies that the keyword fails when the target frame locator is invalid. + Wait Until Page Contains Element id=defaultSource 10s + Run Keyword And Expect Error + ... Element with locator 'id=missingFrame' not found. + ... Drag And Drop Across Frames + ... id=defaultSource id=target id=missingFrame + +Drag And Drop Across Frames Fails With Invalid Target + [Documentation] Verifies that the keyword fails when the target element is not found inside the target iframe. + Wait Until Page Contains Element id=defaultSource 10s + Run Keyword And Expect Error + ... Element with locator 'id=missingTarget' not found. + ... Drag And Drop Across Frames + ... id=defaultSource id=missingTarget id=targetFrame + +Drag And Drop Across Frames Fails With Invalid Source Frame + [Documentation] Verifies that the keyword fails when the source frame locator is invalid. + Wait Until Page Contains Element id=defaultSource 10s + Run Keyword And Expect Error + ... Element with locator 'id=missingSourceFrame' not found. + ... Drag And Drop Across Frames + ... id=frameSource id=target id=targetFrame id=missingSourceFrame + +Drag And Drop Across Frames Fails With Invalid Source + [Documentation] Verifies that the keyword fails when the source element is not found. + Wait Until Page Contains Element id=defaultSource 10s + Run Keyword And Expect Error + ... Element with locator 'id=missingSource' not found. + ... Drag And Drop Across Frames + ... id=missingSource id=target id=targetFrame \ No newline at end of file diff --git a/atest/acceptance/keywords/elements.robot b/atest/acceptance/keywords/elements.robot index a93ccd219..843723cba 100644 --- a/atest/acceptance/keywords/elements.robot +++ b/atest/acceptance/keywords/elements.robot @@ -218,4 +218,37 @@ Cover Element can cover just one element Cover Elements should throw exception when locator is invalid Run Keyword And Expect Error No element with locator '//img?@src="inexistent"?' found. - ... Cover Element //img[@src="inexistent"] \ No newline at end of file + ... Cover Element //img[@src="inexistent"] + +Get CSS Property Value Returns Correct Values For Common Properties + [Setup] Go To Page "cssproperties.html" + ${display}= Get CSS Property Value id:styled-div display + Should Be Equal ${display} block + ${font_size}= Get CSS Property Value id:styled-div font-size + Should Be Equal ${font_size} 16px + ${margin_top}= Get CSS Property Value id:styled-div margin-top + Should Be Equal ${margin_top} 10px + ${text_align}= Get CSS Property Value id:styled-div text-align + Should Be Equal ${text_align} center + +Get CSS Property Value With Missing Element + [Setup] Go To Page "cssproperties.html" + Run Keyword And Expect Error + ... Element with locator 'id:non-existent' not found. + ... Get CSS Property Value id:non-existent color + +Get CSS Property Value Returns Background Color + [Setup] Go To Page "cssproperties.html" + ${color}= Get CSS Property Value id:styled-div background-color + Should Match Regexp ${color} ^rgba?\(.+\)$ + +Get CSS Property Value Using WebElement + [Setup] Go To Page "cssproperties.html" + ${element}= Get WebElement id:styled-div + ${display}= Get CSS Property Value ${element} display + Should Be Equal ${display} block + +Get CSS Property Value With Non Existing Property + [Setup] Go To Page "cssproperties.html" + ${value}= Get CSS Property Value id:styled-div non-existent-property + Should Be Empty ${value} 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/mouse.robot b/atest/acceptance/keywords/mouse.robot index 2c25035e0..734eb2d01 100644 --- a/atest/acceptance/keywords/mouse.robot +++ b/atest/acceptance/keywords/mouse.robot @@ -8,14 +8,16 @@ 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. ... Mouse Over not_there Mouse Over Error - [Tags] Known Issue Safari + [Tags] Known Issue Safari Known Issue Firefox 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. diff --git a/atest/acceptance/keywords/page_load_timeout.robot b/atest/acceptance/keywords/page_load_timeout.robot index 100bfe2c7..d701f1c0c 100644 --- a/atest/acceptance/keywords/page_load_timeout.robot +++ b/atest/acceptance/keywords/page_load_timeout.robot @@ -6,6 +6,7 @@ Test Teardown Close Browser And Reset Page Load Timeout *** Test Cases *** Should Open Browser With Default Page Load Timeout + [Tags] SKIP_ON_WINDOWS [Documentation] Verify that 'Open Browser' changes the page load timeout. ... LOG 1.1.1:26 DEBUG REGEXP: POST http://localhost:\\d{2,5}/session/[a-f0-9-]+/timeouts {['\\\"]pageLoad['\\\"]: 300000} ... LOG 1.1.1:28 DEBUG STARTS: Remote response: status=200 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} diff --git a/atest/acceptance/keywords/textfields.robot b/atest/acceptance/keywords/textfields.robot index 1fa6f4522..b957b1f97 100644 --- a/atest/acceptance/keywords/textfields.robot +++ b/atest/acceptance/keywords/textfields.robot @@ -1,4 +1,5 @@ *** Settings *** +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 @@ -75,3 +76,51 @@ Press Key Attempt Clear Element Text On Non-Editable Field Run Keyword And Expect Error * Clear Element Text can_send_email + +Input Password Accepts Secret Type + [Tags] require-rf-7.4 + [Setup] Go To Page "forms/login.html" + Set Environment Variable TEST_PASSWORD s3cret-pass + VAR ${pw: Secret} %{TEST_PASSWORD} + Input Text username_field my_username + Input Password password_field ${pw} + ${value}= Get Value password_field + Should Be Equal ${value} s3cret-pass + +Input Text Accepts Secret Type + [Tags] require-rf-7.4 + [Setup] Go To Page "forms/login.html" + Set Environment Variable TEST_USERNAME my_username + VAR ${user: Secret} %{TEST_USERNAME} + Input Text username_field ${user} + ${value}= Get Value username_field + Should Be Equal ${value} my_username + +Input Password With Plain String Still Works + [Setup] Go To Page "forms/login.html" + [Documentation] Backwards compatibility — plain str must still be accepted. + Input Text username_field my_username + Input Password password_field plain-pass + ${value}= Get Value password_field + Should Be Equal ${value} plain-pass + +Input Password Does Not Log Secret Value + [Tags] require-rf-7.4 NoGrid + [Setup] Go To Page "forms/login.html" + [Documentation] + ... LOG 3:1 INFO Typing password into text field 'password_field'. + Set Environment Variable TEST_PASSWORD must-not-leak + VAR ${pw: Secret} %{TEST_PASSWORD} + Input Password password_field ${pw} + +*** Keywords *** + +Open Browser To Start Page Disabling Chrome Leaked Password Detection + [Arguments] ${alias}=${None} + ${browser}= Evaluate "${BROWSER}".replace(" ", "").lower() + IF "${browser}" in ["chrome", "googlechrome", "gc", "headlesschrome"] + Open Browser ${FRONT PAGE} ${BROWSER} remote_url=${REMOTE_URL} + ... options=add_experimental_option("prefs", {"profile.password_manager_leak_detection": False}) alias=${alias} + ELSE + Open Browser ${FRONT PAGE} ${BROWSER} remote_url=${REMOTE_URL} alias=${alias} + END 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/multiple_browsers_options.robot b/atest/acceptance/multiple_browsers_options.robot index 2349c9195..81c9c94ae 100644 --- a/atest/acceptance/multiple_browsers_options.robot +++ b/atest/acceptance/multiple_browsers_options.robot @@ -8,6 +8,7 @@ Documentation Creating test which would work on all browser is not possible. *** Test Cases *** Chrome Browser With Selenium Options As String + [Tags] SKIP_ON_WINDOWS [Documentation] ... LOG 1:13 DEBUG REGEXP: .*['\\\"]goog:chromeOptions['\\\"].* ... LOG 1:13 DEBUG REGEXP: .*args['\\\"]: \\\[['\\\"]--disable-dev-shm-usage['\\\"].* @@ -15,6 +16,7 @@ Chrome Browser With Selenium Options As String ... desired_capabilities=${DESIRED_CAPABILITIES} options=add_argument("--disable-dev-shm-usage") Chrome Browser With Selenium Options As String With Attribute As True + [Tags] SKIP_ON_WINDOWS [Documentation] ... LOG 1:13 DEBUG REGEXP: .*['\\\"]goog:chromeOptions['\\\"].* ... LOG 1:13 DEBUG REGEXP: .*args['\\\"]: \\\[['\\\"]--disable-dev-shm-usage['\\\"].* @@ -23,7 +25,7 @@ Chrome Browser With Selenium Options As String With Attribute As True ... desired_capabilities=${DESIRED_CAPABILITIES} options=add_argument ( "--disable-dev-shm-usage" ) ; add_argument ( "--headless=new" ) Chrome Browser With Selenium Options With Complex Object - [Tags] NoGrid + [Tags] NoGrid SKIP_ON_WINDOWS [Documentation] ... LOG 1:13 DEBUG REGEXP: .*['\\\"]goog:chromeOptions['\\\"].* ... LOG 1:13 DEBUG REGEXP: .*['\\\"]mobileEmulation['\\\"]: {['\\\"]deviceName['\\\"]: ['\\\"]Galaxy S5['\\\"].* @@ -32,6 +34,7 @@ Chrome Browser With Selenium Options With Complex Object ... desired_capabilities=${DESIRED_CAPABILITIES} options=add_argument ( "--disable-dev-shm-usage" ) ; add_experimental_option( "mobileEmulation" , { 'deviceName' : 'Galaxy S5'}) Chrome Browser With Selenium Options Object + [Tags] SKIP_ON_WINDOWS [Documentation] ... LOG 2:13 DEBUG REGEXP: .*['\\\"]goog:chromeOptions['\\\"].* ... LOG 2:13 DEBUG REGEXP: .*args['\\\"]: \\\[['\\\"]--disable-dev-shm-usage['\\\"].* @@ -46,6 +49,7 @@ Chrome Browser With Selenium Options Invalid Method Chrome Browser With Selenium Options Argument With Semicolon + [Tags] SKIP_ON_WINDOWS [Documentation] ... LOG 1:13 DEBUG REGEXP: .*['\\\"]goog:chromeOptions['\\\"].* ... LOG 1:13 DEBUG REGEXP: .*\\\[['\\\"]has;semicolon['\\\"].* diff --git a/atest/acceptance/multiple_browsers_service.robot b/atest/acceptance/multiple_browsers_service.robot index e47c917a0..2f98d99ec 100644 --- a/atest/acceptance/multiple_browsers_service.robot +++ b/atest/acceptance/multiple_browsers_service.robot @@ -2,6 +2,7 @@ Suite Teardown Close All Browsers Library ../resources/testlibs/get_driver_path.py Resource resource.robot +Test Tags SKIP_ON_WINDOWS # Force Tags Known Issue Firefox Known Issue Safari Known Issue Internet Explorer Documentation Creating test which would work on all browser is not possible. ... These tests are for Chrome only. @@ -11,11 +12,13 @@ Chrome Browser With Chrome Service As String [Documentation] ... LOG 2:3 DEBUG STARTS: Started executable: ... LOG 2:4 DEBUG GLOB: POST*/session* + [Tags] Known Issue Firefox Known Issue Safari Known Issue Internet Explorer ${driver_path}= Get Driver Path Chrome Open Browser ${FRONT PAGE} Chrome remote_url=${REMOTE_URL} ... service=executable_path='${driver_path}' Chrome Browser With Chrome Service As String With service_args As List + [Tags] Known Issue Firefox Known Issue Safari Known Issue Internet Explorer Open Browser ${FRONT PAGE} Chrome remote_url=${REMOTE_URL} ... service=service_args=['--append-log', '--readable-timestamp']; log_output='${OUTPUT_DIR}/chromedriverlog.txt' File Should Exist ${OUTPUT_DIR}/chromedriverlog.txt @@ -23,6 +26,7 @@ Chrome Browser With Chrome Service As String With service_args As List # ... service=service_args=['--append-log', '--readable-timestamp'] Firefox Browser With Firefox Service As String + [Tags] Known Issue Chrome Known Issue Safari Known Issue Internet Explorer [Documentation] ... LOG 2:3 DEBUG STARTS: Started executable: ... LOG 2:4 DEBUG GLOB: POST*/session* diff --git a/atest/acceptance/open_and_close.robot b/atest/acceptance/open_and_close.robot index 6a0d7a75e..187edad7e 100644 --- a/atest/acceptance/open_and_close.robot +++ b/atest/acceptance/open_and_close.robot @@ -15,6 +15,7 @@ Close Browser Does Nothing When No Browser Is Opened Close Browser Browser Open With Not Well-Formed URL Should Close + [Tags] SKIP_ON_WINDOWS [Documentation] Verify after incomplete 'Open Browser' browser closes ... LOG 1.1:34 DEBUG STARTS: Opened browser with session id ... LOG 1.1:34 DEBUG REGEXP: .*but failed to open url.* 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/atest/resources/html/cssproperties.html b/atest/resources/html/cssproperties.html new file mode 100644 index 000000000..f35e60c3a --- /dev/null +++ b/atest/resources/html/cssproperties.html @@ -0,0 +1,22 @@ + + + + CSS Properties Test Page + + + + +
+ Demo Element +
+ + + \ No newline at end of file diff --git a/atest/resources/html/frames/draganddrop.html b/atest/resources/html/frames/draganddrop.html new file mode 100644 index 000000000..98421dd5f --- /dev/null +++ b/atest/resources/html/frames/draganddrop.html @@ -0,0 +1,260 @@ + + + + + Drag And Drop Across Frames Test Page + + + + +

Drag And Drop Across Frames Test Page

+ +
Default Source
+ +
+ + +
+ +
+ + + + + \ No newline at end of file diff --git a/atest/resources/testlibs/get_driver_path.py b/atest/resources/testlibs/get_driver_path.py index 95c11e924..19d838e0e 100644 --- a/atest/resources/testlibs/get_driver_path.py +++ b/atest/resources/testlibs/get_driver_path.py @@ -18,6 +18,7 @@ def _import_options(self, browser): return options.Options """ + from selenium import webdriver from selenium.webdriver.common import driver_finder import importlib @@ -30,12 +31,12 @@ def get_driver_path(browser): options = importlib.import_module(f"selenium.webdriver.{browser}.options") args = inspect.signature(driver_finder.DriverFinder.__init__).parameters.keys() - if ('service' in args) and ('options' in args): + if ("service" in args) and ("options" in args): # Selenium V4.20.0 or greater finder = driver_finder.DriverFinder(service.Service(), options.Options()) return finder.get_driver_path() else: # Selenium v4.19.0 and prior finder = driver_finder.DriverFinder() - func = getattr(finder, 'get_path') + func = getattr(finder, "get_path") return finder.get_path(service.Service(), options.Options()) diff --git a/atest/run.py b/atest/run.py index 3e7960a15..8ae0049bf 100755 --- a/atest/run.py +++ b/atest/run.py @@ -43,6 +43,7 @@ import zipfile from contextlib import contextmanager import os +import re import sys import argparse import textwrap @@ -181,7 +182,7 @@ def _grid_status(status=False, role="hub"): @contextmanager -def http_server(interpreter, port:int): +def http_server(interpreter, port: int): serverlog = open(os.path.join(RESULTS_DIR, "serverlog.txt"), "w") interpreter = "python" if not interpreter else interpreter process = subprocess.Popen( @@ -211,11 +212,23 @@ def execute_tests(interpreter, browser, rf_options, grid, event_firing, port): if platform.system() == "Darwin": runner.append("--exclude") runner.append("SKIP_ON_MAC") - + if platform.system() == "Windows": + runner.append("--exclude") + runner.append("SKIP_ON_WINDOWS") options.extend([opt.format(browser=browser) for opt in ROBOT_OPTIONS]) if rf_options: options += rf_options - options += ["--exclude", f"known issue {browser.replace('headless', '')}", "--exclude", "triage"] + options += [ + "--exclude", + f"known issue {browser.replace('headless', '')}", + "--exclude", + "triage", + ] + rf_ver = tuple( + int(re.match(r"\d+", x).group()) for x in robot_version.split(".")[:2] + ) + if rf_ver < (7, 4): + options.extend(["--exclude", "require-rf-7.4"]) command = runner if grid: command += [ @@ -251,7 +264,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]) @@ -259,7 +272,7 @@ def process_output(browser): return exit.code -def create_zip(browser = None): +def create_zip(browser=None): if os.path.exists(ZIP_DIR): shutil.rmtree(ZIP_DIR) os.mkdir(ZIP_DIR) diff --git a/docs/SeleniumLibrary-6.6.0.rst b/docs/SeleniumLibrary-6.6.0.rst new file mode 100644 index 000000000..5e0b74f42 --- /dev/null +++ b/docs/SeleniumLibrary-6.6.0.rst @@ -0,0 +1,79 @@ +===================== +SeleniumLibrary 6.6.0 +===================== + + +.. default-role:: code + + +SeleniumLibrary_ is a web testing library for `Robot Framework`_ that utilizes +the Selenium_ tool internally. SeleniumLibrary 6.6.0 is a new release which adds +Python 3.12 support. + +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.6.0 + +to install exactly this version. Alternatively you can download the source +distribution from PyPI_ and install it manually. + +SeleniumLibrary 6.6.0 was released on Friday September 6, 2024. SeleniumLibrary supports +Python 3.8 through 3.12, Selenium 4.21.0 through 4.24.0 and +Robot Framework 6.1.1 and 7.0.1. + +*In addition this version of SeleniumLibrary has been tested against the upcoming Robot +Framework v7.1 release (using v7.1rc2) and was found compatible. We expect it to work +fine with the final release which should be coming out soon.* + +.. _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.6.0 + + +.. contents:: + :depth: 2 + :local: + +Most important enhancements +=========================== + +- Support for Python 3.12 was added in this release. In addition we added Robot Framework 7.0.1 + while dropping 5.0.1 which did not officially support Python 3.12. In addition with the almost + monthly releases of Selenium we have caught up testing against and supporting Selenium versions + 4.21.0, 4.22.0, 4.23.1, and 4.24.0. (`#1906`_) + +Acknowledgements +================ + +- I want to thank grepwood, KotlinIsland, and Robin Mackaij for pushing support python 3.12 and + Yuri, Tatu and Lassi for reviewing the changes. (`#1906`_) + +Full list of fixes and enhancements +=================================== + +.. list-table:: + :header-rows: 1 + + * - ID + - Type + - Priority + - Summary + * - `#1906`_ + - enhancement + - high + - Support python 3.12 + +Altogether 1 issue. View on the `issue tracker `__. + +.. _#1906: https://github.com/robotframework/SeleniumLibrary/issues/1906 diff --git a/docs/SeleniumLibrary-6.6.1.rst b/docs/SeleniumLibrary-6.6.1.rst new file mode 100644 index 000000000..247858ff3 --- /dev/null +++ b/docs/SeleniumLibrary-6.6.1.rst @@ -0,0 +1,81 @@ +===================== +SeleniumLibrary 6.6.1 +===================== + + +.. default-role:: code + + +SeleniumLibrary_ is a web testing library for `Robot Framework`_ that utilizes +the Selenium_ tool internally. SeleniumLibrary 6.6.1 is a new release which adds +Python 3.12 support. + +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.6.1 + +to install exactly this version. Alternatively you can download the source +distribution from PyPI_ and install it manually. + +SeleniumLibrary 6.6.1 was released on Friday September 6, 2024. SeleniumLibrary supports +Python 3.8 through 3.12, Selenium 4.21.0 through 4.24.0 and +Robot Framework 6.1.1 and 7.0.1. + +*In addition this version of SeleniumLibrary has been tested against the upcoming Robot +Framework v7.1 release (using v7.1rc2) and was found compatible. We expect it to work +fine with the final release which should be coming out soon.* + +.. _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.6.0 + + +.. contents:: + :depth: 2 + :local: + +Most important enhancements +=========================== + +- Support for Python 3.12 was added in this release. In addition we added Robot Framework 7.0.1 + while dropping 5.0.1 which did not officially support Python 3.12. In addition with the almost + monthly releases of Selenium we have caught up testing against and supporting Selenium versions + 4.21.0, 4.22.0, 4.23.1, and 4.24.0. (`#1906`_) +- SeleniumLibrary v6.6.1 fixes a bad required version for Python 3.12. v6.6.0 was only compatible + with Python 3.12.0 and not what was desired or any 3.12.x. The point release fixes that issue. + +Acknowledgements +================ + +- I want to thank grepwood, KotlinIsland, and Robin Mackaij for pushing support python 3.12 and + Yuri, Tatu and Lassi for reviewing the changes. (`#1906`_) + +Full list of fixes and enhancements +=================================== + +.. list-table:: + :header-rows: 1 + + * - ID + - Type + - Priority + - Summary + * - `#1906`_ + - enhancement + - high + - Support python 3.12 + +Altogether 1 issue. View on the `issue tracker `__. + +.. _#1906: https://github.com/robotframework/SeleniumLibrary/issues/1906 diff --git a/docs/SeleniumLibrary-6.7.0.rst b/docs/SeleniumLibrary-6.7.0.rst new file mode 100644 index 000000000..f1bf8d778 --- /dev/null +++ b/docs/SeleniumLibrary-6.7.0.rst @@ -0,0 +1,106 @@ +===================== +SeleniumLibrary 6.7.0 +===================== + + +.. default-role:: code + + +SeleniumLibrary_ is a web testing library for `Robot Framework`_ that utilizes +the Selenium_ tool internally. SeleniumLibrary 6.7.0 is a new release with +some minor enhancements and bug fixes. This versions add support for Python 3.13. + + +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.0 + +to install exactly this version. Alternatively you can download the source +distribution from PyPI_ and install it manually. + +SeleniumLibrary 6.7.0 was released on Monday January 6, 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. + +*Note: This release, v 6.7.0, has been tested against the latest release candidate of the +upcoming Robot Framework version, 7.2. It is compatible and expect to support 7.2 when the +final release is made.* + +.. _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.0 + + +.. contents:: + :depth: 2 + :local: + +Most important enhancements +=========================== + +- Fixed _find_by_data_locator when more than one colon was within the locator. If one + used the data strategy and the locator had additional colon in it the locator parser + would incorrectly parse the locator. This has been fixed in this release. (`#1924`_) +- Make SeleniumLibrary support one or more translations from same localisation project (`#1917`_) +- Support for Python version 3.13 + +Acknowledgements +================ + +We want to thank + +- `Markus Leben `_ for discovering, reporting, and fixing + the _find_by_data_locator issue (`#1924`_) +- `The Great Simo `_ and `Pavel `_ + for updating the requirements (`#1849`_) +- `iarmhi `_ for correcting an error the docs (`#1913`_) + +Full list of fixes and enhancements +=================================== + +.. list-table:: + :header-rows: 1 + + * - ID + - Type + - Priority + - Summary + * - `#1924`_ + - bug + - high + - Fix _find_by_data_locator + * - `#1917`_ + - enhancement + - high + - Make SeleniumLibrary support one or more translation from same localisation project + * - `#1849`_ + - --- + - medium + - Update the rerequirements + * - `#1913`_ + - bug + - low + - Remove unneeded 'send_' in docs + * - `#1925`_ + - --- + - --- + - Latest Versions Oct2024 + +Altogether 5 issues. View on the `issue tracker `__. + +.. _#1924: https://github.com/robotframework/SeleniumLibrary/issues/1924 +.. _#1917: https://github.com/robotframework/SeleniumLibrary/issues/1917 +.. _#1849: https://github.com/robotframework/SeleniumLibrary/issues/1849 +.. _#1913: https://github.com/robotframework/SeleniumLibrary/issues/1913 +.. _#1925: https://github.com/robotframework/SeleniumLibrary/issues/1925 diff --git a/docs/SeleniumLibrary-6.7.0rc1.html b/docs/SeleniumLibrary-6.7.0rc1.html new file mode 100644 index 000000000..476977bda --- /dev/null +++ b/docs/SeleniumLibrary-6.7.0rc1.html @@ -0,0 +1,1873 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +
+

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.
  • +
+
+ + + + + + + + + + + + + + + + diff --git a/docs/SeleniumLibrary-6.7.0rc1.rst b/docs/SeleniumLibrary-6.7.0rc1.rst new file mode 100644 index 000000000..cfc0c0665 --- /dev/null +++ b/docs/SeleniumLibrary-6.7.0rc1.rst @@ -0,0 +1,103 @@ +======================== +SeleniumLibrary 6.7.0rc1 +======================== + + +.. default-role:: code + + +SeleniumLibrary_ is a web testing library for `Robot Framework`_ that utilizes +the Selenium_ tool internally. SeleniumLibrary 6.7.0rc1 is a new release with +some minor enhancements and bug fixes. + +All issues targeted for SeleniumLibrary v6.7.0 can be found +from the `issue tracker`_. + +If you have pip_ installed, just run + +:: + + pip install --pre --upgrade robotframework-seleniumlibrary + +to install the latest available release or use + +:: + + pip install robotframework-seleniumlibrary==6.7.0rc1 + +to install exactly this version. Alternatively you can download the source +distribution from PyPI_ and install it manually. + +SeleniumLibrary 6.7.0rc1 was released on Sunday December 29, 2024. 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.0 + + +.. contents:: + :depth: 2 + :local: + +Most important enhancements +=========================== + +- Fixed _find_by_data_locator when more than one colon was within the locator. If one + used the data strategy and the locator had additional colon in it the locator parser + would incorrectly parse the locator. This has been fixed in this release. (`#1924`_) +- Make SeleniumLibrary support one or more translations from same localisation project (`#1917`_) + +Acknowledgements +================ + +We want to thank + +- `Markus Leben `_ for discovering, reporting, and fixing + the _find_by_data_locator issue (`#1924`_) +- `The Great Simo `_ and `Pavel `_ + for updating the requirements (`#1849`_) +- `iarmhi `_ for correcting an error the docs (`#1913`_) + +Full list of fixes and enhancements +=================================== + +.. list-table:: + :header-rows: 1 + + * - ID + - Type + - Priority + - Summary + * - `#1924`_ + - bug + - high + - Fix _find_by_data_locator + * - `#1917`_ + - enhancement + - high + - Make SeleniumLibrary support one or more tranlsation from same localisation project + * - `#1849`_ + - --- + - medium + - Update the rerequirements + * - `#1913`_ + - bug + - low + - Remove unneeded 'send_' in docs + * - `#1925`_ + - --- + - --- + - Latest Versions Oct2024 + +Altogether 5 issues. View on the `issue tracker `__. + +.. _#1924: https://github.com/robotframework/SeleniumLibrary/issues/1924 +.. _#1917: https://github.com/robotframework/SeleniumLibrary/issues/1917 +.. _#1849: https://github.com/robotframework/SeleniumLibrary/issues/1849 +.. _#1913: https://github.com/robotframework/SeleniumLibrary/issues/1913 +.. _#1925: https://github.com/robotframework/SeleniumLibrary/issues/1925 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 diff --git a/docs/SeleniumLibrary-6.8.0.rst b/docs/SeleniumLibrary-6.8.0.rst new file mode 100644 index 000000000..68ee911f9 --- /dev/null +++ b/docs/SeleniumLibrary-6.8.0.rst @@ -0,0 +1,111 @@ +===================== +SeleniumLibrary 6.8.0 +===================== + + +.. default-role:: code + + +SeleniumLibrary_ is a web testing library for `Robot Framework`_ that utilizes +the Selenium_ tool internally. SeleniumLibrary 6.8.0 is a new release with +screenshot enhancements and minor bug and documentation fixes. This version +adds support for Python 3.14. + +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.8.0 + +to install exactly this version. Alternatively you can download the source +distribution from PyPI_ and install it manually. + +SeleniumLibrary 6.8.0 was released on Saturday October 4, 2025. SeleniumLibrary supports +Python 3.8 through 3.14, Selenium 4.28.1 through 4.34.2 and +Robot Framework 6.1.1 and 7.3.2. + +.. _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.8.0 +.. _Selenium Documentation: https://www.selenium.dev/documentation/selenium_manager/ + +.. contents:: + :depth: 2 + :local: + +Most important enhancements +=========================== + +- Option to return embed screenshot while using Capture Page Screenshot (`#1923`_). + One is now given the additional option to return the screenshot as base64 string to be used + elsewhere in the log html. If the screenshot root directory is specified as `BASE64` + then the screenshot string is returned. See the `Capture Page Screenshot` keyword doc + for more information and example to place returned image in the log file. +- Update README.rst 'Browser drivers' section (`#1938`_) + With the (long past) addition of Selenium Manager within the selenium package, the documentation + on browser drivers was outdated and incorrect. This works to correct that. For more + information about Selenium Manager and handling browsers and drivers see the + `Selenium Documentation`_ on the topic. +- Loosen restriction on the upper Python version allowing Python 3.14 (`#1949`_) + +Acknowledgements +================ + +I want to thank the following people for helping getting out this release .. + +- `Hrutvik Jagtap `_ and `Shiva Prasad Adirala `_ + for contributing to the base64 image screenshot functionality (`#1923`_) +- `Corey Goldberg `_ for updating the README concerning Selenium Manager (`#1938`_) +- `DetachHead `_ for reporting the deprecated `is_string` error messages (`#1940`_) +- `Rudolf `_ for pushing for the addition of Python 3.14 (`#1949`_) + +I also want to thank `Yuri Verweij `_, `Lassi Heikkinen `_, +and `Tatu Aalto `_ for their ongoing contributions and support. + +Full list of fixes and enhancements +=================================== + +.. list-table:: + :header-rows: 1 + + * - ID + - Type + - Priority + - Summary + * - `#1923`_ + - enhancement + - high + - Return base64 image in case of EMBED + * - `#1938`_ + - enhancement + - high + - Update README.rst 'Browser drivers' section + * - `#1940`_ + - enhancement + - high + - remove usages of deprecated `is_string` + * - `#1949`_ + - enhancement + - high + - Python 3.14 + * - `#1939`_ + - --- + - --- + - Return screenshot as base64 string and embed into log + +Altogether 5 issues. View on the `issue tracker `__. + +.. _#1923: https://github.com/robotframework/SeleniumLibrary/issues/1923 +.. _#1938: https://github.com/robotframework/SeleniumLibrary/issues/1938 +.. _#1940: https://github.com/robotframework/SeleniumLibrary/issues/1940 +.. _#1949: https://github.com/robotframework/SeleniumLibrary/issues/1949 +.. _#1939: https://github.com/robotframework/SeleniumLibrary/issues/1939 diff --git a/docs/SeleniumLibrary-6.9.0.rst b/docs/SeleniumLibrary-6.9.0.rst new file mode 100644 index 000000000..b395ca42b --- /dev/null +++ b/docs/SeleniumLibrary-6.9.0.rst @@ -0,0 +1,199 @@ +===================== +SeleniumLibrary 6.9.0 +===================== + + +.. default-role:: code + + +SeleniumLibrary_ is a web testing library for `Robot Framework`_ that utilizes +the Selenium_ tool internally. SeleniumLibrary 6.9.0 is a new release with several +enhancements and bug fixes. A couple new keywords, for drag and drop as well as +getting css properties, have been added. Secret type support has be added. An issue +with using lists with chaining locators has been fixed. Several of the minim required +versions have been updated. More information about all the bug fixes and enhancements +can be found in these release notes. + +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.9.0 + +to install exactly this version. Alternatively you can download the source +distribution from PyPI_ and install it manually. + +SeleniumLibrary 6.9.0 was released on Sunday May 17, 2026. SeleniumLibrary supports +Python 3.10 through 3.14, Selenium 4.29.0 through 4.44.0 and +Robot Framework 6.1.1 and 7.4.2. + +.. _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.9.0 + + +.. contents:: + :depth: 2 + :local: + +Most important enhancements +=========================== + +- "Open Browser" keyword documentation has broken links which were fixed (`#1976`_) +- Chaining locators with lists does not work with Robot Framework 6.1 or above (`#1962`_) + There was an issue with the types which prevented using chained locators as lists. This + has been resolved in this release. +- Fix deprecation warnings and improve logging in tests (`#1974`_) +- Added "Drag And Drop Across Frames" keyword for cross-frame drag and drop support (`#1953`_) + Note the still remains an issue with Firefox related to drag and drop. This change does + note resolve the issue within gecko driver and Firefox. +- Input Password does not accept Secret type (`#1966`_) + We have added support for the Secret Type into this release. +- Added "Get CSS Property Value" keyword to retrieve computed CSS values (`#1969`_) +- Selenium manager fails to download firefox/edge with lower versions of selenium (`#1986`_) + +There were also several changes that are focused on internal processes and operations +- Migrate lint/format tooling to Ruff, update CI matrix, and stabilize cross-platform/firefox tests (`#1978`_) +- Update cookie validation regex in Get Cookies test (`#1973`_) +- Added new GitHub Actions workflow and performed yearly update on cookie test suite (`#1955`_) + +Acknowledgements +================ + +I want to give a large shout out to [Yuri](https://github.com/yuriverweij) who had a large hand in getting +this release out the door including resolving issues, reviewing code changes, and fixing up our processes +and tooling, amongst all the other contributions he made towards this release. Some of these include + +- Update cookie validation regex in Get Cookies test (`#1973`_) +- Fix deprecation warnings and improve logging in tests (`#1974`_) +- Review restriction on running ApprovalTests under Windows (`#1884`_) +- Migrate lint/format tooling to Ruff, update CI matrix, and stabilize cross-platform/firefox tests (`#1978`_) + +Yuri along with [Tatu](https://github.com/aaltat) brought in the Secret type into this release. And thank you +to [petobarki](https://github.com/petobarki) for reporting and asking for this feature/support. + +- Input Password does not accept Secret type (`#1966`_) + +I also want to thank a couple of first time contributors. Let me thank [Vamsi](https://github.com/b-vamsipunnam) for a +couple new keywords + +- Added "Drag And Drop Across Frames" keyword for cross-frame drag and drop support (`#1953`_) +- Added "Get CSS Property Value" keyword to retrieve computed CSS values (`#1969`_) + +And I also want to recognize and thank [Jaroslav Cerman](https://github.com/antivirak) for fixing a type error in deprecation message (`#1947`_). +Great job Jaroslav and Vamsi on these first time contributions! + +I also want to thank +- [jjaakkola-atostek](https://github.com/jjaakkola-atostek) for reporting that chaining locators with lists does not work with Robot Framework 6.1 or above (`#1962`_) +- [Slava Semushin](https://github.com/php-coder) for reporting the "Open Browser" keyword documentation has broken links (`#1976`_) + +And I once again want to recognize and give my thanks to the ongoing support by Tatu Aalto. + + +Full list of fixes and enhancements +=================================== + +.. list-table:: + :header-rows: 1 + + * - ID + - Type + - Priority + - Summary + * - `#1962`_ + - bug + - critical + - Chaining locators with lists does not work with Robot Framework 6.1 or above + * - `#1973`_ + - bug + - high + - Update cookie validation regex in Get Cookies test + * - `#1953`_ + - enhancement + - high + - Add "Drag And Drop Across Frames" keyword for cross-frame drag and drop support + * - `#1955`_ + - enhancement + - high + - Added new GitHub Actions workflow and performed yearly update on cookie test suite + * - `#1966`_ + - enhancement + - high + - Input Password does not accept Secret type + * - `#1969`_ + - enhancement + - high + - Add "Get CSS Property Value" keyword to retrieve computed CSS values + * - `#1974`_ + - enhancement + - high + - Fix deprecation warnings and improve logging in tests + * - `#1978`_ + - enhancement + - high + - Migrate lint/format tooling to Ruff, update CI matrix, and stabilize cross-platform/firefox tests + * - `#1986`_ + - enhancement + - high + - Selenium manager fails to download firefox/edge with lower versions of selenium + * - `#1947`_ + - bug + - medium + - Fix typo in deprecation message + * - `#1976`_ + - bug + - medium + - "Open Browser" keyword documentation has broken links + * - `#1921`_ + - enhancement + - medium + - Use Dependabot to update deps automatically + * - `#1884`_ + - --- + - medium + - Review restriction on running ApprovalTests under Windows + * - `#1967`_ + - --- + - medium + - Bump actions/upload-artifact from 4 to 7 + * - `#1963`_ + - bug + - --- + - `#1962`_ fix cascading locators + * - `#1956`_ + - --- + - --- + - Dependabot + * - `#1971`_ + - --- + - --- + - Fixed doc formating issue within xpath examples + +Altogether 17 issues. View on the `issue tracker `__. + +.. _#1962: https://github.com/robotframework/SeleniumLibrary/issues/1962 +.. _#1973: https://github.com/robotframework/SeleniumLibrary/issues/1973 +.. _#1953: https://github.com/robotframework/SeleniumLibrary/issues/1953 +.. _#1955: https://github.com/robotframework/SeleniumLibrary/issues/1955 +.. _#1966: https://github.com/robotframework/SeleniumLibrary/issues/1966 +.. _#1969: https://github.com/robotframework/SeleniumLibrary/issues/1969 +.. _#1974: https://github.com/robotframework/SeleniumLibrary/issues/1974 +.. _#1978: https://github.com/robotframework/SeleniumLibrary/issues/1978 +.. _#1986: https://github.com/robotframework/SeleniumLibrary/issues/1986 +.. _#1947: https://github.com/robotframework/SeleniumLibrary/issues/1947 +.. _#1976: https://github.com/robotframework/SeleniumLibrary/issues/1976 +.. _#1921: https://github.com/robotframework/SeleniumLibrary/issues/1921 +.. _#1884: https://github.com/robotframework/SeleniumLibrary/issues/1884 +.. _#1967: https://github.com/robotframework/SeleniumLibrary/issues/1967 +.. _#1963: https://github.com/robotframework/SeleniumLibrary/issues/1963 +.. _#1956: https://github.com/robotframework/SeleniumLibrary/issues/1956 +.. _#1971: https://github.com/robotframework/SeleniumLibrary/issues/1971 diff --git a/docs/SeleniumLibrary.html b/docs/SeleniumLibrary.html index cf4ebe698..288957d5a 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}} + + + + + diff --git a/docs/index.html b/docs/index.html index d6adb5082..15053c378 100644 --- a/docs/index.html +++ b/docs/index.html @@ -29,7 +29,7 @@

Introduction<

SeleniumLibrary is a web testing library for Robot Framework that utilizes the Selenium tool internally. The project is hosted on GitHub and downloads can be found from PyPI.

-

SeleniumLibrary currently works with Selenium 4. It supports Python 3.8 through 3.11. +

SeleniumLibrary currently works with Selenium 4. It supports Python 3.10 through 3.13. In addition to the normal Python interpreter, it works also with PyPy.

SeleniumLibrary is based on the "old SeleniumLibrary" that was forked to @@ -59,8 +59,7 @@

Installation<

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 latest source from the master branch, use this command:

@@ -74,27 +73,8 @@

Installation<

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:

-
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.

Usage

diff --git a/pyproject.toml b/pyproject.toml index dd1b9775e..a8a12f9c3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,20 +1,52 @@ -[tool.black] -target-version = ['py36'] -exclude = ''' -/( - | \.git - | \.venv - | _build - | dist - | generated - | src/SeleniumLibrary/__init__\.pyi -)/ -''' +[tool.ruff] +target-version = "py310" +line-length = 88 +exclude = [ + "src/SeleniumLibrary/__init__.pyi", +] + +[tool.ruff.lint] +select = [ + "E", + "F", + "W", + "C90", + "I", + "N", + "B", + "PYI", + "PL", + "UP", + "A", + "C4", + "DTZ", + "ISC", + "ICN", + "INP", + "PIE", + "T20", + "PYI", + "PT", + "RSE", + "RET", + "SIM", + "RUF" +] +ignore = [ + "E501", # line too long + "N803", # argument name should be lowercase + "N812", # lowercase imported as non lowercase + "N999", # Invalid module name: 'SeleniumLibrary' + "PLR0913", # too many arguments + "PLR2004", # Magic value used in comparison + "DTZ006", # No timezone specified + "PTH", # Use Path instead of os.path -> maybe soon + "N818", # exception naming convention + "PIE790", # Unnecessary placeholder (pass or ...) +] -[tool.isort] -profile = "black" -src_paths="." -skip_glob = ["src/SeleniumLibrary/__init__.pyi"] +[tool.ruff.format] +quote-style = "double" [tool.pytest.ini_options] diff --git a/requirements-dev.txt b/requirements-dev.txt index 45d9b51e5..71bc8bb10 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,25 +1,29 @@ +# Last reviewed: 2026-04-09 +# Dev and build tools are pinned exactly (==) to ensure a fully +# reproducible development environment. Update deliberately and review +# changelogs before bumping versions. + # Requirements needed for SeleniumLibrary development but not by end users. # Creating releases has its own requirements listed in requirements-build.txt. -invoke >= 1.4.1 -mockito >= 1.2.2 -robotstatuschecker >= 2.0.3 -approvaltests == 8.4.1 -empty_files >= 0.0.3 -pytest >= 6.0.2 -pytest-mockito >= 0.0.4 -pytest-approvaltests >= 0.2.0 -requests >= 2.24.0 -robotframework-pabot >= 1.10.0 -black >= 20.8b1 -flake8 >= 3.9.0 +invoke == 2.2.0 +mockito == 1.4.0 +robotstatuschecker == 4.1.1 +approvaltests == 17.4.3 +empty_files == 0.0.9 +pytest == 9.0.3 +pytest-mockito == 0.0.4 +pytest-approvaltests == 0.2.4 +requests == 2.33.1 +robotframework-pabot == 5.2.2 +ruff == 0.15.12 # Requirements needed when generating releases. See BUILD.rst for details. -rellu >= 0.6 -twine >= 3.2.0 -wheel >= 0.35.1 -docutils >= 0.14 -pygments -beautifulsoup4 >= 4.9.3 +rellu == 0.7 +twine == 6.2.0 +wheel == 0.46.3 +docutils == 0.20.1 +pygments == 2.20.0 +beautifulsoup4 == 4.12.2 # Include normal dependencies from requirements.txt. Makes it possible to use # requirements-dev.txt as a single requirement file in PyCharm and other IDEs. diff --git a/requirements.txt b/requirements.txt index 616d9719e..e15c78e94 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -selenium >= 4.3.0 +selenium >= 4.25.0 robotframework >= 4.1.3 robotframework-pythonlibcore >= 4.4.1 -click >= 8.1.7 +click >= 8.0 diff --git a/setup.py b/setup.py index 8ddead98f..9652afb5d 100755 --- a/setup.py +++ b/setup.py @@ -13,10 +13,11 @@ Operating System :: OS Independent Programming Language :: Python Programming Language :: Python :: 3 -Programming Language :: Python :: 3.8 -Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 +Programming Language :: Python :: 3.12 +Programming Language :: Python :: 3.13 +Programming Language :: Python :: 3.14 Programming Language :: Python :: 3 :: Only Topic :: Software Development :: Testing Framework :: Robot Framework @@ -34,14 +35,14 @@ version = VERSION, description = 'Web testing library for Robot Framework', long_description = DESCRIPTION, - author = 'Ed Manlove, Yuri Verweij, Lisa Crispin', + author = 'Ed Manlove, Yuri Verweij', author_email = 'emanlove@verizon.net', url = 'https://github.com/robotframework/SeleniumLibrary', license = 'Apache License 2.0', keywords = 'robotframework testing testautomation selenium webdriver web', platforms = 'any', classifiers = CLASSIFIERS, - python_requires = '>=3.8, <3.12', + python_requires = '>=3.10', install_requires = REQUIREMENTS, package_dir = {'': 'src'}, packages = find_packages('src'), diff --git a/src/SeleniumLibrary/__init__.py b/src/SeleniumLibrary/__init__.py index 1b2618941..170b99385 100644 --- a/src/SeleniumLibrary/__init__.py +++ b/src/SeleniumLibrary/__init__.py @@ -13,20 +13,17 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from collections import namedtuple -from datetime import timedelta import importlib +import pkgutil +from datetime import timedelta from inspect import getdoc, isclass from pathlib import Path -import pkgutil -from typing import Optional, List, Union +from typing import NamedTuple from robot.api import logger from robot.errors import DataError from robot.libraries.BuiltIn import BuiltIn -from robot.utils import is_string from robot.utils.importer import Importer - from robotlibcore import DynamicCore from selenium.webdriver.remote.webdriver import WebDriver from selenium.webdriver.remote.webelement import WebElement @@ -50,12 +47,16 @@ WebDriverCache, WindowKeywords, ) -from SeleniumLibrary.keywords.screenshot import EMBED +from SeleniumLibrary.keywords.screenshot import BASE64, EMBED from SeleniumLibrary.locators import ElementFinder -from SeleniumLibrary.utils import LibraryListener, is_truthy, _convert_timeout, _convert_delay - +from SeleniumLibrary.utils import ( + LibraryListener, + _convert_delay, + _convert_timeout, + is_truthy, +) -__version__ = "6.5.0" +__version__ = "6.9.0" class SeleniumLibrary(DynamicCore): @@ -203,20 +204,20 @@ class SeleniumLibrary(DynamicCore): used to specify multiple locators. This is useful, is some part of locator would match as the locator separator but it should not. Or if there is need to existing WebElement as locator. - Although all locators support chaining, some locator strategies do not abey the chaining. This is because + Although all locators support chaining, some locator strategies do not obey the chaining. This is because some locator strategies use JavaScript to find elements and JavaScript is executed for the whole browser context and not for the element found be the previous locator. Chaining is supported by locator strategies which are based on Selenium API, like `xpath` or `css`, but example chaining is not supported by `sizzle` or `jquery Examples: - | `Click Element` | css:.bar >> xpath://a | # To find a link which is present after an element with class "bar" | + | `Click Element` | css:.bar >> xpath: //a | # To find a link which is present after an element with class "bar" | List examples: - | ${locator_list} = | `Create List` | css:div#div_id | xpath://*[text(), " >> "] | - | `Page Should Contain Element` | ${locator_list} | | | - | ${element} = | Get WebElement | xpath://*[text(), " >> "] | | - | ${locator_list} = | `Create List` | css:div#div_id | ${element} | - | `Page Should Contain Element` | ${locator_list} | | | + | ${locator_list} = | `Create List` | css:div#div_id | xpath: //*[text(), " >> "] | + | `Page Should Contain Element` | ${locator_list} | | | + | ${element} = | Get WebElement | xpath: //*[text(), " >> "] | | + | ${locator_list} = | `Create List` | css:div#div_id | ${element} | + | `Page Should Contain Element` | ${locator_list} | | | Chaining locators in new in SeleniumLibrary 5.0 @@ -238,7 +239,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 @@ -524,7 +525,7 @@ class SeleniumLibrary(DynamicCore): = EventFiringWebDriver = The SeleniumLibrary offers support for - [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.event_firing_webdriver.html#module-selenium.webdriver.support.event_firing_webdriver|EventFiringWebDriver]. + [https://www.selenium.dev/selenium/docs/api/py/selenium_webdriver_support/selenium.webdriver.support.event_firing_webdriver.html#module-selenium.webdriver.support.event_firing_webdriver|EventFiringWebDriver]. See the Selenium and SeleniumLibrary [https://github.com/robotframework/SeleniumLibrary/blob/master/docs/extending/extending.rst#EventFiringWebDriver|EventFiringWebDriver support] documentation for further details. @@ -598,12 +599,12 @@ def __init__( timeout=timedelta(seconds=5), implicit_wait=timedelta(seconds=0), run_on_failure="Capture Page Screenshot", - screenshot_root_directory: Optional[str] = None, - plugins: Optional[str] = None, - event_firing_webdriver: Optional[str] = None, + screenshot_root_directory: str | None = None, + plugins: str | None = None, + event_firing_webdriver: str | None = None, page_load_timeout=timedelta(minutes=5), action_chain_delay=timedelta(seconds=0.25), - language: Optional[str] = None, + language: str | None = None, ): """SeleniumLibrary can be imported with several optional arguments. @@ -614,14 +615,14 @@ 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. - ``event_firing_webdriver``: Class for wrapping Selenium with - [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.event_firing_webdriver.html#module-selenium.webdriver.support.event_firing_webdriver|EventFiringWebDriver] + [https://www.selenium.dev/selenium/docs/api/py/selenium_webdriver_support/selenium.webdriver.support.event_firing_webdriver.html#module-selenium.webdriver.support.event_firing_webdriver|EventFiringWebDriver] - ``page_load_timeout``: Default value to wait for page load to complete until a timeout exception is raised. - ``action_chain_delay``: @@ -690,10 +691,13 @@ def get_keyword_documentation(self, name: str) -> str: return self._get_intro_documentation() return DynamicCore.get_keyword_documentation(self, name) + class Doc(NamedTuple): + doc: str + name: str + def _parse_plugin_doc(self): - Doc = namedtuple("Doc", "doc, name") for plugin in self._plugins: - yield Doc( + yield self.Doc( doc=getdoc(plugin) or "No plugin documentation found.", name=plugin.__class__.__name__, ) @@ -752,7 +756,7 @@ def driver(self) -> WebDriver: return self._drivers.current def find_element( - self, locator: str, parent: Optional[WebElement] = None + self, locator: str, parent: WebElement | None = None ) -> WebElement: """Find element matching `locator`. @@ -770,7 +774,7 @@ def find_element( def find_elements( self, locator: str, parent: WebElement = None - ) -> List[WebElement]: + ) -> list[WebElement]: """Find all elements matching `locator`. :param locator: Locator to use when searching the element. @@ -808,7 +812,7 @@ def _parse_listener(self, event_firing_webdriver): listener_module = self._string_to_modules(event_firing_webdriver) listener_count = len(listener_module) if listener_count > 1: - message = f"Is is possible import only one listener but there was {listener_count} listeners." + message = f"It is possible to import only one listener but there were {listener_count} listeners." raise ValueError(message) listener_module = listener_module[0] importer = Importer("test library") @@ -818,12 +822,15 @@ def _parse_listener(self, event_firing_webdriver): raise DataError(message) return listener + class Module(NamedTuple): + module: str + args: list + kw_args: dict + def _string_to_modules(self, modules): - Module = namedtuple("Module", "module, args, kw_args") parsed_modules = [] for module in modules.split(","): - module = module.strip() - module_and_args = module.split(";") + module_and_args = module.strip().split(";") module_name = module_and_args.pop(0) kw_args = {} args = [] @@ -833,8 +840,9 @@ def _string_to_modules(self, modules): kw_args[key] = value else: args.append(argument) - module = Module(module=module_name, args=args, kw_args=kw_args) - parsed_modules.append(module) + parsed_modules.append( + self.Module(module=module_name, args=args, kw_args=kw_args) + ) return parsed_modules def _store_plugin_keywords(self, plugin): @@ -843,12 +851,14 @@ 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: + self.screenshot_root_directory = BASE64 @staticmethod - def _get_translation(language: Union[str, None]) -> Union[Path, None]: + def _get_translation(language: str | None) -> Path | None: if not language: return None discovered_plugins = { @@ -856,13 +866,20 @@ def _get_translation(language: Union[str, None]) -> Union[Path, None]: for _, name, _ in pkgutil.iter_modules() if name.startswith("robotframework_seleniumlibrary_translation") } + lang = language.lower() for plugin in discovered_plugins.values(): try: data = plugin.get_language() except AttributeError: continue - if data.get("language", "").lower() == language.lower() and data.get( - "path" + if ( + isinstance(data, dict) + and data.get("language", "").lower() == lang + and data.get("path") ): return Path(data.get("path")).absolute() + if isinstance(data, list): + for item in data: + if item.get("language", "").lower() == lang and item.get("path"): + return Path(item.get("path")).absolute() return None diff --git a/src/SeleniumLibrary/__init__.pyi b/src/SeleniumLibrary/__init__.pyi index d17efdd1c..45998d55a 100644 --- a/src/SeleniumLibrary/__init__.pyi +++ b/src/SeleniumLibrary/__init__.pyi @@ -107,7 +107,7 @@ class SeleniumLibrary: def mouse_out(self, locator: Union): ... def mouse_over(self, locator: Union): ... def mouse_up(self, locator: Union): ... - def open_browser(self, url: Optional[Optional] = None, browser: str = 'firefox', alias: Optional[Optional] = None, remote_url: Union = False, desired_capabilities: Optional[Union] = None, ff_profile_dir: Optional[Union] = None, options: Optional[Optional] = None, service_log_path: Optional[Optional] = None, executable_path: Optional[Optional] = None, service: Optional[Optional] = None): ... + def open_browser(self, url: Optional[Optional] = None, browser: str = 'firefox', alias: Optional[Optional] = None, remote_url: Union = False, desired_capabilities: Optional[Union] = None, ff_profile_dir: Optional[Union] = None, options: Optional[Any] = None, service_log_path: Optional[Optional] = None, executable_path: Optional[Optional] = None, service: Optional[Any] = None): ... def open_context_menu(self, locator: Union): ... def page_should_contain(self, text: str, loglevel: str = 'TRACE'): ... def page_should_contain_button(self, locator: Union, message: Optional[Optional] = None, loglevel: str = 'TRACE'): ... diff --git a/src/SeleniumLibrary/base/context.py b/src/SeleniumLibrary/base/context.py index e55aecdc4..d8fbddffc 100644 --- a/src/SeleniumLibrary/base/context.py +++ b/src/SeleniumLibrary/base/context.py @@ -13,7 +13,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Any, Optional, List +from typing import Any from selenium.webdriver.remote.webelement import WebElement @@ -56,7 +56,7 @@ def event_firing_webdriver(self, event_firing_webdriver: Any): def find_element( self, locator: str, - tag: Optional[str] = None, + tag: str | None = None, required: bool = True, parent: WebElement = None, ) -> WebElement: @@ -82,8 +82,8 @@ def find_element( return self.element_finder.find(locator, tag, True, required, parent) def find_elements( - self, locator: str, tag: Optional[str] = None, parent: WebElement = None - ) -> List[WebElement]: + self, locator: str, tag: str | None = None, parent: WebElement = None + ) -> list[WebElement]: """Find all elements matching `locator`. :param locator: Locator to use when searching the element. @@ -103,7 +103,7 @@ def is_text_present(self, text: str): locator = f"xpath://*[contains(., {escape_xpath_value(text)})]" return self.find_element(locator, required=False) is not None - def is_element_enabled(self, locator: str, tag: Optional[str] = None) -> bool: + def is_element_enabled(self, locator: str, tag: str | None = None) -> bool: element = self.find_element(locator, tag) return element.is_enabled() and element.get_attribute("readonly") is None diff --git a/src/SeleniumLibrary/base/librarycomponent.py b/src/SeleniumLibrary/base/librarycomponent.py index d7174f4de..ae24d57c8 100644 --- a/src/SeleniumLibrary/base/librarycomponent.py +++ b/src/SeleniumLibrary/base/librarycomponent.py @@ -16,14 +16,14 @@ import os from datetime import timedelta -from typing import Optional, Union -from SeleniumLibrary.utils import is_noney from robot.api import logger from robot.libraries.BuiltIn import BuiltIn, RobotNotRunningError -from .context import ContextAware +from SeleniumLibrary.utils import is_noney + from ..utils import _convert_timeout +from .context import ContextAware class LibraryComponent(ContextAware): @@ -46,8 +46,8 @@ def log_source(self, loglevel: str = "INFO"): def assert_page_contains( self, locator: str, - tag: Optional[str] = None, - message: Optional[str] = None, + tag: str | None = None, + message: str | None = None, loglevel: str = "TRACE", ): tag_message = tag or "element" @@ -63,8 +63,8 @@ def assert_page_contains( def assert_page_not_contains( self, locator: str, - tag: Optional[str] = None, - message: Optional[str] = None, + tag: str | None = None, + message: str | None = None, loglevel: str = "TRACE", ): tag_message = tag or "element" @@ -75,7 +75,7 @@ def assert_page_not_contains( raise AssertionError(message) logger.info(f"Current page does not contain {tag_message} '{locator}'.") - def get_timeout(self, timeout: Union[str, int, timedelta, None] = None) -> float: + def get_timeout(self, timeout: str | int | timedelta | None = None) -> float: if timeout is None: return self.ctx.timeout return _convert_timeout(timeout) diff --git a/src/SeleniumLibrary/entry/__main__.py b/src/SeleniumLibrary/entry/__main__.py index 47e049233..d1c494bcd 100644 --- a/src/SeleniumLibrary/entry/__main__.py +++ b/src/SeleniumLibrary/entry/__main__.py @@ -16,13 +16,12 @@ import json from pathlib import Path -from typing import Optional + import click from .get_versions import get_version from .translation import compare_translation, get_library_translation - CONTEXT_SETTINGS = {"help_option_names": ["-h", "--help"]} VERSION = get_version() @@ -63,7 +62,7 @@ def cli(): ) def translation( filename: Path, - plugins: Optional[str] = None, + plugins: str | None = None, compare: bool = False, ): """Default translation file from library keywords. @@ -88,17 +87,17 @@ def translation( lib_translation = get_library_translation(plugins) if compare: if table := compare_translation(filename, lib_translation): - print( + click.echo( "Found differences between translation and library, see below for details." ) for line in table: - print(line) + click.echo(line) else: - print("Translation is valid, no updated needed.") + click.echo("Translation is valid, no updated needed.") else: with filename.open("w") as file: json.dump(lib_translation, file, indent=4) - print(f"Translation file created in {filename.absolute()}") + click.echo(f"Translation file created in {filename.absolute()}") if __name__ == "__main__": diff --git a/src/SeleniumLibrary/entry/get_versions.py b/src/SeleniumLibrary/entry/get_versions.py index 51e68da7a..4ad9a7ce5 100644 --- a/src/SeleniumLibrary/entry/get_versions.py +++ b/src/SeleniumLibrary/entry/get_versions.py @@ -14,10 +14,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -from pathlib import Path import re import subprocess import sys +from pathlib import Path from selenium import __version__ diff --git a/src/SeleniumLibrary/entry/translation.py b/src/SeleniumLibrary/entry/translation.py index 3c98dddaa..0cfdb0e7b 100644 --- a/src/SeleniumLibrary/entry/translation.py +++ b/src/SeleniumLibrary/entry/translation.py @@ -18,7 +18,6 @@ import inspect import json from pathlib import Path -from typing import List, Optional KEYWORD_NAME = "Keyword name" DOC_CHANGED = "Documentation update needed" @@ -33,8 +32,8 @@ ) -def get_library_translation(plugins: Optional[str] = None) -> dict: - from SeleniumLibrary import SeleniumLibrary +def get_library_translation(plugins: str | None = None) -> dict: + from SeleniumLibrary import SeleniumLibrary # noqa: PLC0415 selib = SeleniumLibrary(plugins=plugins) translation = {} @@ -65,7 +64,7 @@ def _max_kw_name_length(project_translation: dict) -> int: return max_lenght -def _get_heading(max_kw_length: int) -> List[str]: +def _get_heading(max_kw_length: int) -> list[str]: heading = f"| {KEYWORD_NAME} " next_line = f"| {'-' * len(KEYWORD_NAME)}" if (padding := max_kw_length - len(KEYWORD_NAME)) > 0: diff --git a/src/SeleniumLibrary/errors.py b/src/SeleniumLibrary/errors.py index 5dd4310d1..636a13a87 100644 --- a/src/SeleniumLibrary/errors.py +++ b/src/SeleniumLibrary/errors.py @@ -40,4 +40,4 @@ class PluginError(SeleniumLibraryException): class UnkownExpectedCondition(SeleniumLibraryException): - pass \ No newline at end of file + pass diff --git a/src/SeleniumLibrary/keywords/alert.py b/src/SeleniumLibrary/keywords/alert.py index 406946d0f..9484360e1 100644 --- a/src/SeleniumLibrary/keywords/alert.py +++ b/src/SeleniumLibrary/keywords/alert.py @@ -14,13 +14,12 @@ # See the License for the specific language governing permissions and # limitations under the License. from datetime import timedelta -from typing import Optional from selenium.common.exceptions import TimeoutException, WebDriverException from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait -from SeleniumLibrary.base import keyword, LibraryComponent +from SeleniumLibrary.base import LibraryComponent, keyword from SeleniumLibrary.utils import secs_to_timestr @@ -32,7 +31,7 @@ class AlertKeywords(LibraryComponent): @keyword def input_text_into_alert( - self, text: str, action: str = ACCEPT, timeout: Optional[timedelta] = None + self, text: str, action: str = ACCEPT, timeout: timedelta | None = None ): """Types the given ``text`` into an input field in an alert. @@ -53,7 +52,7 @@ def alert_should_be_present( self, text: str = "", action: str = ACCEPT, - timeout: Optional[timedelta] = None, + timeout: timedelta | None = None, ): """Verifies that an alert is present and by default, accepts it. @@ -72,12 +71,12 @@ def alert_should_be_present( message = self.handle_alert(action, timeout) if text and text != message: raise AssertionError( - f"Alert message should have been '{text}' but it " f"was '{message}'." + f"Alert message should have been '{text}' but it was '{message}'." ) @keyword def alert_should_not_be_present( - self, action: str = ACCEPT, timeout: Optional[timedelta] = None + self, action: str = ACCEPT, timeout: timedelta | None = None ): """Verifies that no alert is present. @@ -101,7 +100,7 @@ def alert_should_not_be_present( raise AssertionError(f"Alert with message '{text}' present.") @keyword - def handle_alert(self, action: str = ACCEPT, timeout: Optional[timedelta] = None): + def handle_alert(self, action: str = ACCEPT, timeout: timedelta | None = None): """Handles the current alert and returns its message. By default, the alert is accepted, but this can be controlled @@ -146,7 +145,11 @@ def _wait_alert(self, timeout=None): wait = WebDriverWait(self.driver, timeout) try: return wait.until(EC.alert_is_present()) - except TimeoutException: - raise AssertionError(f"Alert not found in {secs_to_timestr(timeout)}.") + except TimeoutException as original_exception: + raise AssertionError( + f"Alert not found in {secs_to_timestr(timeout)}." + ) from original_exception except WebDriverException as err: - raise AssertionError(f"An exception occurred waiting for alert: {err}") + raise AssertionError( + f"An exception occurred waiting for alert: {err}" + ) from err diff --git a/src/SeleniumLibrary/keywords/browsermanagement.py b/src/SeleniumLibrary/keywords/browsermanagement.py index c8114d484..98972762e 100644 --- a/src/SeleniumLibrary/keywords/browsermanagement.py +++ b/src/SeleniumLibrary/keywords/browsermanagement.py @@ -17,15 +17,20 @@ import time import types from datetime import timedelta -from typing import Optional, Union, Any, List +from typing import Any from selenium import webdriver from selenium.webdriver import FirefoxProfile from selenium.webdriver.support.event_firing_webdriver import EventFiringWebDriver -from SeleniumLibrary.base import keyword, LibraryComponent +from SeleniumLibrary.base import LibraryComponent, keyword from SeleniumLibrary.locators import WindowManager -from SeleniumLibrary.utils import timestr_to_secs, secs_to_timestr, _convert_timeout, _convert_delay +from SeleniumLibrary.utils import ( + _convert_delay, + _convert_timeout, + secs_to_timestr, + timestr_to_secs, +) from .webdrivertools import WebDriverCreator @@ -59,15 +64,15 @@ def close_browser(self): @keyword def open_browser( self, - url: Optional[str] = None, + url: str | None = None, browser: str = "firefox", - alias: Optional[str] = None, - remote_url: Union[bool, str] = False, - desired_capabilities: Union[dict, None, str] = None, - ff_profile_dir: Union[FirefoxProfile, str, None] = None, + alias: str | None = None, + remote_url: bool | str = False, + desired_capabilities: dict | None | str = None, + ff_profile_dir: FirefoxProfile | str | None = None, options: Any = None, - service_log_path: Optional[str] = None, - executable_path: Optional[str] = None, + service_log_path: str | None = None, + executable_path: str | None = None, service: Any = None, ) -> str: """Opens a new browser instance to the optional ``url``. @@ -133,7 +138,7 @@ def open_browser( Optional ``ff_profile_dir`` is the path to the Firefox profile directory if you wish to overwrite the default profile Selenium uses. The ``ff_profile_dir`` can also be an instance of the - [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_firefox/selenium.webdriver.firefox.firefox_profile.html|selenium.webdriver.FirefoxProfile] + [https://www.selenium.dev/selenium/docs/api/py/selenium_webdriver_firefox/selenium.webdriver.firefox.firefox_profile.html#module-selenium.webdriver.firefox.firefox_profile|selenium.webdriver.firefox.firefox_profile] . As a third option, it is possible to use `FirefoxProfile` methods and attributes to define the profile using methods and attributes in the same way as with ``options`` argument. Example: It is possible @@ -149,9 +154,9 @@ def open_browser( Optional ``options`` argument allows defining browser specific Selenium options. Example for Chrome, the ``options`` argument allows defining the following - [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_chrome/selenium.webdriver.chrome.options.html#selenium.webdriver.chrome.options.Options|methods and attributes] + [https://www.selenium.dev/selenium/docs/api/py/selenium_webdriver_chrome/selenium.webdriver.chrome.options.html#selenium.webdriver.chrome.options.Options|methods and attributes] and for Firefox these - [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_firefox/selenium.webdriver.firefox.options.html?highlight=firefox#selenium.webdriver.firefox.options.Options|methods and attributes] + [https://www.selenium.dev/selenium/docs/api/py/selenium_webdriver_firefox/selenium.webdriver.firefox.options.html#selenium.webdriver.firefox.options.Options|methods and attributes] are available. Selenium options are also supported, when ``remote_url`` argument is used. @@ -163,7 +168,7 @@ def open_browser( methods or attributes. Example when using - [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_chrome/selenium.webdriver.chrome.options.html#selenium.webdriver.chrome.options.Options|Chrome options] + [https://www.selenium.dev/selenium/docs/api/py/selenium_webdriver_chrome/selenium.webdriver.chrome.options.html#selenium.webdriver.chrome.options.Options|Chrome options] method: | `Open Browser` | http://example.com | Chrome | options=add_argument("--disable-popup-blocking"); add_argument("--ignore-certificate-errors") | # Sting format. | | `Open Browser` | None | Chrome | options=binary_location="/path/to/binary";add_argument("remote-debugging-port=port") | # Start Chomium-based application. | @@ -212,11 +217,17 @@ def open_browser( self.go_to(url) return index if desired_capabilities: - self.warn("desired_capabilities has been deprecated and removed. Please use options to configure browsers as per documentation.") + self.warn( + "desired_capabilities has been deprecated and removed. Please use options to configure browsers as per documentation." + ) if service_log_path: - self.warn("service_log_path is being deprecated. Please use service to configure log_output or equivalent service attribute.") + self.warn( + "service_log_path is being deprecated. Please use service to configure log_output or equivalent service attribute." + ) if executable_path: - self.warn("exexcutable_path is being deprecated. Please use service to configure the driver's executable_path as per documentation.") + self.warn( + "executable_path is being deprecated. Please use service to configure the driver's executable_path as per documentation." + ) return self._make_new_browser( url, browser, @@ -275,7 +286,11 @@ def _make_new_browser( @keyword def create_webdriver( - self, driver_name: str, alias: Optional[str] = None, kwargs: Optional[dict] = None, **init_kwargs + self, + driver_name: str, + alias: str | None = None, + kwargs: dict | None = None, + **init_kwargs, ) -> str: """Creates an instance of Selenium WebDriver. @@ -289,7 +304,7 @@ def create_webdriver( The initialized WebDriver can be configured either with a Python dictionary ``kwargs`` or by using keyword arguments ``**init_kwargs``. These arguments are passed directly to WebDriver without any - processing. See [https://seleniumhq.github.io/selenium/docs/api/py/api.html| + processing. See [https://www.selenium.dev/selenium/docs/api/py/api.html| Selenium API documentation] for details about the supported arguments. Examples: @@ -314,8 +329,10 @@ def create_webdriver( driver_name = driver_name.strip() try: creation_func = getattr(webdriver, driver_name) - except AttributeError: - raise RuntimeError(f"'{driver_name}' is not a valid WebDriver name.") + except AttributeError as original_exception: + raise RuntimeError( + f"'{driver_name}' is not a valid WebDriver name." + ) from original_exception self.info(f"Creating an instance of the {driver_name} WebDriver.") driver = creation_func(**init_kwargs) self.debug( @@ -359,16 +376,16 @@ def switch_browser(self, index_or_alias: str): """ try: self.drivers.switch(index_or_alias) - except RuntimeError: + except RuntimeError as original_exception: raise RuntimeError( f"No browser with index or alias '{index_or_alias}' found." - ) + ) from original_exception self.debug( f"Switched to browser with Selenium session id {self.driver.session_id}." ) @keyword - def get_browser_ids(self) -> List[str]: + def get_browser_ids(self) -> list[str]: """Returns index of all active browser as list. Example: @@ -385,7 +402,7 @@ def get_browser_ids(self) -> List[str]: return self.drivers.active_driver_ids @keyword - def get_browser_aliases(self) -> List[str]: + def get_browser_aliases(self) -> list[str]: """Returns aliases of all active browser that has an alias as NormalizedDict. The dictionary contains the aliases as keys and the index as value. This can be accessed as dictionary ``${aliases.key}`` or as list ``@{aliases}[0]``. @@ -429,7 +446,7 @@ def get_location(self) -> str: return self.driver.current_url @keyword - def location_should_be(self, url: str, message: Optional[str] = None): + def location_should_be(self, url: str, message: str | None = None): """Verifies that the current URL is exactly ``url``. The ``url`` argument contains the exact url that should exist in browser. @@ -442,12 +459,12 @@ def location_should_be(self, url: str, message: Optional[str] = None): actual = self.get_location() if actual != url: if message is None: - message = f"Location should have been '{url}' but " f"was '{actual}'." + message = f"Location should have been '{url}' but was '{actual}'." raise AssertionError(message) self.info(f"Current location is '{url}'.") @keyword - def location_should_contain(self, expected: str, message: Optional[str] = None): + def location_should_contain(self, expected: str, message: str | None = None): """Verifies that the current URL contains ``expected``. The ``expected`` argument contains the expected value in url. @@ -494,7 +511,7 @@ def log_title(self) -> str: return title @keyword - def title_should_be(self, title: str, message: Optional[str] = None): + def title_should_be(self, title: str, message: str | None = None): """Verifies that the current page title equals ``title``. The ``message`` argument can be used to override the default error @@ -654,8 +671,7 @@ def set_action_chain_delay(self, value: timedelta) -> str: @keyword def get_action_chain_delay(self): - """Gets the currently stored value for chain_delay_value in timestr format. - """ + """Gets the currently stored value for chain_delay_value in timestr format.""" return timestr_to_secs(f"{self.ctx.action_chain_delay} milliseconds") @keyword diff --git a/src/SeleniumLibrary/keywords/cookie.py b/src/SeleniumLibrary/keywords/cookie.py index c2c49e8c7..32af0f861 100644 --- a/src/SeleniumLibrary/keywords/cookie.py +++ b/src/SeleniumLibrary/keywords/cookie.py @@ -14,7 +14,6 @@ # See the License for the specific language governing permissions and # limitations under the License. from datetime import datetime -from typing import Union, Optional from robot.libraries.DateTime import convert_date from robot.utils import DotDict @@ -45,7 +44,7 @@ def __init__( self.extra = extra def __str__(self): - items = "name value path domain secure httpOnly expiry".split() + items = ["name", "value", "path", "domain", "secure", "httpOnly", "expiry"] string = "\n".join(f"{item}={getattr(self, item)}" for item in items) if self.extra: string = f"{string}\nextra={self.extra}\n" @@ -67,7 +66,7 @@ def delete_cookie(self, name): self.driver.delete_cookie(name) @keyword - def get_cookies(self, as_dict: bool = False) -> Union[str, dict]: + def get_cookies(self, as_dict: bool = False) -> str | dict: """Returns all cookies of the current page. If ``as_dict`` argument evaluates as false, see `Boolean arguments` @@ -87,11 +86,10 @@ def get_cookies(self, as_dict: bool = False) -> Union[str, dict]: for cookie in self.driver.get_cookies(): pairs.append(f"{cookie['name']}={cookie['value']}") return "; ".join(pairs) - else: - pairs = DotDict() - for cookie in self.driver.get_cookies(): - pairs[cookie["name"]] = cookie["value"] - return pairs + pairs = DotDict() + for cookie in self.driver.get_cookies(): + pairs[cookie["name"]] = cookie["value"] + return pairs @keyword def get_cookie(self, name: str) -> CookieInformation: @@ -144,10 +142,10 @@ def add_cookie( self, name: str, value: str, - path: Optional[str] = None, - domain: Optional[str] = None, - secure: Optional[bool] = None, - expiry: Optional[str] = None, + path: str | None = None, + domain: str | None = None, + secure: bool | None = None, + expiry: str | None = None, ): """Adds a cookie to your current session. diff --git a/src/SeleniumLibrary/keywords/element.py b/src/SeleniumLibrary/keywords/element.py index 131fadbf9..4d482359b 100644 --- a/src/SeleniumLibrary/keywords/element.py +++ b/src/SeleniumLibrary/keywords/element.py @@ -13,23 +13,23 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from collections import namedtuple -from typing import List, Optional, Tuple, Union -from SeleniumLibrary.utils import is_noney -from robot.utils import plural_or_not, is_truthy +from typing import NamedTuple + +from robot.utils import is_truthy, plural_or_not from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.keys import Keys from selenium.webdriver.remote.webelement import WebElement from SeleniumLibrary.base import LibraryComponent, keyword from SeleniumLibrary.errors import ElementNotFound -from SeleniumLibrary.utils.types import type_converter +from SeleniumLibrary.utils import is_noney +from SeleniumLibrary.utils.types import Locator, type_converter class ElementKeywords(LibraryComponent): @keyword(name="Get WebElement") - def get_webelement(self, locator: Union[WebElement, str]) -> WebElement: + def get_webelement(self, locator: Locator) -> WebElement: """Returns the first WebElement matching the given ``locator``. See the `Locating elements` section for details about the locator @@ -38,7 +38,7 @@ def get_webelement(self, locator: Union[WebElement, str]) -> WebElement: return self.find_element(locator) @keyword(name="Get WebElements") - def get_webelements(self, locator: Union[WebElement, str]) -> List[WebElement]: + def get_webelements(self, locator: Locator) -> list[WebElement]: """Returns a list of WebElement objects matching the ``locator``. See the `Locating elements` section for details about the locator @@ -53,9 +53,9 @@ def get_webelements(self, locator: Union[WebElement, str]) -> List[WebElement]: @keyword def element_should_contain( self, - locator: Union[WebElement, str], - expected: Union[None, str], - message: Optional[str] = None, + locator: Locator, + expected: None | str, + message: str | None = None, ignore_case: bool = False, ): """Verifies that element ``locator`` contains text ``expected``. @@ -91,9 +91,9 @@ def element_should_contain( @keyword def element_should_not_contain( self, - locator: Union[WebElement, str], - expected: Union[None, str], - message: Optional[str] = None, + locator: Locator, + expected: None | str, + message: str | None = None, ignore_case: bool = False, ): """Verifies that element ``locator`` does not contain text ``expected``. @@ -149,10 +149,10 @@ def page_should_contain(self, text: str, loglevel: str = "TRACE"): @keyword def page_should_contain_element( self, - locator: Union[WebElement, str, List[Union[WebElement,str]]], - message: Optional[str] = None, + locator: Locator, + message: str | None = None, loglevel: str = "TRACE", - limit: Optional[int] = None, + limit: int | None = None, ): """Verifies that element ``locator`` is found on the current page. @@ -185,14 +185,14 @@ def page_should_contain_element( count = len(self.find_elements(locator)) if count == limit: self.info(f"Current page contains {count} element(s).") - else: - if message is None: - message = ( - f'Page should have contained "{limit}" element(s), ' - f'but it did contain "{count}" element(s).' - ) - self.ctx.log_source(loglevel) - raise AssertionError(message) + return None + if message is None: + message = ( + f'Page should have contained "{limit}" element(s), ' + f'but it did contain "{count}" element(s).' + ) + self.ctx.log_source(loglevel) + raise AssertionError(message) @keyword def page_should_not_contain(self, text: str, loglevel: str = "TRACE"): @@ -209,8 +209,8 @@ def page_should_not_contain(self, text: str, loglevel: str = "TRACE"): @keyword def page_should_not_contain_element( self, - locator: Union[WebElement, str], - message: Optional[str] = None, + locator: Locator, + message: str | None = None, loglevel: str = "TRACE", ): """Verifies that element ``locator`` is not found on the current page. @@ -224,7 +224,7 @@ def page_should_not_contain_element( self.assert_page_not_contains(locator, message=message, loglevel=loglevel) @keyword - def assign_id_to_element(self, locator: Union[WebElement, str], id: str): + def assign_id_to_element(self, locator: Locator, id: str): # noqa: A002 """Assigns a temporary ``id`` to the element specified by ``locator``. This is mainly useful if the locator is complicated and/or slow XPath @@ -243,7 +243,7 @@ def assign_id_to_element(self, locator: Union[WebElement, str], id: str): self.driver.execute_script(f"arguments[0].id = '{id}';", element) @keyword - def element_should_be_disabled(self, locator: Union[WebElement, str]): + def element_should_be_disabled(self, locator: Locator): """Verifies that element identified by ``locator`` is disabled. This keyword considers also elements that are read-only to be @@ -256,7 +256,7 @@ def element_should_be_disabled(self, locator: Union[WebElement, str]): raise AssertionError(f"Element '{locator}' is enabled.") @keyword - def element_should_be_enabled(self, locator: Union[WebElement, str]): + def element_should_be_enabled(self, locator: Locator): """Verifies that element identified by ``locator`` is enabled. This keyword considers also elements that are read-only to be @@ -269,7 +269,7 @@ def element_should_be_enabled(self, locator: Union[WebElement, str]): raise AssertionError(f"Element '{locator}' is disabled.") @keyword - def element_should_be_focused(self, locator: Union[WebElement, str]): + def element_should_be_focused(self, locator: Locator): """Verifies that element identified by ``locator`` is focused. See the `Locating elements` section for details about the locator @@ -286,9 +286,7 @@ def element_should_be_focused(self, locator: Union[WebElement, str]): raise AssertionError(f"Element '{locator}' does not have focus.") @keyword - def element_should_be_visible( - self, locator: Union[WebElement, str], message: Optional[str] = None - ): + def element_should_be_visible(self, locator: Locator, message: str | None = None): """Verifies that the element identified by ``locator`` is visible. Herein, visible means that the element is logically visible, not @@ -310,7 +308,7 @@ def element_should_be_visible( @keyword def element_should_not_be_visible( - self, locator: Union[WebElement, str], message: Optional[str] = None + self, locator: Locator, message: str | None = None ): """Verifies that the element identified by ``locator`` is NOT visible. @@ -330,9 +328,9 @@ def element_should_not_be_visible( @keyword def element_text_should_be( self, - locator: Union[WebElement, str], - expected: Union[None, str], - message: Optional[str] = None, + locator: Locator, + expected: None | str, + message: str | None = None, ignore_case: bool = False, ): """Verifies that element ``locator`` contains exact the text ``expected``. @@ -366,9 +364,9 @@ def element_text_should_be( @keyword def element_text_should_not_be( self, - locator: Union[WebElement, str], - not_expected: Union[None, str], - message: Optional[str] = None, + locator: Locator, + not_expected: None | str, + message: str | None = None, ignore_case: bool = False, ): """Verifies that element ``locator`` does not contain exact the text ``not_expected``. @@ -398,9 +396,7 @@ def element_text_should_not_be( raise AssertionError(message) @keyword - def get_element_attribute( - self, locator: Union[WebElement, str], attribute: str - ) -> str: + def get_element_attribute(self, locator: Locator, attribute: str) -> str: """Returns the value of ``attribute`` from the element ``locator``. See the `Locating elements` section for details about the locator @@ -416,9 +412,7 @@ def get_element_attribute( return self.find_element(locator).get_attribute(attribute) @keyword - def get_dom_attribute( - self, locator: Union[WebElement, str], attribute: str - ) -> str: + def get_dom_attribute(self, locator: Locator, attribute: str) -> str: """Returns the value of ``attribute`` from the element ``locator``. `Get DOM Attribute` keyword only returns attributes declared within the element's HTML markup. If the requested attribute is not there, the keyword returns ${None}. @@ -434,7 +428,9 @@ def get_dom_attribute( @keyword def get_property( - self, locator: Union[WebElement, str], property: str + self, + locator: Locator, + property: str, # noqa: A002 ) -> str: """Returns the value of ``property`` from the element ``locator``. @@ -450,10 +446,10 @@ def get_property( @keyword def element_attribute_value_should_be( self, - locator: Union[WebElement, str], + locator: Locator, attribute: str, - expected: Union[None, str], - message: Optional[str] = None, + expected: None | str, + message: str | None = None, ): """Verifies element identified by ``locator`` contains expected attribute value. @@ -479,7 +475,7 @@ def element_attribute_value_should_be( ) @keyword - def get_horizontal_position(self, locator: Union[WebElement, str]) -> int: + def get_horizontal_position(self, locator: Locator) -> int: """Returns the horizontal position of the element identified by ``locator``. See the `Locating elements` section for details about the locator @@ -493,7 +489,7 @@ def get_horizontal_position(self, locator: Union[WebElement, str]) -> int: return self.find_element(locator).location["x"] @keyword - def get_element_size(self, locator: Union[WebElement, str]) -> Tuple[int, int]: + def get_element_size(self, locator: Locator) -> tuple[int, int]: """Returns width and height of the element identified by ``locator``. See the `Locating elements` section for details about the locator @@ -508,7 +504,7 @@ def get_element_size(self, locator: Union[WebElement, str]) -> Tuple[int, int]: return element.size["width"], element.size["height"] @keyword - def cover_element(self, locator: Union[WebElement, str]): + def cover_element(self, locator: Locator): """Will cover elements identified by ``locator`` with a blue div without breaking page layout. See the `Locating elements` section for details about the locator @@ -540,7 +536,7 @@ def cover_element(self, locator: Union[WebElement, str]): self.driver.execute_script(script, element) @keyword - def get_value(self, locator: Union[WebElement, str]) -> str: + def get_value(self, locator: Locator) -> str: """Returns the value attribute of the element identified by ``locator``. See the `Locating elements` section for details about the locator @@ -549,7 +545,7 @@ def get_value(self, locator: Union[WebElement, str]) -> str: return self.get_element_attribute(locator, "value") @keyword - def get_text(self, locator: Union[WebElement, str]) -> str: + def get_text(self, locator: Locator) -> str: """Returns the text value of the element identified by ``locator``. See the `Locating elements` section for details about the locator @@ -558,7 +554,7 @@ def get_text(self, locator: Union[WebElement, str]) -> str: return self.find_element(locator).text @keyword - def clear_element_text(self, locator: Union[WebElement, str]): + def clear_element_text(self, locator: Locator): """Clears the value of the text-input-element identified by ``locator``. See the `Locating elements` section for details about the locator @@ -567,7 +563,7 @@ def clear_element_text(self, locator: Union[WebElement, str]): self.find_element(locator).clear() @keyword - def get_vertical_position(self, locator: Union[WebElement, str]) -> int: + def get_vertical_position(self, locator: Locator) -> int: """Returns the vertical position of the element identified by ``locator``. See the `Locating elements` section for details about the locator @@ -581,9 +577,7 @@ def get_vertical_position(self, locator: Union[WebElement, str]) -> int: return self.find_element(locator).location["y"] @keyword - def click_button( - self, locator: Union[WebElement, str], modifier: Union[bool, str] = False - ): + def click_button(self, locator: Locator, modifier: bool | str = False): """Clicks the button identified by ``locator``. See the `Locating elements` section for details about the locator @@ -605,9 +599,7 @@ def click_button( self._click_with_modifier(locator, ["button", "input"], modifier) @keyword - def click_image( - self, locator: Union[WebElement, str], modifier: Union[bool, str] = False - ): + def click_image(self, locator: Locator, modifier: bool | str = False): """Clicks an image identified by ``locator``. See the `Locating elements` section for details about the locator @@ -630,9 +622,7 @@ def click_image( self._click_with_modifier(locator, ["image", "input"], modifier) @keyword - def click_link( - self, locator: Union[WebElement, str], modifier: Union[bool, str] = False - ): + def click_link(self, locator: Locator, modifier: bool | str = False): """Clicks a link identified by ``locator``. See the `Locating elements` section for details about the locator @@ -653,8 +643,8 @@ def click_link( @keyword def click_element( self, - locator: Union[WebElement, str], - modifier: Union[bool, str] = False, + locator: Locator, + modifier: bool | str = False, action_chain: bool = False, ): """Click the element identified by ``locator``. @@ -663,12 +653,12 @@ def click_element( syntax. The ``modifier`` argument can be used to pass - [https://seleniumhq.github.io/selenium/docs/api/py/webdriver/selenium.webdriver.common.keys.html#selenium.webdriver.common.keys.Keys|Selenium Keys] + [https://www.selenium.dev/selenium/docs/api/py/selenium_webdriver_common/selenium.webdriver.common.keys.html#module-selenium.webdriver.common.keys|Selenium Keys] when clicking the element. The `+` can be used as a separator for different Selenium Keys. The `CTRL` is internally translated to the `CONTROL` key. The ``modifier`` is space and case insensitive, example "alt" and " aLt " are supported formats to - [https://seleniumhq.github.io/selenium/docs/api/py/webdriver/selenium.webdriver.common.keys.html#selenium.webdriver.common.keys.Keys.ALT|ALT key] + [https://www.selenium.dev/selenium/docs/api/py/selenium_webdriver_common/selenium.webdriver.common.keys.html#selenium.webdriver.common.keys.Keys.ALT|ALT key] . If ``modifier`` does not match to Selenium Keys, keyword fails. If ``action_chain`` argument is true, see `Boolean arguments` for more @@ -694,7 +684,7 @@ def click_element( self.info(f"Clicking element '{locator}'.") self.find_element(locator).click() - def _click_with_action_chain(self, locator: Union[WebElement, str]): + def _click_with_action_chain(self, locator: Locator): self.info(f"Clicking '{locator}' using an action chain.") action = ActionChains(self.driver, duration=self.ctx.action_chain_delay) element = self.find_element(locator) @@ -720,7 +710,7 @@ def _click_with_modifier(self, locator, tag, modifier): @keyword def click_element_at_coordinates( - self, locator: Union[WebElement, str], xoffset: int, yoffset: int + self, locator: Locator, xoffset: int, yoffset: int ): """Click the element ``locator`` at ``xoffset/yoffset``. @@ -741,7 +731,7 @@ def click_element_at_coordinates( action.perform() @keyword - def double_click_element(self, locator: Union[WebElement, str]): + def double_click_element(self, locator: Locator): """Double clicks the element identified by ``locator``. See the `Locating elements` section for details about the locator @@ -753,7 +743,7 @@ def double_click_element(self, locator: Union[WebElement, str]): action.double_click(element).perform() @keyword - def set_focus_to_element(self, locator: Union[WebElement, str]): + def set_focus_to_element(self, locator: Locator): """Sets the focus to the element identified by ``locator``. See the `Locating elements` section for details about the locator @@ -765,7 +755,7 @@ def set_focus_to_element(self, locator: Union[WebElement, str]): self.driver.execute_script("arguments[0].focus();", element) @keyword - def scroll_element_into_view(self, locator: Union[WebElement, str]): + def scroll_element_into_view(self, locator: Locator): """Scrolls the element identified by ``locator`` into view. See the `Locating elements` section for details about the locator @@ -774,12 +764,12 @@ def scroll_element_into_view(self, locator: Union[WebElement, str]): New in SeleniumLibrary 3.2.0 """ element = self.find_element(locator) - ActionChains(self.driver, duration=self.ctx.action_chain_delay).move_to_element(element).perform() + ActionChains(self.driver, duration=self.ctx.action_chain_delay).move_to_element( + element + ).perform() @keyword - def drag_and_drop( - self, locator: Union[WebElement, str], target: Union[WebElement, str] - ): + def drag_and_drop(self, locator: Locator, target: Locator): """Drags the element identified by ``locator`` into the ``target`` element. The ``locator`` argument is the locator of the dragged element @@ -795,9 +785,7 @@ def drag_and_drop( action.drag_and_drop(element, target).perform() @keyword - def drag_and_drop_by_offset( - self, locator: Union[WebElement, str], xoffset: int, yoffset: int - ): + def drag_and_drop_by_offset(self, locator: Locator, xoffset: int, yoffset: int): """Drags the element identified with ``locator`` by ``xoffset/yoffset``. See the `Locating elements` section for details about the locator @@ -815,7 +803,7 @@ def drag_and_drop_by_offset( action.perform() @keyword - def mouse_down(self, locator: Union[WebElement, str]): + def mouse_down(self, locator: Locator): """Simulates pressing the left mouse button on the element ``locator``. See the `Locating elements` section for details about the locator @@ -832,7 +820,7 @@ def mouse_down(self, locator: Union[WebElement, str]): action.click_and_hold(element).perform() @keyword - def mouse_out(self, locator: Union[WebElement, str]): + def mouse_out(self, locator: Locator): """Simulates moving the mouse away from the element ``locator``. See the `Locating elements` section for details about the locator @@ -849,7 +837,7 @@ def mouse_out(self, locator: Union[WebElement, str]): action.perform() @keyword - def mouse_over(self, locator: Union[WebElement, str]): + def mouse_over(self, locator: Locator): """Simulates hovering the mouse over the element ``locator``. See the `Locating elements` section for details about the locator @@ -861,7 +849,7 @@ def mouse_over(self, locator: Union[WebElement, str]): action.move_to_element(element).perform() @keyword - def mouse_up(self, locator: Union[WebElement, str]): + def mouse_up(self, locator: Locator): """Simulates releasing the left mouse button on the element ``locator``. See the `Locating elements` section for details about the locator @@ -869,17 +857,19 @@ def mouse_up(self, locator: Union[WebElement, str]): """ self.info(f"Simulating Mouse Up on element '{locator}'.") element = self.find_element(locator) - ActionChains(self.driver, duration=self.ctx.action_chain_delay).release(element).perform() + ActionChains(self.driver, duration=self.ctx.action_chain_delay).release( + element + ).perform() @keyword - def open_context_menu(self, locator: Union[WebElement, str]): + def open_context_menu(self, locator: Locator): """Opens the context menu on the element identified by ``locator``.""" element = self.find_element(locator) action = ActionChains(self.driver, duration=self.ctx.action_chain_delay) action.context_click(element).perform() @keyword - def simulate_event(self, locator: Union[WebElement, str], event: str): + def simulate_event(self, locator: Locator, event: str): """Simulates ``event`` on the element identified by ``locator``. This keyword is useful if element has ``OnEvent`` handler that @@ -904,7 +894,7 @@ def simulate_event(self, locator: Union[WebElement, str], event: str): self.driver.execute_script(script, element, event) @keyword - def press_key(self, locator: Union[WebElement, str], key: str): + def press_key(self, locator: Locator, key: str): """Simulates user pressing key on element identified by ``locator``. See the `Locating elements` section for details about the locator @@ -923,7 +913,6 @@ def press_key(self, locator: Union[WebElement, str], key: str): using the selenium send_keys method. Although one is not recommended over the other if `Press Key` does not work we recommend trying `Press Keys`. - send_ """ if key.startswith("\\") and len(key) > 1: key = self._map_ascii_key_code_to_key(int(key[1:])) @@ -931,7 +920,7 @@ def press_key(self, locator: Union[WebElement, str], key: str): element.send_keys(key) @keyword - def press_keys(self, locator: Union[WebElement, None, str] = None, *keys: str): + def press_keys(self, locator: Locator | None = None, *keys: str): """Simulates the user pressing key(s) to an element or on the active browser. If ``locator`` evaluates as false, see `Boolean arguments` for more @@ -943,7 +932,7 @@ def press_keys(self, locator: Union[WebElement, None, str] = None, *keys: str): ``keys`` arguments can contain one or many strings, but it can not be empty. ``keys`` can also be a combination of - [https://seleniumhq.github.io/selenium/docs/api/py/webdriver/selenium.webdriver.common.keys.html|Selenium Keys] + [https://www.selenium.dev/selenium/docs/api/py/selenium_webdriver_common/selenium.webdriver.common.keys.html|Selenium Keys] and strings or a single Selenium Key. If Selenium Key is combined with strings, Selenium key and strings must be separated by the `+` character, like in `CONTROL+c`. Selenium Keys @@ -961,9 +950,9 @@ def press_keys(self, locator: Union[WebElement, None, str] = None, *keys: str): `+` character, example `E+N+D`. `CTRL` is alias for - [https://seleniumhq.github.io/selenium/docs/api/py/webdriver/selenium.webdriver.common.keys.html#selenium.webdriver.common.keys.Keys.CONTROL|Selenium CONTROL] + [https://www.selenium.dev/selenium/docs/api/py/selenium_webdriver_common/selenium.webdriver.common.keys.html#selenium.webdriver.common.keys.Keys.CONTROL|Selenium CONTROL] and ESC is alias for - [https://seleniumhq.github.io/selenium/docs/api/py/webdriver/selenium.webdriver.common.keys.html#selenium.webdriver.common.keys.Keys.ESCAPE|Selenium ESCAPE] + [https://www.selenium.dev/selenium/docs/api/py/selenium_webdriver_common/selenium.webdriver.common.keys.html#selenium.webdriver.common.keys.Keys.ESCAPE|Selenium ESCAPE] New in SeleniumLibrary 3.3 @@ -989,7 +978,9 @@ def press_keys(self, locator: Union[WebElement, None, str] = None, *keys: str): if not is_noney(locator): self.info(f"Sending key(s) {keys} to {locator} element.") element = self.find_element(locator) - ActionChains(self.driver, duration=self.ctx.action_chain_delay).click(element).perform() + ActionChains(self.driver, duration=self.ctx.action_chain_delay).click( + element + ).perform() else: self.info(f"Sending key(s) {keys} to page.") element = None @@ -1025,7 +1016,7 @@ def _special_key_up(self, actions, parsed_key): actions.key_up(key.converted) @keyword - def get_all_links(self) -> List[str]: + def get_all_links(self) -> list[str]: """Returns a list containing ids of all links found in current page. If a link has no id, an empty string will be in the list instead. @@ -1034,7 +1025,7 @@ def get_all_links(self) -> List[str]: return [link.get_attribute("id") for link in links] @keyword - def mouse_down_on_link(self, locator: Union[WebElement, str]): + def mouse_down_on_link(self, locator: Locator): """Simulates a mouse down event on a link identified by ``locator``. See the `Locating elements` section for details about the locator @@ -1048,8 +1039,8 @@ def mouse_down_on_link(self, locator: Union[WebElement, str]): @keyword def page_should_contain_link( self, - locator: Union[WebElement, str], - message: Optional[str] = None, + locator: Locator, + message: str | None = None, loglevel: str = "TRACE", ): """Verifies link identified by ``locator`` is found from current page. @@ -1066,8 +1057,8 @@ def page_should_contain_link( @keyword def page_should_not_contain_link( self, - locator: Union[WebElement, str], - message: Optional[str] = None, + locator: Locator, + message: str | None = None, loglevel: str = "TRACE", ): """Verifies link identified by ``locator`` is not found from current page. @@ -1082,7 +1073,7 @@ def page_should_not_contain_link( self.assert_page_not_contains(locator, "link", message, loglevel) @keyword - def mouse_down_on_image(self, locator: Union[WebElement, str]): + def mouse_down_on_image(self, locator: Locator): """Simulates a mouse down event on an image identified by ``locator``. See the `Locating elements` section for details about the locator @@ -1096,8 +1087,8 @@ def mouse_down_on_image(self, locator: Union[WebElement, str]): @keyword def page_should_contain_image( self, - locator: Union[WebElement, str], - message: Optional[str] = None, + locator: Locator, + message: str | None = None, loglevel: str = "TRACE", ): """Verifies image identified by ``locator`` is found from current page. @@ -1114,8 +1105,8 @@ def page_should_contain_image( @keyword def page_should_not_contain_image( self, - locator: Union[WebElement, str], - message: Optional[str] = None, + locator: Locator, + message: str | None = None, loglevel: str = "TRACE", ): """Verifies image identified by ``locator`` is not found from current page. @@ -1130,7 +1121,7 @@ def page_should_not_contain_image( self.assert_page_not_contains(locator, "image", message, loglevel) @keyword - def get_element_count(self, locator: Union[WebElement, str]) -> int: + def get_element_count(self, locator: Locator) -> int: """Returns the number of elements matching ``locator``. If you wish to assert the number of matching elements, use @@ -1172,7 +1163,7 @@ def remove_location_strategy(self, strategy_name: str): self.element_finder.unregister(strategy_name) def _map_ascii_key_code_to_key(self, key_code): - map = { + key_map = { 0: Keys.NULL, 8: Keys.BACK_SPACE, 9: Keys.TAB, @@ -1191,7 +1182,7 @@ def _map_ascii_key_code_to_key(self, key_code): 61: Keys.EQUALS, 127: Keys.DELETE, } - key = map.get(key_code) + key = key_map.get(key_code) if key is None: key = chr(key_code) return key @@ -1199,10 +1190,10 @@ def _map_ascii_key_code_to_key(self, key_code): def _map_named_key_code_to_special_key(self, key_name): try: return getattr(Keys, key_name) - except AttributeError: + except AttributeError as original_exception: message = f"Unknown key named '{key_name}'." self.debug(message) - raise ValueError(message) + raise ValueError(message) from original_exception def _page_contains(self, text): self.driver.switch_to.default_content() @@ -1225,12 +1216,13 @@ def parse_modifier(self, modifier): modifiers = modifier.split("+") keys = [] for item in modifiers: - item = item.strip() - item = self._parse_aliases(item) - if hasattr(Keys, item): - keys.append(getattr(Keys, item)) + modifier = self._parse_aliases(item.strip()) + if hasattr(Keys, modifier): + keys.append(getattr(Keys, modifier)) else: - raise ValueError(f"'{item}' modifier does not match to Selenium Keys") + raise ValueError( + f"'{modifier}' modifier does not match to Selenium Keys" + ) return keys def _parse_keys(self, *keys): @@ -1263,16 +1255,95 @@ def _separate_key(self, key): list_keys.append(one_key) return list_keys + class KeysRecord(NamedTuple): + converted: object + original: str + special: bool + def _convert_special_keys(self, keys): - KeysRecord = namedtuple("KeysRecord", "converted, original special") converted_keys = [] for key in keys: - key = self._parse_aliases(key) - if self._selenium_keys_has_attr(key): - converted_keys.append(KeysRecord(getattr(Keys, key), key, True)) + resolved_key = self._parse_aliases(key) + if self._selenium_keys_has_attr(resolved_key): + converted_keys.append( + self.KeysRecord(getattr(Keys, resolved_key), resolved_key, True) + ) else: - converted_keys.append(KeysRecord(key, key, False)) + converted_keys.append( + self.KeysRecord(resolved_key, resolved_key, False) + ) return converted_keys def _selenium_keys_has_attr(self, key): return hasattr(Keys, key) + + @keyword("Get CSS Property Value") + def get_css_property_value(self, locator: Locator, css_property: str) -> str: + """Returns the computed value of ``css_property`` from the element ``locator``. + + See the `Locating elements` section for details about the locator syntax. + + The value returned is the browser-computed CSS value of the property. + For example, colors are often returned in ``rgba(...)`` format and sizes + are typically returned in pixels. + + Example: + | ${color}= | `Get CSS Property Value` | css:button.submit | background-color | + | ${size}= | `Get CSS Property Value` | id:username | font-size | + """ + return self.find_element(locator).value_of_css_property(css_property) + + @keyword("Drag And Drop Across Frames") + def drag_and_drop_across_frames( + self, + locator: Locator, + target: Locator, + target_frame: Locator, + source_frame: Locator | None = None, + ) -> None: + """ + Drags an element and drops it onto a target element across frame boundaries. + + The ``locator`` argument is the locator of the element to drag. The ``target`` + argument is the locator of the drop target. The ``target_frame`` argument is + the locator of the iframe containing the target. The optional ``source_frame`` + argument is the locator of the iframe containing the source. If + ``source_frame`` is not provided, the source element is located in the default content. + + After this keyword runs, the browser context is always reset to default content. + + See the `Locating elements` section for details about the locator syntax. + + Examples: + | Drag And Drop Across Frames | id:source | id:target | id:target-frame | + | Drag And Drop Across Frames | id:source | id:target | id:target-frame | id:source-frame | + """ + released = False + + try: + if source_frame is not None: + source_frame_element = self.find_element(source_frame) + self.driver.switch_to.frame(source_frame_element) + + source_element = self.find_element(locator) + ActionChains( + self.driver, duration=self.ctx.action_chain_delay + ).click_and_hold(source_element).perform() + + self.driver.switch_to.default_content() + + target_frame_element = self.find_element(target_frame) + self.driver.switch_to.frame(target_frame_element) + + target_element = self.find_element(target) + ActionChains( + self.driver, duration=self.ctx.action_chain_delay + ).move_to_element(target_element).release().perform() + released = True + + finally: + if not released: + ActionChains( + self.driver, duration=self.ctx.action_chain_delay + ).release().perform() + self.driver.switch_to.default_content() diff --git a/src/SeleniumLibrary/keywords/expectedconditions.py b/src/SeleniumLibrary/keywords/expectedconditions.py index c0272ae75..4635ce54f 100644 --- a/src/SeleniumLibrary/keywords/expectedconditions.py +++ b/src/SeleniumLibrary/keywords/expectedconditions.py @@ -11,17 +11,18 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -import string -from typing import Optional +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support.wait import WebDriverWait from SeleniumLibrary.base import LibraryComponent, keyword from SeleniumLibrary.errors import UnkownExpectedCondition -from selenium.webdriver.support.wait import WebDriverWait -from selenium.webdriver.support import expected_conditions as EC + class ExpectedConditionKeywords(LibraryComponent): @keyword - def wait_for_expected_condition(self, condition: string, *args, timeout: Optional[float]=10): + def wait_for_expected_condition( + self, condition: str, *args, timeout: float | None = 10 + ): """Waits until ``condition`` is true or ``timeout`` expires. The condition must be one of selenium's expected condition which @@ -51,13 +52,15 @@ def wait_for_expected_condition(self, condition: string, *args, timeout: Optiona condition = self._parse_condition(condition) wait = WebDriverWait(self.driver, timeout, 0.1) try: - c = getattr(EC, condition) - except: - # ToDo: provide hints as to what is avaialbel or find closet match - raise UnkownExpectedCondition(f"{condition} is an unknown expected condition") - result = wait.until(c(*args), message="Expected Condition not met within set timeout of " + str(timeout)) - return result - - def _parse_condition(self, condition: string): - parsed = condition.replace(' ','_').lower() - return parsed \ No newline at end of file + condition_func = getattr(EC, condition) + except AttributeError as original_exception: + raise UnkownExpectedCondition( + f"{condition} is an unknown expected condition" + ) from original_exception + return wait.until( + condition_func(*args), + message=f"Expected Condition not met within set timeout of {timeout}s", + ) + + def _parse_condition(self, condition: str): + return condition.replace(" ", "_").lower() diff --git a/src/SeleniumLibrary/keywords/formelement.py b/src/SeleniumLibrary/keywords/formelement.py index 15ef61256..123b20c27 100644 --- a/src/SeleniumLibrary/keywords/formelement.py +++ b/src/SeleniumLibrary/keywords/formelement.py @@ -15,18 +15,17 @@ # limitations under the License. import os -from typing import Optional, Union from robot.libraries.BuiltIn import BuiltIn -from selenium.webdriver.remote.webelement import WebElement from SeleniumLibrary.base import LibraryComponent, keyword from SeleniumLibrary.errors import ElementNotFound +from SeleniumLibrary.utils.types import Locator, Secret class FormElementKeywords(LibraryComponent): @keyword - def submit_form(self, locator: Union[WebElement, None, str] = None): + def submit_form(self, locator: Locator | None = None): """Submits a form identified by ``locator``. If ``locator`` is not given, first form on the page is submitted. @@ -41,7 +40,7 @@ def submit_form(self, locator: Union[WebElement, None, str] = None): element.submit() @keyword - def checkbox_should_be_selected(self, locator: Union[WebElement, str]): + def checkbox_should_be_selected(self, locator: Locator): """Verifies checkbox ``locator`` is selected/checked. See the `Locating elements` section for details about the locator @@ -55,7 +54,7 @@ def checkbox_should_be_selected(self, locator: Union[WebElement, str]): ) @keyword - def checkbox_should_not_be_selected(self, locator: Union[WebElement, str]): + def checkbox_should_not_be_selected(self, locator: Locator): """Verifies checkbox ``locator`` is not selected/checked. See the `Locating elements` section for details about the locator @@ -69,8 +68,8 @@ def checkbox_should_not_be_selected(self, locator: Union[WebElement, str]): @keyword def page_should_contain_checkbox( self, - locator: Union[WebElement, str], - message: Optional[str] = None, + locator: Locator, + message: str | None = None, loglevel: str = "TRACE", ): """Verifies checkbox ``locator`` is found from the current page. @@ -86,8 +85,8 @@ def page_should_contain_checkbox( @keyword def page_should_not_contain_checkbox( self, - locator: Union[WebElement, str], - message: Optional[str] = None, + locator: Locator, + message: str | None = None, loglevel: str = "TRACE", ): """Verifies checkbox ``locator`` is not found from the current page. @@ -101,7 +100,7 @@ def page_should_not_contain_checkbox( self.assert_page_not_contains(locator, "checkbox", message, loglevel) @keyword - def select_checkbox(self, locator: Union[WebElement, str]): + def select_checkbox(self, locator: Locator): """Selects the checkbox identified by ``locator``. Does nothing if checkbox is already selected. @@ -115,7 +114,7 @@ def select_checkbox(self, locator: Union[WebElement, str]): element.click() @keyword - def unselect_checkbox(self, locator: Union[WebElement, str]): + def unselect_checkbox(self, locator: Locator): """Removes the selection of checkbox identified by ``locator``. Does nothing if the checkbox is not selected. @@ -131,8 +130,8 @@ def unselect_checkbox(self, locator: Union[WebElement, str]): @keyword def page_should_contain_radio_button( self, - locator: Union[WebElement, str], - message: Optional[str] = None, + locator: Locator, + message: str | None = None, loglevel: str = "TRACE", ): """Verifies radio button ``locator`` is found from current page. @@ -149,8 +148,8 @@ def page_should_contain_radio_button( @keyword def page_should_not_contain_radio_button( self, - locator: Union[WebElement, str], - message: Optional[str] = None, + locator: Locator, + message: str | None = None, loglevel: str = "TRACE", ): """Verifies radio button ``locator`` is not found from current page. @@ -213,14 +212,14 @@ def select_radio_button(self, group_name: str, value: str): element.click() @keyword - def choose_file(self, locator: Union[WebElement, str], file_path: str): + def choose_file(self, locator: Locator, file_path: str): """Inputs the ``file_path`` into the file input field ``locator``. This keyword is most often used to input files into upload forms. The keyword does not check ``file_path`` is the file or folder available on the machine where tests are executed. If the ``file_path`` points at a file and when using Selenium Grid, Selenium will - [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_remote/selenium.webdriver.remote.command.html?highlight=upload#selenium.webdriver.remote.command.Command.UPLOAD_FILE|magically], + [https://www.selenium.dev/selenium/docs/api/py/selenium_webdriver_remote/selenium.webdriver.remote.command.html#selenium.webdriver.remote.command.Command.UPLOAD_FILE|magically], transfer the file from the machine where the tests are executed to the Selenium Grid node where the browser is running. Then Selenium will send the file path, from the nodes file @@ -240,7 +239,7 @@ def choose_file(self, locator: Union[WebElement, str], file_path: str): @keyword def input_password( - self, locator: Union[WebElement, str], password: str, clear: bool = True + self, locator: Locator, password: str | Secret, clear: bool = True ): """Types the given password into the text field identified by ``locator``. @@ -259,8 +258,15 @@ def input_password( | Input Password | password_field | ${PASSWORD} | Please notice that Robot Framework logs all arguments using - the TRACE level and tests must not be executed using level below - DEBUG if the password should not be logged in any format. + the TRACE level. When not using the ``Secret`` type, tests must + not be executed using level below DEBUG if the password should + not be logged in any format. + + This keyword supports Robot Framework 7.4 + [https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#secret-variables|Secret] + variable type. When a ``Secret`` is passed, the value is protected + from Robot Framework logs and Selenium internal logging is also + suppressed during typing. The `clear` argument is new in SeleniumLibrary 4.0. Hiding password logging from Selenium logs is new in SeleniumLibrary 4.2. @@ -269,9 +275,7 @@ def input_password( self._input_text_into_text_field(locator, password, clear, disable_log=True) @keyword - def input_text( - self, locator: Union[WebElement, str], text: str, clear: bool = True - ): + def input_text(self, locator: Locator, text: str | Secret, clear: bool = True): """Types the given ``text`` into the text field identified by ``locator``. When ``clear`` is true, the input element is cleared before @@ -279,6 +283,13 @@ def input_text( is not cleared from the element. Use `Input Password` if you do not want the given ``text`` to be logged. + This keyword supports Robot Framework 7.4 + [https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#secret-variables|Secret] + variable type. When a ``Secret`` is passed, the value is masked in + Robot Framework logs and Selenium's internal logs are suppressed during + typing. When a plain string is passed, Selenium's internal logs are not + suppressed. + If [https://github.com/SeleniumHQ/selenium/wiki/Grid2|Selenium Grid] is used and the ``text`` argument points to a file in the file system, then this keyword prevents the Selenium to transfer the file to the @@ -294,13 +305,15 @@ def input_text( argument are new in SeleniumLibrary 4.0 """ self.info(f"Typing text '{text}' into text field '{locator}'.") - self._input_text_into_text_field(locator, text, clear) + self._input_text_into_text_field( + locator, text, clear, disable_log=isinstance(text, Secret) + ) @keyword def page_should_contain_textfield( self, - locator: Union[WebElement, str], - message: Optional[str] = None, + locator: Locator, + message: str | None = None, loglevel: str = "TRACE", ): """Verifies text field ``locator`` is found from current page. @@ -316,8 +329,8 @@ def page_should_contain_textfield( @keyword def page_should_not_contain_textfield( self, - locator: Union[WebElement, str], - message: Optional[str] = None, + locator: Locator, + message: str | None = None, loglevel: str = "TRACE", ): """Verifies text field ``locator`` is not found from current page. @@ -333,9 +346,9 @@ def page_should_not_contain_textfield( @keyword def textfield_should_contain( self, - locator: Union[WebElement, str], + locator: Locator, expected: str, - message: Optional[str] = None, + message: str | None = None, ): """Verifies text field ``locator`` contains text ``expected``. @@ -357,9 +370,9 @@ def textfield_should_contain( @keyword def textfield_value_should_be( self, - locator: Union[WebElement, str], + locator: Locator, expected: str, - message: Optional[str] = None, + message: str | None = None, ): """Verifies text field ``locator`` has exactly text ``expected``. @@ -381,9 +394,9 @@ def textfield_value_should_be( @keyword def textarea_should_contain( self, - locator: Union[WebElement, str], + locator: Locator, expected: str, - message: Optional[str] = None, + message: str | None = None, ): """Verifies text area ``locator`` contains text ``expected``. @@ -405,9 +418,9 @@ def textarea_should_contain( @keyword def textarea_value_should_be( self, - locator: Union[WebElement, str], + locator: Locator, expected: str, - message: Optional[str] = None, + message: str | None = None, ): """Verifies text area ``locator`` has exactly text ``expected``. @@ -429,8 +442,8 @@ def textarea_value_should_be( @keyword def page_should_contain_button( self, - locator: Union[WebElement, str], - message: Optional[str] = None, + locator: Locator, + message: str | None = None, loglevel: str = "TRACE", ): """Verifies button ``locator`` is found from current page. @@ -450,8 +463,8 @@ def page_should_contain_button( @keyword def page_should_not_contain_button( self, - locator: Union[WebElement, str], - message: Optional[str] = None, + locator: Locator, + message: str | None = None, loglevel: str = "TRACE", ): """Verifies button ``locator`` is not found from current page. @@ -469,7 +482,7 @@ def page_should_not_contain_button( def _get_value(self, locator, tag): return self.find_element(locator, tag).get_attribute("value") - def _get_checkbox(self, locator: Union[WebElement, str]): + def _get_checkbox(self, locator: Locator): return self.find_element(locator, tag="checkbox") def _get_radio_buttons(self, group_name): @@ -488,11 +501,10 @@ def _get_radio_button_with_value(self, group_name, value): self.debug(f"Radio group locator: {xpath}") try: return self.find_element(xpath) - except ElementNotFound: + except ElementNotFound as original_exception: raise ElementNotFound( - f"No radio button with name '{group_name}' " - f"and value '{value}' found." - ) + f"No radio button with name '{group_name}' and value '{value}' found." + ) from original_exception def _get_value_from_radio_buttons(self, elements): for element in elements: @@ -508,7 +520,7 @@ def _input_text_into_text_field(self, locator, text, clear=True, disable_log=Fal self.info("Temporally setting log level to: NONE") previous_level = BuiltIn().set_log_level("NONE") try: - element.send_keys(text) + element.send_keys(text.value if isinstance(text, Secret) else text) finally: if disable_log: BuiltIn().set_log_level(previous_level) diff --git a/src/SeleniumLibrary/keywords/frames.py b/src/SeleniumLibrary/keywords/frames.py index 296b1ee6b..f2653fc03 100644 --- a/src/SeleniumLibrary/keywords/frames.py +++ b/src/SeleniumLibrary/keywords/frames.py @@ -13,16 +13,14 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Union - -from selenium.webdriver.remote.webelement import WebElement from SeleniumLibrary.base import LibraryComponent, keyword +from SeleniumLibrary.utils.types import Locator class FrameKeywords(LibraryComponent): @keyword - def select_frame(self, locator: Union[WebElement, str]): + def select_frame(self, locator: Locator): """Sets frame identified by ``locator`` as the current frame. See the `Locating elements` section for details about the locator @@ -82,7 +80,7 @@ def current_frame_should_not_contain(self, text: str, loglevel: str = "TRACE"): @keyword def frame_should_contain( - self, locator: Union[WebElement, str], text: str, loglevel: str = "TRACE" + self, locator: Locator, text: str, loglevel: str = "TRACE" ): """Verifies that frame identified by ``locator`` contains ``text``. @@ -99,7 +97,7 @@ def frame_should_contain( ) self.info(f"Frame '{locator}' contains text '{text}'.") - def _frame_contains(self, locator: Union[WebElement, str], text: str): + def _frame_contains(self, locator: Locator, text: str): element = self.find_element(locator) self.driver.switch_to.frame(element) self.info(f"Searching for text from frame '{locator}'.") diff --git a/src/SeleniumLibrary/keywords/javascript.py b/src/SeleniumLibrary/keywords/javascript.py index 9c2bb1c90..583cd91f7 100644 --- a/src/SeleniumLibrary/keywords/javascript.py +++ b/src/SeleniumLibrary/keywords/javascript.py @@ -15,17 +15,14 @@ # limitations under the License. import os -from collections import namedtuple -from typing import Any, Union +from typing import Any, NamedTuple from robot.utils import plural_or_not, seq2str -from selenium.webdriver.remote.webelement import WebElement from SeleniumLibrary.base import LibraryComponent, keyword class JavaScriptKeywords(LibraryComponent): - js_marker = "JAVASCRIPT" arg_marker = "ARGUMENTS" @@ -52,7 +49,7 @@ def execute_javascript(self, *code: Any) -> Any: Return values are converted to the appropriate Python types. Starting from SeleniumLibrary 3.2 it is possible to provide JavaScript - [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_remote/selenium.webdriver.remote.webdriver.html#selenium.webdriver.remote.webdriver.WebDriver.execute_script| + [https://www.selenium.dev/selenium/docs/api/py/selenium_webdriver_remote/selenium.webdriver.remote.webdriver.html#selenium.webdriver.remote.webdriver.WebDriver.execute_script| arguments] as part of ``code`` argument. The JavaScript code and arguments must be separated with `JAVASCRIPT` and `ARGUMENTS` markers and must be used exactly with this format. If the Javascript code is @@ -85,7 +82,7 @@ def execute_async_javascript(self, *code: Any) -> Any: fail. See the `Timeout` section for more information. Starting from SeleniumLibrary 3.2 it is possible to provide JavaScript - [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_remote/selenium.webdriver.remote.webdriver.html#selenium.webdriver.remote.webdriver.WebDriver.execute_async_script| + [https://www.selenium.dev/selenium/docs/api/py/selenium_webdriver_remote/selenium.webdriver.remote.webdriver.html#selenium.webdriver.remote.webdriver.WebDriver.execute_async_script| arguments] as part of ``code`` argument. See `Execute Javascript` for more details. @@ -130,11 +127,9 @@ def _separate_code_and_args(self, code): return code[index.js + 1 :], [] if self.js_marker not in code: return code[0 : index.arg], code[index.arg + 1 :] - else: - if index.js == 0: - return code[index.js + 1 : index.arg], code[index.arg + 1 :] - else: - return code[index.js + 1 :], code[index.arg + 1 : index.js] + if index.js == 0: + return code[index.js + 1 : index.arg], code[index.arg + 1 :] + return code[index.js + 1 :], code[index.arg + 1 : index.js] def _check_marker_error(self, code): if not code: @@ -151,17 +146,14 @@ def _check_marker_error(self, code): if message: raise ValueError(message) + class Index(NamedTuple): + js: int + arg: int + def _get_marker_index(self, code): - Index = namedtuple("Index", "js arg") - if self.js_marker in code: - js = code.index(self.js_marker) - else: - js = -1 - if self.arg_marker in code: - arg = code.index(self.arg_marker) - else: - arg = -1 - return Index(js=js, arg=arg) + js = code.index(self.js_marker) if self.js_marker in code else -1 + arg = code.index(self.arg_marker) if self.arg_marker in code else -1 + return self.Index(js=js, arg=arg) def _read_javascript_from_file(self, path): self.info( diff --git a/src/SeleniumLibrary/keywords/runonfailure.py b/src/SeleniumLibrary/keywords/runonfailure.py index 4d23c5ade..78832055b 100644 --- a/src/SeleniumLibrary/keywords/runonfailure.py +++ b/src/SeleniumLibrary/keywords/runonfailure.py @@ -13,14 +13,13 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Optional from SeleniumLibrary.base import LibraryComponent, keyword class RunOnFailureKeywords(LibraryComponent): @keyword - def register_keyword_to_run_on_failure(self, keyword: Optional[str]) -> str: + def register_keyword_to_run_on_failure(self, keyword: str | None) -> str: """Sets the keyword to execute, when a SeleniumLibrary keyword fails. ``keyword`` is the name of a keyword that will be executed if a @@ -64,10 +63,6 @@ def register_keyword_to_run_on_failure(self, keyword: Optional[str]) -> str: def resolve_keyword(name): if name is None: return None - if ( - isinstance(name, str) - and name.upper() == "NOTHING" - or name.upper() == "NONE" - ): + if isinstance(name, str) and name.upper() in ("NOTHING", "NONE"): return None return name diff --git a/src/SeleniumLibrary/keywords/screenshot.py b/src/SeleniumLibrary/keywords/screenshot.py index 8cd8dc299..58854edff 100644 --- a/src/SeleniumLibrary/keywords/screenshot.py +++ b/src/SeleniumLibrary/keywords/screenshot.py @@ -13,26 +13,28 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + import os -from typing import Optional, Union from base64 import b64decode from robot.utils import get_link_path -from selenium.webdriver.remote.webelement import WebElement -from selenium.webdriver.common.print_page_options import PrintOptions, Orientation +from selenium.webdriver.common.print_page_options import Orientation, PrintOptions from SeleniumLibrary.base import LibraryComponent, keyword from SeleniumLibrary.utils.path_formatter import _format_path +from SeleniumLibrary.utils.types import Locator 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" class ScreenshotKeywords(LibraryComponent): @keyword - def set_screenshot_directory(self, path: Union[None, str]) -> str: + def set_screenshot_directory(self, path: None | str) -> str: """Sets the directory for captured screenshots. ``path`` argument specifies the absolute path to a directory where @@ -59,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) @@ -67,7 +71,9 @@ def set_screenshot_directory(self, path: Union[None, str]) -> str: return previous @keyword - def capture_page_screenshot(self, filename: str = DEFAULT_FILENAME_PAGE) -> str: + def capture_page_screenshot( + self, filename: str = DEFAULT_FILENAME_PAGE + ) -> str | None: """Takes a screenshot of the current page and embeds it into a log file. ``filename`` argument specifies the name of the file to write the @@ -79,7 +85,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 @@ -89,9 +102,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` | | @@ -110,9 +124,10 @@ 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() + return None + 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,44 +138,53 @@ 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 base64_str return EMBED @keyword def capture_element_screenshot( self, - locator: Union[WebElement, str], + locator: Locator, filename: str = DEFAULT_FILENAME_ELEMENT, - ) -> str: + ) -> str | None: """Captures a screenshot from the element identified by ``locator`` and embeds it into log file. See `Capture Page Screenshot` for details about ``filename`` argument. 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( "Cannot capture screenshot from element because no browser is open." ) - return + return None 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 +195,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 +210,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 + filename == DEFAULT_FILENAME_PAGE.upper() + 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 + filename == DEFAULT_FILENAME_ELEMENT.upper() + 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: @@ -238,24 +264,25 @@ def _embed_to_log_as_file(self, path, width): f'', html=True, ) - + @keyword - def print_page_as_pdf(self, - filename: str = DEFAULT_FILENAME_PDF, - background: Optional[bool] = None, - margin_bottom: Optional[float] = None, - margin_left: Optional[float] = None, - margin_right: Optional[float] = None, - margin_top: Optional[float] = None, - orientation: Optional[Orientation] = None, - page_height: Optional[float] = None, - page_ranges: Optional[list] = None, - page_width: Optional[float] = None, - scale: Optional[float] = None, - shrink_to_fit: Optional[bool] = None, - # path_to_file=None, - ): - """ Print the current page as a PDF + def print_page_as_pdf( # noqa: PLR0912 C901 + self, + filename: str = DEFAULT_FILENAME_PDF, + background: bool | None = None, + margin_bottom: float | None = None, + margin_left: float | None = None, + margin_right: float | None = None, + margin_top: float | None = None, + orientation: Orientation | None = None, + page_height: float | None = None, + page_ranges: list | None = None, + page_width: float | None = None, + scale: float | None = None, + shrink_to_fit: bool | None = None, + # path_to_file=None, + ): + """Print the current page as a PDF ``page_ranges`` defaults to `['-']` or "all" pages. ``page_ranges`` takes a list of strings indicating the ranges. @@ -279,11 +306,11 @@ def print_page_as_pdf(self, """ if page_ranges is None: - page_ranges = ['-'] + page_ranges = ["-"] print_options = PrintOptions() if background is not None: - print_options.background = background + print_options.background = background if margin_bottom is not None: print_options.margin_bottom = margin_bottom if margin_left is not None: @@ -307,7 +334,7 @@ def print_page_as_pdf(self, if not self.drivers.current: self.info("Cannot print page to pdf because no browser is open.") - return + return None return self._print_page_as_pdf_to_file(filename, print_options) def _print_page_as_pdf_to_file(self, filename, options): @@ -315,13 +342,13 @@ def _print_page_as_pdf_to_file(self, filename, options): self._create_directory(path) pdfdata = self.driver.print_page(options) if not pdfdata: - raise RuntimeError(f"Failed to print page.") + raise RuntimeError("Failed to print page.") self._save_pdf_to_file(pdfdata, path) return path def _save_pdf_to_file(self, pdfbase64, path): pdfdata = b64decode(pdfbase64) - with open(path, mode='wb') as pdf: + with open(path, mode="wb") as pdf: pdf.write(pdfdata) def _get_pdf_path(self, filename): diff --git a/src/SeleniumLibrary/keywords/selectelement.py b/src/SeleniumLibrary/keywords/selectelement.py index 910fb081e..24b45978f 100644 --- a/src/SeleniumLibrary/keywords/selectelement.py +++ b/src/SeleniumLibrary/keywords/selectelement.py @@ -13,20 +13,17 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import List, Optional, Union -from selenium.webdriver.remote.webelement import WebElement from selenium.webdriver.support.ui import Select from SeleniumLibrary.base import LibraryComponent, keyword from SeleniumLibrary.utils import is_truthy, plural_or_not +from SeleniumLibrary.utils.types import Locator class SelectElementKeywords(LibraryComponent): @keyword - def get_list_items( - self, locator: Union[WebElement, str], values: bool = False - ) -> List[str]: + def get_list_items(self, locator: Locator, values: bool = False) -> list[str]: """Returns all labels or values of selection list ``locator``. See the `Locating elements` section for details about the locator @@ -45,11 +42,10 @@ def get_list_items( options = self._get_options(locator) if is_truthy(values): return self._get_values(options) - else: - return self._get_labels(options) + return self._get_labels(options) @keyword - def get_selected_list_label(self, locator: Union[WebElement, str]) -> str: + def get_selected_list_label(self, locator: Locator) -> str: """Returns the label of selected option from selection list ``locator``. If there are multiple selected options, the label of the first option @@ -62,7 +58,7 @@ def get_selected_list_label(self, locator: Union[WebElement, str]) -> str: return select.first_selected_option.text @keyword - def get_selected_list_labels(self, locator: Union[WebElement, str]) -> List[str]: + def get_selected_list_labels(self, locator: Locator) -> list[str]: """Returns labels of selected options from selection list ``locator``. Starting from SeleniumLibrary 3.0, returns an empty list if there @@ -75,7 +71,7 @@ def get_selected_list_labels(self, locator: Union[WebElement, str]) -> List[str] return self._get_labels(options) @keyword - def get_selected_list_value(self, locator: Union[WebElement, str]) -> str: + def get_selected_list_value(self, locator: Locator) -> str: """Returns the value of selected option from selection list ``locator``. If there are multiple selected options, the value of the first option @@ -88,7 +84,7 @@ def get_selected_list_value(self, locator: Union[WebElement, str]) -> str: return select.first_selected_option.get_attribute("value") @keyword - def get_selected_list_values(self, locator: Union[WebElement, str]) -> List[str]: + def get_selected_list_values(self, locator: Locator) -> list[str]: """Returns values of selected options from selection list ``locator``. Starting from SeleniumLibrary 3.0, returns an empty list if there @@ -101,7 +97,7 @@ def get_selected_list_values(self, locator: Union[WebElement, str]) -> List[str] return self._get_values(options) @keyword - def list_selection_should_be(self, locator: Union[WebElement, str], *expected: str): + def list_selection_should_be(self, locator: Locator, *expected: str): """Verifies selection list ``locator`` has ``expected`` options selected. It is possible to give expected options both as visible labels and @@ -135,10 +131,12 @@ def list_selection_should_be(self, locator: Union[WebElement, str], *expected: s ) def _format_selection(self, labels, values): - return " | ".join(f"{label} ({value})" for label, value in zip(labels, values)) + return " | ".join( + f"{label} ({value})" for label, value in zip(labels, values, strict=True) + ) @keyword - def list_should_have_no_selections(self, locator: Union[WebElement, str]): + def list_should_have_no_selections(self, locator: Locator): """Verifies selection list ``locator`` has no options selected. See the `Locating elements` section for details about the locator @@ -158,8 +156,8 @@ def list_should_have_no_selections(self, locator: Union[WebElement, str]): @keyword def page_should_contain_list( self, - locator: Union[WebElement, str], - message: Optional[str] = None, + locator: Locator, + message: str | None = None, loglevel: str = "TRACE", ): """Verifies selection list ``locator`` is found from current page. @@ -175,8 +173,8 @@ def page_should_contain_list( @keyword def page_should_not_contain_list( self, - locator: Union[WebElement, str], - message: Optional[str] = None, + locator: Locator, + message: str | None = None, loglevel: str = "TRACE", ): """Verifies selection list ``locator`` is not found from current page. @@ -190,7 +188,7 @@ def page_should_not_contain_list( self.assert_page_not_contains(locator, "list", message, loglevel) @keyword - def select_all_from_list(self, locator: Union[WebElement, str]): + def select_all_from_list(self, locator: Locator): """Selects all options from multi-selection list ``locator``. See the `Locating elements` section for details about the locator @@ -206,7 +204,7 @@ def select_all_from_list(self, locator: Union[WebElement, str]): select.select_by_index(index) @keyword - def select_from_list_by_index(self, locator: Union[WebElement, str], *indexes: str): + def select_from_list_by_index(self, locator: Locator, *indexes: str): """Selects options from selection list ``locator`` by ``indexes``. Indexes of list options start from 0. @@ -231,7 +229,7 @@ def select_from_list_by_index(self, locator: Union[WebElement, str], *indexes: s select.select_by_index(int(index)) @keyword - def select_from_list_by_value(self, locator: Union[WebElement, str], *values: str): + def select_from_list_by_value(self, locator: Locator, *values: str): """Selects options from selection list ``locator`` by ``values``. If more than one option is given for a single-selection list, @@ -253,7 +251,7 @@ def select_from_list_by_value(self, locator: Union[WebElement, str], *values: st select.select_by_value(value) @keyword - def select_from_list_by_label(self, locator: Union[WebElement, str], *labels: str): + def select_from_list_by_label(self, locator: Locator, *labels: str): """Selects options from selection list ``locator`` by ``labels``. If more than one option is given for a single-selection list, @@ -275,7 +273,7 @@ def select_from_list_by_label(self, locator: Union[WebElement, str], *labels: st select.select_by_visible_text(label) @keyword - def unselect_all_from_list(self, locator: Union[WebElement, str]): + def unselect_all_from_list(self, locator: Locator): """Unselects all options from multi-selection list ``locator``. See the `Locating elements` section for details about the locator @@ -292,9 +290,7 @@ def unselect_all_from_list(self, locator: Union[WebElement, str]): select.deselect_all() @keyword - def unselect_from_list_by_index( - self, locator: Union[WebElement, str], *indexes: str - ): + def unselect_from_list_by_index(self, locator: Locator, *indexes: str): """Unselects options from selection list ``locator`` by ``indexes``. Indexes of list options start from 0. This keyword works only with @@ -319,9 +315,7 @@ def unselect_from_list_by_index( select.deselect_by_index(int(index)) @keyword - def unselect_from_list_by_value( - self, locator: Union[WebElement, str], *values: str - ): + def unselect_from_list_by_value(self, locator: Locator, *values: str): """Unselects options from selection list ``locator`` by ``values``. This keyword works only with multi-selection lists. @@ -344,9 +338,7 @@ def unselect_from_list_by_value( select.deselect_by_value(value) @keyword - def unselect_from_list_by_label( - self, locator: Union[WebElement, str], *labels: str - ): + def unselect_from_list_by_label(self, locator: Locator, *labels: str): """Unselects options from selection list ``locator`` by ``labels``. This keyword works only with multi-selection lists. @@ -368,14 +360,14 @@ def unselect_from_list_by_label( for label in labels: select.deselect_by_visible_text(label) - def _get_select_list(self, locator: Union[WebElement, str]): + def _get_select_list(self, locator: Locator): el = self.find_element(locator, tag="list") return Select(el) - def _get_options(self, locator: Union[WebElement, str]): + def _get_options(self, locator: Locator): return self._get_select_list(locator).options - def _get_selected_options(self, locator: Union[WebElement, str]): + def _get_selected_options(self, locator: Locator): return self._get_select_list(locator).all_selected_options def _get_labels(self, options): diff --git a/src/SeleniumLibrary/keywords/tableelement.py b/src/SeleniumLibrary/keywords/tableelement.py index e054e9d77..a3100425f 100644 --- a/src/SeleniumLibrary/keywords/tableelement.py +++ b/src/SeleniumLibrary/keywords/tableelement.py @@ -13,19 +13,18 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Union from selenium.webdriver.common.by import By -from selenium.webdriver.remote.webelement import WebElement from SeleniumLibrary.base import LibraryComponent, keyword +from SeleniumLibrary.utils.types import Locator class TableElementKeywords(LibraryComponent): @keyword def get_table_cell( self, - locator: Union[WebElement, str], + locator: Locator, row: int, column: int, loglevel: str = "TRACE", @@ -89,7 +88,7 @@ def _get_rows(self, locator, count): @keyword def table_cell_should_contain( self, - locator: Union[WebElement, str], + locator: Locator, row: int, column: int, expected: str, @@ -112,7 +111,7 @@ def table_cell_should_contain( @keyword def table_column_should_contain( self, - locator: Union[WebElement, str], + locator: Locator, column: int, expected: str, loglevel: str = "TRACE", @@ -143,7 +142,7 @@ def table_column_should_contain( @keyword def table_footer_should_contain( self, - locator: Union[WebElement, str], + locator: Locator, expected: str, loglevel: str = "TRACE", ): @@ -168,7 +167,7 @@ def table_footer_should_contain( @keyword def table_header_should_contain( self, - locator: Union[WebElement, str], + locator: Locator, expected: str, loglevel: str = "TRACE", ): @@ -193,7 +192,7 @@ def table_header_should_contain( @keyword def table_row_should_contain( self, - locator: Union[WebElement, str], + locator: Locator, row: int, expected: str, loglevel: str = "TRACE", @@ -224,7 +223,7 @@ def table_row_should_contain( @keyword def table_should_contain( self, - locator: Union[WebElement, str], + locator: Locator, expected: str, loglevel: str = "TRACE", ): diff --git a/src/SeleniumLibrary/keywords/waiting.py b/src/SeleniumLibrary/keywords/waiting.py index eeec6756e..2d6cfe81e 100644 --- a/src/SeleniumLibrary/keywords/waiting.py +++ b/src/SeleniumLibrary/keywords/waiting.py @@ -16,14 +16,13 @@ import time from datetime import timedelta -from typing import Optional, Union from selenium.common.exceptions import StaleElementReferenceException -from selenium.webdriver.remote.webelement import WebElement from SeleniumLibrary.base import LibraryComponent, keyword from SeleniumLibrary.errors import ElementNotFound from SeleniumLibrary.utils import secs_to_timestr +from SeleniumLibrary.utils.types import Locator class WaitingKeywords(LibraryComponent): @@ -31,8 +30,8 @@ class WaitingKeywords(LibraryComponent): def wait_for_condition( self, condition: str, - timeout: Optional[timedelta] = None, - error: Optional[str] = None, + timeout: timedelta | None = None, + error: str | None = None, ): """Waits until ``condition`` is true or ``timeout`` expires. @@ -66,8 +65,8 @@ def wait_for_condition( def wait_until_location_is( self, expected: str, - timeout: Optional[timedelta] = None, - message: Optional[str] = None, + timeout: timedelta | None = None, + message: str | None = None, ): """Waits until the current URL is ``expected``. @@ -95,8 +94,8 @@ def wait_until_location_is( def wait_until_location_is_not( self, location: str, - timeout: Optional[timedelta] = None, - message: Optional[str] = None, + timeout: timedelta | None = None, + message: str | None = None, ): """Waits until the current URL is not ``location``. @@ -123,8 +122,8 @@ def wait_until_location_is_not( def wait_until_location_contains( self, expected: str, - timeout: Optional[timedelta] = None, - message: Optional[str] = None, + timeout: timedelta | None = None, + message: str | None = None, ): """Waits until the current URL contains ``expected``. @@ -151,8 +150,8 @@ def wait_until_location_contains( def wait_until_location_does_not_contain( self, location: str, - timeout: Optional[timedelta] = None, - message: Optional[str] = None, + timeout: timedelta | None = None, + message: str | None = None, ): """Waits until the current URL does not contains ``location``. @@ -179,8 +178,8 @@ def wait_until_location_does_not_contain( def wait_until_page_contains( self, text: str, - timeout: Optional[timedelta] = None, - error: Optional[str] = None, + timeout: timedelta | None = None, + error: str | None = None, ): """Waits until ``text`` appears on the current page. @@ -201,8 +200,8 @@ def wait_until_page_contains( def wait_until_page_does_not_contain( self, text: str, - timeout: Optional[timedelta] = None, - error: Optional[str] = None, + timeout: timedelta | None = None, + error: str | None = None, ): """Waits until ``text`` disappears from the current page. @@ -222,10 +221,10 @@ def wait_until_page_does_not_contain( @keyword def wait_until_page_contains_element( self, - locator: Union[WebElement, str], - timeout: Optional[timedelta] = None, - error: Optional[str] = None, - limit: Optional[int] = None, + locator: Locator, + timeout: timedelta | None = None, + error: str | None = None, + limit: int | None = None, ): """Waits until the element ``locator`` appears on the current page. @@ -244,12 +243,13 @@ def wait_until_page_contains_element( ``limit`` is new in SeleniumLibrary 4.4 """ if limit is None: - return self._wait_until( + self._wait_until( lambda: self.find_element(locator, required=False) is not None, f"Element '{locator}' did not appear in .", timeout, error, ) + return self._wait_until( lambda: len(self.find_elements(locator)) == limit, f'Page should have contained "{limit}" {locator} element(s) within .', @@ -260,10 +260,10 @@ def wait_until_page_contains_element( @keyword def wait_until_page_does_not_contain_element( self, - locator: Union[WebElement, str], - timeout: Optional[timedelta] = None, - error: Optional[str] = None, - limit: Optional[int] = None, + locator: Locator, + timeout: timedelta | None = None, + error: str | None = None, + limit: int | None = None, ): """Waits until the element ``locator`` disappears from the current page. @@ -282,12 +282,13 @@ def wait_until_page_does_not_contain_element( ``limit`` is new in SeleniumLibrary 4.4 """ if limit is None: - return self._wait_until( + self._wait_until( lambda: self.find_element(locator, required=False) is None, f"Element '{locator}' did not disappear in .", timeout, error, ) + return self._wait_until( lambda: len(self.find_elements(locator)) != limit, f'Page should have not contained "{limit}" {locator} element(s) within .', @@ -298,9 +299,9 @@ def wait_until_page_does_not_contain_element( @keyword def wait_until_element_is_visible( self, - locator: Union[WebElement, str], - timeout: Optional[timedelta] = None, - error: Optional[str] = None, + locator: Locator, + timeout: timedelta | None = None, + error: str | None = None, ): """Waits until the element ``locator`` is visible. @@ -321,9 +322,9 @@ def wait_until_element_is_visible( @keyword def wait_until_element_is_not_visible( self, - locator: Union[WebElement, str], - timeout: Optional[timedelta] = None, - error: Optional[str] = None, + locator: Locator, + timeout: timedelta | None = None, + error: str | None = None, ): """Waits until the element ``locator`` is not visible. @@ -344,9 +345,9 @@ def wait_until_element_is_not_visible( @keyword def wait_until_element_is_enabled( self, - locator: Union[WebElement, str], - timeout: Optional[timedelta] = None, - error: Optional[str] = None, + locator: Locator, + timeout: timedelta | None = None, + error: str | None = None, ): """Waits until the element ``locator`` is enabled. @@ -372,10 +373,10 @@ def wait_until_element_is_enabled( @keyword def wait_until_element_contains( self, - locator: Union[WebElement, str], + locator: Locator, text: str, - timeout: Optional[timedelta] = None, - error: Optional[str] = None, + timeout: timedelta | None = None, + error: str | None = None, ): """Waits until the element ``locator`` contains ``text``. @@ -396,10 +397,10 @@ def wait_until_element_contains( @keyword def wait_until_element_does_not_contain( self, - locator: Union[WebElement, str], + locator: Locator, text: str, - timeout: Optional[timedelta] = None, - error: Optional[str] = None, + timeout: timedelta | None = None, + error: str | None = None, ): """Waits until the element ``locator`` does not contain ``text``. diff --git a/src/SeleniumLibrary/keywords/webdrivertools/sl_file_detector.py b/src/SeleniumLibrary/keywords/webdrivertools/sl_file_detector.py index 73d26f539..841c357c6 100644 --- a/src/SeleniumLibrary/keywords/webdrivertools/sl_file_detector.py +++ b/src/SeleniumLibrary/keywords/webdrivertools/sl_file_detector.py @@ -33,12 +33,11 @@ def choose_file(self): sl = self._get_sl() except Exception: sl = None - if sl and sl._running_keyword == "choose_file": - return True - return False + return bool(sl and sl._running_keyword == "choose_file") def _get_sl(self): libraries = BuiltIn().get_library_instance(all=True) for library in libraries: if isinstance(libraries[library], SeleniumLibrary.SeleniumLibrary): return libraries[library] + return None diff --git a/src/SeleniumLibrary/keywords/webdrivertools/webdrivertools.py b/src/SeleniumLibrary/keywords/webdrivertools/webdrivertools.py index 3e05294ae..ae193efe3 100644 --- a/src/SeleniumLibrary/keywords/webdrivertools/webdrivertools.py +++ b/src/SeleniumLibrary/keywords/webdrivertools/webdrivertools.py @@ -18,15 +18,15 @@ import inspect import os import token -import warnings +from inspect import signature from io import StringIO from tokenize import generate_tokens +from typing import ClassVar from robot.api import logger from robot.utils import ConnectionCache from selenium import webdriver from selenium.webdriver import FirefoxProfile - from selenium.webdriver.chrome.service import Service as ChromeService from selenium.webdriver.edge.service import Service as EdgeService from selenium.webdriver.firefox.service import Service as FirefoxService @@ -40,8 +40,7 @@ class WebDriverCreator: - - browser_names = { + browser_names: ClassVar[dict] = { "googlechrome": "chrome", "gc": "chrome", "chrome": "chrome", @@ -80,10 +79,7 @@ def create_driver( if service_log_path: logger.info(f"Browser driver log file created to: {service_log_path}") self._create_directory(service_log_path) - if ( - creation_method == self.create_firefox - or creation_method == self.create_headless_firefox - ): + if creation_method in [self.create_firefox, self.create_headless_firefox]: return creation_method( desired_capabilities, remote_url, @@ -137,12 +133,10 @@ def _remote_capabilities_resolver(self, set_capabilities, default_capabilities): def _get_log_method(self, service_cls, service_log_path): # -- temporary fix to transition selenium to v4.13 from v4.11 and prior - from inspect import signature sig = signature(service_cls) - if 'log_output' in str(sig): - return {'log_output': service_log_path} - else: - return {'log_path': service_log_path} + if "log_output" in str(sig): + return {"log_output": service_log_path} + return {"log_path": service_log_path} # -- def create_chrome( @@ -159,7 +153,9 @@ def create_chrome( options = webdriver.ChromeOptions() return self._remote(remote_url, options=options) if not executable_path: - executable_path = self._get_executable_path(webdriver.chrome.service.Service) + executable_path = self._get_executable_path( + webdriver.chrome.service.Service + ) log_method = self._get_log_method(ChromeService, service_log_path) if not service: service = ChromeService(executable_path=executable_path, **log_method) @@ -179,9 +175,14 @@ def create_headless_chrome( ): if not options: options = webdriver.ChromeOptions() - options.add_argument('--headless=new') + options.add_argument("--headless=new") return self.create_chrome( - desired_capabilities, remote_url, options, service_log_path, executable_path, service + desired_capabilities, + remote_url, + options, + service_log_path, + executable_path, + service, ) def _get_executable_path(self, webdriver): @@ -215,8 +216,12 @@ def create_firefox( if remote_url: return self._remote(remote_url, options) if not executable_path: - executable_path = self._get_executable_path(webdriver.firefox.service.Service) - log_method = self._get_log_method(FirefoxService, service_log_path or self._geckodriver_log) + executable_path = self._get_executable_path( + webdriver.firefox.service.Service + ) + log_method = self._get_log_method( + FirefoxService, service_log_path or self._geckodriver_log + ) if service is None: service = FirefoxService(executable_path=executable_path, **log_method) return webdriver.Firefox( @@ -263,7 +268,7 @@ def create_headless_firefox( ): if not options: options = webdriver.FirefoxOptions() - options.add_argument('-headless') + options.add_argument("-headless") return self.create_firefox( desired_capabilities, remote_url, @@ -295,7 +300,7 @@ def create_ie( return webdriver.Ie( options=options, service=service, - #**desired_capabilities, + # **desired_capabilities, ) def _has_options(self, web_driver): @@ -323,7 +328,7 @@ def create_edge( return webdriver.Edge( options=options, service=service, - #**desired_capabilities, + # **desired_capabilities, ) def create_safari( @@ -461,10 +466,8 @@ def _get_index(self, alias_or_index): except ValueError: return None -class SeleniumService: - """ - """ +class SeleniumService: def create(self, browser, service): if not service: return None @@ -478,10 +481,13 @@ def create(self, browser, service): service_parameters = inspect.signature(selenium_service).parameters for key in attrs: if key not in service_parameters: - service_module = '.'.join((selenium_service.__module__, selenium_service.__qualname__)) - raise ValueError(f"{key} is not a member of {service_module} Service class") - selenium_service_inst = selenium_service(**attrs) - return selenium_service_inst + service_module = ".".join( + (selenium_service.__module__, selenium_service.__qualname__) + ) + raise ValueError( + f"{key} is not a member of {service_module} Service class" + ) + return selenium_service(**attrs) def _parse(self, service): """The service argument parses slightly different than the options argument. As of @@ -489,12 +495,14 @@ def _parse(self, service): instantiation. Thus each item is split instead parsed as done with options. """ result = {} - for item in self._split(service,';'): + for item in self._split(service, ";"): try: - attr, val = self._split(item, '=') - result[attr]=ast.literal_eval(val) - except (ValueError, SyntaxError): - raise ValueError(f'Unable to parse service: "{item}"') + attr, val = self._split(item, "=") + result[attr] = ast.literal_eval(val) + except (ValueError, SyntaxError) as original_exception: + raise ValueError( + f'Unable to parse service: "{item}"' + ) from original_exception return result def _import_service(self, browser): @@ -514,6 +522,7 @@ def _split(self, service_or_attr, splittok): split_string.append(service_or_attr[start_position:]) return split_string + class SeleniumOptions: def create(self, browser, options): if not options: @@ -525,8 +534,10 @@ def create(self, browser, options): selenium_options = selenium_options() for option in options: for key in option: - if key == '' and option[key]==[]: - logger.warn('Empty selenium option found and ignored. Suggested you review options passed to `Open Browser` keyword') + if key == "" and option[key] == []: + logger.warn( + "Empty selenium option found and ignored. Suggested you review options passed to `Open Browser` keyword" + ) continue attr = getattr(selenium_options, key) if callable(attr): @@ -575,8 +586,10 @@ def _parse(self, options): for item in self._split(options): try: result.append(self._parse_to_tokens(item)) - except (ValueError, SyntaxError): - raise ValueError(f'Unable to parse option: "{item}"') + except (ValueError, SyntaxError) as original_exception: + raise ValueError( + f'Unable to parse option: "{item}"' + ) from original_exception return result def _parse_to_tokens(self, item): diff --git a/src/SeleniumLibrary/keywords/window.py b/src/SeleniumLibrary/keywords/window.py index 01feee1fe..e0393cbe9 100644 --- a/src/SeleniumLibrary/keywords/window.py +++ b/src/SeleniumLibrary/keywords/window.py @@ -14,14 +14,12 @@ # See the License for the specific language governing permissions and # limitations under the License. import time -from typing import Optional, List, Tuple, Union -from SeleniumLibrary.utils import is_truthy, is_falsy, timestr_to_secs from selenium.common.exceptions import NoSuchWindowException -from SeleniumLibrary.base import keyword, LibraryComponent +from SeleniumLibrary.base import LibraryComponent, keyword from SeleniumLibrary.locators import WindowManager -from SeleniumLibrary.utils import plural_or_not, is_string +from SeleniumLibrary.utils import is_falsy, is_truthy, plural_or_not, timestr_to_secs class WindowKeywords(LibraryComponent): @@ -32,8 +30,8 @@ def __init__(self, ctx): @keyword def switch_window( self, - locator: Union[list, str] = "MAIN", - timeout: Optional[str] = None, + locator: list | str = "MAIN", + timeout: str | None = None, browser: str = "CURRENT", ): """Switches to browser window matching ``locator``. @@ -117,17 +115,17 @@ def switch_window( except NoSuchWindowException: pass finally: - if not is_string(browser) or not browser.upper() == "CURRENT": + if not isinstance(browser, str) or browser.upper() != "CURRENT": self.drivers.switch(browser) self._window_manager.select(locator, timeout) @keyword def close_window(self): - """Closes currently opened and selected browser window/tab. """ + """Closes currently opened and selected browser window/tab.""" self.driver.close() @keyword - def get_window_handles(self, browser: str = "CURRENT") -> List[str]: + def get_window_handles(self, browser: str = "CURRENT") -> list[str]: """Returns all child window handles of the selected browser as a list. Can be used as a list of windows to exclude with `Select Window`. @@ -139,7 +137,7 @@ def get_window_handles(self, browser: str = "CURRENT") -> List[str]: return self._window_manager.get_window_handles(browser) @keyword - def get_window_identifiers(self, browser: str = "CURRENT") -> List: + def get_window_identifiers(self, browser: str = "CURRENT") -> list: """Returns and logs id attributes of all windows of the selected browser. How to select the ``browser`` scope of this keyword, see `Get Locations`.""" @@ -147,7 +145,7 @@ def get_window_identifiers(self, browser: str = "CURRENT") -> List: return self._log_list(ids) @keyword - def get_window_names(self, browser: str = "CURRENT") -> List[str]: + def get_window_names(self, browser: str = "CURRENT") -> list[str]: """Returns and logs names of all windows of the selected browser. How to select the ``browser`` scope of this keyword, see `Get Locations`.""" @@ -155,7 +153,7 @@ def get_window_names(self, browser: str = "CURRENT") -> List[str]: return self._log_list(names) @keyword - def get_window_titles(self, browser: str = "CURRENT") -> List[str]: + def get_window_titles(self, browser: str = "CURRENT") -> list[str]: """Returns and logs titles of all windows of the selected browser. How to select the ``browser`` scope of this keyword, see `Get Locations`.""" @@ -163,7 +161,7 @@ def get_window_titles(self, browser: str = "CURRENT") -> List[str]: return self._log_list(titles) @keyword - def get_locations(self, browser: str = "CURRENT") -> List[str]: + def get_locations(self, browser: str = "CURRENT") -> list[str]: """Returns and logs URLs of all windows of the selected browser. *Browser Scope:* @@ -192,7 +190,7 @@ def minimize_browser_window(self): self.driver.minimize_window() @keyword - def get_window_size(self, inner: bool = False) -> Tuple[float, float]: + def get_window_size(self, inner: bool = False) -> tuple[float, float]: """Returns current window width and height as integers. See also `Set Window Size`. @@ -239,7 +237,8 @@ def set_window_size(self, width: int, height: int, inner: bool = False): | `Set Window Size` | 800 | 600 | True | """ if is_falsy(inner): - return self.driver.set_window_size(width, height) + self.driver.set_window_size(width, height) + return self.driver.set_window_size(width, height) inner_width = int(self.driver.execute_script("return window.innerWidth;")) inner_height = int(self.driver.execute_script("return window.innerHeight;")) @@ -258,7 +257,7 @@ def set_window_size(self, width: int, height: int, inner: bool = False): raise AssertionError("Keyword failed setting correct window size.") @keyword - def get_window_position(self) -> Tuple[int, int]: + def get_window_position(self) -> tuple[int, int]: """Returns current window position. The position is relative to the top left corner of the screen. Returned diff --git a/src/SeleniumLibrary/locators/customlocator.py b/src/SeleniumLibrary/locators/customlocator.py index ab967e0e2..96555c7a2 100644 --- a/src/SeleniumLibrary/locators/customlocator.py +++ b/src/SeleniumLibrary/locators/customlocator.py @@ -31,7 +31,7 @@ def find(self, criteria, tag, constraints, parent): element = BuiltIn().run_keyword( self.finder, parent, criteria, tag, constraints ) - elif hasattr(self.finder, "__call__"): + elif callable(self.finder): element = self.finder(parent, criteria, tag, constraints) else: raise AttributeError( @@ -41,5 +41,4 @@ def find(self, criteria, tag, constraints, parent): # Always return an array if hasattr(element, "__len__") and not isinstance(element, str): return element - else: - return [element] + return [element] diff --git a/src/SeleniumLibrary/locators/elementfinder.py b/src/SeleniumLibrary/locators/elementfinder.py index d74486a3e..b3749b522 100644 --- a/src/SeleniumLibrary/locators/elementfinder.py +++ b/src/SeleniumLibrary/locators/elementfinder.py @@ -14,13 +14,12 @@ # See the License for the specific language governing permissions and # limitations under the License. import re -from typing import Union from robot.api import logger from robot.utils import NormalizedDict +from selenium.webdriver.common.by import By from selenium.webdriver.remote.webelement import WebElement from selenium.webdriver.support.event_firing_webdriver import EventFiringWebElement -from selenium.webdriver.common.by import By from SeleniumLibrary.base import ContextAware from SeleniumLibrary.errors import ElementNotFound @@ -78,7 +77,7 @@ def __init__(self, ctx): def find( self, - locator: Union[str, list], + locator: str | list, tag=None, first_only=True, required=True, @@ -92,7 +91,7 @@ def find( ) return self._find(locators[-1], tag, first_only, required, element) - def _split_locator(self, locator: Union[str, list]) -> list: + def _split_locator(self, locator: str | list) -> list: if isinstance(locator, list): return locator if not isinstance(locator, str): @@ -223,13 +222,13 @@ def _find_by_tag_name(self, criteria, tag, constraints, parent): def _find_by_data_locator(self, criteria, tag, constraints, parent): try: - name, value = criteria.split(":", 2) + name, value = criteria.split(":", 1) if "" in [name, value]: raise ValueError - except ValueError: + except ValueError as original_exception: raise ValueError( f"Provided selector ({criteria}) is malformed. Correct format: name:value." - ) + ) from original_exception local_criteria = f'//*[@data-{name}="{value}"]' return self._find_by_xpath(local_criteria, tag, constraints, parent) @@ -257,20 +256,18 @@ def _find_by_default(self, criteria, tag, constraints, parent): return self._normalize(parent.find_elements(By.XPATH, xpath)) def _get_xpath_constraints(self, constraints): - xpath_constraints = [ + return [ self._get_xpath_constraint(name, value) for name, value in constraints.items() ] - return xpath_constraints def _get_xpath_constraint(self, name, value): if isinstance(value, list): value = "' or . = '".join(value) return f"@{name}[. = '{value}']" - else: - return f"@{name}='{value}'" + return f"@{name}='{value}'" - def _get_tag_and_constraints(self, tag): + def _get_tag_and_constraints(self, tag): # noqa: C901 if tag is None: return None, {} tag = tag.lower() @@ -331,7 +328,7 @@ def _get_locator_separator_index(self, locator): return min(locator.find("="), locator.find(":")) def _element_matches(self, element, tag, constraints): - if not element.tag_name.lower() == tag: + if element.tag_name.lower() != tag: return False for name in constraints: if isinstance(constraints[name], list): diff --git a/src/SeleniumLibrary/locators/windowmanager.py b/src/SeleniumLibrary/locators/windowmanager.py index 1dcff9330..8244c8236 100644 --- a/src/SeleniumLibrary/locators/windowmanager.py +++ b/src/SeleniumLibrary/locators/windowmanager.py @@ -15,16 +15,20 @@ # limitations under the License. import time -from collections import namedtuple +from typing import NamedTuple from selenium.common.exceptions import NoSuchWindowException, WebDriverException from SeleniumLibrary.base import ContextAware from SeleniumLibrary.errors import WindowNotFound -from SeleniumLibrary.utils import is_string -WindowInfo = namedtuple("WindowInfo", "handle, id, name, title, url") +class WindowInfo(NamedTuple): + handle: str + id: object + name: str + title: str + url: str class WindowManager(ContextAware): @@ -38,42 +42,40 @@ 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): + for index, _driver in enumerate(self.drivers, 1): self.drivers.switch(index) handles.extend(self.driver.window_handles) self.drivers.switch(current_index) return handles - elif is_string(browser) and browser == "CURRENT": + if isinstance(browser, str) and browser == "CURRENT": return self.driver.window_handles - else: - current_index = self.drivers.current_index - self.drivers.switch(browser) - handles = self.driver.window_handles - self.drivers.switch(current_index) - return handles + current_index = self.drivers.current_index + self.drivers.switch(browser) + handles = self.driver.window_handles + self.drivers.switch(current_index) + return handles def get_window_infos(self, browser="CURRENT"): try: 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): + 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": + if isinstance(browser, str) and browser.upper() == "CURRENT": return self._get_window_infos() - else: - self.drivers.switch(browser) - infos = self._get_window_infos() - self.drivers.switch(current_index) - return infos + self.drivers.switch(browser) + infos = self._get_window_infos() + self.drivers.switch(current_index) + return infos def _get_window_infos(self): infos = [] @@ -100,7 +102,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 @@ -197,14 +199,16 @@ def _select_matching(self, matcher, error): def _get_current_window_info(self): try: - id, name = self.driver.execute_script("return [ window.id, window.name ];") + window_id, name = self.driver.execute_script( + "return [ window.id, window.name ];" + ) except WebDriverException: # The webdriver implementation doesn't support Javascript so we # can't get window id or name this way. - id = name = None + window_id = name = None return WindowInfo( self.driver.current_window_handle, - id if id is not None else "undefined", + window_id if window_id is not None else "undefined", name or "undefined", self.driver.title or "undefined", self.driver.current_url or "undefined", diff --git a/src/SeleniumLibrary/utils/__init__.py b/src/SeleniumLibrary/utils/__init__.py index ccc4df2c6..1a368f764 100644 --- a/src/SeleniumLibrary/utils/__init__.py +++ b/src/SeleniumLibrary/utils/__init__.py @@ -17,15 +17,13 @@ from robot.utils import plural_or_not, secs_to_timestr, timestr_to_secs # noqa from .librarylistener import LibraryListener # noqa -from .types import ( +from .types import ( # noqa is_falsy, is_noney, - is_string, is_truthy, - WINDOWS, _convert_timeout, _convert_delay, -) # noqa +) def escape_xpath_value(value: str): diff --git a/src/SeleniumLibrary/utils/events/__init__.py b/src/SeleniumLibrary/utils/events/__init__.py index edbae3fb5..d1f90519d 100644 --- a/src/SeleniumLibrary/utils/events/__init__.py +++ b/src/SeleniumLibrary/utils/events/__init__.py @@ -14,10 +14,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -from .scope_event import ScopeStart, ScopeEnd +from .scope_event import ScopeEnd, ScopeStart - -__all__ = ["on", "dispatch", "register_event"] +__all__ = ["dispatch", "on", "register_event"] _registered_events = [ScopeStart, ScopeEnd] _events = [] diff --git a/src/SeleniumLibrary/utils/events/event.py b/src/SeleniumLibrary/utils/events/event.py index 711ea7af4..ec5381548 100644 --- a/src/SeleniumLibrary/utils/events/event.py +++ b/src/SeleniumLibrary/utils/events/event.py @@ -15,8 +15,8 @@ # limitations under the License. import abc -from selenium.webdriver.support.event_firing_webdriver import EventFiringWebElement -from robot.api import logger + +import selenium class Event: @@ -26,8 +26,4 @@ def trigger(self, *args, **kwargs): def selenium_major_version(): - import selenium - - selenium_version = selenium.__version__ - (major, *sub_versions) = selenium_version.split(".") - return int(major) + return int(selenium.__version__.split(".", 1)[0]) diff --git a/src/SeleniumLibrary/utils/types.py b/src/SeleniumLibrary/utils/types.py index 82a94ada5..c2d9edc82 100644 --- a/src/SeleniumLibrary/utils/types.py +++ b/src/SeleniumLibrary/utils/types.py @@ -13,27 +13,47 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -import os from datetime import timedelta -from typing import Any +from typing import Any, TypeAlias -from robot.utils import is_string, timestr_to_secs -from robot.utils import is_truthy, is_falsy # noqa +from robot.utils import is_falsy, is_truthy, timestr_to_secs # noqa +from selenium.webdriver.remote.webelement import WebElement -# Need only for unit tests and can be removed when Approval tests fixes: -# https://github.com/approvals/ApprovalTests.Python/issues/41 -WINDOWS = os.name == "nt" +try: + from robot.api.types import Secret +except ImportError: + # Secret was introduced in Robot Framework 7.4. On older versions we + # provide a minimal stand-in so that the type hint ``str | Secret`` and + # ``isinstance`` checks work without requiring an upgrade. + class Secret: # type: ignore[no-redef] + """Stand-in for ``robot.api.types.Secret`` on Robot Framework < 7.4. + + Exposes the same ``.value`` attribute and masked string representation + as the real class, so keyword code can treat both identically. + """ + + def __init__(self, value: str): + self.value = value + + def __str__(self) -> str: + return "" + + def __repr__(self) -> str: + return f"{type(self).__name__}(value=)" + + +Locator: TypeAlias = WebElement | str | list["Locator"] 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): return delay.microseconds // 1000 - else: - x = timestr_to_secs(delay) - return int( x * 1000) + x = timestr_to_secs(delay) + return int(x * 1000) def _convert_timeout(timeout): diff --git a/tasks.py b/tasks.py index 84c093b98..6b350d6da 100644 --- a/tasks.py +++ b/tasks.py @@ -4,11 +4,10 @@ import bs4 from docutils.core import publish_cmdline from invoke import task -from rellu import initialize_labels, ReleaseNotesGenerator, Version +from rellu import ReleaseNotesGenerator, Version, initialize_labels from rellu.tasks import clean # noqa from robot.libdoc import libdoc - assert Path.cwd() == Path(__file__).parent VERSION_PATTERN = '__version__ = "(.*)"' @@ -110,7 +109,7 @@ def project_docs(ctx): "docs/index.html", ] publish_cmdline(writer_name="html5", argv=args) - print(Path(args[-1]).absolute()) + print(Path(args[-1]).absolute()) # noqa: T201 @task @@ -133,13 +132,13 @@ def set_version(ctx, version): """ version = Version(version, VERSION_PATH, VERSION_PATTERN) version.write() - print(version) + print(version) # noqa: T201 @task def print_version(ctx): """Print the current project version.""" - print(Version(path=VERSION_PATH)) + print(Version(path=VERSION_PATH)) # noqa: T201 @task @@ -186,11 +185,29 @@ def init_labels(ctx, username=None, password=None): @task -def lint(ctx): - """Runs black and flake8 for project Python code.""" - ctx.run("black --config pyproject.toml tasks.py src/ utest/ atest/") - ctx.run("flake8 --config .flake8 tasks.py src/ utest/ atest/") +def lint(ctx, fix=False): + """Run Ruff lint checks. + Args: + fix: Apply safe fixes when True. Defaults to False. + """ + cmd = f"{sys.executable} -m ruff check --config pyproject.toml tasks.py src/ utest/" # atest/" + if fix: + cmd = f"{cmd} --fix" + ctx.run(cmd) + +@task +def formatter(ctx, check=False): + """Run Ruff formatter. + + Args: + check: When True, only check formatting and show diff. + When False, apply formatting changes. + """ + cmd = f"{sys.executable} -m ruff format --config pyproject.toml src/ utest/ atest/" + if check: + cmd = f"{cmd} --check --diff" + ctx.run(cmd) @task def gen_stub(ctx): @@ -207,12 +224,12 @@ def atest(ctx, suite=None): Args: suite: Select which suite to run. - + Example: inv utest --suite keywords/test_browsermanagement.py inv utest --suite keywords/test_selenium_options_parser.py::test_create_chrome_with_options """ - command = "python atest/run.py headlesschrome" + command = f"{sys.executable} atest/run.py headlesschrome" if suite: command = f"{command} --suite {suite}" ctx.run(command) diff --git a/utest/run.py b/utest/run.py index f201c61f2..4f4785dce 100755 --- a/utest/run.py +++ b/utest/run.py @@ -1,13 +1,13 @@ #!/usr/bin/env python import argparse +import logging import os import shutil import sys from os.path import join from pathlib import Path -from pytest import main as py_main - +import pytest CURDIR = Path(__file__).parent SRC = join(CURDIR, os.pardir, "src") @@ -38,9 +38,9 @@ def run_unit_tests(reporter, reporter_args, suite, verbose): if reporter_args: py_args.insert(1, f"--approvaltests-add-reporter-args={reporter_args}") try: - result = py_main(py_args) + result = pytest.main(py_args) except Exception as error: - print(f"Suppressed error: {error}") + logging.exception(f"Suppressed error: {error}") result = 254 finally: sys.path.pop(0) diff --git a/utest/test/api/approved_files/PluginDocumentation.test_many_plugins.approved.txt b/utest/test/api/approved_files/PluginDocumentation.test_many_plugins.approved.txt index 447445852..e6909280a 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 @@ -142,20 +142,20 @@ space. It is also possible mix different locator strategies, example css or xpat used to specify multiple locators. This is useful, is some part of locator would match as the locator separator but it should not. Or if there is need to existing WebElement as locator. -Although all locators support chaining, some locator strategies do not abey the chaining. This is because +Although all locators support chaining, some locator strategies do not obey the chaining. This is because some locator strategies use JavaScript to find elements and JavaScript is executed for the whole browser context and not for the element found be the previous locator. Chaining is supported by locator strategies which are based on Selenium API, like `xpath` or `css`, but example chaining is not supported by `sizzle` or `jquery Examples: -| `Click Element` | css:.bar >> xpath://a | # To find a link which is present after an element with class "bar" | +| `Click Element` | css:.bar >> xpath: //a | # To find a link which is present after an element with class "bar" | List examples: -| ${locator_list} = | `Create List` | css:div#div_id | xpath://*[text(), " >> "] | -| `Page Should Contain Element` | ${locator_list} | | | -| ${element} = | Get WebElement | xpath://*[text(), " >> "] | | -| ${locator_list} = | `Create List` | css:div#div_id | ${element} | -| `Page Should Contain Element` | ${locator_list} | | | +| ${locator_list} = | `Create List` | css:div#div_id | xpath: //*[text(), " >> "] | +| `Page Should Contain Element` | ${locator_list} | | | +| ${element} = | Get WebElement | xpath: //*[text(), " >> "] | | +| ${locator_list} = | `Create List` | css:div#div_id | ${element} | +| `Page Should Contain Element` | ${locator_list} | | | Chaining locators in new in SeleniumLibrary 5.0 @@ -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 @@ -463,7 +463,7 @@ arguments to boolean values. = EventFiringWebDriver = The SeleniumLibrary offers support for -[https://seleniumhq.github.io/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.event_firing_webdriver.html#module-selenium.webdriver.support.event_firing_webdriver|EventFiringWebDriver]. +[https://www.selenium.dev/selenium/docs/api/py/selenium_webdriver_support/selenium.webdriver.support.event_firing_webdriver.html#module-selenium.webdriver.support.event_firing_webdriver|EventFiringWebDriver]. See the Selenium and SeleniumLibrary [https://github.com/robotframework/SeleniumLibrary/blob/master/docs/extending/extending.rst#EventFiringWebDriver|EventFiringWebDriver support] documentation for further details. 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..9d42a3b01 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,14 +7,14 @@ 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. - ``event_firing_webdriver``: Class for wrapping Selenium with - [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.event_firing_webdriver.html#module-selenium.webdriver.support.event_firing_webdriver|EventFiringWebDriver] + [https://www.selenium.dev/selenium/docs/api/py/selenium_webdriver_support/selenium.webdriver.support.event_firing_webdriver.html#module-selenium.webdriver.support.event_firing_webdriver|EventFiringWebDriver] - ``page_load_timeout``: Default value to wait for page load to complete until a timeout exception is raised. - ``action_chain_delay``: diff --git a/utest/test/api/approved_files/PluginDocumentation.test_parse_plugin_kw_doc.approved.txt b/utest/test/api/approved_files/PluginDocumentation.test_parse_plugin_kw_doc.approved.txt index cd6a05c98..cad1b65de 100644 --- a/utest/test/api/approved_files/PluginDocumentation.test_parse_plugin_kw_doc.approved.txt +++ b/utest/test/api/approved_files/PluginDocumentation.test_parse_plugin_kw_doc.approved.txt @@ -19,7 +19,7 @@ This keyword returns whatever the executed JavaScript code returns. Return values are converted to the appropriate Python types. Starting from SeleniumLibrary 3.2 it is possible to provide JavaScript -[https://seleniumhq.github.io/selenium/docs/api/py/webdriver_remote/selenium.webdriver.remote.webdriver.html#selenium.webdriver.remote.webdriver.WebDriver.execute_script| +[https://www.selenium.dev/selenium/docs/api/py/selenium_webdriver_remote/selenium.webdriver.remote.webdriver.html#selenium.webdriver.remote.webdriver.WebDriver.execute_script| arguments] as part of ``code`` argument. The JavaScript code and arguments must be separated with `JAVASCRIPT` and `ARGUMENTS` markers and must be used exactly with this format. If the Javascript code is diff --git a/utest/test/api/my_lib.py b/utest/test/api/my_lib.py index b5c45c932..dd7667c1e 100644 --- a/utest/test/api/my_lib.py +++ b/utest/test/api/my_lib.py @@ -1,7 +1,7 @@ from SeleniumLibrary.base import LibraryComponent, keyword -class my_lib(LibraryComponent): +class my_lib(LibraryComponent): # noqa: N801 - prefer RF syntax for test libraries """Some dummy documentation. = my_lib Heading 1 = diff --git a/utest/test/api/my_lib_args.py b/utest/test/api/my_lib_args.py index e1736ca02..0cdab7839 100644 --- a/utest/test/api/my_lib_args.py +++ b/utest/test/api/my_lib_args.py @@ -1,7 +1,7 @@ from SeleniumLibrary.base import LibraryComponent, keyword -class my_lib_args(LibraryComponent): +class my_lib_args(LibraryComponent): # noqa: N801 - prefer RF syntax for test libraries def __init__(self, ctx, arg1, arg2, *args, **kwargs): LibraryComponent.__init__(self, ctx) self.arg1 = arg1 diff --git a/utest/test/api/my_lib_not_inherit.py b/utest/test/api/my_lib_not_inherit.py index 37210be63..847b3157c 100644 --- a/utest/test/api/my_lib_not_inherit.py +++ b/utest/test/api/my_lib_not_inherit.py @@ -1,7 +1,7 @@ from SeleniumLibrary.base import keyword -class my_lib_not_inherit: +class my_lib_not_inherit: # noqa: N801 - prefer RF syntax for test libraries def __init__(self, ctx): self.ctx = ctx diff --git a/utest/test/api/my_lib_wrong_name.py b/utest/test/api/my_lib_wrong_name.py index 8d23a5ba3..49724e70f 100644 --- a/utest/test/api/my_lib_wrong_name.py +++ b/utest/test/api/my_lib_wrong_name.py @@ -1,7 +1,7 @@ from SeleniumLibrary.base import LibraryComponent, keyword -class my_lib(LibraryComponent): +class my_lib(LibraryComponent): # noqa: N801 - prefer RF syntax for test libraries @keyword def tidii(self, arg): self.info(arg) diff --git a/utest/test/api/plugin_tester.py b/utest/test/api/plugin_tester.py index 1df9b23e6..39480f1b6 100644 --- a/utest/test/api/plugin_tester.py +++ b/utest/test/api/plugin_tester.py @@ -1,7 +1,7 @@ from SeleniumLibrary.base import LibraryComponent, keyword -class plugin_tester(LibraryComponent): +class PluginTester(LibraryComponent): def __init__(self, ctx): LibraryComponent.__init__(self, ctx) ctx.event_firing_webdriver = "should be last" @@ -13,3 +13,6 @@ def foo(self): @keyword def bar(self, arg): self.info(arg) + + +plugin_tester = PluginTester diff --git a/utest/test/api/plugin_with_event_firing_webdriver.py b/utest/test/api/plugin_with_event_firing_webdriver.py index 4246838e6..d90c34ab7 100644 --- a/utest/test/api/plugin_with_event_firing_webdriver.py +++ b/utest/test/api/plugin_with_event_firing_webdriver.py @@ -1,9 +1,8 @@ from SeleniumLibrary.base import LibraryComponent, keyword -class plugin_with_event_firing_webdriver(LibraryComponent): - - """This is example for plugin_with_event_firing_webdriver plugin documentation. +class PluginWithEventFiringWebdriver(LibraryComponent): + """This is example for PluginWithEventFiringWebdriver plugin documentation. It may contains many chapters and there might be many words in the documentation. This is really boring example but let @@ -11,11 +10,11 @@ class plugin_with_event_firing_webdriver(LibraryComponent): There might be reference to keywords, like `Open Browser` - == plugin_with_event_firing_webdriver Heading 2 part 1 == + == PluginWithEventFiringWebdriver Heading 2 part 1 == This is chapter in heading 2. - == plugin_with_event_firing_webdriver Heading 2 part 2== + == PluginWithEventFiringWebdriver Heading 2 part 2== This is another chapter in heading 2 """ @@ -32,3 +31,6 @@ def __init__(self, ctx): @keyword def tidii(self): self.info("foo") + + +plugin_with_event_firing_webdriver = PluginWithEventFiringWebdriver diff --git a/utest/test/api/test_accessing_keywod_methods.py b/utest/test/api/test_accessing_keywod_methods.py index 9576a7f4c..8049c676a 100644 --- a/utest/test/api/test_accessing_keywod_methods.py +++ b/utest/test/api/test_accessing_keywod_methods.py @@ -1,5 +1,7 @@ import unittest +import pytest + from SeleniumLibrary import SeleniumLibrary @@ -9,19 +11,19 @@ def setUpClass(cls): cls.selib = SeleniumLibrary() def test_kw_with_method_name(self): - self.assertTrue(self.selib.keywords["add_cookie"]) - self.assertTrue(self.selib.attributes["add_cookie"]) - self.assertTrue(self.selib.keywords["page_should_contain_image"]) - self.assertTrue(self.selib.attributes["page_should_contain_image"]) + assert self.selib.keywords["add_cookie"] + assert self.selib.attributes["add_cookie"] + assert self.selib.keywords["page_should_contain_image"] + assert self.selib.attributes["page_should_contain_image"] def test_kw_with_methods_name_do_not_have_kw_name(self): - with self.assertRaises(KeyError): + with pytest.raises(KeyError): self.selib.keywords["Add Cookie"] - with self.assertRaises(KeyError): + with pytest.raises(KeyError): self.selib.keywords["Page Should Contain Image"] def test_kw_with_decorated_name(self): - self.assertTrue(self.selib.attributes["get_webelement"]) - self.assertTrue(self.selib.keywords["Get WebElement"]) - self.assertTrue(self.selib.attributes["get_webelements"]) - self.assertTrue(self.selib.keywords["Get WebElements"]) + assert self.selib.attributes["get_webelement"] + assert self.selib.keywords["Get WebElement"] + assert self.selib.attributes["get_webelements"] + assert self.selib.keywords["Get WebElements"] diff --git a/utest/test/api/test_event_firing_webdriver.py b/utest/test/api/test_event_firing_webdriver.py index 205eace61..d9c03ef1d 100644 --- a/utest/test/api/test_event_firing_webdriver.py +++ b/utest/test/api/test_event_firing_webdriver.py @@ -1,6 +1,7 @@ import os import unittest +import pytest from robot.errors import DataError from selenium.webdriver.support.events import AbstractEventListener @@ -19,13 +20,18 @@ def test_import_event_firing_webdriver(self): def test_no_event_firing_webdriver(self): sl = SeleniumLibrary() - self.assertIsNone(sl.event_firing_webdriver) + assert sl.event_firing_webdriver is None def test_import_event_firing_webdriver_error_module(self): listener = os.path.join(self.root_dir, "MyListenerWrongName.py") - with self.assertRaises(DataError): + with pytest.raises( + DataError, match=r"Importing test Selenium lister class '.*' failed." + ): SeleniumLibrary(event_firing_webdriver=listener) def test_too_many_event_firing_webdriver(self): - with self.assertRaises(ValueError): + with pytest.raises( + ValueError, + match=r"It is possible to import only one listener but there were 2 listeners.", + ): SeleniumLibrary(event_firing_webdriver=f"{self.listener},{self.listener}") diff --git a/utest/test/api/test_filepath_unusual_characters.py b/utest/test/api/test_filepath_unusual_characters.py index fdfc5fa9d..395d1e87a 100644 --- a/utest/test/api/test_filepath_unusual_characters.py +++ b/utest/test/api/test_filepath_unusual_characters.py @@ -5,7 +5,6 @@ from approvaltests.reporters.generic_diff_reporter_factory import ( GenericDiffReporterFactory, ) -from robot.utils import WINDOWS from SeleniumLibrary.utils.path_formatter import _format_path @@ -21,7 +20,6 @@ def reporter(): return factory.get_first_working() -@pytest.mark.skipif(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_normal_file_path(reporter): results = [] results.append(_format_path("/foo/file.log", 1)) diff --git a/utest/test/api/test_plugin_documentation.py b/utest/test/api/test_plugin_documentation.py index 3e1c273f2..06c5a6e1f 100644 --- a/utest/test/api/test_plugin_documentation.py +++ b/utest/test/api/test_plugin_documentation.py @@ -2,10 +2,11 @@ import unittest from approvaltests.approvals import verify +from approvaltests.reporters.first_working_reporter import FirstWorkingReporter from approvaltests.reporters.generic_diff_reporter_factory import ( GenericDiffReporterFactory, ) -from robot.utils import WINDOWS +from approvaltests.reporters.python_native_reporter import PythonNativeReporter from SeleniumLibrary import SeleniumLibrary @@ -24,21 +25,20 @@ def setUp(self): ) factory = GenericDiffReporterFactory() factory.load(reporter_json) - self.reporter = factory.get_first_working() + self.reporter = FirstWorkingReporter( + factory.get_first_working(), PythonNativeReporter() + ) - @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_many_plugins(self): sl = SeleniumLibrary( plugins=f"{self.plugin_1}, {self.plugin_3};arg1=Text1;arg2=Text2" ) verify(sl.get_keyword_documentation("__intro__"), self.reporter) - @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_parse_plugin_init_doc(self): sl = SeleniumLibrary(plugins=f"{self.plugin_3};arg1=Text1;arg2=Text2") verify(sl.get_keyword_documentation("__init__"), self.reporter) - @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_parse_plugin_kw_doc(self): sl = SeleniumLibrary(plugins=f"{self.plugin_3};arg1=Text1;arg2=Text2") verify(sl.get_keyword_documentation("execute_javascript"), self.reporter) diff --git a/utest/test/api/test_plugin_keyword_tags.py b/utest/test/api/test_plugin_keyword_tags.py index 368f67783..8e4292bf6 100644 --- a/utest/test/api/test_plugin_keyword_tags.py +++ b/utest/test/api/test_plugin_keyword_tags.py @@ -2,6 +2,7 @@ import unittest from SeleniumLibrary import SeleniumLibrary + from .my_lib import my_lib from .my_lib_args import my_lib_args @@ -16,33 +17,33 @@ def setUpClass(cls): def test_no_plugin(self): sl = SeleniumLibrary() tags = sl.get_keyword_tags("open_browser") - self.assertFalse(tags) + assert not tags def test_store_plugin_keywords(self): sl = SeleniumLibrary() sl._store_plugin_keywords(my_lib("0")) - self.assertEqual(sl._plugin_keywords, ["bar", "foo"]) + assert sl._plugin_keywords == ["bar", "foo"] def test_store_plugin_keywords_with_args(self): sl = SeleniumLibrary() sl._store_plugin_keywords(my_lib_args("000", "111", "222")) - self.assertEqual(sl._plugin_keywords, ["add_cookie", "bar_2", "foo_1"]) + assert sl._plugin_keywords == ["add_cookie", "bar_2", "foo_1"] def test_tags_in_plugin(self): sl = SeleniumLibrary(plugins=self.plugin) tags = sl.get_keyword_tags("foo") - self.assertEqual(tags, ["plugin"]) + assert tags == ["plugin"] tags = sl.get_keyword_tags("open_browser") - self.assertFalse(tags) + assert not tags def test_tags_in_plugin_args(self): sl = SeleniumLibrary(plugins=f"{self.plugin_varargs};foo;bar") tags = sl.get_keyword_tags("foo_1") - self.assertEqual(tags, ["MyTag", "plugin"]) + assert tags == ["MyTag", "plugin"] tags = sl.get_keyword_tags("open_browser") - self.assertFalse(tags) + assert not tags tags = sl.get_keyword_tags("add_cookie") - self.assertEqual(tags, ["plugin"]) + assert tags == ["plugin"] diff --git a/utest/test/api/test_plugins.py b/utest/test/api/test_plugins.py index c8241d8ba..d7fba9665 100644 --- a/utest/test/api/test_plugins.py +++ b/utest/test/api/test_plugins.py @@ -1,7 +1,8 @@ -from collections import namedtuple import os import unittest +from typing import NamedTuple +import pytest from robot.errors import DataError from SeleniumLibrary import SeleniumLibrary @@ -13,7 +14,12 @@ class ExtendingSeleniumLibrary(unittest.TestCase): def setUpClass(cls): cls.sl = SeleniumLibrary() cls.root_dir = os.path.dirname(os.path.abspath(__file__)) - Plugin = namedtuple("Plugin", "plugin, args, kw_args") + + class Plugin(NamedTuple): + plugin: str + args: list + kw_args: dict + lib = Plugin( plugin=os.path.join(cls.root_dir, "my_lib.py"), args=[], kw_args={} ) @@ -22,75 +28,75 @@ def setUpClass(cls): def test_no_libraries(self): for item in [None, "None", ""]: sl = SeleniumLibrary(plugins=item) - self.assertEqual(len(sl.get_keyword_names()), 182) + assert len(sl.get_keyword_names()) == 184 def test_parse_library(self): plugin = "path.to.MyLibrary" plugins = self.sl._string_to_modules(plugin) - self.assertEqual(len(plugins), 1) - self.assertEqual(plugins[0].module, plugin) - self.assertEqual(plugins[0].args, []) - self.assertEqual(plugins[0].kw_args, {}) + assert len(plugins) == 1 + assert plugins[0].module == plugin + assert plugins[0].args == [] + assert plugins[0].kw_args == {} def test_parse_libraries(self): plugin = "path.to.MyLibrary,path.to.OtherLibrary" plugins = self.sl._string_to_modules(plugin) - self.assertEqual(len(plugins), 2) - self.assertEqual(plugins[0].module, plugin.split(",")[0]) - self.assertEqual(plugins[0].args, []) - self.assertEqual(plugins[1].module, plugin.split(",")[1]) - self.assertEqual(plugins[1].args, []) + assert len(plugins) == 2 + assert plugins[0].module == plugin.split(",", maxsplit=1)[0] + assert plugins[0].args == [] + assert plugins[1].module == plugin.split(",")[1] + assert plugins[1].args == [] def test_comma_and_space(self): plugin = "path.to.MyLibrary , path.to.OtherLibrary" plugins = self.sl._string_to_modules(plugin) - self.assertEqual(len(plugins), 2) - self.assertEqual(plugins[0].module, "path.to.MyLibrary") - self.assertEqual(plugins[0].args, []) - self.assertEqual(plugins[1].module, "path.to.OtherLibrary") - self.assertEqual(plugins[1].args, []) + assert len(plugins) == 2 + assert plugins[0].module == "path.to.MyLibrary" + assert plugins[0].args == [] + assert plugins[1].module == "path.to.OtherLibrary" + assert plugins[1].args == [] def test_comma_and_space_with_arg(self): plugin = "path.to.MyLibrary;foo;bar , path.to.OtherLibrary" plugins = self.sl._string_to_modules(plugin) - self.assertEqual(len(plugins), 2) - self.assertEqual(plugins[0].module, "path.to.MyLibrary") - self.assertEqual(plugins[0].args, ["foo", "bar"]) - self.assertEqual(plugins[1].module, "path.to.OtherLibrary") - self.assertEqual(plugins[1].args, []) + assert len(plugins) == 2 + assert plugins[0].module == "path.to.MyLibrary" + assert plugins[0].args == ["foo", "bar"] + assert plugins[1].module == "path.to.OtherLibrary" + assert plugins[1].args == [] def test_parse_library_with_args(self): plugin = "path.to.MyLibrary" plugin_args = "arg1;arg2" parsed_plugins = self.sl._string_to_modules(f"{plugin};{plugin_args}") parsed_plugin = parsed_plugins[0] - self.assertEqual(len(parsed_plugins), 1) - self.assertEqual(parsed_plugin.module, plugin) - self.assertEqual(parsed_plugin.args, [arg for arg in plugin_args.split(";")]) - self.assertEqual(parsed_plugin.kw_args, {}) + assert len(parsed_plugins) == 1 + assert parsed_plugin.module == plugin + assert parsed_plugin.args == plugin_args.split(";") + assert parsed_plugin.kw_args == {} def test_parse_plugin_with_kw_args(self): plugin = "PluginWithKwArgs.py" plugin_args = "kw1=Text1;kw2=Text2" parsed_plugins = self.sl._string_to_modules(f"{plugin};{plugin_args}") parsed_plugin = parsed_plugins[0] - self.assertEqual(len(parsed_plugins), 1) - self.assertEqual(parsed_plugin.module, plugin) - self.assertEqual(parsed_plugin.args, []) - self.assertEqual(parsed_plugin.kw_args, {"kw1": "Text1", "kw2": "Text2"}) + assert len(parsed_plugins) == 1 + assert parsed_plugin.module == plugin + assert parsed_plugin.args == [] + assert parsed_plugin.kw_args == {"kw1": "Text1", "kw2": "Text2"} def test_plugin_does_not_exist(self): not_here = os.path.join(self.root_dir, "not_here.py") - with self.assertRaises(DataError): + with pytest.raises(DataError): SeleniumLibrary(plugins=not_here) - with self.assertRaises(DataError): + with pytest.raises(DataError): SeleniumLibrary(plugins="SeleniumLibrary.NotHere") def test_plugin_wrong_import_with_path(self): my_lib = os.path.join(self.root_dir, "my_lib.py") wrong_name = os.path.join(self.root_dir, "my_lib_wrong_name.py") - with self.assertRaises(DataError): + with pytest.raises(DataError): SeleniumLibrary(plugins=f"{my_lib}, {wrong_name}") def test_sl_with_kw_args_plugin(self): @@ -108,7 +114,7 @@ def test_sl_with_kw_args_plugin(self): def test_no_library_component_inherit(self): no_inherit = os.path.join(self.root_dir, "my_lib_not_inherit.py") - with self.assertRaises(PluginError): + with pytest.raises(PluginError): SeleniumLibrary(plugins=no_inherit) def test_plugin_as_last_in_init(self): @@ -117,12 +123,12 @@ def test_plugin_as_last_in_init(self): sl = SeleniumLibrary( plugins=plugin_file, event_firing_webdriver=event_firing_wd ) - self.assertEqual(sl.event_firing_webdriver, "should be last") + assert sl.event_firing_webdriver == "should be last" def test_easier_event_firing_webdriver_from_plugin(self): plugin_file = os.path.join( self.root_dir, "plugin_with_event_firing_webdriver.py" ) sl = SeleniumLibrary(plugins=plugin_file) - self.assertEqual(sl._plugin_keywords, ["tidii"]) - self.assertEqual(sl.event_firing_webdriver, "event_firing_webdriver") + assert sl._plugin_keywords == ["tidii"] + assert sl.event_firing_webdriver == "event_firing_webdriver" diff --git a/utest/test/entry/test_entry_point.py b/utest/test/entry/test_entry_point.py index fcbc10bbf..2d94a64c0 100644 --- a/utest/test/entry/test_entry_point.py +++ b/utest/test/entry/test_entry_point.py @@ -1,6 +1,6 @@ import json -from pathlib import Path import sys +from pathlib import Path from approvaltests import verify_all diff --git a/utest/test/keywords/IGNOREDtest_webdrivercreator.py b/utest/test/keywords/IGNOREDtest_webdrivercreator.py index dd33da50b..c74852517 100644 --- a/utest/test/keywords/IGNOREDtest_webdrivercreator.py +++ b/utest/test/keywords/IGNOREDtest_webdrivercreator.py @@ -1,7 +1,7 @@ import os import pytest -from mockito import mock, verify, when, unstub, ANY +from mockito import ANY, mock, unstub, verify, when from selenium import webdriver from SeleniumLibrary.keywords import WebDriverCreator @@ -36,9 +36,8 @@ def test_get_creator_method(creator): method = creator._get_creator_method("firefox") assert method - with pytest.raises(ValueError) as error: + with pytest.raises(ValueError, match=r"foobar is not a supported browser\."): creator._get_creator_method("foobar") - assert "foobar is not a supported browser." in str(error.value) def test_parse_capabilities(creator): @@ -135,7 +134,8 @@ def test_capabilities_resolver_chrome(creator): def test_chrome(creator): expected_webdriver = mock() when(webdriver).Chrome( - options=None, service=None # service=ANY # service_log_path=None, executable_path="chromedriver" + options=None, + service=None, # service=ANY # service_log_path=None, executable_path="chromedriver" ).thenReturn(expected_webdriver) driver = creator.create_chrome({}, None) assert driver == expected_webdriver @@ -172,7 +172,7 @@ def test_chrome_remote_no_caps(creator): def test_chrome_remote_caps(creator): url = "http://localhost:4444/wd/hub" expected_webdriver = mock() - # capabilities = {"browserName": "chrome"} + capabilities = {"browserName": "chrome"} file_detector = mock_file_detector(creator) when(webdriver).Remote( command_executor=url, @@ -205,10 +205,10 @@ def test_chrome_headless(creator): expected_webdriver = mock() options = mock() when(webdriver).ChromeOptions().thenReturn(options) - service = mock() when(webdriver).ChromeOptions().thenReturn(options) when(webdriver).Chrome( - options=options, service=ANY # service=None # service_log_path=None, executable_path="chromedriver" + options=options, + service=ANY, # service=None # service_log_path=None, executable_path="chromedriver" ).thenReturn(expected_webdriver) driver = creator.create_headless_chrome({}, None) assert options.headless is True @@ -265,7 +265,7 @@ def test_get_ff_profile_no_path(creator): assert profile == profile_mock -def test_get_ff_profile_instance_FirefoxProfile(creator): +def test_get_ff_profile_instance_FirefoxProfile(creator): # noqa: N802 input_profile = webdriver.FirefoxProfile() profile = creator._get_ff_profile(input_profile) assert profile == input_profile diff --git a/utest/test/keywords/IGNOREtest_webdrivercreator_executable_path.py b/utest/test/keywords/IGNOREtest_webdrivercreator_executable_path.py index c4f05b547..d51d23c0b 100644 --- a/utest/test/keywords/IGNOREtest_webdrivercreator_executable_path.py +++ b/utest/test/keywords/IGNOREtest_webdrivercreator_executable_path.py @@ -1,12 +1,11 @@ import os import pytest -from mockito import mock, unstub, when, ANY +from mockito import ANY, mock, unstub, when from selenium import webdriver from SeleniumLibrary.keywords import WebDriverCreator - LOG_DIR = "/log/dir" @@ -24,7 +23,8 @@ def teardown_function(): def test_create_chrome_executable_path_set(creator): expected_webdriver = mock() when(webdriver).Chrome( - options=None, service=ANY, # service_log_path=None, executable_path="/path/to/chromedriver" + options=None, + service=ANY, # service_log_path=None, executable_path="/path/to/chromedriver" ).thenReturn(expected_webdriver) driver = creator.create_chrome({}, None, executable_path="/path/to/chromedriver") assert driver == expected_webdriver @@ -33,7 +33,8 @@ def test_create_chrome_executable_path_set(creator): def test_create_chrome_executable_path_not_set(creator): expected_webdriver = mock() when(webdriver).Chrome( - options=None, service=ANY, # service_log_path=None, executable_path="chromedriver" + options=None, + service=ANY, # service_log_path=None, executable_path="chromedriver" ).thenReturn(expected_webdriver) when(creator)._get_executable_path(ANY).thenReturn("chromedriver") driver = creator.create_chrome({}, None, executable_path=None) @@ -72,7 +73,8 @@ def test_create_heasless_chrome_executable_path_set(creator): options = mock() when(webdriver).ChromeOptions().thenReturn(options) when(webdriver).Chrome( - options=options, service = ANY # service_log_path=None, executable_path="/path/to/chromedriver" + options=options, + service=ANY, # service_log_path=None, executable_path="/path/to/chromedriver" ).thenReturn(expected_webdriver) driver = creator.create_headless_chrome( {}, None, executable_path="/path/to/chromedriver" @@ -92,7 +94,7 @@ def test_create_firefox_executable_path_set(creator): when(webdriver).Firefox( options=options, # firefox_profile=profile, - service = ANY, + service=ANY, # service_log_path=log_file, # executable_path=executable, ).thenReturn(expected_webdriver) @@ -247,5 +249,4 @@ def mock_file_detector(creator): def get_geckodriver_log(): # return os.path.join(LOG_DIR, "geckodriver-1.log") # print(f"{os.getcwd()}") - cwd = os.getcwd() - return cwd \ No newline at end of file + return os.getcwd() diff --git a/utest/test/keywords/IGNOREtest_webdrivercreator_service_log_path.py b/utest/test/keywords/IGNOREtest_webdrivercreator_service_log_path.py index eb9fe6c5f..1e7a61e11 100644 --- a/utest/test/keywords/IGNOREtest_webdrivercreator_service_log_path.py +++ b/utest/test/keywords/IGNOREtest_webdrivercreator_service_log_path.py @@ -1,25 +1,25 @@ import os -from collections import namedtuple +from typing import NamedTuple import pytest - -from mockito import mock, when, unstub, ANY +from mockito import ANY, mock, unstub, when from selenium import webdriver -from selenium.webdriver import chrome -#from selenium.webdriver.chrome.service import Service as ChromeService -from selenium.webdriver.chrome.service import Service from selenium.webdriver.chrome import service as chromeservice +# from selenium.webdriver.chrome.service import Service as ChromeService from SeleniumLibrary.keywords import WebDriverCreator from SeleniumLibrary.utils import WINDOWS @pytest.fixture(scope="module") def creator(): + class Creator(NamedTuple): + creator: WebDriverCreator + output_dir: str + curr_dir = os.path.dirname(os.path.abspath(__file__)) output_dir = os.path.abspath(os.path.join(curr_dir, "..", "..", "output_dir")) creator = WebDriverCreator(output_dir) - Creator = namedtuple("Creator", "creator, output_dir") return Creator(creator, output_dir) @@ -57,7 +57,9 @@ def test_log_file_with_index_exist(creator): def test_create_chrome_with_service_log_path_none(creator): expected_webdriver = mock() service = mock() - when(chromeservice).Service(log_path=None, executable_path="chromedriver").thenReturn(service) + when(chromeservice).Service( + log_path=None, executable_path="chromedriver" + ).thenReturn(service) # when(chrome).service(log_path=None, executable_path="chromedriver").thenReturn(service) # service = ChromeService(log_path=None, executable_path="chromedriver") # service = Service(log_path=None, executable_path="chromedriver") @@ -65,7 +67,8 @@ def test_create_chrome_with_service_log_path_none(creator): # when(webdriver).chrome.service().thenReturn(service) when(webdriver).Chrome( # options=None, service_log_path=None, executable_path="chromedriver" - options=None, service=ANY, + options=None, + service=ANY, # options=None, service=service, ).thenReturn(expected_webdriver) driver = creator.creator.create_chrome({}, None, service_log_path=None) @@ -76,7 +79,8 @@ def test_create_chrome_with_service_log_path_real_path(creator): log_file = os.path.join(creator.output_dir, "firefox-{index}.log") expected_webdriver = mock() when(webdriver).Chrome( - options=None, service=ANY, + options=None, + service=ANY, ).thenReturn(expected_webdriver) driver = creator.creator.create_chrome({}, None, service_log_path=log_file) assert driver == expected_webdriver @@ -88,14 +92,15 @@ def test_create_headlesschrome_with_service_log_path_real_path(creator): options = mock() when(webdriver).ChromeOptions().thenReturn(options) when(webdriver).Chrome( - options=options, service=ANY, + options=options, + service=ANY, ).thenReturn(expected_webdriver) driver = creator.creator.create_headless_chrome({}, None, service_log_path=log_file) assert driver == expected_webdriver def test_create_firefox_with_service_log_path_none(creator): - log_file = os.path.join(creator.output_dir, "geckodriver-1.log") + # log_file = os.path.join(creator.output_dir, "geckodriver-1.log") expected_webdriver = mock() options = mock() when(webdriver).FirefoxOptions().thenReturn(options) @@ -162,18 +167,20 @@ def test_create_ie_with_service_log_path_real_path(creator): log_file = os.path.join(creator.output_dir, "ie-1.log") expected_webdriver = mock() when(webdriver).Ie( - options=None, service=ANY, + options=None, + service=ANY, ).thenReturn(expected_webdriver) driver = creator.creator.create_ie({}, None, service_log_path=log_file) assert driver == expected_webdriver def test_create_edge_with_service_log_path_real_path(creator): - executable_path = "msedgedriver" + # executable_path = "msedgedriver" log_file = os.path.join(creator.output_dir, "edge-1.log") expected_webdriver = mock() when(webdriver).Edge( - options=None, service=ANY, + options=None, + service=ANY, ).thenReturn(expected_webdriver) driver = creator.creator.create_edge({}, None, service_log_path=log_file) assert driver == expected_webdriver @@ -197,4 +204,4 @@ def test_create_edge_with_service_log_path_real_path(creator): # expected_webdriver # ) # driver = creator.creator.create_safari({}, None, service_log_path=log_file) -# assert driver == expected_webdriver \ No newline at end of file +# assert driver == expected_webdriver diff --git a/utest/test/keywords/approved_files/test_selenium_options_parser.test_parse_options_string_errors_py3_12.approved.txt b/utest/test/keywords/approved_files/test_selenium_options_parser.test_parse_options_string_errors_py3_12.approved.txt new file mode 100644 index 000000000..d57473c22 --- /dev/null +++ b/utest/test/keywords/approved_files/test_selenium_options_parser.test_parse_options_string_errors_py3_12.approved.txt @@ -0,0 +1,8 @@ +Selenium options string errors + +0) method("arg1) ('unterminated string literal (detected at line 1)', (1, 8)) +1) method(arg1") ('unterminated string literal (detected at line 1)', (1, 12)) +2) method(arg1) Unable to parse option: "method(arg1)" +3) attribute=arg1 Unable to parse option: "attribute=arg1" +4) attribute=webdriver Unable to parse option: "attribute=webdriver" +5) method(argument="value") Unable to parse option: "method(argument="value")" diff --git a/utest/test/keywords/approved_files/test_selenium_service_parser.test_parse_service_string_errors_py3_12.approved.txt b/utest/test/keywords/approved_files/test_selenium_service_parser.test_parse_service_string_errors_py3_12.approved.txt new file mode 100644 index 000000000..44dc032d0 --- /dev/null +++ b/utest/test/keywords/approved_files/test_selenium_service_parser.test_parse_service_string_errors_py3_12.approved.txt @@ -0,0 +1,8 @@ +Selenium service string errors + +0) attribute=arg1 Unable to parse service: "attribute=arg1" +1) attribute='arg1 ('unterminated string literal (detected at line 1)', (1, 11)) +2) attribute=['arg1' ('unexpected EOF in multi-line statement', (1, 0)) +3) attribute=['arg1';'arg2'] ('unexpected EOF in multi-line statement', (1, 0)) +4) attribute['arg1'] Unable to parse service: "attribute['arg1']" +5) attribute=['arg1'] attribute=['arg2'] Unable to parse service: "attribute=['arg1'] attribute=['arg2']" diff --git a/utest/test/keywords/test_browsermanagement.py b/utest/test/keywords/test_browsermanagement.py index 9fcce8eb8..5b9e03213 100644 --- a/utest/test/keywords/test_browsermanagement.py +++ b/utest/test/keywords/test_browsermanagement.py @@ -1,11 +1,9 @@ import pytest -from mockito import when, mock, verify, verifyNoMoreInteractions, ANY +from mockito import ANY, mock, verify, verifyNoUnwantedInteractions, when from selenium import webdriver -from selenium.webdriver.chrome.service import Service as ChromeService -from selenium.webdriver.chrome.service import Service -from SeleniumLibrary.keywords import BrowserManagementKeywords from SeleniumLibrary import SeleniumLibrary +from SeleniumLibrary.keywords import BrowserManagementKeywords def test_set_selenium_timeout_only_affects_open_browsers(): @@ -21,22 +19,22 @@ def test_set_selenium_timeout_only_affects_open_browsers(): verify(second_browser).set_script_timeout(10.0) ctx._drivers.active_drivers = [] bm.set_selenium_timeout("20 seconds") - verifyNoMoreInteractions(first_browser) - verifyNoMoreInteractions(second_browser) + verifyNoUnwantedInteractions(first_browser) + verifyNoUnwantedInteractions(second_browser) def test_action_chain_delay_default(): sl = SeleniumLibrary() - assert sl.action_chain_delay == 250, f"Delay should have 250" + assert sl.action_chain_delay == 250, "Delay should have 250" def test_set_action_chain_delay_default(): sl = SeleniumLibrary() sl.set_action_chain_delay("3.0") - assert sl.action_chain_delay == 3000, f"Delay should have 3000" + assert sl.action_chain_delay == 3000, "Delay should have 3000" sl.set_action_chain_delay("258 milliseconds") - assert sl.action_chain_delay == 258, f"Delay should have 258" + assert sl.action_chain_delay == 258, "Delay should have 258" def test_get_action_chain_delay_default(): @@ -44,6 +42,7 @@ def test_get_action_chain_delay_default(): sl.set_action_chain_delay("300 milliseconds") assert sl.get_action_chain_delay() == 0.3 + def test_selenium_implicit_wait_default(): sl = SeleniumLibrary() assert sl.implicit_wait == 0.0, "Wait should have 0.0" @@ -59,10 +58,10 @@ def test_set_selenium_implicit_wait(): def test_selenium_implicit_wait_error(): - with pytest.raises(ValueError): + with pytest.raises(ValueError, match=r"Invalid time string 'False'\."): SeleniumLibrary(implicit_wait="False") sl = SeleniumLibrary(implicit_wait="3") - with pytest.raises(ValueError): + with pytest.raises(ValueError, match=r"Invalid time string '1 vuosi'\."): sl.set_selenium_implicit_wait("1 vuosi") @@ -77,7 +76,9 @@ def test_selenium_implicit_wait_get(): def test_selenium_page_load_timeout_with_default(): sl = SeleniumLibrary() - assert sl.page_load_timeout == 300.0, "Default page load timeout should be 5 minutes" + assert sl.page_load_timeout == 300.0, ( + "Default page load timeout should be 5 minutes" + ) def test_set_selenium_page_load_timeout(): @@ -106,23 +107,20 @@ def test_get_selenium_page_load_timeout(): def test_bad_browser_name(): ctx = mock() bm = BrowserManagementKeywords(ctx) - try: + with pytest.raises(ValueError, match=r"fireox is not a supported browser\."): bm._make_driver("fireox") - raise ValueError("Exception not raised") - except ValueError as e: - assert str(e) == "fireox is not a supported browser." def test_create_webdriver(): ctx = mock() ctx.event_firing_webdriver = None bm = BrowserManagementKeywords(ctx) - FakeWebDriver = mock() + fake_webdriver = mock() driver = mock() - when(FakeWebDriver).__call__(some_arg=1).thenReturn(driver) - when(FakeWebDriver).__call__(some_arg=2).thenReturn(driver) + when(fake_webdriver).__call__(some_arg=1).thenReturn(driver) + when(fake_webdriver).__call__(some_arg=2).thenReturn(driver) when(ctx).register_driver(driver, "fake1").thenReturn(0) - webdriver.FakeWebDriver = FakeWebDriver + webdriver.FakeWebDriver = fake_webdriver try: index = bm.create_webdriver("FakeWebDriver", "fake1", some_arg=1) verify(ctx).register_driver(driver, "fake1") @@ -142,7 +140,8 @@ def test_open_browser_speed(): browser = mock() executable_path = "chromedriver" when(webdriver).Chrome( - options=None, service=ANY, + options=None, + service=ANY, ).thenReturn(browser) bm = BrowserManagementKeywords(ctx) when(bm._webdriver_creator)._get_executable_path(ANY).thenReturn(executable_path) @@ -157,17 +156,17 @@ def test_create_webdriver_speed(): ctx.speed = 0.0 browser = mock() executable_path = "chromedriver" - #Original code: + # Original code: # when(webdriver).Chrome( # options=None, service_log_path=None, executable_path=executable_path # ).thenReturn(browser) - #Tried: + # Tried: # service = ChromeService(executable_path="chromedriver", log_path=None) # when(webdriver).Chrome( # options=None, service=Service, # ).thenReturn(browser) - #Results in .. + # Results in .. # E mockito.invocation.InvocationError: # E Called but not expected: # E @@ -177,11 +176,11 @@ def test_create_webdriver_speed(): # E # E Chrome(options=None, service=) - #Tried: + # Tried: # when(webdriver).Chrome( # options=None, service=None, # ).thenReturn(browser) - #Results in .. + # Results in .. # E mockito.invocation.InvocationError: # E Called but not expected: # E @@ -191,7 +190,7 @@ def test_create_webdriver_speed(): # E # E Chrome(options=None, service=None) - #Tried: + # Tried: # service = mock() # when(webdriver.chrome.service).Service( # executable_path="chromedriver", log_path=None, @@ -199,10 +198,10 @@ def test_create_webdriver_speed(): # when(webdriver).Chrome( # options=None, service=service, # ).thenReturn(browser) - #Results in .. + # Results in .. # ... - #Tried: + # Tried: # service = ChromeService(executable_path="chromedriver", log_path=None) # when(webdriver.chrome.service).Service( # executable_path="chromedriver", log_path=None, @@ -210,7 +209,7 @@ def test_create_webdriver_speed(): # when(webdriver).Chrome( # options=None, service=service, # ).thenReturn(browser) - #Results in .. + # Results in .. # E mockito.invocation.InvocationError: # E Called but not expected: # E @@ -219,16 +218,16 @@ def test_create_webdriver_speed(): # E Stubbed invocations are: # E # E Chrome(options=None, service=) - #which does seem closer .. - - #Tried: + # which does seem closer .. + + # Tried: # service = Service(executable_path="chromedriver", log_path=None) # when(webdriver).Chrome( # options=None, service=service, # ).thenReturn(browser) - #Results in .. + # Results in .. - #Tried: + # Tried: # service = mock() # ## when(Service).__init__( # when(Chrome).Service( @@ -237,36 +236,37 @@ def test_create_webdriver_speed(): # when(webdriver).Chrome( # options=None, service=service, # ).thenReturn(browser) - #Results in .. + # Results in .. - #Tried: + # Tried: when(webdriver).Chrome( - options=None, service=ANY, + options=None, + service=ANY, ).thenReturn(browser) - #Results in .. + # Results in .. # .. passed ?? Is this truely correct? - #Also tried: + # Also tried: # service_log_path = None # service = ChromeService(executable_path=executable_path, log_path=service_log_path) # when(webdriver).Chrome( # options=None, service=service, # ).thenReturn(browser) - #Also tried: + # Also tried: # service = ChromeService() # when(webdriver).Chrome( # options=None, service=service, # ).thenReturn(browser) - #Also tried: + # Also tried: # service = mock(ChromeService) # when(webdriver).Chrome( # options=None, service=service, # ).thenReturn(browser) - #Also tried: - #service = mock(Service) + # Also tried: + # service = mock(Service) # when(webdriver).Chrome( # options=None, service=service, # ).thenReturn(browser) diff --git a/utest/test/keywords/test_click_modifier.py b/utest/test/keywords/test_click_modifier.py index 0b651c276..5b3e0560e 100644 --- a/utest/test/keywords/test_click_modifier.py +++ b/utest/test/keywords/test_click_modifier.py @@ -40,24 +40,19 @@ def test_parsing_multiple_modifiers(element): def test_invalid_modifier(element): - with pytest.raises(ValueError) as error: + with pytest.raises(ValueError, match="'FOO' modifier "): element.parse_modifier("FOO") - assert "'FOO' modifier " in str(error.value) - with pytest.raises(ValueError) as error: + with pytest.raises(ValueError, match="'FOO' modifier "): element.parse_modifier("FOO+CTRL") - assert "'FOO' modifier " in str(error.value) - with pytest.raises(ValueError) as error: + with pytest.raises(ValueError, match="'FOO' modifier "): element.parse_modifier("CTRL+FOO") - assert "'FOO' modifier " in str(error.value) - with pytest.raises(ValueError) as error: + with pytest.raises(ValueError, match="'CTRLFOO' modifier "): element.parse_modifier("CTRLFOO") - assert "'CTRLFOO' modifier " in str(error.value) def test_invalid_key_separator(element): - with pytest.raises(ValueError) as error: + with pytest.raises(ValueError, match="'CTRL-CTRL' modifier "): element.parse_modifier("CTRL-CTRL") - assert "'CTRL-CTRL' modifier " in str(error.value) diff --git a/utest/test/keywords/test_cookie.py b/utest/test/keywords/test_cookie.py index 1fe110efa..52d42a681 100644 --- a/utest/test/keywords/test_cookie.py +++ b/utest/test/keywords/test_cookie.py @@ -6,7 +6,6 @@ from SeleniumLibrary.keywords import CookieKeywords from SeleniumLibrary.keywords.cookie import CookieInformation - ALL_ARGS = { "name": "foo", "value": "123", @@ -20,24 +19,24 @@ pytestmark = pytest.mark.usefixtures("unstub") -@pytest.fixture() +@pytest.fixture def driver(): return mock() -@pytest.fixture() +@pytest.fixture def ctx(driver): ctx = mock() ctx.driver = driver return ctx -@pytest.fixture() +@pytest.fixture def default_cookie(): return {"name": "name", "value": "value"} -@pytest.fixture() +@pytest.fixture def cookie(ctx): return CookieKeywords(ctx) diff --git a/utest/test/keywords/test_expectedconditions.py b/utest/test/keywords/test_expectedconditions.py index 3ade2e5fa..d6052e08c 100644 --- a/utest/test/keywords/test_expectedconditions.py +++ b/utest/test/keywords/test_expectedconditions.py @@ -20,12 +20,13 @@ # Element\ To\ Be\ Clickable # Element${SPACE}To${SPACE}Be${SPACE}Clickable -class ExpectedConditionKeywords(unittest.TestCase): + +class TestExpectedConditionKeywords(unittest.TestCase): @classmethod def setUpClass(cls): cls.ec_keywords = ExpectedConditionKeywords(None) - def WorkInProgresstest_parse_condition(self): + def workinprogresstest_parse_condition(self): results = [] results.append(self.ec_keywords._parse_condition("Element To Be Clickable")) results.append(self.ec_keywords._parse_condition("eLEment TO be ClIcKable")) diff --git a/utest/test/keywords/test_firefox_profile_parsing.py b/utest/test/keywords/test_firefox_profile_parsing.py index 3a7e895e2..ad3864d5f 100644 --- a/utest/test/keywords/test_firefox_profile_parsing.py +++ b/utest/test/keywords/test_firefox_profile_parsing.py @@ -5,7 +5,6 @@ from approvaltests.reporters.generic_diff_reporter_factory import ( GenericDiffReporterFactory, ) -from robot.utils import WINDOWS from selenium import webdriver from SeleniumLibrary.keywords import WebDriverCreator @@ -27,7 +26,6 @@ def setUpClass(cls): def setUp(self): self.results = [] - @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_single_method(self): self._parse_result( self.creator._get_ff_profile('set_preference("key1", "arg1")') @@ -67,10 +65,9 @@ def _get_preferences_attribute(self, result): # -- temporary fix to transition selenium to v4.17.2 from v4.16.0 and prior # from inspect import signature # sig = signature(result) - if hasattr(result,'default_preferences'): + if hasattr(result, "default_preferences"): return result.default_preferences - elif hasattr(result,'_desired_preferences'): + if hasattr(result, "_desired_preferences"): return result._desired_preferences - else: - return None + return None # -- diff --git a/utest/test/keywords/test_input_text_file_decorator.py b/utest/test/keywords/test_input_text_file_decorator.py index cd748e785..a0ec8fa13 100644 --- a/utest/test/keywords/test_input_text_file_decorator.py +++ b/utest/test/keywords/test_input_text_file_decorator.py @@ -17,8 +17,8 @@ def tearDown(self): def test_file_decorator_not_file(self): when(self.file).choose_file().thenReturn(False) - self.assertEqual(self.file.is_local_file("some string"), None) + assert self.file.is_local_file("some string") is None def test_file_decodator_is_file_choose_file(self): when(self.file).choose_file().thenReturn(True) - self.assertEqual(self.file.is_local_file("some_file"), None) + assert self.file.is_local_file("some_file") is None diff --git a/utest/test/keywords/test_javascript.py b/utest/test/keywords/test_javascript.py index 1b4b469c5..2e35bae4e 100644 --- a/utest/test/keywords/test_javascript.py +++ b/utest/test/keywords/test_javascript.py @@ -5,14 +5,12 @@ from approvaltests.reporters.generic_diff_reporter_factory import ( GenericDiffReporterFactory, ) -from robot.utils import WINDOWS from SeleniumLibrary.keywords import JavaScriptKeywords class JavaScriptKeywordsTest(unittest.TestCase): @classmethod - @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") def setUpClass(cls): cls.code_examples = [ (), @@ -40,13 +38,11 @@ def setUpClass(cls): factory.load(reporter_json) cls.reporter = factory.get_first_working() - @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_get_javascript(self): code, args = self.js._get_javascript_to_execute(("code", "here")) result = f"{code} + {args}" verify(result, self.reporter) - @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_get_javascript_no_code(self): code = ("ARGUMENTS", "arg1", "arg1") try: @@ -55,21 +51,18 @@ def test_get_javascript_no_code(self): result = str(error) verify(result, self.reporter) - @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_separate_code_and_args(self): all_results = [] for code in self.code_examples: all_results.append(self.js_reporter(code)) verify_all("code and args", all_results, reporter=self.reporter) - @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_indexing(self): all_results = [] for code in self.code_examples: all_results.append(self.js._get_marker_index(code)) verify_all("index", all_results, reporter=self.reporter) - @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_check_marker_error(self): examples = [ (), diff --git a/utest/test/keywords/test_keyword_arguments_browsermanagement.py b/utest/test/keywords/test_keyword_arguments_browsermanagement.py index 0d730878a..6237a89cb 100644 --- a/utest/test/keywords/test_keyword_arguments_browsermanagement.py +++ b/utest/test/keywords/test_keyword_arguments_browsermanagement.py @@ -1,6 +1,6 @@ import unittest -from mockito import mock, unstub, when, verify, ANY +from mockito import ANY, mock, unstub, verify, when from SeleniumLibrary.keywords import BrowserManagementKeywords @@ -25,13 +25,13 @@ def test_open_browser(self): "firefox", None, None, False, None, None, None, None ).thenReturn(browser) alias = self.brorser.open_browser(url) - self.assertEqual(alias, None) + assert alias is None when(self.brorser)._make_driver( "firefox", None, None, remote_url, None, None, None, None ).thenReturn(browser) alias = self.brorser.open_browser(url, alias="None", remote_url=remote_url) - self.assertEqual(alias, None) + assert alias is None def test_same_alias(self): url = "https://github.com/robotframework" diff --git a/utest/test/keywords/test_keyword_arguments_element.py b/utest/test/keywords/test_keyword_arguments_element.py index c35b402ec..d6662e40a 100644 --- a/utest/test/keywords/test_keyword_arguments_element.py +++ b/utest/test/keywords/test_keyword_arguments_element.py @@ -1,10 +1,11 @@ import pytest -from mockito import mock, unstub, when, matchers -from SeleniumLibrary.keywords import ElementKeywords +from mockito import matchers, mock, unstub, when + import SeleniumLibrary.keywords.element as SUT +from SeleniumLibrary.keywords import ElementKeywords -@pytest.fixture(scope="function") +@pytest.fixture def element(): ctx = mock() ctx._browser = mock() @@ -30,7 +31,6 @@ def test_element_text_should_be(element): assert "foobar" in str(error.value) - def test_action_chain_delay_in_elements(element): locator = "//div" webelement = mock() @@ -40,8 +40,7 @@ def test_action_chain_delay_in_elements(element): expected_delay_in_ms = 1000 element.ctx.action_chain_delay = expected_delay_in_ms when(chain_mock).move_to_element(matchers.ANY).thenReturn(mock()) - when(SUT).ActionChains(matchers.ANY, duration=expected_delay_in_ms).thenReturn(chain_mock) + when(SUT).ActionChains(matchers.ANY, duration=expected_delay_in_ms).thenReturn( + chain_mock + ) element.scroll_element_into_view(locator) - - - diff --git a/utest/test/keywords/test_keyword_arguments_formelement.py b/utest/test/keywords/test_keyword_arguments_formelement.py index 193ba0dac..322ae6475 100644 --- a/utest/test/keywords/test_keyword_arguments_formelement.py +++ b/utest/test/keywords/test_keyword_arguments_formelement.py @@ -3,11 +3,10 @@ from SeleniumLibrary.keywords import FormElementKeywords - FALSES = ["False", False, "", None, "NONE"] -@pytest.fixture(scope="function") +@pytest.fixture def form(): ctx = mock() ctx.driver = mock() @@ -21,7 +20,7 @@ def teardown_function(): def test_submit_form_false(form): element = mock() when(form).find_element("tag:form", tag="form").thenReturn(element) - for false in FALSES: + for _false in FALSES: form.submit_form() form.submit_form() diff --git a/utest/test/keywords/test_keyword_arguments_selectelement.py b/utest/test/keywords/test_keyword_arguments_selectelement.py index 8e8c78999..bfe671ae0 100644 --- a/utest/test/keywords/test_keyword_arguments_selectelement.py +++ b/utest/test/keywords/test_keyword_arguments_selectelement.py @@ -2,7 +2,6 @@ from mockito import mock, unstub, when - from SeleniumLibrary.keywords import SelectElementKeywords diff --git a/utest/test/keywords/test_keyword_arguments_waiting.py b/utest/test/keywords/test_keyword_arguments_waiting.py index 9809b8314..26ccf28a5 100644 --- a/utest/test/keywords/test_keyword_arguments_waiting.py +++ b/utest/test/keywords/test_keyword_arguments_waiting.py @@ -20,7 +20,6 @@ def teardown_module(): def test_wait_for_condition(waiting): condition = 'return document.getElementById("intro")' - error = "did not become true" with pytest.raises(AssertionError) as error: waiting.wait_for_condition(condition) assert "did not become true" in str(error.value) diff --git a/utest/test/keywords/test_press_keys.py b/utest/test/keywords/test_press_keys.py index d168814dc..ebea52ff6 100644 --- a/utest/test/keywords/test_press_keys.py +++ b/utest/test/keywords/test_press_keys.py @@ -1,11 +1,10 @@ -import unittest import os +import unittest from approvaltests.approvals import verify_all from approvaltests.reporters.generic_diff_reporter_factory import ( GenericDiffReporterFactory, ) -from robot.utils import WINDOWS from SeleniumLibrary.keywords import ElementKeywords @@ -24,7 +23,6 @@ def setUp(self): factory.load(reporter_json) self.reporter = factory.get_first_working() - @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_parse_keys(self): results = [] results.append(self.element_keywords._parse_keys("A", "B", "C")) @@ -41,7 +39,6 @@ def test_parse_keys(self): results.append(self.element_keywords._parse_keys("IS", "ALT", "HERE")) verify_all("index", results, reporter=self.reporter) - @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_parse_keys_aliases(self): results = [] results.append(self.element_keywords._parse_aliases("CTRL")) @@ -51,7 +48,6 @@ def test_parse_keys_aliases(self): results.append(self.element_keywords._parse_aliases("END")) verify_all("Alias testing", results, reporter=self.reporter) - @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_separate_key(self): results = [] results.append(self.element_keywords._separate_key("BB")) @@ -65,7 +61,6 @@ def test_separate_key(self): results.append(self.element_keywords._separate_key("+++")) verify_all("Separate key", results, reporter=self.reporter) - @unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_convert_key(self): results = [] results.append(self.element_keywords._convert_special_keys(["B"])) diff --git a/utest/test/keywords/test_runonfailure_from_lib.py b/utest/test/keywords/test_runonfailure_from_lib.py index 8034a4002..530820d3d 100644 --- a/utest/test/keywords/test_runonfailure_from_lib.py +++ b/utest/test/keywords/test_runonfailure_from_lib.py @@ -1,6 +1,6 @@ import unittest -from mockito import when, unstub, verify +from mockito import unstub, verify, when from SeleniumLibrary import SeleniumLibrary diff --git a/utest/test/keywords/test_screen_shot.py b/utest/test/keywords/test_screen_shot.py index a5cac9248..128d98230 100644 --- a/utest/test/keywords/test_screen_shot.py +++ b/utest/test/keywords/test_screen_shot.py @@ -1,4 +1,4 @@ -from os.path import dirname, abspath, join +from os.path import abspath, dirname, join import pytest from mockito import mock, unstub @@ -8,6 +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") @@ -22,24 +23,34 @@ 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_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) is True - assert screen_shot._decide_embedded("other.psn") is False + 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) + screen_shot.ctx.screenshot_root_directory = BASE64 + assert screen_shot._decide_embedded(BASE64) == (True, BASE64) def test_screenshot_path_embedded(screen_shot): @@ -56,6 +67,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 +93,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) diff --git a/utest/test/keywords/test_selenium_options_parser.py b/utest/test/keywords/test_selenium_options_parser.py index 40e51bdd9..77a3ed9a2 100644 --- a/utest/test/keywords/test_selenium_options_parser.py +++ b/utest/test/keywords/test_selenium_options_parser.py @@ -1,13 +1,12 @@ import os -import unittest +import sys import pytest from approvaltests.approvals import verify_all from approvaltests.reporters.generic_diff_reporter_factory import ( GenericDiffReporterFactory, ) -from mockito import mock, when, unstub, ANY -from robot.utils import WINDOWS +from mockito import ANY, mock, unstub, when from selenium import webdriver from SeleniumLibrary.keywords.webdrivertools import SeleniumOptions, WebDriverCreator @@ -17,6 +16,7 @@ def options(): return SeleniumOptions() + @pytest.fixture(scope="module") def reporter(): path = os.path.dirname(__file__) @@ -32,7 +32,6 @@ def teardown_function(): unstub() -@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_parse_options_string(options, reporter): results = [] results.append(options._parse('method("arg1")')) @@ -71,7 +70,6 @@ def test_parse_options_string(options, reporter): verify_all("Selenium options string to dict", results, reporter=reporter) -@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_index_of_separator(options, reporter): results = [] results.append(options._get_arument_index('method({"key": "value"})')) @@ -81,7 +79,6 @@ def test_index_of_separator(options, reporter): verify_all("Get argument index", results, reporter=reporter) -@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_parse_complex_object(options, reporter): results = [] results.append(options._parse_to_tokens('method({"key": "value"})')) @@ -91,7 +88,6 @@ def test_parse_complex_object(options, reporter): verify_all("Parse complex Python object", results, reporter=reporter) -@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_parse_arguemnts(options, reporter): results = [] results.append(options._parse_arguments(("arg1",), True)) @@ -102,7 +98,7 @@ def test_parse_arguemnts(options, reporter): verify_all("Parse arguments from complex object", results, reporter=reporter) -@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") +@pytest.mark.skipif(sys.version_info > (3, 11), reason="Errors change with Python 3.12") def test_parse_options_string_errors(options, reporter): results = [] results.append(error_formatter(options._parse, 'method("arg1)', True)) @@ -114,7 +110,18 @@ def test_parse_options_string_errors(options, reporter): verify_all("Selenium options string errors", results, reporter=reporter) -@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") +@pytest.mark.skipif(sys.version_info < (3, 12), reason="Errors change with Python 3.12") +def test_parse_options_string_errors_py3_12(options, reporter): + results = [] + results.append(error_formatter(options._parse, 'method("arg1)', True)) + results.append(error_formatter(options._parse, 'method(arg1")', True)) + results.append(error_formatter(options._parse, "method(arg1)", True)) + results.append(error_formatter(options._parse, "attribute=arg1", True)) + results.append(error_formatter(options._parse, "attribute=webdriver", True)) + results.append(error_formatter(options._parse, 'method(argument="value")', True)) + verify_all("Selenium options string errors", results, reporter=reporter) + + def test_split_options(options, reporter): results = [] results.append(options._split('method("arg1");method("arg2")')) @@ -128,7 +135,6 @@ def test_split_options(options, reporter): verify_all("Selenium options string splitting", results, reporter=reporter) -@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_options_create(options, reporter): results = [] options_str = 'add_argument("--disable-dev-shm-usage")' @@ -160,7 +166,6 @@ def test_options_create(options, reporter): verify_all("Selenium options", results, reporter=reporter) -@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_get_options(options, reporter): options_str = 'add_argument("--proxy-server=66.97.38.58:80")' sel_options = options.create("chrome", options_str) @@ -168,7 +173,6 @@ def test_get_options(options, reporter): verify_all("Selenium options with string.", results, reporter=reporter) -@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_importer(options, reporter): results = [] results.append(options._import_options("firefox")) @@ -187,7 +191,7 @@ def error_formatter(method, arg, full=False): except Exception as error: if full: return f"{arg} {error}" - return "{} {}".format(arg, error.__str__()[:15]) + return f"{arg} {error.__str__()[:15]}" @pytest.fixture(scope="module") @@ -200,10 +204,7 @@ def creator(): @pytest.fixture(scope="module") def output_dir(): curr_dir = os.path.dirname(os.path.abspath(__file__)) - output_dir = os.path.abspath(os.path.join(curr_dir, "..", "..", "output_dir")) - return output_dir - -from selenium.webdriver.chrome.service import Service as ChromeService + return os.path.abspath(os.path.join(curr_dir, "..", "..", "output_dir")) def test_create_chrome_with_options(creator): @@ -214,7 +215,8 @@ def test_create_chrome_with_options(creator): # executable_path=ANY, log_path=ANY, # ).thenReturn(service) when(webdriver).Chrome( - options=options, service=ANY # service_log_path=None, executable_path="chromedriver" + options=options, + service=ANY, # service_log_path=None, executable_path="chromedriver" ).thenReturn(expected_webdriver) driver = creator.create_chrome({}, None, options=options) assert driver == expected_webdriver @@ -222,13 +224,13 @@ def test_create_chrome_with_options(creator): def test_create_chrome_with_options_and_remote_url(creator): url = "http://localhost:4444/wd/hub" - #caps = webdriver.DesiredCapabilities.CHROME.copy() + # caps = webdriver.DesiredCapabilities.CHROME.copy() options = mock() expected_webdriver = mock() file_detector = mock_file_detector(creator) when(webdriver).Remote( command_executor=url, - #desired_capabilities=caps, + # desired_capabilities=caps, # browser_profile=None, options=options, file_detector=file_detector, @@ -241,21 +243,22 @@ def test_create_headless_chrome_with_options(creator): options = mock() expected_webdriver = mock() when(webdriver).Chrome( - options=options, service=ANY # service_log_path=None, options=options, executable_path="chromedriver" + options=options, + service=ANY, # service_log_path=None, options=options, executable_path="chromedriver" ).thenReturn(expected_webdriver) driver = creator.create_headless_chrome({}, None, options=options) assert driver == expected_webdriver def test_create_firefox_with_options(creator, output_dir): - log_file = os.path.join(output_dir, "geckodriver-1.log") + # log_file = os.path.join(output_dir, "geckodriver-1.log") options = mock() profile = mock() expected_webdriver = mock() when(webdriver).FirefoxProfile().thenReturn(profile) when(webdriver).Firefox( options=options, - service=ANY + service=ANY, # firefox_profile=profile, # executable_path="geckodriver", # service_log_path=log_file, @@ -284,14 +287,14 @@ def test_create_firefox_with_options_and_remote_url(creator): def test_create_headless_firefox_with_options(creator, output_dir): - log_file = os.path.join(output_dir, "geckodriver-1.log") + # log_file = os.path.join(output_dir, "geckodriver-1.log") options = mock() profile = mock() expected_webdriver = mock() when(webdriver).FirefoxProfile().thenReturn(profile) when(webdriver).Firefox( options=options, - service=ANY + service=ANY, # firefox_profile=profile, # executable_path="geckodriver", # service_log_path=log_file, @@ -304,7 +307,8 @@ def test_create_ie_with_options(creator): options = mock() expected_webdriver = mock() when(webdriver).Ie( - options=options, service=ANY # service_log_path=None, options=options, executable_path="IEDriverServer.exe" + options=options, + service=ANY, # service_log_path=None, options=options, executable_path="IEDriverServer.exe" ).thenReturn(expected_webdriver) driver = creator.create_ie({}, None, options=options) assert driver == expected_webdriver @@ -331,7 +335,8 @@ def test_create_ie_with_options_and_log_path(creator): options = mock() expected_webdriver = mock() when(webdriver).Ie( - options=options, service=ANY # service_log_path=None, executable_path="IEDriverServer.exe" + options=options, + service=ANY, # service_log_path=None, executable_path="IEDriverServer.exe" ).thenReturn(expected_webdriver) driver = creator.create_ie({}, None, options=options) assert driver == expected_webdriver @@ -364,7 +369,8 @@ def test_create_driver_chrome(creator): executable_path = "chromedriver" when(creator)._get_executable_path(ANY).thenReturn(executable_path) when(webdriver).Chrome( - options=options, service=ANY # service_log_path=None, options=options, executable_path=executable_path + options=options, + service=ANY, # service_log_path=None, options=options, executable_path=executable_path ).thenReturn(expected_webdriver) driver = creator.create_driver( "Chrome", desired_capabilities={}, remote_url=None, options=str_options @@ -373,7 +379,7 @@ def test_create_driver_chrome(creator): def test_create_driver_firefox(creator, output_dir): - log_file = os.path.join(output_dir, "geckodriver-1.log") + # log_file = os.path.join(output_dir, "geckodriver-1.log") str_options = "add_argument:--disable-dev-shm-usage" options = mock() profile = mock() @@ -384,7 +390,7 @@ def test_create_driver_firefox(creator, output_dir): when(creator)._get_executable_path(ANY).thenReturn(executable_path) when(webdriver).Firefox( options=options, - service=ANY + service=ANY, # firefox_profile=profile, # executable_path=executable_path, # service_log_path=log_file, diff --git a/utest/test/keywords/test_selenium_service_parser.py b/utest/test/keywords/test_selenium_service_parser.py index 637a208c6..309b2203e 100644 --- a/utest/test/keywords/test_selenium_service_parser.py +++ b/utest/test/keywords/test_selenium_service_parser.py @@ -1,22 +1,21 @@ import os -import unittest +import sys import pytest from approvaltests.approvals import verify_all from approvaltests.reporters.generic_diff_reporter_factory import ( GenericDiffReporterFactory, ) -from mockito import mock, when, unstub, ANY -from robot.utils import WINDOWS -from selenium import webdriver +from mockito import unstub -from SeleniumLibrary.keywords.webdrivertools import SeleniumService, WebDriverCreator +from SeleniumLibrary.keywords.webdrivertools import SeleniumService @pytest.fixture(scope="module") def service(): return SeleniumService() + @pytest.fixture(scope="module") def reporter(): path = os.path.dirname(__file__) @@ -32,28 +31,25 @@ def teardown_function(): unstub() -@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_parse_service_string(service, reporter): results = [] results.append(service._parse('attribute="arg1"')) # results.append(service._parse(" attribute = True ")) # need to resolve issues with spaces in service string. results.append(service._parse('attribute="arg1";attribute=True')) - results.append(service._parse('attribute=["arg1","arg2","arg3"] ; attribute=True ; attribute="arg4"')) results.append( service._parse( - 'attribute="C:\\\\path\\to\\\\profile"' + 'attribute=["arg1","arg2","arg3"] ; attribute=True ; attribute="arg4"' ) ) + results.append(service._parse('attribute="C:\\\\path\\to\\\\profile"')) results.append( - service._parse( - r'attribute="arg1"; attribute="C:\\path\\to\\profile"' - ) + service._parse(r'attribute="arg1"; attribute="C:\\path\\to\\profile"') ) results.append(service._parse("attribute=None")) verify_all("Selenium service string to dict", results, reporter=reporter) -@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") +@pytest.mark.skipif(sys.version_info > (3, 11), reason="Errors change with Python 3.12") def test_parse_service_string_errors(service, reporter): results = [] results.append(error_formatter(service._parse, "attribute=arg1", True)) @@ -61,30 +57,45 @@ def test_parse_service_string_errors(service, reporter): results.append(error_formatter(service._parse, "attribute=['arg1'", True)) results.append(error_formatter(service._parse, "attribute=['arg1';'arg2']", True)) results.append(error_formatter(service._parse, "attribute['arg1']", True)) - results.append(error_formatter(service._parse, "attribute=['arg1'] attribute=['arg2']", True)) + results.append( + error_formatter(service._parse, "attribute=['arg1'] attribute=['arg2']", True) + ) + verify_all("Selenium service string errors", results, reporter=reporter) + + +@pytest.mark.skipif(sys.version_info < (3, 12), reason="Errors change with Python 3.12") +def test_parse_service_string_errors_py3_12(service, reporter): + results = [] + results.append(error_formatter(service._parse, "attribute=arg1", True)) + results.append(error_formatter(service._parse, "attribute='arg1", True)) + results.append(error_formatter(service._parse, "attribute=['arg1'", True)) + results.append(error_formatter(service._parse, "attribute=['arg1';'arg2']", True)) + results.append(error_formatter(service._parse, "attribute['arg1']", True)) + results.append( + error_formatter(service._parse, "attribute=['arg1'] attribute=['arg2']", True) + ) verify_all("Selenium service string errors", results, reporter=reporter) -@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_split_service(service, reporter): results = [] - results.append(service._split("attribute='arg1'", ';')) - results.append(service._split("attribute='arg1';attribute='arg2'", ';')) - results.append(service._split("attribute=['arg1','arg2'];attribute='arg3'", ';')) - results.append(service._split(" attribute = 'arg1' ; attribute = 'arg2' ", ';')) + results.append(service._split("attribute='arg1'", ";")) + results.append(service._split("attribute='arg1';attribute='arg2'", ";")) + results.append(service._split("attribute=['arg1','arg2'];attribute='arg3'", ";")) + results.append(service._split(" attribute = 'arg1' ; attribute = 'arg2' ", ";")) verify_all("Selenium service string splitting", results, reporter=reporter) -@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_split_attribute(service, reporter): results = [] - results.append(service._split("attribute='arg1'", '=')) - results.append(service._split("attribute=['arg1','arg2']", '=')) - results.append(service._split(" attribute = [ 'arg1' , 'arg2' ]", '=')) - verify_all("Selenium service attribute string splitting", results, reporter=reporter) + results.append(service._split("attribute='arg1'", "=")) + results.append(service._split("attribute=['arg1','arg2']", "=")) + results.append(service._split(" attribute = [ 'arg1' , 'arg2' ]", "=")) + verify_all( + "Selenium service attribute string splitting", results, reporter=reporter + ) -@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_service_create(service, reporter): results = [] service_str = "service_args=['--log-level=DEBUG']" @@ -102,7 +113,6 @@ def test_service_create(service, reporter): verify_all("Selenium service", results, reporter=reporter) -@unittest.skipIf(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_importer(service, reporter): results = [] results.append(service._import_service("firefox")) @@ -121,4 +131,4 @@ def error_formatter(method, arg, full=False): except Exception as error: if full: return f"{arg} {error}" - return "{} {}".format(arg, error.__str__()[:15]) \ No newline at end of file + return f"{arg} {error.__str__()[:15]}" diff --git a/utest/test/keywords/test_tablekeywords.py b/utest/test/keywords/test_tablekeywords.py index 6e8c1cf32..87275bc31 100644 --- a/utest/test/keywords/test_tablekeywords.py +++ b/utest/test/keywords/test_tablekeywords.py @@ -1,6 +1,6 @@ import unittest -from mockito import mock, when, unstub +from mockito import mock, unstub, when from SeleniumLibrary.keywords import TableElementKeywords diff --git a/utest/test/keywords/test_waiting_stale_element_refereance_exception.py b/utest/test/keywords/test_waiting_stale_element_refereance_exception.py index 910d9cb6c..3b5b53e1a 100644 --- a/utest/test/keywords/test_waiting_stale_element_refereance_exception.py +++ b/utest/test/keywords/test_waiting_stale_element_refereance_exception.py @@ -1,6 +1,6 @@ import pytest +from mockito import mock, unstub, when from selenium.common.exceptions import StaleElementReferenceException -from mockito import mock, when, unstub from SeleniumLibrary.keywords import WaitingKeywords diff --git a/utest/test/keywords/test_webdrivercache.py b/utest/test/keywords/test_webdrivercache.py index f138565f2..900aaefb1 100644 --- a/utest/test/keywords/test_webdrivercache.py +++ b/utest/test/keywords/test_webdrivercache.py @@ -1,6 +1,7 @@ import unittest -from mockito import mock, verify, when, unstub +import pytest +from mockito import mock, unstub, verify, when from robot.utils.connectioncache import NoConnection from selenium.common.exceptions import TimeoutException, WebDriverException @@ -13,10 +14,9 @@ def tearDown(self): def test_no_current_message(self): cache = WebDriverCache() - try: - self.assertRaises(RuntimeError, cache.current.anyMember()) - except RuntimeError as e: - self.assertEqual(str(e), "No current browser") + with pytest.raises(RuntimeError) as e: + cache.current.anyMember() + assert str(e.value) == "No current browser" def test_browsers_property(self): cache = WebDriverCache() @@ -29,13 +29,13 @@ def test_browsers_property(self): index2 = cache.register(driver2) index3 = cache.register(driver3) - self.assertEqual(len(cache.drivers), 3) - self.assertEqual(cache.drivers[0], driver1) - self.assertEqual(cache.drivers[1], driver2) - self.assertEqual(cache.drivers[2], driver3) - self.assertEqual(index1, 1) - self.assertEqual(index2, 2) - self.assertEqual(index3, 3) + assert len(cache.drivers) == 3 + assert cache.drivers[0] == driver1 + assert cache.drivers[1] == driver2 + assert cache.drivers[2] == driver3 + assert index1 == 1 + assert index2 == 2 + assert index3 == 3 def test_get_open_browsers(self): cache = WebDriverCache() @@ -49,16 +49,16 @@ def test_get_open_browsers(self): cache.register(driver3) drivers = cache.active_drivers - self.assertEqual(len(drivers), 3) - self.assertEqual(drivers[0], driver1) - self.assertEqual(drivers[1], driver2) - self.assertEqual(drivers[2], driver3) + assert len(drivers) == 3 + assert drivers[0] == driver1 + assert drivers[1] == driver2 + assert drivers[2] == driver3 cache.close() drivers = cache.active_drivers - self.assertEqual(len(drivers), 2) - self.assertEqual(drivers[0], driver1) - self.assertEqual(drivers[1], driver2) + assert len(drivers) == 2 + assert drivers[0] == driver1 + assert drivers[1] == driver2 def test_close(self): cache = WebDriverCache() @@ -96,19 +96,19 @@ def test_resolve_alias_or_index(self): cache.register(mock()) index = cache.get_index("foo") - self.assertEqual(index, 1) + assert index == 1 index = cache.get_index(1) - self.assertEqual(index, 1) + assert index == 1 index = cache.get_index(3) - self.assertEqual(index, 3) + assert index == 3 index = cache.get_index(None) - self.assertEqual(index, None) + assert index is None index = cache.get_index("None") - self.assertEqual(index, None) + assert index is None def test_resolve_alias_or_index_with_none(self): cache = WebDriverCache() @@ -117,13 +117,13 @@ def test_resolve_alias_or_index_with_none(self): cache.register(mock(), "None") index = cache.get_index("foo") - self.assertEqual(index, 1) + assert index == 1 index = cache.get_index(1) - self.assertEqual(index, 1) + assert index == 1 index = cache.get_index(None) - self.assertEqual(index, None) + assert index is None def test_resolve_alias_or_index_error(self): cache = WebDriverCache() @@ -132,13 +132,13 @@ def test_resolve_alias_or_index_error(self): cache.register(mock()) index = cache.get_index("bar") - self.assertEqual(index, None) + assert index is None index = cache.get_index(12) - self.assertEqual(index, None) + assert index is None index = cache.get_index(-1) - self.assertEqual(index, None) + assert index is None def test_close_and_same_alias(self): cache = WebDriverCache() @@ -147,20 +147,20 @@ def test_close_and_same_alias(self): cache.register(mock(), "bar") cache.close() index = cache.get_index("bar") - self.assertEqual(index, None) + assert index is None def test_same_alias_new_browser(self): cache = WebDriverCache() cache.close() index = cache.get_index("bar") - self.assertEqual(index, None) + assert index is None def test_close_all_cache_first_quite_fails(self): cache = WebDriverCache() driver = mock() when(driver).quit().thenRaise(TimeoutException("timeout.")) cache.register(driver, "bar") - with self.assertRaises(TimeoutException): + with pytest.raises(TimeoutException): cache.close_all() self.verify_cache(cache) @@ -173,7 +173,7 @@ def test_close_all_cache_middle_quite_fails(self): cache.register(driver0, "bar0") cache.register(driver1, "bar1") cache.register(driver2, "bar2") - with self.assertRaises(TimeoutException): + with pytest.raises(TimeoutException): cache.close_all() self.verify_cache(cache) @@ -186,7 +186,7 @@ def test_close_all_cache_all_quite_fails(self): cache.register(driver0, "bar0") cache.register(driver1, "bar1") cache.register(driver2, "bar2") - with self.assertRaises(TimeoutException): + with pytest.raises(TimeoutException): cache.close_all() self.verify_cache(cache) @@ -199,7 +199,7 @@ def test_close_all_cache_not_selenium_error(self): cache.register(driver0, "bar0") cache.register(driver1, "bar1") cache.register(driver2, "bar2") - with self.assertRaises(TimeoutException): + with pytest.raises(TimeoutException): cache.close_all() self.verify_cache(cache) @@ -217,10 +217,10 @@ def test_close_quite_fails(self): driver = mock() when(driver).quit().thenRaise(TimeoutException("timeout.")) cache.register(driver, "bar") - with self.assertRaises(TimeoutException): + with pytest.raises(TimeoutException): cache.close() - self.assertTrue(isinstance(cache.current, NoConnection)) - self.assertTrue(driver in cache._closed) + assert isinstance(cache.current, NoConnection) + assert driver in cache._closed def test_close_no_error(self): cache = WebDriverCache() @@ -228,10 +228,10 @@ def test_close_no_error(self): when(driver).quit().thenReturn(None) cache.register(driver, "bar") cache.close() - self.assertTrue(isinstance(cache.current, NoConnection)) - self.assertTrue(driver in cache._closed) + assert isinstance(cache.current, NoConnection) + assert driver in cache._closed def verify_cache(self, cache): - self.assertEqual(cache._connections, []) - self.assertEqual(cache._aliases, {}) - self.assertTrue(isinstance(cache.current, NoConnection)) + assert cache._connections == [] + assert cache._aliases == {} + assert isinstance(cache.current, NoConnection) diff --git a/utest/test/keywords/test_windowmananger_window_info.py b/utest/test/keywords/test_windowmananger_window_info.py index 16abd144e..f58300c9a 100644 --- a/utest/test/keywords/test_windowmananger_window_info.py +++ b/utest/test/keywords/test_windowmananger_window_info.py @@ -1,9 +1,9 @@ import unittest -from mockito import mock, when, unstub +from mockito import mock, unstub, when +from selenium.common.exceptions import WebDriverException from SeleniumLibrary.locators.windowmanager import WindowManager -from selenium.common.exceptions import WebDriverException SCRIPT = "return [ window.id, window.name ];" HANDLE = "17c3dc18-0443-478b-aec6-ed7e2a5da7e1" @@ -28,50 +28,48 @@ def mock_window_info(self, id_, name, title, url): def test_window_info_values_are_strings(self): self.mock_window_info("id", "name", "title", "url") info = self.manager._get_current_window_info() - self.assertEqual(info, (HANDLE, "id", "name", "title", "url")) + assert info == (HANDLE, "id", "name", "title", "url") def test_window_info_values_are_none(self): self.mock_window_info(None, None, None, None) info = self.manager._get_current_window_info() - self.assertEqual( - info, (HANDLE, "undefined", "undefined", "undefined", "undefined") - ) + assert info == (HANDLE, "undefined", "undefined", "undefined", "undefined") def test_window_info_values_are_empty_strings(self): self.mock_window_info("", "", "", "") info = self.manager._get_current_window_info() - self.assertEqual(info, (HANDLE, "", "undefined", "undefined", "undefined")) + assert info == (HANDLE, "", "undefined", "undefined", "undefined") def test_window_id_is_bool(self): self.mock_window_info(True, "", "", "") info = self.manager._get_current_window_info() - self.assertEqual(info[1], True) + assert info[1] self.mock_window_info(False, "", "", "") info = self.manager._get_current_window_info() - self.assertEqual(info[1], False) + assert not info[1] def test_window_id_is_web_element(self): elem = mock() self.mock_window_info(*[elem, "", "", ""]) info = self.manager._get_current_window_info() - self.assertEqual(info[1], elem) + assert info[1] == elem def test_window_id_is_container(self): self.mock_window_info(*[["1"], "", "", ""]) info = self.manager._get_current_window_info() - self.assertEqual(info[1], ["1"]) + assert info[1] == ["1"] self.mock_window_info(*[{"a": 2}, "", "", ""]) info = self.manager._get_current_window_info() - self.assertEqual(info[1], {"a": 2}) + assert info[1] == {"a": 2} def test_window_id_is_empty_container(self): self.mock_window_info(*[[], "", "", ""]) info = self.manager._get_current_window_info() - self.assertEqual(info[1], []) + assert info[1] == [] self.mock_window_info(*[{}, "", "", ""]) info = self.manager._get_current_window_info() - self.assertEqual(info[1], {}) + assert info[1] == {} def test_no_javascript_support(self): when(self.driver).execute_script(SCRIPT).thenRaise(WebDriverException) @@ -79,4 +77,4 @@ def test_no_javascript_support(self): self.driver.current_url = "url" self.driver.current_window_handle = HANDLE info = self.manager._get_current_window_info() - self.assertEqual(info, (HANDLE, "undefined", "undefined", "title", "url")) + assert info == (HANDLE, "undefined", "undefined", "title", "url") diff --git a/utest/test/locators/test_elementfinder.py b/utest/test/locators/test_elementfinder.py index ed7b801bd..21792ea33 100644 --- a/utest/test/locators/test_elementfinder.py +++ b/utest/test/locators/test_elementfinder.py @@ -3,14 +3,15 @@ import pytest from approvaltests import verify_all from approvaltests.reporters import GenericDiffReporterFactory -from mockito import any, mock, verify, when, unstub +from mockito import any as mockito_any +from mockito import mock, unstub, verify, when from selenium.webdriver.common.by import By from SeleniumLibrary.errors import ElementNotFound from SeleniumLibrary.locators.elementfinder import ElementFinder -@pytest.fixture(scope="function") +@pytest.fixture def finder(): ctx = mock() ctx.driver = mock() @@ -105,7 +106,7 @@ def _verify_parse_locator(locator, prefix, criteria, finder=None): def test_parent_is_not_webelement(finder): - with pytest.raises(ValueError): + with pytest.raises(ValueError, match=r"^Parent must be Selenium WebElement"): finder.find("//div", parent="//button") @@ -155,9 +156,8 @@ def test_find_by_dom__parent_is_webelement(finder): when(finder)._disallow_webelement_parent(webelement).thenRaise( ValueError("This method does not allow webelement as parent") ) - with pytest.raises(ValueError) as error: + with pytest.raises(ValueError, match="not allow webelement as parent"): finder.find("dom=value", parent=webelement) - assert "not allow webelement as parent" in str(error.value) def test_find_by_sizzle_parent_is_webelement(finder): @@ -167,9 +167,8 @@ def test_find_by_sizzle_parent_is_webelement(finder): when(finder)._disallow_webelement_parent(webelement).thenRaise( ValueError("This method does not allow webelement as parent") ) - with pytest.raises(ValueError) as error: + with pytest.raises(ValueError, match="not allow webelement as parent"): finder.find("sizzle=div.class", parent=webelement) - assert "not allow webelement as parent" in str(error.value) def test_find_by_link_text_parent_is_webelement(finder): @@ -224,9 +223,8 @@ def test_find_sc_locator_parent_is_webelement(finder): when(finder)._disallow_webelement_parent(webelement).thenRaise( ValueError("This method does not allow webelement as parent") ) - with pytest.raises(ValueError) as error: + with pytest.raises(ValueError, match="not allow webelement as parent"): finder.find("scLocator=div", parent=webelement) - assert "not allow webelement as parent" in str(error.value) def test_find_by_default_parent_is_webelement(finder): @@ -250,13 +248,13 @@ def test_non_existing_prefix(finder): def test_find_with_no_tag(finder): driver = _get_driver(finder) finder.find("test1", required=False) - verify(driver).find_elements(By.XPATH, "//*[(@id='test1' or " "@name='test1')]") + verify(driver).find_elements(By.XPATH, "//*[(@id='test1' or @name='test1')]") def test_find_with_explicit_default_strategy(finder): driver = _get_driver(finder) finder.find("default=test1", required=False) - verify(driver).find_elements(By.XPATH, "//*[(@id='test1' or " "@name='test1')]") + verify(driver).find_elements(By.XPATH, "//*[(@id='test1' or @name='test1')]") def test_find_with_explicit_default_strategy_and_equals(finder): @@ -284,6 +282,16 @@ def test_find_with_data(finder): verify(driver).find_elements(By.XPATH, '//*[@data-id="my_id"]') +def test_find_with_data_multiple_colons(finder): + driver = _get_driver(finder) + elements = _make_mock_elements("div", "a", "span", "a") + when(driver).find_elements( + By.XPATH, '//*[@data-automation-id="foo:bar"]' + ).thenReturn(elements) + result = finder.find("data:automation-id:foo:bar", first_only=False) + assert result == elements + + def test_find_with_invalid_data(finder): with pytest.raises( ValueError, @@ -297,6 +305,12 @@ def test_find_with_invalid_data(finder): ): finder.find("data:", tag="div", required=False) + with pytest.raises( + ValueError, + match=r"^Provided selector \(:value\) is malformed\. Correct format: name:value\.", + ): + finder.find("data::value", tag="div", required=False) + def test_find_with_locator_with_apos(finder): driver = _get_driver(finder) @@ -642,7 +656,7 @@ def test_find_returns_bad_values(finder): for bad_value in (None, {"": None}): for locator_strategy in locator_strategies: when_find_func = getattr(when(driver), func_name) - when_find_func(locator_strategy, any()).thenReturn(bad_value) + when_find_func(locator_strategy, mockito_any()).thenReturn(bad_value) for locator in ( "identifier=it", "id=it", diff --git a/utest/test/locators/test_windowmanager.py b/utest/test/locators/test_windowmanager.py index f40770ae4..393faad60 100644 --- a/utest/test/locators/test_windowmanager.py +++ b/utest/test/locators/test_windowmanager.py @@ -1,6 +1,7 @@ import unittest import uuid +import pytest from mockito import mock from SeleniumLibrary.errors import WindowNotFound @@ -10,11 +11,11 @@ class WindowManagerTests(unittest.TestCase): def test_select_with_invalid_prefix(self): manager = WindowManagerWithMockBrowser() - with self.assertRaises(WindowNotFound) as context: + with pytest.raises(WindowNotFound) as context: manager.select("something=test1") - self.assertEqual( - str(context.exception), - "No window matching handle, name, title or URL 'something=test1' found.", + assert ( + str(context.value) + == "No window matching handle, name, title or URL 'something=test1' found." ) def test_select_by_title(self): @@ -24,7 +25,7 @@ def test_select_by_title(self): {"name": "win3", "title": "Title 3", "url": "http://localhost/page3.html"}, ) manager.select("title=Title 2") - self.assertEqual(manager.driver.current_window.name, "win2") + assert manager.driver.current_window.name == "win2" def test_select_by_title_with_multiple_matches(self): manager = WindowManagerWithMockBrowser( @@ -41,7 +42,7 @@ def test_select_by_title_with_multiple_matches(self): }, ) manager.select("title=Title 2") - self.assertEqual(manager.driver.current_window.name, "win2a") + assert manager.driver.current_window.name == "win2a" def test_select_by_title_no_match(self): manager = WindowManagerWithMockBrowser( @@ -49,11 +50,9 @@ def test_select_by_title_no_match(self): {"name": "win2", "title": "Title 2", "url": "http://localhost/page2.html"}, {"name": "win3", "title": "Title 3", "url": "http://localhost/page3.html"}, ) - with self.assertRaises(WindowNotFound) as context: + with pytest.raises(WindowNotFound) as context: manager.select("title=Title -1") - self.assertEqual( - str(context.exception), "Unable to locate window with title 'Title -1'." - ) + assert str(context.value) == "Unable to locate window with title 'Title -1'." def test_select_by_name(self): manager = WindowManagerWithMockBrowser( @@ -62,7 +61,7 @@ def test_select_by_name(self): {"name": "win3", "title": "Title 3", "url": "http://localhost/page3.html"}, ) manager.select("name=win2") - self.assertEqual(manager.driver.current_window.name, "win2") + assert manager.driver.current_window.name == "win2" def test_select_by_name_no_match(self): manager = WindowManagerWithMockBrowser( @@ -70,11 +69,9 @@ def test_select_by_name_no_match(self): {"name": "win2", "title": "Title 2", "url": "http://localhost/page2.html"}, {"name": "win3", "title": "Title 3", "url": "http://localhost/page3.html"}, ) - with self.assertRaises(WindowNotFound) as context: + with pytest.raises(WindowNotFound) as context: manager.select("name=win-1") - self.assertEqual( - str(context.exception), "Unable to locate window with name 'win-1'." - ) + assert str(context.value) == "Unable to locate window with name 'win-1'." def test_select_by_url(self): manager = WindowManagerWithMockBrowser( @@ -83,7 +80,7 @@ def test_select_by_url(self): {"name": "win3", "title": "Title 3", "url": "http://localhost/page3.html"}, ) manager.select("url=http://localhost/page2.html") - self.assertEqual(manager.driver.current_window.name, "win2") + assert manager.driver.current_window.name == "win2" def test_select_by_url_with_multiple_matches(self): manager = WindowManagerWithMockBrowser( @@ -100,7 +97,7 @@ def test_select_by_url_with_multiple_matches(self): }, ) manager.select("url=http://localhost/page2.html") - self.assertEqual(manager.driver.current_window.name, "win2a") + assert manager.driver.current_window.name == "win2a" def test_select_by_url_no_match(self): manager = WindowManagerWithMockBrowser( @@ -108,11 +105,11 @@ def test_select_by_url_no_match(self): {"name": "win2", "title": "Title 2", "url": "http://localhost/page2.html"}, {"name": "win3", "title": "Title 3", "url": "http://localhost/page3.html"}, ) - with self.assertRaises(WindowNotFound) as context: + with pytest.raises(WindowNotFound) as context: manager.select("url=http://localhost/page-1.html") - self.assertEqual( - str(context.exception), - "Unable to locate window with URL 'http://localhost/page-1.html'.", + assert ( + str(context.value) + == "Unable to locate window with URL 'http://localhost/page-1.html'." ) def test_select_main_window(self): @@ -122,11 +119,11 @@ def test_select_main_window(self): {"name": "win3", "title": "Title 3", "url": "http://localhost/page3.html"}, ) manager.select("name=win2") - self.assertEqual(manager.driver.current_window.name, "win2") + assert manager.driver.current_window.name == "win2" manager.select("main") - self.assertEqual(manager.driver.current_window.name, "win1") + assert manager.driver.current_window.name == "win1" manager.select("MAIN") - self.assertEqual(manager.driver.current_window.name, "win1") + assert manager.driver.current_window.name == "win1" def test_select_by_default_with_name(self): manager = WindowManagerWithMockBrowser( @@ -135,7 +132,7 @@ def test_select_by_default_with_name(self): {"name": "win3", "title": "Title 3", "url": "http://localhost/page3.html"}, ) manager.select("win2") - self.assertEqual(manager.driver.current_window.name, "win2") + assert manager.driver.current_window.name == "win2" def test_select_by_default_with_title(self): manager = WindowManagerWithMockBrowser( @@ -144,7 +141,7 @@ def test_select_by_default_with_title(self): {"name": "win3", "title": "Title 3", "url": "http://localhost/page3.html"}, ) manager.select("Title 2") - self.assertEqual(manager.driver.current_window.name, "win2") + assert manager.driver.current_window.name == "win2" def test_select_by_default_no_match(self): manager = WindowManagerWithMockBrowser( @@ -152,11 +149,11 @@ def test_select_by_default_no_match(self): {"name": "win2", "title": "Title 2", "url": "http://localhost/page2.html"}, {"name": "win3", "title": "Title 3", "url": "http://localhost/page3.html"}, ) - with self.assertRaises(WindowNotFound) as context: + with pytest.raises(WindowNotFound) as context: manager.select("foobar") - self.assertEqual( - str(context.exception), - "No window matching handle, name, title or URL 'foobar' found.", + assert ( + str(context.value) + == "No window matching handle, name, title or URL 'foobar' found." ) def test_prefix_is_case_sensitive(self): @@ -166,12 +163,12 @@ def test_prefix_is_case_sensitive(self): {"name": "win3", "title": "Title 3", "url": "http://localhost/page3.html"}, ) manager.select("name=win2") - self.assertEqual(manager.driver.current_window.name, "win2") - with self.assertRaises(WindowNotFound) as context: + assert manager.driver.current_window.name == "win2" + with pytest.raises(WindowNotFound) as context: manager.select("nAmE=win2") - self.assertEqual( - str(context.exception), - "No window matching handle, name, title or URL 'nAmE=win2' found.", + assert ( + str(context.value) + == "No window matching handle, name, title or URL 'nAmE=win2' found." ) def test_get_window_infos(self): @@ -180,21 +177,26 @@ def test_get_window_infos(self): {"id": "id2", "name": "win2", "title": "Title 2", "url": "http://url.2"}, {"name": "win3", "title": "Title 3", "url": "http://url.3"}, ) - self.assertEqual( - [info.id for info in manager.get_window_infos()], - ["id1", "id2", "undefined"], - ) - self.assertEqual( - [info.name for info in manager.get_window_infos()], ["win1", "win2", "win3"] - ) - self.assertEqual( - [info.title for info in manager.get_window_infos()], - ["Title 1", "Title 2", "Title 3"], - ) - self.assertEqual( - [info.url for info in manager.get_window_infos()], - ["http://url.1", "http://url.2", "http://url.3"], - ) + assert [info.id for info in manager.get_window_infos()] == [ + "id1", + "id2", + "undefined", + ] + assert [info.name for info in manager.get_window_infos()] == [ + "win1", + "win2", + "win3", + ] + assert [info.title for info in manager.get_window_infos()] == [ + "Title 1", + "Title 2", + "Title 3", + ] + assert [info.url for info in manager.get_window_infos()] == [ + "http://url.1", + "http://url.2", + "http://url.3", + ] class WindowManagerWithMockBrowser(WindowManager): @@ -238,6 +240,7 @@ def execute_script(script): handle_ = driver.session_id if handle_ in driver.window_handles: return window_infos[handle_][:2] + return None driver.execute_script = execute_script return driver diff --git a/utest/test/robotframework_seleniumlibrary_translation_fi/__init__.py b/utest/test/robotframework_seleniumlibrary_translation_fi/__init__.py index 369b7c953..55f6e3a2d 100644 --- a/utest/test/robotframework_seleniumlibrary_translation_fi/__init__.py +++ b/utest/test/robotframework_seleniumlibrary_translation_fi/__init__.py @@ -3,7 +3,4 @@ def get_language() -> dict: curr_dir = Path(__file__).parent.absolute() - return { - "language": "fi", - "path": curr_dir / "translate.json" - } + return {"language": "fi", "path": curr_dir / "translate.json"} diff --git a/utest/test/robotframework_seleniumlibrary_translation_fi/translate.json b/utest/test/robotframework_seleniumlibrary_translation_fi/translate.json index fa46a7425..67bfb7579 100644 --- a/utest/test/robotframework_seleniumlibrary_translation_fi/translate.json +++ b/utest/test/robotframework_seleniumlibrary_translation_fi/translate.json @@ -906,12 +906,12 @@ }, "__init__": { "name": "__init__", - "doc": "1 SeleniumLibrary is a web testing library for Robot Framework.\n\nThis document explains how to use keywords provided by SeleniumLibrary.\nFor information about installation, support, and more, please visit the\n[https://github.com/robotframework/SeleniumLibrary|project pages].\nFor more information about Robot Framework, see http://robotframework.org.\n\nSeleniumLibrary uses the Selenium WebDriver modules internally to\ncontrol a web browser. See http://seleniumhq.org for more information\nabout Selenium in general and SeleniumLibrary README.rst\n[https://github.com/robotframework/SeleniumLibrary#browser-drivers|Browser drivers chapter]\nfor more details about WebDriver binary installation.\n\n%TOC%\n\n= Locating elements =\n\nAll keywords in SeleniumLibrary that need to interact with an element\non a web page take an argument typically named ``locator`` that specifies\nhow to find the element. Most often the locator is given as a string\nusing the locator syntax described below, but `using WebElements` is\npossible too.\n\n== Locator syntax ==\n\nSeleniumLibrary supports finding elements based on different strategies\nsuch as the element id, XPath expressions, or CSS selectors. The strategy\ncan either be explicitly specified with a prefix or the strategy can be\nimplicit.\n\n=== Default locator strategy ===\n\nBy default, locators are considered to use the keyword specific default\nlocator strategy. All keywords support finding elements based on ``id``\nand ``name`` attributes, but some keywords support additional attributes\nor other values that make sense in their context. For example, `Click\nLink` supports the ``href`` attribute and the link text and addition\nto the normal ``id`` and ``name``.\n\nExamples:\n\n| `Click Element` | example | # Match based on ``id`` or ``name``. |\n| `Click Link` | example | # Match also based on link text and ``href``. |\n| `Click Button` | example | # Match based on ``id``, ``name`` or ``value``. |\n\nIf a locator accidentally starts with a prefix recognized as `explicit\nlocator strategy` or `implicit XPath strategy`, it is possible to use\nthe explicit ``default`` prefix to enable the default strategy.\n\nExamples:\n\n| `Click Element` | name:foo | # Find element with name ``foo``. |\n| `Click Element` | default:name:foo | # Use default strategy with value ``name:foo``. |\n| `Click Element` | //foo | # Find element using XPath ``//foo``. |\n| `Click Element` | default: //foo | # Use default strategy with value ``//foo``. |\n\n=== Explicit locator strategy ===\n\nThe explicit locator strategy is specified with a prefix using either\nsyntax ``strategy:value`` or ``strategy=value``. The former syntax\nis preferred because the latter is identical to Robot Framework's\n[http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#named-argument-syntax|\nnamed argument syntax] and that can cause problems. Spaces around\nthe separator are ignored, so ``id:foo``, ``id: foo`` and ``id : foo``\nare all equivalent.\n\nLocator strategies that are supported by default are listed in the table\nbelow. In addition to them, it is possible to register `custom locators`.\n\n| = Strategy = | = Match based on = | = Example = |\n| id | Element ``id``. | ``id:example`` |\n| name | ``name`` attribute. | ``name:example`` |\n| identifier | Either ``id`` or ``name``. | ``identifier:example`` |\n| class | Element ``class``. | ``class:example`` |\n| tag | Tag name. | ``tag:div`` |\n| xpath | XPath expression. | ``xpath://div[@id=\"example\"]`` |\n| css | CSS selector. | ``css:div#example`` |\n| dom | DOM expression. | ``dom:document.images[5]`` |\n| link | Exact text a link has. | ``link:The example`` |\n| partial link | Partial link text. | ``partial link:he ex`` |\n| sizzle | Sizzle selector deprecated. | ``sizzle:div.example`` |\n| data | Element ``data-*`` attribute | ``data:id:my_id`` |\n| jquery | jQuery expression. | ``jquery:div.example`` |\n| default | Keyword specific default behavior. | ``default:example`` |\n\nSee the `Default locator strategy` section below for more information\nabout how the default strategy works. Using the explicit ``default``\nprefix is only necessary if the locator value itself accidentally\nmatches some of the explicit strategies.\n\nDifferent locator strategies have different pros and cons. Using ids,\neither explicitly like ``id:foo`` or by using the `default locator\nstrategy` simply like ``foo``, is recommended when possible, because\nthe syntax is simple and locating elements by id is fast for browsers.\nIf an element does not have an id or the id is not stable, other\nsolutions need to be used. If an element has a unique tag name or class,\nusing ``tag``, ``class`` or ``css`` strategy like ``tag:h1``,\n``class:example`` or ``css:h1.example`` is often an easy solution. In\nmore complex cases using XPath expressions is typically the best\napproach. They are very powerful but a downside is that they can also\nget complex.\n\nExamples:\n\n| `Click Element` | id:foo | # Element with id 'foo'. |\n| `Click Element` | css:div#foo h1 | # h1 element under div with id 'foo'. |\n| `Click Element` | xpath: //div[@id=\"foo\"]//h1 | # Same as the above using XPath, not CSS. |\n| `Click Element` | xpath: //*[contains(text(), \"example\")] | # Element containing text 'example'. |\n\n*NOTE:*\n\n- The ``strategy:value`` syntax is only supported by SeleniumLibrary 3.0\n and newer.\n- Using the ``sizzle`` strategy or its alias ``jquery`` requires that\n the system under test contains the jQuery library.\n- Prior to SeleniumLibrary 3.0, table related keywords only supported\n ``xpath``, ``css`` and ``sizzle/jquery`` strategies.\n- ``data`` strategy is conveniance locator that will construct xpath from the parameters.\n If you have element like `

`, you locate the element via\n ``data:automation:automation-id-2``. This feature was added in SeleniumLibrary 5.2.0\n\n=== Implicit XPath strategy ===\n\nIf the locator starts with ``//`` or multiple opening parenthesis in front\nof the ``//``, the locator is considered to be an XPath expression. In other\nwords, using ``//div`` is equivalent to using explicit ``xpath://div`` and\n``((//div))`` is equivalent to using explicit ``xpath:((//div))``\n\nExamples:\n\n| `Click Element` | //div[@id=\"foo\"]//h1 |\n| `Click Element` | (//div)[2] |\n\nThe support for the ``(//`` prefix is new in SeleniumLibrary 3.0.\nSupporting multiple opening parenthesis is new in SeleniumLibrary 5.0.\n\n=== Chaining locators ===\n\nIt is possible chain multiple locators together as single locator. Each chained locator must start with locator\nstrategy. Chained locators must be separated with single space, two greater than characters and followed with\nspace. It is also possible mix different locator strategies, example css or xpath. Also a list can also be\nused to specify multiple locators. This is useful, is some part of locator would match as the locator separator\nbut it should not. Or if there is need to existing WebElement as locator.\n\nAlthough all locators support chaining, some locator strategies do not abey the chaining. This is because\nsome locator strategies use JavaScript to find elements and JavaScript is executed for the whole browser context\nand not for the element found be the previous locator. Chaining is supported by locator strategies which\nare based on Selenium API, like `xpath` or `css`, but example chaining is not supported by `sizzle` or `jquery\n\nExamples:\n| `Click Element` | css:.bar >> xpath://a | # To find a link which is present after an element with class \"bar\" |\n\nList examples:\n| ${locator_list} = | `Create List` | css:div#div_id | xpath://*[text(), \" >> \"] |\n| `Page Should Contain Element` | ${locator_list} | | |\n| ${element} = | Get WebElement | xpath://*[text(), \" >> \"] | |\n| ${locator_list} = | `Create List` | css:div#div_id | ${element} |\n| `Page Should Contain Element` | ${locator_list} | | |\n\nChaining locators in new in SeleniumLibrary 5.0\n\n== Using WebElements ==\n\nIn addition to specifying a locator as a string, it is possible to use\nSelenium's WebElement objects. This requires first getting a WebElement,\nfor example, by using the `Get WebElement` keyword.\n\n| ${elem} = | `Get WebElement` | id:example |\n| `Click Element` | ${elem} | |\n\n== Custom locators ==\n\nIf more complex lookups are required than what is provided through the\ndefault locators, custom lookup strategies can be created. Using custom\nlocators is a two part process. First, create a keyword that returns\na WebElement that should be acted on:\n\n| Custom Locator Strategy | [Arguments] | ${browser} | ${locator} | ${tag} | ${constraints} |\n| | ${element}= | Execute Javascript | return window.document.getElementById('${locator}'); |\n| | [Return] | ${element} |\n\nThis keyword is a reimplementation of the basic functionality of the\n``id`` locator where ``${browser}`` is a reference to a WebDriver\ninstance and ``${locator}`` is the name of the locator strategy. To use\nthis locator, it must first be registered by using the\n`Add Location Strategy` keyword:\n\n| `Add Location Strategy` | custom | Custom Locator Strategy |\n\nThe first argument of `Add Location Strategy` specifies the name of\nthe strategy and it must be unique. After registering the strategy,\nthe usage is the same as with other locators:\n\n| `Click Element` | custom:example |\n\nSee the `Add Location Strategy` keyword for more details.\n\n= Browser and Window =\n\nThere is different conceptual meaning when SeleniumLibrary talks\nabout windows or browsers. This chapter explains those differences.\n\n== Browser ==\n\nWhen `Open Browser` or `Create WebDriver` keyword is called, it\nwill create a new Selenium WebDriver instance by using the\n[https://www.seleniumhq.org/docs/03_webdriver.jsp|Selenium WebDriver]\nAPI. In SeleniumLibrary terms, a new browser is created. It is\npossible to start multiple independent browsers (Selenium Webdriver\ninstances) at the same time, by calling `Open Browser` or\n`Create WebDriver` multiple times. These browsers are usually\nindependent of each other and do not share data like cookies,\nsessions or profiles. Typically when the browser starts, it\ncreates a single window which is shown to the user.\n\n== Window ==\n\nWindows are the part of a browser that loads the web site and presents\nit to the user. All content of the site is the content of the window.\nWindows are children of a browser. In SeleniumLibrary browser is a\nsynonym for WebDriver instance. One browser may have multiple\nwindows. Windows can appear as tabs, as separate windows or pop-ups with\ndifferent position and size. Windows belonging to the same browser\ntypically share the sessions detail, like cookies. If there is a\nneed to separate sessions detail, example login with two different\nusers, two browsers (Selenium WebDriver instances) must be created.\nNew windows can be opened example by the application under test or\nby example `Execute Javascript` keyword:\n\n| `Execute Javascript` window.open() # Opens a new window with location about:blank\n\nThe example below opens multiple browsers and windows,\nto demonstrate how the different keywords can be used to interact\nwith browsers, and windows attached to these browsers.\n\nStructure:\n| BrowserA\n| Window 1 (location=https://robotframework.org/)\n| Window 2 (location=https://robocon.io/)\n| Window 3 (location=https://github.com/robotframework/)\n|\n| BrowserB\n| Window 1 (location=https://github.com/)\n\nExample:\n| `Open Browser` | https://robotframework.org | ${BROWSER} | alias=BrowserA | # BrowserA with first window is opened. |\n| `Execute Javascript` | window.open() | | | # In BrowserA second window is opened. |\n| `Switch Window` | locator=NEW | | | # Switched to second window in BrowserA |\n| `Go To` | https://robocon.io | | | # Second window navigates to robocon site. |\n| `Execute Javascript` | window.open() | | | # In BrowserA third window is opened. |\n| ${handle} | `Switch Window` | locator=NEW | | # Switched to third window in BrowserA |\n| `Go To` | https://github.com/robotframework/ | | | # Third windows goes to robot framework github site. |\n| `Open Browser` | https://github.com | ${BROWSER} | alias=BrowserB | # BrowserB with first windows is opened. |\n| ${location} | `Get Location` | | | # ${location} is: https://www.github.com |\n| `Switch Window` | ${handle} | browser=BrowserA | | # BrowserA second windows is selected. |\n| ${location} | `Get Location` | | | # ${location} = https://robocon.io/ |\n| @{locations 1} | `Get Locations` | | | # By default, lists locations under the currectly active browser (BrowserA). |\n| @{locations 2} | `Get Locations` | browser=ALL | | # By using browser=ALL argument keyword list all locations from all browsers. |\n\nThe above example, @{locations 1} contains the following items:\nhttps://robotframework.org/, https://robocon.io/ and\nhttps://github.com/robotframework/'. The @{locations 2}\ncontains the following items: https://robotframework.org/,\nhttps://robocon.io/, https://github.com/robotframework/'\nand 'https://github.com/.\n\n= Timeouts, waits, and delays =\n\nThis section discusses different ways how to wait for elements to\nappear on web pages and to slow down execution speed otherwise.\nIt also explains the `time format` that can be used when setting various\ntimeouts, waits, and delays.\n\n== Timeout ==\n\nSeleniumLibrary contains various keywords that have an optional\n``timeout`` argument that specifies how long these keywords should\nwait for certain events or actions. These keywords include, for example,\n``Wait ...`` keywords and keywords related to alerts. Additionally\n`Execute Async Javascript`. Although it does not have ``timeout``,\nargument, uses a timeout to define how long asynchronous JavaScript\ncan run.\n\nThe default timeout these keywords use can be set globally either by\nusing the `Set Selenium Timeout` keyword or with the ``timeout`` argument\nwhen `importing` the library. If no default timeout is set globally, the\ndefault is 5 seconds. If None is specified for the timeout argument in the\nkeywords, the default is used. See `time format` below for supported\ntimeout syntax.\n\n== Implicit wait ==\n\nImplicit wait specifies the maximum time how long Selenium waits when\nsearching for elements. It can be set by using the `Set Selenium Implicit\nWait` keyword or with the ``implicit_wait`` argument when `importing`\nthe library. See [https://www.seleniumhq.org/docs/04_webdriver_advanced.jsp|\nSelenium documentation] for more information about this functionality.\n\nSee `time format` below for supported syntax.\n\n== Page load ==\nPage load timeout is the amount of time to wait for page load to complete\nuntil a timeout exception is raised.\n\nThe default page load timeout can be set globally\nwhen `importing` the library with the ``page_load_timeout`` argument\nor by using the `Set Selenium Page Load Timeout` keyword.\n\nSee `time format` below for supported timeout syntax.\n\nSupport for page load is new in SeleniumLibrary 6.1\n\n== Selenium speed ==\n\nSelenium execution speed can be slowed down globally by using `Set\nSelenium speed` keyword. This functionality is designed to be used for\ndemonstrating or debugging purposes. Using it to make sure that elements\nappear on a page is not a good idea. The above-explained timeouts\nand waits should be used instead.\n\nSee `time format` below for supported syntax.\n\n== Time format ==\n\nAll timeouts and waits can be given as numbers considered seconds\n(e.g. ``0.5`` or ``42``) or in Robot Framework's time syntax\n(e.g. ``1.5 seconds`` or ``1 min 30 s``). For more information about\nthe time syntax see the\n[http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#time-format|Robot Framework User Guide].\n\n= Run-on-failure functionality =\n\nSeleniumLibrary has a handy feature that it can automatically execute\na keyword if any of its own keywords fails. By default, it uses the\n`Capture Page Screenshot` keyword, but this can be changed either by\nusing the `Register Keyword To Run On Failure` keyword or with the\n``run_on_failure`` argument when `importing` the library. It is\npossible to use any keyword from any imported library or resource file.\n\nThe run-on-failure functionality can be disabled by using a special value\n``NOTHING`` or anything considered false (see `Boolean arguments`)\nsuch as ``NONE``.\n\n= Boolean arguments =\n\nStarting from 5.0 SeleniumLibrary relies on Robot Framework to perform the\nboolean conversion based on keyword arguments [https://docs.python.org/3/library/typing.html|type hint].\nMore details in Robot Framework\n[http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#supported-conversions|user guide]\n\nPlease note SeleniumLibrary 3 and 4 did have own custom methods to covert\narguments to boolean values.\n\n= EventFiringWebDriver =\n\nThe SeleniumLibrary offers support for\n[https://seleniumhq.github.io/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.event_firing_webdriver.html#module-selenium.webdriver.support.event_firing_webdriver|EventFiringWebDriver].\nSee the Selenium and SeleniumLibrary\n[https://github.com/robotframework/SeleniumLibrary/blob/master/docs/extending/extending.rst#EventFiringWebDriver|EventFiringWebDriver support]\ndocumentation for further details.\n\nEventFiringWebDriver is new in SeleniumLibrary 4.0\n\n= Thread support =\n\nSeleniumLibrary is not thread-safe. This is mainly due because the underlying\n[https://github.com/SeleniumHQ/selenium/wiki/Frequently-Asked-Questions#q-is-webdriver-thread-safe|\nSelenium tool is not thread-safe] within one browser/driver instance.\nBecause of the limitation in the Selenium side, the keywords or the\nAPI provided by the SeleniumLibrary is not thread-safe.\n\n= Plugins =\n\nSeleniumLibrary offers plugins as a way to modify and add library keywords and modify some of the internal\nfunctionality without creating a new library or hacking the source code. See\n[https://github.com/robotframework/SeleniumLibrary/blob/master/docs/extending/extending.rst#Plugins|plugin API]\ndocumentation for further details.\n\nPlugin API is new SeleniumLibrary 4.0", + "doc": "00 SeleniumLibrary is a web testing library for Robot Framework.\n\nThis document explains how to use keywords provided by SeleniumLibrary.\nFor information about installation, support, and more, please visit the\n[https://github.com/robotframework/SeleniumLibrary|project pages].\nFor more information about Robot Framework, see http://robotframework.org.\n\nSeleniumLibrary uses the Selenium WebDriver modules internally to\ncontrol a web browser. See http://seleniumhq.org for more information\nabout Selenium in general and SeleniumLibrary README.rst\n[https://github.com/robotframework/SeleniumLibrary#browser-drivers|Browser drivers chapter]\nfor more details about WebDriver binary installation.\n\n%TOC%\n\n= Locating elements =\n\nAll keywords in SeleniumLibrary that need to interact with an element\non a web page take an argument typically named ``locator`` that specifies\nhow to find the element. Most often the locator is given as a string\nusing the locator syntax described below, but `using WebElements` is\npossible too.\n\n== Locator syntax ==\n\nSeleniumLibrary supports finding elements based on different strategies\nsuch as the element id, XPath expressions, or CSS selectors. The strategy\ncan either be explicitly specified with a prefix or the strategy can be\nimplicit.\n\n=== Default locator strategy ===\n\nBy default, locators are considered to use the keyword specific default\nlocator strategy. All keywords support finding elements based on ``id``\nand ``name`` attributes, but some keywords support additional attributes\nor other values that make sense in their context. For example, `Click\nLink` supports the ``href`` attribute and the link text and addition\nto the normal ``id`` and ``name``.\n\nExamples:\n\n| `Click Element` | example | # Match based on ``id`` or ``name``. |\n| `Click Link` | example | # Match also based on link text and ``href``. |\n| `Click Button` | example | # Match based on ``id``, ``name`` or ``value``. |\n\nIf a locator accidentally starts with a prefix recognized as `explicit\nlocator strategy` or `implicit XPath strategy`, it is possible to use\nthe explicit ``default`` prefix to enable the default strategy.\n\nExamples:\n\n| `Click Element` | name:foo | # Find element with name ``foo``. |\n| `Click Element` | default:name:foo | # Use default strategy with value ``name:foo``. |\n| `Click Element` | //foo | # Find element using XPath ``//foo``. |\n| `Click Element` | default: //foo | # Use default strategy with value ``//foo``. |\n\n=== Explicit locator strategy ===\n\nThe explicit locator strategy is specified with a prefix using either\nsyntax ``strategy:value`` or ``strategy=value``. The former syntax\nis preferred because the latter is identical to Robot Framework's\n[http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#named-argument-syntax|\nnamed argument syntax] and that can cause problems. Spaces around\nthe separator are ignored, so ``id:foo``, ``id: foo`` and ``id : foo``\nare all equivalent.\n\nLocator strategies that are supported by default are listed in the table\nbelow. In addition to them, it is possible to register `custom locators`.\n\n| = Strategy = | = Match based on = | = Example = |\n| id | Element ``id``. | ``id:example`` |\n| name | ``name`` attribute. | ``name:example`` |\n| identifier | Either ``id`` or ``name``. | ``identifier:example`` |\n| class | Element ``class``. | ``class:example`` |\n| tag | Tag name. | ``tag:div`` |\n| xpath | XPath expression. | ``xpath://div[@id=\"example\"]`` |\n| css | CSS selector. | ``css:div#example`` |\n| dom | DOM expression. | ``dom:document.images[5]`` |\n| link | Exact text a link has. | ``link:The example`` |\n| partial link | Partial link text. | ``partial link:he ex`` |\n| sizzle | Sizzle selector deprecated. | ``sizzle:div.example`` |\n| data | Element ``data-*`` attribute | ``data:id:my_id`` |\n| jquery | jQuery expression. | ``jquery:div.example`` |\n| default | Keyword specific default behavior. | ``default:example`` |\n\nSee the `Default locator strategy` section below for more information\nabout how the default strategy works. Using the explicit ``default``\nprefix is only necessary if the locator value itself accidentally\nmatches some of the explicit strategies.\n\nDifferent locator strategies have different pros and cons. Using ids,\neither explicitly like ``id:foo`` or by using the `default locator\nstrategy` simply like ``foo``, is recommended when possible, because\nthe syntax is simple and locating elements by id is fast for browsers.\nIf an element does not have an id or the id is not stable, other\nsolutions need to be used. If an element has a unique tag name or class,\nusing ``tag``, ``class`` or ``css`` strategy like ``tag:h1``,\n``class:example`` or ``css:h1.example`` is often an easy solution. In\nmore complex cases using XPath expressions is typically the best\napproach. They are very powerful but a downside is that they can also\nget complex.\n\nExamples:\n\n| `Click Element` | id:foo | # Element with id 'foo'. |\n| `Click Element` | css:div#foo h1 | # h1 element under div with id 'foo'. |\n| `Click Element` | xpath: //div[@id=\"foo\"]//h1 | # Same as the above using XPath, not CSS. |\n| `Click Element` | xpath: //*[contains(text(), \"example\")] | # Element containing text 'example'. |\n\n*NOTE:*\n\n- The ``strategy:value`` syntax is only supported by SeleniumLibrary 3.0\n and newer.\n- Using the ``sizzle`` strategy or its alias ``jquery`` requires that\n the system under test contains the jQuery library.\n- Prior to SeleniumLibrary 3.0, table related keywords only supported\n ``xpath``, ``css`` and ``sizzle/jquery`` strategies.\n- ``data`` strategy is conveniance locator that will construct xpath from the parameters.\n If you have element like `
`, you locate the element via\n ``data:automation:automation-id-2``. This feature was added in SeleniumLibrary 5.2.0\n\n=== Implicit XPath strategy ===\n\nIf the locator starts with ``//`` or multiple opening parenthesis in front\nof the ``//``, the locator is considered to be an XPath expression. In other\nwords, using ``//div`` is equivalent to using explicit ``xpath://div`` and\n``((//div))`` is equivalent to using explicit ``xpath:((//div))``\n\nExamples:\n\n| `Click Element` | //div[@id=\"foo\"]//h1 |\n| `Click Element` | (//div)[2] |\n\nThe support for the ``(//`` prefix is new in SeleniumLibrary 3.0.\nSupporting multiple opening parenthesis is new in SeleniumLibrary 5.0.\n\n=== Chaining locators ===\n\nIt is possible chain multiple locators together as single locator. Each chained locator must start with locator\nstrategy. Chained locators must be separated with single space, two greater than characters and followed with\nspace. It is also possible mix different locator strategies, example css or xpath. Also a list can also be\nused to specify multiple locators. This is useful, is some part of locator would match as the locator separator\nbut it should not. Or if there is need to existing WebElement as locator.\n\nAlthough all locators support chaining, some locator strategies do not abey the chaining. This is because\nsome locator strategies use JavaScript to find elements and JavaScript is executed for the whole browser context\nand not for the element found be the previous locator. Chaining is supported by locator strategies which\nare based on Selenium API, like `xpath` or `css`, but example chaining is not supported by `sizzle` or `jquery\n\nExamples:\n| `Click Element` | css:.bar >> xpath://a | # To find a link which is present after an element with class \"bar\" |\n\nList examples:\n| ${locator_list} = | `Create List` | css:div#div_id | xpath://*[text(), \" >> \"] |\n| `Page Should Contain Element` | ${locator_list} | | |\n| ${element} = | Get WebElement | xpath://*[text(), \" >> \"] | |\n| ${locator_list} = | `Create List` | css:div#div_id | ${element} |\n| `Page Should Contain Element` | ${locator_list} | | |\n\nChaining locators in new in SeleniumLibrary 5.0\n\n== Using WebElements ==\n\nIn addition to specifying a locator as a string, it is possible to use\nSelenium's WebElement objects. This requires first getting a WebElement,\nfor example, by using the `Get WebElement` keyword.\n\n| ${elem} = | `Get WebElement` | id:example |\n| `Click Element` | ${elem} | |\n\n== Custom locators ==\n\nIf more complex lookups are required than what is provided through the\ndefault locators, custom lookup strategies can be created. Using custom\nlocators is a two part process. First, create a keyword that returns\na WebElement that should be acted on:\n\n| Custom Locator Strategy | [Arguments] | ${browser} | ${locator} | ${tag} | ${constraints} |\n| | ${element}= | Execute Javascript | return window.document.getElementById('${locator}'); |\n| | [Return] | ${element} |\n\nThis keyword is a reimplementation of the basic functionality of the\n``id`` locator where ``${browser}`` is a reference to a WebDriver\ninstance and ``${locator}`` is the name of the locator strategy. To use\nthis locator, it must first be registered by using the\n`Add Location Strategy` keyword:\n\n| `Add Location Strategy` | custom | Custom Locator Strategy |\n\nThe first argument of `Add Location Strategy` specifies the name of\nthe strategy and it must be unique. After registering the strategy,\nthe usage is the same as with other locators:\n\n| `Click Element` | custom:example |\n\nSee the `Add Location Strategy` keyword for more details.\n\n= Browser and Window =\n\nThere is different conceptual meaning when SeleniumLibrary talks\nabout windows or browsers. This chapter explains those differences.\n\n== Browser ==\n\nWhen `Open Browser` or `Create WebDriver` keyword is called, it\nwill create a new Selenium WebDriver instance by using the\n[https://www.seleniumhq.org/docs/03_webdriver.jsp|Selenium WebDriver]\nAPI. In SeleniumLibrary terms, a new browser is created. It is\npossible to start multiple independent browsers (Selenium Webdriver\ninstances) at the same time, by calling `Open Browser` or\n`Create WebDriver` multiple times. These browsers are usually\nindependent of each other and do not share data like cookies,\nsessions or profiles. Typically when the browser starts, it\ncreates a single window which is shown to the user.\n\n== Window ==\n\nWindows are the part of a browser that loads the web site and presents\nit to the user. All content of the site is the content of the window.\nWindows are children of a browser. In SeleniumLibrary browser is a\nsynonym for WebDriver instance. One browser may have multiple\nwindows. Windows can appear as tabs, as separate windows or pop-ups with\ndifferent position and size. Windows belonging to the same browser\ntypically share the sessions detail, like cookies. If there is a\nneed to separate sessions detail, example login with two different\nusers, two browsers (Selenium WebDriver instances) must be created.\nNew windows can be opened example by the application under test or\nby example `Execute Javascript` keyword:\n\n| `Execute Javascript` window.open() # Opens a new window with location about:blank\n\nThe example below opens multiple browsers and windows,\nto demonstrate how the different keywords can be used to interact\nwith browsers, and windows attached to these browsers.\n\nStructure:\n| BrowserA\n| Window 1 (location=https://robotframework.org/)\n| Window 2 (location=https://robocon.io/)\n| Window 3 (location=https://github.com/robotframework/)\n|\n| BrowserB\n| Window 1 (location=https://github.com/)\n\nExample:\n| `Open Browser` | https://robotframework.org | ${BROWSER} | alias=BrowserA | # BrowserA with first window is opened. |\n| `Execute Javascript` | window.open() | | | # In BrowserA second window is opened. |\n| `Switch Window` | locator=NEW | | | # Switched to second window in BrowserA |\n| `Go To` | https://robocon.io | | | # Second window navigates to robocon site. |\n| `Execute Javascript` | window.open() | | | # In BrowserA third window is opened. |\n| ${handle} | `Switch Window` | locator=NEW | | # Switched to third window in BrowserA |\n| `Go To` | https://github.com/robotframework/ | | | # Third windows goes to robot framework github site. |\n| `Open Browser` | https://github.com | ${BROWSER} | alias=BrowserB | # BrowserB with first windows is opened. |\n| ${location} | `Get Location` | | | # ${location} is: https://www.github.com |\n| `Switch Window` | ${handle} | browser=BrowserA | | # BrowserA second windows is selected. |\n| ${location} | `Get Location` | | | # ${location} = https://robocon.io/ |\n| @{locations 1} | `Get Locations` | | | # By default, lists locations under the currectly active browser (BrowserA). |\n| @{locations 2} | `Get Locations` | browser=ALL | | # By using browser=ALL argument keyword list all locations from all browsers. |\n\nThe above example, @{locations 1} contains the following items:\nhttps://robotframework.org/, https://robocon.io/ and\nhttps://github.com/robotframework/'. The @{locations 2}\ncontains the following items: https://robotframework.org/,\nhttps://robocon.io/, https://github.com/robotframework/'\nand 'https://github.com/.\n\n= Timeouts, waits, and delays =\n\nThis section discusses different ways how to wait for elements to\nappear on web pages and to slow down execution speed otherwise.\nIt also explains the `time format` that can be used when setting various\ntimeouts, waits, and delays.\n\n== Timeout ==\n\nSeleniumLibrary contains various keywords that have an optional\n``timeout`` argument that specifies how long these keywords should\nwait for certain events or actions. These keywords include, for example,\n``Wait ...`` keywords and keywords related to alerts. Additionally\n`Execute Async Javascript`. Although it does not have ``timeout``,\nargument, uses a timeout to define how long asynchronous JavaScript\ncan run.\n\nThe default timeout these keywords use can be set globally either by\nusing the `Set Selenium Timeout` keyword or with the ``timeout`` argument\nwhen `importing` the library. If no default timeout is set globally, the\ndefault is 5 seconds. If None is specified for the timeout argument in the\nkeywords, the default is used. See `time format` below for supported\ntimeout syntax.\n\n== Implicit wait ==\n\nImplicit wait specifies the maximum time how long Selenium waits when\nsearching for elements. It can be set by using the `Set Selenium Implicit\nWait` keyword or with the ``implicit_wait`` argument when `importing`\nthe library. See [https://www.seleniumhq.org/docs/04_webdriver_advanced.jsp|\nSelenium documentation] for more information about this functionality.\n\nSee `time format` below for supported syntax.\n\n== Page load ==\nPage load timeout is the amount of time to wait for page load to complete\nuntil a timeout exception is raised.\n\nThe default page load timeout can be set globally\nwhen `importing` the library with the ``page_load_timeout`` argument\nor by using the `Set Selenium Page Load Timeout` keyword.\n\nSee `time format` below for supported timeout syntax.\n\nSupport for page load is new in SeleniumLibrary 6.1\n\n== Selenium speed ==\n\nSelenium execution speed can be slowed down globally by using `Set\nSelenium speed` keyword. This functionality is designed to be used for\ndemonstrating or debugging purposes. Using it to make sure that elements\nappear on a page is not a good idea. The above-explained timeouts\nand waits should be used instead.\n\nSee `time format` below for supported syntax.\n\n== Time format ==\n\nAll timeouts and waits can be given as numbers considered seconds\n(e.g. ``0.5`` or ``42``) or in Robot Framework's time syntax\n(e.g. ``1.5 seconds`` or ``1 min 30 s``). For more information about\nthe time syntax see the\n[http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#time-format|Robot Framework User Guide].\n\n= Run-on-failure functionality =\n\nSeleniumLibrary has a handy feature that it can automatically execute\na keyword if any of its own keywords fails. By default, it uses the\n`Capture Page Screenshot` keyword, but this can be changed either by\nusing the `Register Keyword To Run On Failure` keyword or with the\n``run_on_failure`` argument when `importing` the library. It is\npossible to use any keyword from any imported library or resource file.\n\nThe run-on-failure functionality can be disabled by using a special value\n``NOTHING`` or anything considered false (see `Boolean arguments`)\nsuch as ``NONE``.\n\n= Boolean arguments =\n\nStarting from 5.0 SeleniumLibrary relies on Robot Framework to perform the\nboolean conversion based on keyword arguments [https://docs.python.org/3/library/typing.html|type hint].\nMore details in Robot Framework\n[http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#supported-conversions|user guide]\n\nPlease note SeleniumLibrary 3 and 4 did have own custom methods to covert\narguments to boolean values.\n\n= EventFiringWebDriver =\n\nThe SeleniumLibrary offers support for\n[https://seleniumhq.github.io/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.event_firing_webdriver.html#module-selenium.webdriver.support.event_firing_webdriver|EventFiringWebDriver].\nSee the Selenium and SeleniumLibrary\n[https://github.com/robotframework/SeleniumLibrary/blob/master/docs/extending/extending.rst#EventFiringWebDriver|EventFiringWebDriver support]\ndocumentation for further details.\n\nEventFiringWebDriver is new in SeleniumLibrary 4.0\n\n= Thread support =\n\nSeleniumLibrary is not thread-safe. This is mainly due because the underlying\n[https://github.com/SeleniumHQ/selenium/wiki/Frequently-Asked-Questions#q-is-webdriver-thread-safe|\nSelenium tool is not thread-safe] within one browser/driver instance.\nBecause of the limitation in the Selenium side, the keywords or the\nAPI provided by the SeleniumLibrary is not thread-safe.\n\n= Plugins =\n\nSeleniumLibrary offers plugins as a way to modify and add library keywords and modify some of the internal\nfunctionality without creating a new library or hacking the source code. See\n[https://github.com/robotframework/SeleniumLibrary/blob/master/docs/extending/extending.rst#Plugins|plugin API]\ndocumentation for further details.\n\nPlugin API is new SeleniumLibrary 4.0", "sha256": "3d660b78fb0d75d9f2f8265fa6f29967ae30b712f545661d64de0f05f2c1b913" }, "__intro__": { "name": "__intro__", - "doc": "2 SeleniumLibrary is a web testing library for Robot Framework.\n\n This document explains how to use keywords provided by SeleniumLibrary.\n For information about installation, support, and more, please visit the\n [https://github.com/robotframework/SeleniumLibrary|project pages].\n For more information about Robot Framework, see http://robotframework.org.\n\n SeleniumLibrary uses the Selenium WebDriver modules internally to\n control a web browser. See http://seleniumhq.org for more information\n about Selenium in general and SeleniumLibrary README.rst\n [https://github.com/robotframework/SeleniumLibrary#browser-drivers|Browser drivers chapter]\n for more details about WebDriver binary installation.\n\n %TOC%\n\n = Locating elements =\n\n All keywords in SeleniumLibrary that need to interact with an element\n on a web page take an argument typically named ``locator`` that specifies\n how to find the element. Most often the locator is given as a string\n using the locator syntax described below, but `using WebElements` is\n possible too.\n\n == Locator syntax ==\n\n SeleniumLibrary supports finding elements based on different strategies\n such as the element id, XPath expressions, or CSS selectors. The strategy\n can either be explicitly specified with a prefix or the strategy can be\n implicit.\n\n === Default locator strategy ===\n\n By default, locators are considered to use the keyword specific default\n locator strategy. All keywords support finding elements based on ``id``\n and ``name`` attributes, but some keywords support additional attributes\n or other values that make sense in their context. For example, `Click\n Link` supports the ``href`` attribute and the link text and addition\n to the normal ``id`` and ``name``.\n\n Examples:\n\n | `Click Element` | example | # Match based on ``id`` or ``name``. |\n | `Click Link` | example | # Match also based on link text and ``href``. |\n | `Click Button` | example | # Match based on ``id``, ``name`` or ``value``. |\n\n If a locator accidentally starts with a prefix recognized as `explicit\n locator strategy` or `implicit XPath strategy`, it is possible to use\n the explicit ``default`` prefix to enable the default strategy.\n\n Examples:\n\n | `Click Element` | name:foo | # Find element with name ``foo``. |\n | `Click Element` | default:name:foo | # Use default strategy with value ``name:foo``. |\n | `Click Element` | //foo | # Find element using XPath ``//foo``. |\n | `Click Element` | default: //foo | # Use default strategy with value ``//foo``. |\n\n === Explicit locator strategy ===\n\n The explicit locator strategy is specified with a prefix using either\n syntax ``strategy:value`` or ``strategy=value``. The former syntax\n is preferred because the latter is identical to Robot Framework's\n [http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#named-argument-syntax|\n named argument syntax] and that can cause problems. Spaces around\n the separator are ignored, so ``id:foo``, ``id: foo`` and ``id : foo``\n are all equivalent.\n\n Locator strategies that are supported by default are listed in the table\n below. In addition to them, it is possible to register `custom locators`.\n\n | = Strategy = | = Match based on = | = Example = |\n | id | Element ``id``. | ``id:example`` |\n | name | ``name`` attribute. | ``name:example`` |\n | identifier | Either ``id`` or ``name``. | ``identifier:example`` |\n | class | Element ``class``. | ``class:example`` |\n | tag | Tag name. | ``tag:div`` |\n | xpath | XPath expression. | ``xpath://div[@id=\"example\"]`` |\n | css | CSS selector. | ``css:div#example`` |\n | dom | DOM expression. | ``dom:document.images[5]`` |\n | link | Exact text a link has. | ``link:The example`` |\n | partial link | Partial link text. | ``partial link:he ex`` |\n | sizzle | Sizzle selector deprecated. | ``sizzle:div.example`` |\n | data | Element ``data-*`` attribute | ``data:id:my_id`` |\n | jquery | jQuery expression. | ``jquery:div.example`` |\n | default | Keyword specific default behavior. | ``default:example`` |\n\n See the `Default locator strategy` section below for more information\n about how the default strategy works. Using the explicit ``default``\n prefix is only necessary if the locator value itself accidentally\n matches some of the explicit strategies.\n\n Different locator strategies have different pros and cons. Using ids,\n either explicitly like ``id:foo`` or by using the `default locator\n strategy` simply like ``foo``, is recommended when possible, because\n the syntax is simple and locating elements by id is fast for browsers.\n If an element does not have an id or the id is not stable, other\n solutions need to be used. If an element has a unique tag name or class,\n using ``tag``, ``class`` or ``css`` strategy like ``tag:h1``,\n ``class:example`` or ``css:h1.example`` is often an easy solution. In\n more complex cases using XPath expressions is typically the best\n approach. They are very powerful but a downside is that they can also\n get complex.\n\n Examples:\n\n | `Click Element` | id:foo | # Element with id 'foo'. |\n | `Click Element` | css:div#foo h1 | # h1 element under div with id 'foo'. |\n | `Click Element` | xpath: //div[@id=\"foo\"]//h1 | # Same as the above using XPath, not CSS. |\n | `Click Element` | xpath: //*[contains(text(), \"example\")] | # Element containing text 'example'. |\n\n *NOTE:*\n\n - The ``strategy:value`` syntax is only supported by SeleniumLibrary 3.0\n and newer.\n - Using the ``sizzle`` strategy or its alias ``jquery`` requires that\n the system under test contains the jQuery library.\n - Prior to SeleniumLibrary 3.0, table related keywords only supported\n ``xpath``, ``css`` and ``sizzle/jquery`` strategies.\n - ``data`` strategy is conveniance locator that will construct xpath from the parameters.\n If you have element like `
`, you locate the element via\n ``data:automation:automation-id-2``. This feature was added in SeleniumLibrary 5.2.0\n\n === Implicit XPath strategy ===\n\n If the locator starts with ``//`` or multiple opening parenthesis in front\n of the ``//``, the locator is considered to be an XPath expression. In other\n words, using ``//div`` is equivalent to using explicit ``xpath://div`` and\n ``((//div))`` is equivalent to using explicit ``xpath:((//div))``\n\n Examples:\n\n | `Click Element` | //div[@id=\"foo\"]//h1 |\n | `Click Element` | (//div)[2] |\n\n The support for the ``(//`` prefix is new in SeleniumLibrary 3.0.\n Supporting multiple opening parenthesis is new in SeleniumLibrary 5.0.\n\n === Chaining locators ===\n\n It is possible chain multiple locators together as single locator. Each chained locator must start with locator\n strategy. Chained locators must be separated with single space, two greater than characters and followed with\n space. It is also possible mix different locator strategies, example css or xpath. Also a list can also be\n used to specify multiple locators. This is useful, is some part of locator would match as the locator separator\n but it should not. Or if there is need to existing WebElement as locator.\n\n Although all locators support chaining, some locator strategies do not abey the chaining. This is because\n some locator strategies use JavaScript to find elements and JavaScript is executed for the whole browser context\n and not for the element found be the previous locator. Chaining is supported by locator strategies which\n are based on Selenium API, like `xpath` or `css`, but example chaining is not supported by `sizzle` or `jquery\n\n Examples:\n | `Click Element` | css:.bar >> xpath://a | # To find a link which is present after an element with class \"bar\" |\n\n List examples:\n | ${locator_list} = | `Create List` | css:div#div_id | xpath://*[text(), \" >> \"] |\n | `Page Should Contain Element` | ${locator_list} | | |\n | ${element} = | Get WebElement | xpath://*[text(), \" >> \"] | |\n | ${locator_list} = | `Create List` | css:div#div_id | ${element} |\n | `Page Should Contain Element` | ${locator_list} | | |\n\n Chaining locators in new in SeleniumLibrary 5.0\n\n == Using WebElements ==\n\n In addition to specifying a locator as a string, it is possible to use\n Selenium's WebElement objects. This requires first getting a WebElement,\n for example, by using the `Get WebElement` keyword.\n\n | ${elem} = | `Get WebElement` | id:example |\n | `Click Element` | ${elem} | |\n\n == Custom locators ==\n\n If more complex lookups are required than what is provided through the\n default locators, custom lookup strategies can be created. Using custom\n locators is a two part process. First, create a keyword that returns\n a WebElement that should be acted on:\n\n | Custom Locator Strategy | [Arguments] | ${browser} | ${locator} | ${tag} | ${constraints} |\n | | ${element}= | Execute Javascript | return window.document.getElementById('${locator}'); |\n | | [Return] | ${element} |\n\n This keyword is a reimplementation of the basic functionality of the\n ``id`` locator where ``${browser}`` is a reference to a WebDriver\n instance and ``${locator}`` is the name of the locator strategy. To use\n this locator, it must first be registered by using the\n `Add Location Strategy` keyword:\n\n | `Add Location Strategy` | custom | Custom Locator Strategy |\n\n The first argument of `Add Location Strategy` specifies the name of\n the strategy and it must be unique. After registering the strategy,\n the usage is the same as with other locators:\n\n | `Click Element` | custom:example |\n\n See the `Add Location Strategy` keyword for more details.\n\n = Browser and Window =\n\n There is different conceptual meaning when SeleniumLibrary talks\n about windows or browsers. This chapter explains those differences.\n\n == Browser ==\n\n When `Open Browser` or `Create WebDriver` keyword is called, it\n will create a new Selenium WebDriver instance by using the\n [https://www.seleniumhq.org/docs/03_webdriver.jsp|Selenium WebDriver]\n API. In SeleniumLibrary terms, a new browser is created. It is\n possible to start multiple independent browsers (Selenium Webdriver\n instances) at the same time, by calling `Open Browser` or\n `Create WebDriver` multiple times. These browsers are usually\n independent of each other and do not share data like cookies,\n sessions or profiles. Typically when the browser starts, it\n creates a single window which is shown to the user.\n\n == Window ==\n\n Windows are the part of a browser that loads the web site and presents\n it to the user. All content of the site is the content of the window.\n Windows are children of a browser. In SeleniumLibrary browser is a\n synonym for WebDriver instance. One browser may have multiple\n windows. Windows can appear as tabs, as separate windows or pop-ups with\n different position and size. Windows belonging to the same browser\n typically share the sessions detail, like cookies. If there is a\n need to separate sessions detail, example login with two different\n users, two browsers (Selenium WebDriver instances) must be created.\n New windows can be opened example by the application under test or\n by example `Execute Javascript` keyword:\n\n | `Execute Javascript` window.open() # Opens a new window with location about:blank\n\n The example below opens multiple browsers and windows,\n to demonstrate how the different keywords can be used to interact\n with browsers, and windows attached to these browsers.\n\n Structure:\n | BrowserA\n | Window 1 (location=https://robotframework.org/)\n | Window 2 (location=https://robocon.io/)\n | Window 3 (location=https://github.com/robotframework/)\n |\n | BrowserB\n | Window 1 (location=https://github.com/)\n\n Example:\n | `Open Browser` | https://robotframework.org | ${BROWSER} | alias=BrowserA | # BrowserA with first window is opened. |\n | `Execute Javascript` | window.open() | | | # In BrowserA second window is opened. |\n | `Switch Window` | locator=NEW | | | # Switched to second window in BrowserA |\n | `Go To` | https://robocon.io | | | # Second window navigates to robocon site. |\n | `Execute Javascript` | window.open() | | | # In BrowserA third window is opened. |\n | ${handle} | `Switch Window` | locator=NEW | | # Switched to third window in BrowserA |\n | `Go To` | https://github.com/robotframework/ | | | # Third windows goes to robot framework github site. |\n | `Open Browser` | https://github.com | ${BROWSER} | alias=BrowserB | # BrowserB with first windows is opened. |\n | ${location} | `Get Location` | | | # ${location} is: https://www.github.com |\n | `Switch Window` | ${handle} | browser=BrowserA | | # BrowserA second windows is selected. |\n | ${location} | `Get Location` | | | # ${location} = https://robocon.io/ |\n | @{locations 1} | `Get Locations` | | | # By default, lists locations under the currectly active browser (BrowserA). |\n | @{locations 2} | `Get Locations` | browser=ALL | | # By using browser=ALL argument keyword list all locations from all browsers. |\n\n The above example, @{locations 1} contains the following items:\n https://robotframework.org/, https://robocon.io/ and\n https://github.com/robotframework/'. The @{locations 2}\n contains the following items: https://robotframework.org/,\n https://robocon.io/, https://github.com/robotframework/'\n and 'https://github.com/.\n\n = Timeouts, waits, and delays =\n\n This section discusses different ways how to wait for elements to\n appear on web pages and to slow down execution speed otherwise.\n It also explains the `time format` that can be used when setting various\n timeouts, waits, and delays.\n\n == Timeout ==\n\n SeleniumLibrary contains various keywords that have an optional\n ``timeout`` argument that specifies how long these keywords should\n wait for certain events or actions. These keywords include, for example,\n ``Wait ...`` keywords and keywords related to alerts. Additionally\n `Execute Async Javascript`. Although it does not have ``timeout``,\n argument, uses a timeout to define how long asynchronous JavaScript\n can run.\n\n The default timeout these keywords use can be set globally either by\n using the `Set Selenium Timeout` keyword or with the ``timeout`` argument\n when `importing` the library. If no default timeout is set globally, the\n default is 5 seconds. If None is specified for the timeout argument in the\n keywords, the default is used. See `time format` below for supported\n timeout syntax.\n\n == Implicit wait ==\n\n Implicit wait specifies the maximum time how long Selenium waits when\n searching for elements. It can be set by using the `Set Selenium Implicit\n Wait` keyword or with the ``implicit_wait`` argument when `importing`\n the library. See [https://www.seleniumhq.org/docs/04_webdriver_advanced.jsp|\n Selenium documentation] for more information about this functionality.\n\n See `time format` below for supported syntax.\n\n == Page load ==\n Page load timeout is the amount of time to wait for page load to complete\n until a timeout exception is raised.\n\n The default page load timeout can be set globally\n when `importing` the library with the ``page_load_timeout`` argument\n or by using the `Set Selenium Page Load Timeout` keyword.\n\n See `time format` below for supported timeout syntax.\n\n Support for page load is new in SeleniumLibrary 6.1\n\n == Selenium speed ==\n\n Selenium execution speed can be slowed down globally by using `Set\n Selenium speed` keyword. This functionality is designed to be used for\n demonstrating or debugging purposes. Using it to make sure that elements\n appear on a page is not a good idea. The above-explained timeouts\n and waits should be used instead.\n\n See `time format` below for supported syntax.\n\n == Time format ==\n\n All timeouts and waits can be given as numbers considered seconds\n (e.g. ``0.5`` or ``42``) or in Robot Framework's time syntax\n (e.g. ``1.5 seconds`` or ``1 min 30 s``). For more information about\n the time syntax see the\n [http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#time-format|Robot Framework User Guide].\n\n = Run-on-failure functionality =\n\n SeleniumLibrary has a handy feature that it can automatically execute\n a keyword if any of its own keywords fails. By default, it uses the\n `Capture Page Screenshot` keyword, but this can be changed either by\n using the `Register Keyword To Run On Failure` keyword or with the\n ``run_on_failure`` argument when `importing` the library. It is\n possible to use any keyword from any imported library or resource file.\n\n The run-on-failure functionality can be disabled by using a special value\n ``NOTHING`` or anything considered false (see `Boolean arguments`)\n such as ``NONE``.\n\n = Boolean arguments =\n\n Starting from 5.0 SeleniumLibrary relies on Robot Framework to perform the\n boolean conversion based on keyword arguments [https://docs.python.org/3/library/typing.html|type hint].\n More details in Robot Framework\n [http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#supported-conversions|user guide]\n\n Please note SeleniumLibrary 3 and 4 did have own custom methods to covert\n arguments to boolean values.\n\n = EventFiringWebDriver =\n\n The SeleniumLibrary offers support for\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.event_firing_webdriver.html#module-selenium.webdriver.support.event_firing_webdriver|EventFiringWebDriver].\n See the Selenium and SeleniumLibrary\n [https://github.com/robotframework/SeleniumLibrary/blob/master/docs/extending/extending.rst#EventFiringWebDriver|EventFiringWebDriver support]\n documentation for further details.\n\n EventFiringWebDriver is new in SeleniumLibrary 4.0\n\n = Thread support =\n\n SeleniumLibrary is not thread-safe. This is mainly due because the underlying\n [https://github.com/SeleniumHQ/selenium/wiki/Frequently-Asked-Questions#q-is-webdriver-thread-safe|\n Selenium tool is not thread-safe] within one browser/driver instance.\n Because of the limitation in the Selenium side, the keywords or the\n API provided by the SeleniumLibrary is not thread-safe.\n\n = Plugins =\n\n SeleniumLibrary offers plugins as a way to modify and add library keywords and modify some of the internal\n functionality without creating a new library or hacking the source code. See\n [https://github.com/robotframework/SeleniumLibrary/blob/master/docs/extending/extending.rst#Plugins|plugin API]\n documentation for further details.\n\n Plugin API is new SeleniumLibrary 4.0\n ", + "doc": "000 SeleniumLibrary is a web testing library for Robot Framework.\n\n This document explains how to use keywords provided by SeleniumLibrary.\n For information about installation, support, and more, please visit the\n [https://github.com/robotframework/SeleniumLibrary|project pages].\n For more information about Robot Framework, see http://robotframework.org.\n\n SeleniumLibrary uses the Selenium WebDriver modules internally to\n control a web browser. See http://seleniumhq.org for more information\n about Selenium in general and SeleniumLibrary README.rst\n [https://github.com/robotframework/SeleniumLibrary#browser-drivers|Browser drivers chapter]\n for more details about WebDriver binary installation.\n\n %TOC%\n\n = Locating elements =\n\n All keywords in SeleniumLibrary that need to interact with an element\n on a web page take an argument typically named ``locator`` that specifies\n how to find the element. Most often the locator is given as a string\n using the locator syntax described below, but `using WebElements` is\n possible too.\n\n == Locator syntax ==\n\n SeleniumLibrary supports finding elements based on different strategies\n such as the element id, XPath expressions, or CSS selectors. The strategy\n can either be explicitly specified with a prefix or the strategy can be\n implicit.\n\n === Default locator strategy ===\n\n By default, locators are considered to use the keyword specific default\n locator strategy. All keywords support finding elements based on ``id``\n and ``name`` attributes, but some keywords support additional attributes\n or other values that make sense in their context. For example, `Click\n Link` supports the ``href`` attribute and the link text and addition\n to the normal ``id`` and ``name``.\n\n Examples:\n\n | `Click Element` | example | # Match based on ``id`` or ``name``. |\n | `Click Link` | example | # Match also based on link text and ``href``. |\n | `Click Button` | example | # Match based on ``id``, ``name`` or ``value``. |\n\n If a locator accidentally starts with a prefix recognized as `explicit\n locator strategy` or `implicit XPath strategy`, it is possible to use\n the explicit ``default`` prefix to enable the default strategy.\n\n Examples:\n\n | `Click Element` | name:foo | # Find element with name ``foo``. |\n | `Click Element` | default:name:foo | # Use default strategy with value ``name:foo``. |\n | `Click Element` | //foo | # Find element using XPath ``//foo``. |\n | `Click Element` | default: //foo | # Use default strategy with value ``//foo``. |\n\n === Explicit locator strategy ===\n\n The explicit locator strategy is specified with a prefix using either\n syntax ``strategy:value`` or ``strategy=value``. The former syntax\n is preferred because the latter is identical to Robot Framework's\n [http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#named-argument-syntax|\n named argument syntax] and that can cause problems. Spaces around\n the separator are ignored, so ``id:foo``, ``id: foo`` and ``id : foo``\n are all equivalent.\n\n Locator strategies that are supported by default are listed in the table\n below. In addition to them, it is possible to register `custom locators`.\n\n | = Strategy = | = Match based on = | = Example = |\n | id | Element ``id``. | ``id:example`` |\n | name | ``name`` attribute. | ``name:example`` |\n | identifier | Either ``id`` or ``name``. | ``identifier:example`` |\n | class | Element ``class``. | ``class:example`` |\n | tag | Tag name. | ``tag:div`` |\n | xpath | XPath expression. | ``xpath://div[@id=\"example\"]`` |\n | css | CSS selector. | ``css:div#example`` |\n | dom | DOM expression. | ``dom:document.images[5]`` |\n | link | Exact text a link has. | ``link:The example`` |\n | partial link | Partial link text. | ``partial link:he ex`` |\n | sizzle | Sizzle selector deprecated. | ``sizzle:div.example`` |\n | data | Element ``data-*`` attribute | ``data:id:my_id`` |\n | jquery | jQuery expression. | ``jquery:div.example`` |\n | default | Keyword specific default behavior. | ``default:example`` |\n\n See the `Default locator strategy` section below for more information\n about how the default strategy works. Using the explicit ``default``\n prefix is only necessary if the locator value itself accidentally\n matches some of the explicit strategies.\n\n Different locator strategies have different pros and cons. Using ids,\n either explicitly like ``id:foo`` or by using the `default locator\n strategy` simply like ``foo``, is recommended when possible, because\n the syntax is simple and locating elements by id is fast for browsers.\n If an element does not have an id or the id is not stable, other\n solutions need to be used. If an element has a unique tag name or class,\n using ``tag``, ``class`` or ``css`` strategy like ``tag:h1``,\n ``class:example`` or ``css:h1.example`` is often an easy solution. In\n more complex cases using XPath expressions is typically the best\n approach. They are very powerful but a downside is that they can also\n get complex.\n\n Examples:\n\n | `Click Element` | id:foo | # Element with id 'foo'. |\n | `Click Element` | css:div#foo h1 | # h1 element under div with id 'foo'. |\n | `Click Element` | xpath: //div[@id=\"foo\"]//h1 | # Same as the above using XPath, not CSS. |\n | `Click Element` | xpath: //*[contains(text(), \"example\")] | # Element containing text 'example'. |\n\n *NOTE:*\n\n - The ``strategy:value`` syntax is only supported by SeleniumLibrary 3.0\n and newer.\n - Using the ``sizzle`` strategy or its alias ``jquery`` requires that\n the system under test contains the jQuery library.\n - Prior to SeleniumLibrary 3.0, table related keywords only supported\n ``xpath``, ``css`` and ``sizzle/jquery`` strategies.\n - ``data`` strategy is conveniance locator that will construct xpath from the parameters.\n If you have element like `
`, you locate the element via\n ``data:automation:automation-id-2``. This feature was added in SeleniumLibrary 5.2.0\n\n === Implicit XPath strategy ===\n\n If the locator starts with ``//`` or multiple opening parenthesis in front\n of the ``//``, the locator is considered to be an XPath expression. In other\n words, using ``//div`` is equivalent to using explicit ``xpath://div`` and\n ``((//div))`` is equivalent to using explicit ``xpath:((//div))``\n\n Examples:\n\n | `Click Element` | //div[@id=\"foo\"]//h1 |\n | `Click Element` | (//div)[2] |\n\n The support for the ``(//`` prefix is new in SeleniumLibrary 3.0.\n Supporting multiple opening parenthesis is new in SeleniumLibrary 5.0.\n\n === Chaining locators ===\n\n It is possible chain multiple locators together as single locator. Each chained locator must start with locator\n strategy. Chained locators must be separated with single space, two greater than characters and followed with\n space. It is also possible mix different locator strategies, example css or xpath. Also a list can also be\n used to specify multiple locators. This is useful, is some part of locator would match as the locator separator\n but it should not. Or if there is need to existing WebElement as locator.\n\n Although all locators support chaining, some locator strategies do not abey the chaining. This is because\n some locator strategies use JavaScript to find elements and JavaScript is executed for the whole browser context\n and not for the element found be the previous locator. Chaining is supported by locator strategies which\n are based on Selenium API, like `xpath` or `css`, but example chaining is not supported by `sizzle` or `jquery\n\n Examples:\n | `Click Element` | css:.bar >> xpath://a | # To find a link which is present after an element with class \"bar\" |\n\n List examples:\n | ${locator_list} = | `Create List` | css:div#div_id | xpath://*[text(), \" >> \"] |\n | `Page Should Contain Element` | ${locator_list} | | |\n | ${element} = | Get WebElement | xpath://*[text(), \" >> \"] | |\n | ${locator_list} = | `Create List` | css:div#div_id | ${element} |\n | `Page Should Contain Element` | ${locator_list} | | |\n\n Chaining locators in new in SeleniumLibrary 5.0\n\n == Using WebElements ==\n\n In addition to specifying a locator as a string, it is possible to use\n Selenium's WebElement objects. This requires first getting a WebElement,\n for example, by using the `Get WebElement` keyword.\n\n | ${elem} = | `Get WebElement` | id:example |\n | `Click Element` | ${elem} | |\n\n == Custom locators ==\n\n If more complex lookups are required than what is provided through the\n default locators, custom lookup strategies can be created. Using custom\n locators is a two part process. First, create a keyword that returns\n a WebElement that should be acted on:\n\n | Custom Locator Strategy | [Arguments] | ${browser} | ${locator} | ${tag} | ${constraints} |\n | | ${element}= | Execute Javascript | return window.document.getElementById('${locator}'); |\n | | [Return] | ${element} |\n\n This keyword is a reimplementation of the basic functionality of the\n ``id`` locator where ``${browser}`` is a reference to a WebDriver\n instance and ``${locator}`` is the name of the locator strategy. To use\n this locator, it must first be registered by using the\n `Add Location Strategy` keyword:\n\n | `Add Location Strategy` | custom | Custom Locator Strategy |\n\n The first argument of `Add Location Strategy` specifies the name of\n the strategy and it must be unique. After registering the strategy,\n the usage is the same as with other locators:\n\n | `Click Element` | custom:example |\n\n See the `Add Location Strategy` keyword for more details.\n\n = Browser and Window =\n\n There is different conceptual meaning when SeleniumLibrary talks\n about windows or browsers. This chapter explains those differences.\n\n == Browser ==\n\n When `Open Browser` or `Create WebDriver` keyword is called, it\n will create a new Selenium WebDriver instance by using the\n [https://www.seleniumhq.org/docs/03_webdriver.jsp|Selenium WebDriver]\n API. In SeleniumLibrary terms, a new browser is created. It is\n possible to start multiple independent browsers (Selenium Webdriver\n instances) at the same time, by calling `Open Browser` or\n `Create WebDriver` multiple times. These browsers are usually\n independent of each other and do not share data like cookies,\n sessions or profiles. Typically when the browser starts, it\n creates a single window which is shown to the user.\n\n == Window ==\n\n Windows are the part of a browser that loads the web site and presents\n it to the user. All content of the site is the content of the window.\n Windows are children of a browser. In SeleniumLibrary browser is a\n synonym for WebDriver instance. One browser may have multiple\n windows. Windows can appear as tabs, as separate windows or pop-ups with\n different position and size. Windows belonging to the same browser\n typically share the sessions detail, like cookies. If there is a\n need to separate sessions detail, example login with two different\n users, two browsers (Selenium WebDriver instances) must be created.\n New windows can be opened example by the application under test or\n by example `Execute Javascript` keyword:\n\n | `Execute Javascript` window.open() # Opens a new window with location about:blank\n\n The example below opens multiple browsers and windows,\n to demonstrate how the different keywords can be used to interact\n with browsers, and windows attached to these browsers.\n\n Structure:\n | BrowserA\n | Window 1 (location=https://robotframework.org/)\n | Window 2 (location=https://robocon.io/)\n | Window 3 (location=https://github.com/robotframework/)\n |\n | BrowserB\n | Window 1 (location=https://github.com/)\n\n Example:\n | `Open Browser` | https://robotframework.org | ${BROWSER} | alias=BrowserA | # BrowserA with first window is opened. |\n | `Execute Javascript` | window.open() | | | # In BrowserA second window is opened. |\n | `Switch Window` | locator=NEW | | | # Switched to second window in BrowserA |\n | `Go To` | https://robocon.io | | | # Second window navigates to robocon site. |\n | `Execute Javascript` | window.open() | | | # In BrowserA third window is opened. |\n | ${handle} | `Switch Window` | locator=NEW | | # Switched to third window in BrowserA |\n | `Go To` | https://github.com/robotframework/ | | | # Third windows goes to robot framework github site. |\n | `Open Browser` | https://github.com | ${BROWSER} | alias=BrowserB | # BrowserB with first windows is opened. |\n | ${location} | `Get Location` | | | # ${location} is: https://www.github.com |\n | `Switch Window` | ${handle} | browser=BrowserA | | # BrowserA second windows is selected. |\n | ${location} | `Get Location` | | | # ${location} = https://robocon.io/ |\n | @{locations 1} | `Get Locations` | | | # By default, lists locations under the currectly active browser (BrowserA). |\n | @{locations 2} | `Get Locations` | browser=ALL | | # By using browser=ALL argument keyword list all locations from all browsers. |\n\n The above example, @{locations 1} contains the following items:\n https://robotframework.org/, https://robocon.io/ and\n https://github.com/robotframework/'. The @{locations 2}\n contains the following items: https://robotframework.org/,\n https://robocon.io/, https://github.com/robotframework/'\n and 'https://github.com/.\n\n = Timeouts, waits, and delays =\n\n This section discusses different ways how to wait for elements to\n appear on web pages and to slow down execution speed otherwise.\n It also explains the `time format` that can be used when setting various\n timeouts, waits, and delays.\n\n == Timeout ==\n\n SeleniumLibrary contains various keywords that have an optional\n ``timeout`` argument that specifies how long these keywords should\n wait for certain events or actions. These keywords include, for example,\n ``Wait ...`` keywords and keywords related to alerts. Additionally\n `Execute Async Javascript`. Although it does not have ``timeout``,\n argument, uses a timeout to define how long asynchronous JavaScript\n can run.\n\n The default timeout these keywords use can be set globally either by\n using the `Set Selenium Timeout` keyword or with the ``timeout`` argument\n when `importing` the library. If no default timeout is set globally, the\n default is 5 seconds. If None is specified for the timeout argument in the\n keywords, the default is used. See `time format` below for supported\n timeout syntax.\n\n == Implicit wait ==\n\n Implicit wait specifies the maximum time how long Selenium waits when\n searching for elements. It can be set by using the `Set Selenium Implicit\n Wait` keyword or with the ``implicit_wait`` argument when `importing`\n the library. See [https://www.seleniumhq.org/docs/04_webdriver_advanced.jsp|\n Selenium documentation] for more information about this functionality.\n\n See `time format` below for supported syntax.\n\n == Page load ==\n Page load timeout is the amount of time to wait for page load to complete\n until a timeout exception is raised.\n\n The default page load timeout can be set globally\n when `importing` the library with the ``page_load_timeout`` argument\n or by using the `Set Selenium Page Load Timeout` keyword.\n\n See `time format` below for supported timeout syntax.\n\n Support for page load is new in SeleniumLibrary 6.1\n\n == Selenium speed ==\n\n Selenium execution speed can be slowed down globally by using `Set\n Selenium speed` keyword. This functionality is designed to be used for\n demonstrating or debugging purposes. Using it to make sure that elements\n appear on a page is not a good idea. The above-explained timeouts\n and waits should be used instead.\n\n See `time format` below for supported syntax.\n\n == Time format ==\n\n All timeouts and waits can be given as numbers considered seconds\n (e.g. ``0.5`` or ``42``) or in Robot Framework's time syntax\n (e.g. ``1.5 seconds`` or ``1 min 30 s``). For more information about\n the time syntax see the\n [http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#time-format|Robot Framework User Guide].\n\n = Run-on-failure functionality =\n\n SeleniumLibrary has a handy feature that it can automatically execute\n a keyword if any of its own keywords fails. By default, it uses the\n `Capture Page Screenshot` keyword, but this can be changed either by\n using the `Register Keyword To Run On Failure` keyword or with the\n ``run_on_failure`` argument when `importing` the library. It is\n possible to use any keyword from any imported library or resource file.\n\n The run-on-failure functionality can be disabled by using a special value\n ``NOTHING`` or anything considered false (see `Boolean arguments`)\n such as ``NONE``.\n\n = Boolean arguments =\n\n Starting from 5.0 SeleniumLibrary relies on Robot Framework to perform the\n boolean conversion based on keyword arguments [https://docs.python.org/3/library/typing.html|type hint].\n More details in Robot Framework\n [http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#supported-conversions|user guide]\n\n Please note SeleniumLibrary 3 and 4 did have own custom methods to covert\n arguments to boolean values.\n\n = EventFiringWebDriver =\n\n The SeleniumLibrary offers support for\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.event_firing_webdriver.html#module-selenium.webdriver.support.event_firing_webdriver|EventFiringWebDriver].\n See the Selenium and SeleniumLibrary\n [https://github.com/robotframework/SeleniumLibrary/blob/master/docs/extending/extending.rst#EventFiringWebDriver|EventFiringWebDriver support]\n documentation for further details.\n\n EventFiringWebDriver is new in SeleniumLibrary 4.0\n\n = Thread support =\n\n SeleniumLibrary is not thread-safe. This is mainly due because the underlying\n [https://github.com/SeleniumHQ/selenium/wiki/Frequently-Asked-Questions#q-is-webdriver-thread-safe|\n Selenium tool is not thread-safe] within one browser/driver instance.\n Because of the limitation in the Selenium side, the keywords or the\n API provided by the SeleniumLibrary is not thread-safe.\n\n = Plugins =\n\n SeleniumLibrary offers plugins as a way to modify and add library keywords and modify some of the internal\n functionality without creating a new library or hacking the source code. See\n [https://github.com/robotframework/SeleniumLibrary/blob/master/docs/extending/extending.rst#Plugins|plugin API]\n documentation for further details.\n\n Plugin API is new SeleniumLibrary 4.0\n ", "sha256": "59c13272c5a498ee00aa6f3e5e2d1f9cec5c355267e1b03f88c604f15dab6c4e" } } \ No newline at end of file diff --git a/utest/test/robotframework_seleniumlibrary_translation_list/__init__.py b/utest/test/robotframework_seleniumlibrary_translation_list/__init__.py new file mode 100644 index 000000000..a3758c18a --- /dev/null +++ b/utest/test/robotframework_seleniumlibrary_translation_list/__init__.py @@ -0,0 +1,9 @@ +from pathlib import Path + + +def get_language() -> list: + curr_dir = Path(__file__).parent.absolute() + return [ + {"language": "eng", "path": curr_dir / "translate1.json"}, + {"language": "swe", "path": curr_dir / "translate2.json"}, + ] diff --git a/utest/test/robotframework_seleniumlibrary_translation_list/translate1.json b/utest/test/robotframework_seleniumlibrary_translation_list/translate1.json new file mode 100644 index 000000000..c0f6ab677 --- /dev/null +++ b/utest/test/robotframework_seleniumlibrary_translation_list/translate1.json @@ -0,0 +1,917 @@ +{ + "alert_should_be_present": { + "name": "1 alert_should_be_present", + "doc": "2 Verifies that an alert is present and by default, accepts it.\n\n Fails if no alert is present. If ``text`` is a non-empty string,\n then it is used to verify alert's message. The alert is accepted\n by default, but that behavior can be controlled by using the\n ``action`` argument same way as with `Handle Alert`.\n\n ``timeout`` specifies how long to wait for the alert to appear.\n If it is not given, the global default `timeout` is used instead.\n\n ``action`` and ``timeout`` arguments are new in SeleniumLibrary 3.0.\n In earlier versions, the alert was always accepted and a timeout was\n hardcoded to one second.\n ", + "sha256": "c2389ab996f30509c4a5951f32dcfe2c8630040e00cedba19e19faa76a15299d" + }, + "alert_should_not_be_present": { + "name": "alert_should_not_be_present", + "doc": "Verifies that no alert is present.\n\n If the alert actually exists, the ``action`` argument determines\n how it should be handled. By default, the alert is accepted, but\n it can be also dismissed or left open the same way as with the\n `Handle Alert` keyword.\n\n ``timeout`` specifies how long to wait for the alert to appear.\n By default, is not waited for the alert at all, but a custom time can\n be given if alert may be delayed. See the `time format` section\n for information about the syntax.\n\n New in SeleniumLibrary 3.0.\n ", + "sha256": "75343dfda0a68c40607e961ead1e104553ba074110f33627131125e8c11ecef0" + }, + "handle_alert": { + "name": "hallinnoi_hälytys", + "doc": "Hallinnoi hälytyksen uusi dokkari\n\nToinen rivi", + "sha256": "7620b9059b37d2cb1d5823256d0f71d32d3f66af153d6be8ff5100219d4270d6" + }, + "input_text_into_alert": { + "name": "input_text_into_alert", + "doc": "Types the given ``text`` into an input field in an alert.\n\n The alert is accepted by default, but that behavior can be controlled\n by using the ``action`` argument same way as with `Handle Alert`.\n\n ``timeout`` specifies how long to wait for the alert to appear.\n If it is not given, the global default `timeout` is used instead.\n\n New in SeleniumLibrary 3.0.\n ", + "sha256": "77f522107ebbde4fbcca0e9d1f1e31911dad7f3256ea39d078ed3365cfefbc46" + }, + "close_all_browsers": { + "name": "close_all_browsers", + "doc": "Closes all open browsers and resets the browser cache.\n\n After this keyword, new indexes returned from `Open Browser` keyword\n are reset to 1.\n\n This keyword should be used in test or suite teardown to make sure\n all browsers are closed.\n ", + "sha256": "34bfcab8a0c99c9fc0ebeeaec4432664ab8fbcc99673bd4bb3f9be2e897dbb5b" + }, + "close_browser": { + "name": "close_browser", + "doc": "Closes the current browser.", + "sha256": "a13d34e21bad1e0a76dab6f27c3f8b803825b8996c989f5b106918e27f0d0eb1" + }, + "create_webdriver": { + "name": "create_webdriver", + "doc": "Creates an instance of Selenium WebDriver.\n\n Like `Open Browser`, but allows passing arguments to the created\n WebDriver instance directly. This keyword should only be used if\n the functionality provided by `Open Browser` is not adequate.\n\n ``driver_name`` must be a WebDriver implementation name like Firefox,\n Chrome, Ie, Edge, Safari, or Remote.\n\n The initialized WebDriver can be configured either with a Python\n dictionary ``kwargs`` or by using keyword arguments ``**init_kwargs``.\n These arguments are passed directly to WebDriver without any\n processing. See [https://seleniumhq.github.io/selenium/docs/api/py/api.html|\n Selenium API documentation] for details about the supported arguments.\n\n Examples:\n | # Use proxy with Firefox | | | |\n | ${proxy}= | `Evaluate` | selenium.webdriver.Proxy() | modules=selenium, selenium.webdriver |\n | ${proxy.http_proxy}= | `Set Variable` | localhost:8888 | |\n | `Create Webdriver` | Firefox | proxy=${proxy} | |\n\n Returns the index of this browser instance which can be used later to\n switch back to it. Index starts from 1 and is reset back to it when\n `Close All Browsers` keyword is used. See `Switch Browser` for an\n example.\n ", + "sha256": "c7efa8a6295acc8336de8f8fdccec61b8a19cfc1b091382753929f9d86d2e292" + }, + "get_action_chain_delay": { + "name": "get_action_chain_delay", + "doc": "Gets the currently stored value for chain_delay_value in timestr format.\n ", + "sha256": "167a6689441f92c4099130c03e41a6c1595bcc1a37a207ac0f970b08b1591fdf" + }, + "get_browser_aliases": { + "name": "get_browser_aliases", + "doc": "Returns aliases of all active browser that has an alias as NormalizedDict.\n The dictionary contains the aliases as keys and the index as value.\n This can be accessed as dictionary ``${aliases.key}`` or as list ``@{aliases}[0]``.\n\n Example:\n | `Open Browser` | https://example.com | alias=BrowserA | |\n | `Open Browser` | https://example.com | alias=BrowserB | |\n | &{aliases} | `Get Browser Aliases` | | # &{aliases} = { BrowserA=1|BrowserB=2 } |\n | `Log` | ${aliases.BrowserA} | | # logs ``1`` |\n | FOR | ${alias} | IN | @{aliases} |\n | | `Log` | ${alias} | # logs ``BrowserA`` and ``BrowserB`` |\n | END | | | |\n\n See `Switch Browser` for more information and examples.\n\n New in SeleniumLibrary 4.0\n ", + "sha256": "defef82080de396568467a48c850a3db67484a7b786d8ebd76a3f3ba02c71dff" + }, + "get_browser_ids": { + "name": "get_browser_ids", + "doc": "Returns index of all active browser as list.\n\n Example:\n | @{browser_ids}= | Get Browser Ids | | |\n | FOR | ${id} | IN | @{browser_ids} |\n | | @{window_titles}= | Get Window Titles | browser=${id} |\n | | Log | Browser ${id} has these windows: ${window_titles} | |\n | END | | | |\n\n See `Switch Browser` for more information and examples.\n\n New in SeleniumLibrary 4.0\n ", + "sha256": "c320152b2a66ba066b100fb8c729f3d36c04a5b72ed753b09d29b6e13613a004" + }, + "get_location": { + "name": "get_location", + "doc": "Returns the current browser window URL.", + "sha256": "3dda250c7af426a85b6ec9c6be5ec5b4a4df41d4b2c72f0fa53b905384c29fc1" + }, + "get_selenium_implicit_wait": { + "name": "get_selenium_implicit_wait", + "doc": "Gets the implicit wait value used by Selenium.\n\n The value is returned as a human-readable string like ``1 second``.\n\n See the `Implicit wait` section above for more information.\n ", + "sha256": "f506381005ec3abf34b359df073e602f6589fac8d030a5369156016bbfacfde2" + }, + "get_selenium_page_load_timeout": { + "name": "get_selenium_page_load_timeout", + "doc": "Gets the time to wait for a page load to complete\n before raising a timeout exception.\n\n The value is returned as a human-readable string like ``1 second``.\n\n See the `Page load` section above for more information.\n\n New in SeleniumLibrary 6.1\n ", + "sha256": "18d82c9e55e7d06156a7fcccd2f96ddd6185a4c3625c344073a3f3e33d6e1e72" + }, + "get_selenium_speed": { + "name": "get_selenium_speed", + "doc": "Gets the delay that is waited after each Selenium command.\n\n The value is returned as a human-readable string like ``1 second``.\n\n See the `Selenium Speed` section above for more information.\n ", + "sha256": "e310cfaddced1d3088b673df4c7c469f10d3992116e2fabe048be986462febc5" + }, + "get_selenium_timeout": { + "name": "get_selenium_timeout", + "doc": "Gets the timeout that is used by various keywords.\n\n The value is returned as a human-readable string like ``1 second``.\n\n See the `Timeout` section above for more information.\n ", + "sha256": "9ebe70c2d1751c70d0f646c8c0e91e3c924ae6062c4c961432405b1fa2e0efe3" + }, + "get_session_id": { + "name": "get_session_id", + "doc": "Returns the currently active browser session id.\n\n New in SeleniumLibrary 3.2\n ", + "sha256": "26f4581c49c3930c0bbc7ff188330eff3bdb9822556ed029c8b47e5cb75949d2" + }, + "get_source": { + "name": "get_source", + "doc": "Returns the entire HTML source of the current page or frame.", + "sha256": "186bf0854602fddcbf9400b50a6db19549cfa23171c01e4708702cbfeaf4a921" + }, + "get_title": { + "name": "get_title", + "doc": "Returns the title of the current page.", + "sha256": "15ca2c42f74a7447ac29d6431219afa7b827245f9bd45e8d220c597c8c76ea72" + }, + "go_back": { + "name": "go_back", + "doc": "Simulates the user clicking the back button on their browser.", + "sha256": "c1ad3668ded03441f5e9019fe3e6417d6c0786fad522ef2d126b233112436ae7" + }, + "go_to": { + "name": "go_to", + "doc": "Navigates the current browser window to the provided ``url``.", + "sha256": "c7db5e459ba7a16a1e895bd0a948765b75bfc536284a2a50ac02e7153ccb0450" + }, + "location_should_be": { + "name": "location_should_be", + "doc": "Verifies that the current URL is exactly ``url``.\n\n The ``url`` argument contains the exact url that should exist in browser.\n\n The ``message`` argument can be used to override the default error\n message.\n\n ``message`` argument is new in SeleniumLibrary 3.2.0.\n ", + "sha256": "ea4b77e8386a52d7881a76cc42cf6c7754da4c44f1b54aa8d71467770a919839" + }, + "location_should_contain": { + "name": "location_should_contain", + "doc": "Verifies that the current URL contains ``expected``.\n\n The ``expected`` argument contains the expected value in url.\n\n The ``message`` argument can be used to override the default error\n message.\n\n ``message`` argument is new in SeleniumLibrary 3.2.0.\n ", + "sha256": "be7e648ca2a1f5a7d83f5fe99d0e9aef696f0c645b57985059179476c4d1d0ed" + }, + "log_location": { + "name": "log_location", + "doc": "Logs and returns the current browser window URL.", + "sha256": "ecdeee422f6587f42650730b5d1510d9f207cda56a2346fa3f6245ad62f4bac5" + }, + "log_source": { + "name": "log_source", + "doc": "Logs and returns the HTML source of the current page or frame.\n\n The ``loglevel`` argument defines the used log level. Valid log\n levels are ``WARN``, ``INFO`` (default), ``DEBUG``, ``TRACE``\n and ``NONE`` (no logging).\n ", + "sha256": "ccfb24c918224eb021f3f020cd9dd1375b128835d8295fc0a40d7f76c628d0b7" + }, + "log_title": { + "name": "log_title", + "doc": "Logs and returns the title of the current page.", + "sha256": "3722f0e150770d3b876af7a430c3a0e22f09a3b847c61b467cce146ed64ceea5" + }, + "open_browser": { + "name": "open_browser", + "doc": "Opens a new browser instance to the optional ``url``.\n\n The ``browser`` argument specifies which browser to use. The\n supported browsers are listed in the table below. The browser names\n are case-insensitive and some browsers have multiple supported names.\n\n | = Browser = | = Name(s) = |\n | Firefox | firefox, ff |\n | Google Chrome | googlechrome, chrome, gc |\n | Headless Firefox | headlessfirefox |\n | Headless Chrome | headlesschrome |\n | Internet Explorer | internetexplorer, ie |\n | Edge | edge |\n | Safari | safari |\n\n To be able to actually use one of these browsers, you need to have\n a matching Selenium browser driver available. See the\n [https://github.com/robotframework/SeleniumLibrary#browser-drivers|\n project documentation] for more details. Headless Firefox and\n Headless Chrome are new additions in SeleniumLibrary 3.1.0\n and require Selenium 3.8.0 or newer.\n\n After opening the browser, it is possible to use optional\n ``url`` to navigate the browser to the desired address.\n\n Optional ``alias`` is an alias given for this browser instance and\n it can be used for switching between browsers. When same ``alias``\n is given with two `Open Browser` keywords, the first keyword will\n open a new browser, but the second one will switch to the already\n opened browser and will not open a new browser. The ``alias``\n definition overrules ``browser`` definition. When same ``alias``\n is used but a different ``browser`` is defined, then switch to\n a browser with same alias is done and new browser is not opened.\n An alternative approach for switching is using an index returned\n by this keyword. These indices start from 1, are incremented when new\n browsers are opened, and reset back to 1 when `Close All Browsers`\n is called. See `Switch Browser` for more information and examples.\n\n Optional ``remote_url`` is the URL for a\n [https://github.com/SeleniumHQ/selenium/wiki/Grid2|Selenium Grid].\n\n Optional ``desired_capabilities`` is deprecated and will be ignored. Capabilities of each\n individual browser is now done through options or services. Please refer to those arguments\n for configuring specific browsers.\n\n Optional ``ff_profile_dir`` is the path to the Firefox profile\n directory if you wish to overwrite the default profile Selenium\n uses. Notice that prior to SeleniumLibrary 3.0, the library\n contained its own profile that was used by default. The\n ``ff_profile_dir`` can also be an instance of the\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_firefox/selenium.webdriver.firefox.firefox_profile.html|selenium.webdriver.FirefoxProfile]\n . As a third option, it is possible to use `FirefoxProfile` methods\n and attributes to define the profile using methods and attributes\n in the same way as with ``options`` argument. Example: It is possible\n to use FirefoxProfile `set_preference` to define different\n profile settings. See ``options`` argument documentation in below\n how to handle backslash escaping.\n\n Optional ``options`` argument allows defining browser specific\n Selenium options. Example for Chrome, the ``options`` argument\n allows defining the following\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_chrome/selenium.webdriver.chrome.options.html#selenium.webdriver.chrome.options.Options|methods and attributes]\n and for Firefox these\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_firefox/selenium.webdriver.firefox.options.html?highlight=firefox#selenium.webdriver.firefox.options.Options|methods and attributes]\n are available. Please note that not all browsers, supported by the\n SeleniumLibrary, have Selenium options available. Therefore please\n consult the Selenium documentation which browsers do support\n the Selenium options. Selenium options are also supported, when ``remote_url``\n argument is used.\n\n The SeleniumLibrary ``options`` argument accepts Selenium\n options in two different formats: as a string and as Python object\n which is an instance of the Selenium options class.\n\n The string format allows defining Selenium options methods\n or attributes and their arguments in Robot Framework test data.\n The method and attributes names are case and space sensitive and\n must match to the Selenium options methods and attributes names.\n When defining a method, it must be defined in a similar way as in\n python: method name, opening parenthesis, zero to many arguments\n and closing parenthesis. If there is a need to define multiple\n arguments for a single method, arguments must be separated with\n comma, just like in Python. Example: `add_argument(\"--headless\")`\n or `add_experimental_option(\"key\", \"value\")`. Attributes are\n defined in a similar way as in Python: attribute name, equal sign,\n and attribute value. Example, `headless=True`. Multiple methods\n and attributes must be separated by a semicolon. Example:\n `add_argument(\"--headless\");add_argument(\"--start-maximized\")`.\n\n Arguments allow defining Python data types and arguments are\n evaluated by using Python\n [https://docs.python.org/3/library/ast.html#ast.literal_eval|ast.literal_eval].\n Strings must be quoted with single or double quotes, example \"value\"\n or 'value'. It is also possible to define other Python builtin\n data types, example `True` or `None`, by not using quotes\n around the arguments.\n\n The string format is space friendly. Usually, spaces do not alter\n the defining methods or attributes. There are two exceptions.\n In some Robot Framework test data formats, two or more spaces are\n considered as cell separator and instead of defining a single\n argument, two or more arguments may be defined. Spaces in string\n arguments are not removed and are left as is. Example\n `add_argument ( \"--headless\" )` is same as\n `add_argument(\"--headless\")`. But `add_argument(\" --headless \")` is\n not same same as `add_argument ( \"--headless\" )`, because\n spaces inside of quotes are not removed. Please note that if\n options string contains backslash, example a Windows OS path,\n the backslash needs escaping both in Robot Framework data and\n in Python side. This means single backslash must be writen using\n four backslash characters. Example, Windows path:\n \"C:\\path\\to\\profile\" must be written as\n \"C:\\\\\\\\path\\\\\\to\\\\\\\\profile\". Another way to write\n backslash is use Python\n [https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals|raw strings]\n and example write: r\"C:\\\\path\\\\to\\\\profile\".\n\n As last format, ``options`` argument also supports receiving\n the Selenium options as Python class instance. In this case, the\n instance is used as-is and the SeleniumLibrary will not convert\n the instance to other formats.\n For example, if the following code return value is saved to\n `${options}` variable in the Robot Framework data:\n | options = webdriver.ChromeOptions()\n | options.add_argument('--disable-dev-shm-usage')\n | return options\n\n Then the `${options}` variable can be used as an argument to\n ``options``.\n\n Example the ``options`` argument can be used to launch Chomium-based\n applications which utilize the\n [https://bitbucket.org/chromiumembedded/cef/wiki/UsingChromeDriver|Chromium Embedded Framework]\n . To lauch Chomium-based application, use ``options`` to define\n `binary_location` attribute and use `add_argument` method to define\n `remote-debugging-port` port for the application. Once the browser\n is opened, the test can interact with the embedded web-content of\n the system under test.\n\n Optional ``service_log_path`` argument defines the name of the\n file where to write the browser driver logs. If the\n ``service_log_path`` argument contain a marker ``{index}``, it\n will be automatically replaced with unique running\n index preventing files to be overwritten. Indices start's from 1,\n and how they are represented can be customized using Python's\n [https://docs.python.org/3/library/string.html#format-string-syntax|\n format string syntax].\n\n Optional ``executable_path`` argument defines the path to the driver\n executable, example to a chromedriver or a geckodriver. If not defined\n it is assumed the executable is in the\n [https://en.wikipedia.org/wiki/PATH_(variable)|$PATH].\n\n Examples:\n | `Open Browser` | http://example.com | Chrome | |\n | `Open Browser` | http://example.com | Firefox | alias=Firefox |\n | `Open Browser` | http://example.com | Edge | remote_url=http://127.0.0.1:4444/wd/hub |\n | `Open Browser` | about:blank | | |\n | `Open Browser` | browser=Chrome | | |\n\n Alias examples:\n | ${1_index} = | `Open Browser` | http://example.com | Chrome | alias=Chrome | # Opens new browser because alias is new. |\n | ${2_index} = | `Open Browser` | http://example.com | Firefox | | # Opens new browser because alias is not defined. |\n | ${3_index} = | `Open Browser` | http://example.com | Chrome | alias=Chrome | # Switches to the browser with Chrome alias. |\n | ${4_index} = | `Open Browser` | http://example.com | Chrome | alias=${1_index} | # Switches to the browser with Chrome alias. |\n | Should Be Equal | ${1_index} | ${3_index} | | | |\n | Should Be Equal | ${1_index} | ${4_index} | | | |\n | Should Be Equal | ${2_index} | ${2} | | | |\n\n Example when using\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_chrome/selenium.webdriver.chrome.options.html#selenium.webdriver.chrome.options.Options|Chrome options]\n method:\n | `Open Browser` | http://example.com | Chrome | options=add_argument(\"--disable-popup-blocking\"); add_argument(\"--ignore-certificate-errors\") | # Sting format. |\n | ${options} = | Get Options | | | # Selenium options instance. |\n | `Open Browser` | http://example.com | Chrome | options=${options} | |\n | `Open Browser` | None | Chrome | options=binary_location=\"/path/to/binary\";add_argument(\"remote-debugging-port=port\") | # Start Chomium-based application. |\n | `Open Browser` | None | Chrome | options=binary_location=r\"C:\\\\path\\\\to\\\\binary\" | # Windows OS path escaping. |\n\n Example for FirefoxProfile\n | `Open Browser` | http://example.com | Firefox | ff_profile_dir=/path/to/profile | # Using profile from disk. |\n | `Open Browser` | http://example.com | Firefox | ff_profile_dir=${FirefoxProfile_instance} | # Using instance of FirefoxProfile. |\n | `Open Browser` | http://example.com | Firefox | ff_profile_dir=set_preference(\"key\", \"value\");set_preference(\"other\", \"setting\") | # Defining profile using FirefoxProfile mehtods. |\n\n If the provided configuration options are not enough, it is possible\n to use `Create Webdriver` to customize browser initialization even\n more.\n\n Applying ``desired_capabilities`` argument also for local browser is\n new in SeleniumLibrary 3.1.\n\n Using ``alias`` to decide, is the new browser opened is new\n in SeleniumLibrary 4.0. The ``options`` and ``service_log_path``\n are new in SeleniumLibrary 4.0. Support for ``ff_profile_dir``\n accepting an instance of the `selenium.webdriver.FirefoxProfile`\n and support defining FirefoxProfile with methods and\n attributes are new in SeleniumLibrary 4.0.\n\n Making ``url`` optional is new in SeleniumLibrary 4.1.\n\n The ``executable_path`` argument is new in SeleniumLibrary 4.2.\n ", + "sha256": "0c3f6191eb0bb2f557a3f93ab0c99c6137361091c73d09186c3846208a9ad7ff" + }, + "reload_page": { + "name": "reload_page", + "doc": "Simulates user reloading page.", + "sha256": "29308a1588c11a36ee1e46274959c9fb83b01fa628d38f7d1e60615cfa3c1d54" + }, + "set_action_chain_delay": { + "name": "set_action_chain_delay", + "doc": "Sets the duration of delay in ActionChains() used by SeleniumLibrary.\n\n The value can be given as a number that is considered to be\n seconds or as a human-readable string like ``1 second``.\n\n Value is always stored as milliseconds internally.\n\n The previous value is returned and can be used to restore\n the original value later if needed.\n ", + "sha256": "30a861e88589e077326d025611cd558432a5426b6b002aface8b8367286eca24" + }, + "set_browser_implicit_wait": { + "name": "set_browser_implicit_wait", + "doc": "Sets the implicit wait value used by Selenium.\n\n Same as `Set Selenium Implicit Wait` but only affects the current\n browser.\n ", + "sha256": "a5097a7357967bebd69e46c700917daaa41994d0235b77da90ce0b88d1bd3518" + }, + "set_selenium_implicit_wait": { + "name": "set_selenium_implicit_wait", + "doc": "Sets the implicit wait value used by Selenium.\n\n The value can be given as a number that is considered to be\n seconds or as a human-readable string like ``1 second``.\n The previous value is returned and can be used to restore\n the original value later if needed.\n\n This keyword sets the implicit wait for all opened browsers.\n Use `Set Browser Implicit Wait` to set it only to the current\n browser.\n\n See the `Implicit wait` section above for more information.\n\n Example:\n | ${orig wait} = | `Set Selenium Implicit Wait` | 10 seconds |\n | `Perform AJAX call that is slow` |\n | `Set Selenium Implicit Wait` | ${orig wait} |\n ", + "sha256": "1df9421daaba885bd06552d7b62030b285ac8472b98e09e0719554fd2448547c" + }, + "set_selenium_page_load_timeout": { + "name": "set_selenium_page_load_timeout", + "doc": "Sets the page load timeout value used by Selenium.\n\n The value can be given as a number that is considered to be\n seconds or as a human-readable string like ``1 second``.\n The previous value is returned and can be used to restore\n the original value later if needed.\n\n In contrast to `Set Selenium Timeout` and `Set Selenium Implicit Wait`,\n this keywords sets the time for the Webdriver to wait until the page\n is loaded before raising a timeout exception.\n\n See the `Page load` section above for more information.\n\n Example:\n | ${orig page load timeout} = | `Set Selenium Page Load Timeout` | 30 seconds |\n | `Open page that loads slowly` |\n | `Set Selenium Page Load Timeout` | ${orig page load timeout} |\n\n New in SeleniumLibrary 6.1\n ", + "sha256": "37e2b5f6af58ce3b2e1d520c0c2d56b99cadf175dd31f1ccfb05de36c8cfdab0" + }, + "set_selenium_speed": { + "name": "set_selenium_speed", + "doc": "Sets the delay that is waited after each Selenium command.\n\n The value can be given as a number that is considered to be\n seconds or as a human-readable string like ``1 second``.\n The previous value is returned and can be used to restore\n the original value later if needed.\n\n See the `Selenium Speed` section above for more information.\n\n Example:\n | `Set Selenium Speed` | 0.5 seconds |\n ", + "sha256": "143bd7c58689c676a711dcf2571cfdd8ee609325264bd632db2945dce3300ae5" + }, + "set_selenium_timeout": { + "name": "set_selenium_timeout", + "doc": "Sets the timeout that is used by various keywords.\n\n The value can be given as a number that is considered to be\n seconds or as a human-readable string like ``1 second``.\n The previous value is returned and can be used to restore\n the original value later if needed.\n\n See the `Timeout` section above for more information.\n\n Example:\n | ${orig timeout} = | `Set Selenium Timeout` | 15 seconds |\n | `Open page that loads slowly` |\n | `Set Selenium Timeout` | ${orig timeout} |\n ", + "sha256": "6e78114e0e60f0148629589b897d6a67b1c492317eb883b2ca4f3c6457a5d01b" + }, + "switch_browser": { + "name": "switch_browser", + "doc": "Switches between active browsers using ``index_or_alias``.\n\n Indices are returned by the `Open Browser` keyword and aliases can\n be given to it explicitly. Indices start from 1.\n\n Example:\n | `Open Browser` | http://google.com | ff |\n | `Location Should Be` | http://google.com | |\n | `Open Browser` | http://yahoo.com | ie | alias=second |\n | `Location Should Be` | http://yahoo.com | |\n | `Switch Browser` | 1 | # index |\n | `Page Should Contain` | I'm feeling lucky | |\n | `Switch Browser` | second | # alias |\n | `Page Should Contain` | More Yahoo! | |\n | `Close All Browsers` | | |\n\n Above example expects that there was no other open browsers when\n opening the first one because it used index ``1`` when switching to\n it later. If you are not sure about that, you can store the index\n into a variable as below.\n\n | ${index} = | `Open Browser` | http://google.com |\n | # Do something ... | | |\n | `Switch Browser` | ${index} | |\n ", + "sha256": "de918f9e83ebecafb37ba3704649efb39dfbf405960597e1e99dddffdf69c1fb" + }, + "title_should_be": { + "name": "title_should_be", + "doc": "Verifies that the current page title equals ``title``.\n\n The ``message`` argument can be used to override the default error\n message.\n\n ``message`` argument is new in SeleniumLibrary 3.1.\n ", + "sha256": "f3ed755ed3bdbb8e7b334bce951620ceb83c3aca1cad51a31b2eea42260e1199" + }, + "add_cookie": { + "name": "add_cookie", + "doc": "Adds a cookie to your current session.\n\n ``name`` and ``value`` are required, ``path``, ``domain``, ``secure``\n and ``expiry`` are optional. Expiry supports the same formats as\n the [http://robotframework.org/robotframework/latest/libraries/DateTime.html|DateTime]\n library or an epoch timestamp.\n\n Example:\n | `Add Cookie` | foo | bar | |\n | `Add Cookie` | foo | bar | domain=example.com |\n | `Add Cookie` | foo | bar | expiry=2027-09-28 16:21:35 | # Expiry as timestamp. |\n | `Add Cookie` | foo | bar | expiry=1822137695 | # Expiry as epoch seconds. |\n\n Prior to SeleniumLibrary 3.0 setting expiry did not work.\n ", + "sha256": "4824fdf8e69148f3f74ed2a177fc4417caa1b7d24b5fd55378e8cdbd3ace04a5" + }, + "delete_all_cookies": { + "name": "delete_all_cookies", + "doc": "Deletes all cookies.", + "sha256": "3300bc6758bd113107fb425664eacbda4143514393c4d4197ac28626592b77c5" + }, + "delete_cookie": { + "name": "delete_cookie", + "doc": "Deletes the cookie matching ``name``.\n\n If the cookie is not found, nothing happens.\n ", + "sha256": "9f69becc9575a4dc10a09bebdcb7405fbfba883c8268c889baca4659ba549d04" + }, + "get_cookie": { + "name": "get_cookie", + "doc": "Returns information of cookie with ``name`` as an object.\n\n If no cookie is found with ``name``, keyword fails. The cookie object\n contains details about the cookie. Attributes available in the object\n are documented in the table below.\n\n | = Attribute = | = Explanation = |\n | name | The name of a cookie. |\n | value | Value of the cookie. |\n | path | Indicates a URL path, for example ``/``. |\n | domain | The domain, the cookie is visible to. |\n | secure | When true, the cookie is only used with HTTPS connections. |\n | httpOnly | When true, the cookie is not accessible via JavaScript. |\n | expiry | Python datetime object indicating when the cookie expires. |\n | extra | Possible attributes outside of the WebDriver specification |\n\n See the\n [https://w3c.github.io/webdriver/#cookies|WebDriver specification]\n for details about the cookie information.\n Notice that ``expiry`` is specified as a\n [https://docs.python.org/3/library/datetime.html#datetime.datetime|datetime object],\n not as seconds since Unix Epoch like WebDriver natively does.\n\n In some cases, example when running a browser in the cloud, it is possible that\n the cookie contains other attributes than is defined in the\n [https://w3c.github.io/webdriver/#cookies|WebDriver specification].\n These other attributes are available in an ``extra`` attribute in the cookie\n object and it contains a dictionary of the other attributes. The ``extra``\n attribute is new in SeleniumLibrary 4.0.\n\n Example:\n | `Add Cookie` | foo | bar |\n | ${cookie} = | `Get Cookie` | foo |\n | `Should Be Equal` | ${cookie.name} | foo |\n | `Should Be Equal` | ${cookie.value} | bar |\n | `Should Be True` | ${cookie.expiry.year} > 2017 |\n\n New in SeleniumLibrary 3.0.\n ", + "sha256": "747951f772be34600739a36f99d276499abc5137ddb8994e1773b68cc7c2e05b" + }, + "get_cookies": { + "name": "get_cookies", + "doc": "Returns all cookies of the current page.\n\n If ``as_dict`` argument evaluates as false, see `Boolean arguments`\n for more details, then cookie information is returned as\n a single string in format ``name1=value1; name2=value2; name3=value3``.\n When ``as_dict`` argument evaluates as true, cookie information\n is returned as Robot Framework dictionary format. The string format\n can be used, for example, for logging purposes or in headers when\n sending HTTP requests. The dictionary format is helpful when\n the result can be passed to requests library's Create Session\n keyword's optional cookies parameter.\n\n The `` as_dict`` argument is new in SeleniumLibrary 3.3\n ", + "sha256": "7a9bda6590cdb1aa8825e385ffefc087a7ca087936dd11350d6234e6e2c05e6c" + }, + "add_location_strategy": { + "name": "add_location_strategy", + "doc": "Adds a custom location strategy.\n\n See `Custom locators` for information on how to create and use\n custom strategies. `Remove Location Strategy` can be used to\n remove a registered strategy.\n\n Location strategies are automatically removed after leaving the\n current scope by default. Setting ``persist`` to a true value (see\n `Boolean arguments`) will cause the location strategy to stay\n registered throughout the life of the test.\n ", + "sha256": "046e816fd4d028592aaa9146fd815aec20809f88d4160fdf166fb19d5fdcfa0c" + }, + "assign_id_to_element": { + "name": "assign_id_to_element", + "doc": "Assigns a temporary ``id`` to the element specified by ``locator``.\n\n This is mainly useful if the locator is complicated and/or slow XPath\n expression and it is needed multiple times. Identifier expires when\n the page is reloaded.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n Example:\n | `Assign ID to Element` | //ul[@class='example' and ./li[contains(., 'Stuff')]] | my id |\n | `Page Should Contain Element` | my id |\n ", + "sha256": "2ce9ab7a44154be53f32d6d6e8b1b6e9dd8bbff880048c99ed4b62763a0b522c" + }, + "clear_element_text": { + "name": "clear_element_text", + "doc": "Clears the value of the text-input-element identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "31d7803b76e63ff90ff333f06e323aba4f820632b8795d51d24242fb65f4e7d2" + }, + "click_button": { + "name": "click_button", + "doc": "Clicks the button identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax. When using the default locator strategy, buttons are\n searched using ``id``, ``name``, and ``value``.\n\n See the `Click Element` keyword for details about the\n ``modifier`` argument.\n\n The ``modifier`` argument is new in SeleniumLibrary 3.3\n ", + "sha256": "72dcaeaa3bc1a4e14c596d72a19cbd82e0881732440153cbfb27272b2066dd77" + }, + "click_element": { + "name": "click_element", + "doc": "Click the element identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n The ``modifier`` argument can be used to pass\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver/selenium.webdriver.common.keys.html#selenium.webdriver.common.keys.Keys|Selenium Keys]\n when clicking the element. The `+` can be used as a separator\n for different Selenium Keys. The `CTRL` is internally translated to\n the `CONTROL` key. The ``modifier`` is space and case insensitive, example\n \"alt\" and \" aLt \" are supported formats to\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver/selenium.webdriver.common.keys.html#selenium.webdriver.common.keys.Keys.ALT|ALT key]\n . If ``modifier`` does not match to Selenium Keys, keyword fails.\n\n If ``action_chain`` argument is true, see `Boolean arguments` for more\n details on how to set boolean argument, then keyword uses ActionChain\n based click instead of the .click() function. If both\n ``action_chain`` and ``modifier`` are defined, the click will be\n performed using ``modifier`` and ``action_chain`` will be ignored.\n\n Example:\n | Click Element | id:button | | # Would click element without any modifiers. |\n | Click Element | id:button | CTRL | # Would click element with CTLR key pressed down. |\n | Click Element | id:button | CTRL+ALT | # Would click element with CTLR and ALT keys pressed down. |\n | Click Element | id:button | action_chain=True | # Clicks the button using an Selenium ActionChains |\n\n The ``modifier`` argument is new in SeleniumLibrary 3.2\n The ``action_chain`` argument is new in SeleniumLibrary 4.1\n ", + "sha256": "5099da1ff98ae3351fb740f301498066e1f86b8f9a6ef7f178e2b29d5d5afb35" + }, + "click_element_at_coordinates": { + "name": "click_element_at_coordinates", + "doc": "Click the element ``locator`` at ``xoffset/yoffset``.\n\n The Cursor is moved and the center of the element and x/y coordinates are\n calculated from that point.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "6c9be5ef41acf068a8ecf3972fe88f5f9c5257cf843d014dd9a76f7b4a3719c7" + }, + "click_image": { + "name": "click_image", + "doc": "Clicks an image identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax. When using the default locator strategy, images are searched\n using ``id``, ``name``, ``src`` and ``alt``.\n\n See the `Click Element` keyword for details about the\n ``modifier`` argument.\n\n The ``modifier`` argument is new in SeleniumLibrary 3.3\n ", + "sha256": "a83623f5affb23d6a089b6cab14e9983dd55eba3b11deedf672c6d2c3d387cf4" + }, + "click_link": { + "name": "click_link", + "doc": "Clicks a link identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax. When using the default locator strategy, links are searched\n using ``id``, ``name``, ``href`` and the link text.\n\n See the `Click Element` keyword for details about the\n ``modifier`` argument.\n\n The ``modifier`` argument is new in SeleniumLibrary 3.3\n ", + "sha256": "d8c5ec4c5359fed7c6a5094f5d18e8766b4dfb6f4e4d5ea1d61d50b7b09e7c31" + }, + "cover_element": { + "name": "cover_element", + "doc": "Will cover elements identified by ``locator`` with a blue div without breaking page layout.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n New in SeleniumLibrary 3.3.0\n\n Example:\n |`Cover Element` | css:div#container |\n ", + "sha256": "0dd30bea744e70b71f3e5fc5358833c291d404cdfa23970d09ece25f2380fb28" + }, + "double_click_element": { + "name": "double_click_element", + "doc": "Double clicks the element identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "c7b11722014178d683d80e276fcea367307d1d4cbe3b93b17cbbbe30b35b7174" + }, + "drag_and_drop": { + "name": "drag_and_drop", + "doc": "Drags the element identified by ``locator`` into the ``target`` element.\n\n The ``locator`` argument is the locator of the dragged element\n and the ``target`` is the locator of the target. See the\n `Locating elements` section for details about the locator syntax.\n\n Example:\n | `Drag And Drop` | css:div#element | css:div.target |\n ", + "sha256": "af13a511a462a2540dc93baf3bc42d05143aaf0de6ce9771029044a25b40bd64" + }, + "drag_and_drop_by_offset": { + "name": "drag_and_drop_by_offset", + "doc": "Drags the element identified with ``locator`` by ``xoffset/yoffset``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n The element will be moved by ``xoffset`` and ``yoffset``, each of which\n is a negative or positive number specifying the offset.\n\n Example:\n | `Drag And Drop By Offset` | myElem | 50 | -35 | # Move myElem 50px right and 35px down |\n ", + "sha256": "89750f538dc14ca0c04fbe1a3aba732352f9723d658bbd971905003ee9c351f6" + }, + "element_attribute_value_should_be": { + "name": "element_attribute_value_should_be", + "doc": "Verifies element identified by ``locator`` contains expected attribute value.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n Example:\n `Element Attribute Value Should Be` | css:img | href | value\n\n New in SeleniumLibrary 3.2.\n ", + "sha256": "330701ee8d3307c6543bdfeafa649d14689f639f2e139e499aae8ec495d7d015" + }, + "element_should_be_disabled": { + "name": "element_should_be_disabled", + "doc": "Verifies that element identified by ``locator`` is disabled.\n\n This keyword considers also elements that are read-only to be\n disabled.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "6f34019f6e68805c2b73ef5207b424743c9461dfd30061f163d21948304bb012" + }, + "element_should_be_enabled": { + "name": "element_should_be_enabled", + "doc": "Verifies that element identified by ``locator`` is enabled.\n\n This keyword considers also elements that are read-only to be\n disabled.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "014f8538093bdcef0ed8c7a13020ae513a4a14bd2d0b71f1843de951f5c7b5d3" + }, + "element_should_be_focused": { + "name": "element_should_be_focused", + "doc": "Verifies that element identified by ``locator`` is focused.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n New in SeleniumLibrary 3.0.\n ", + "sha256": "f327420520f06421e0a11062af115eaa7bb3eaf97a0ae4b6f02c0c82c9fa1f73" + }, + "element_should_be_visible": { + "name": "element_should_be_visible", + "doc": "Verifies that the element identified by ``locator`` is visible.\n\n Herein, visible means that the element is logically visible, not\n optically visible in the current browser viewport. For example,\n an element that carries ``display:none`` is not logically visible,\n so using this keyword on that element would fail.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n The ``message`` argument can be used to override the default error\n message.\n ", + "sha256": "98c4fb9d0b90e73c3d702b553aa6a30f027320463eb18e298cd5b9133f1cc36a" + }, + "element_should_contain": { + "name": "element_should_contain", + "doc": "Verifies that element ``locator`` contains text ``expected``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n The ``message`` argument can be used to override the default error\n message.\n\n The ``ignore_case`` argument can be set to True to compare case\n insensitive, default is False. New in SeleniumLibrary 3.1.\n\n ``ignore_case`` argument is new in SeleniumLibrary 3.1.\n\n Use `Element Text Should Be` if you want to match the exact text,\n not a substring.\n ", + "sha256": "998a924785fef84597b5e5fc866f4c5d7e4b0a753cba68d15be0f3b44588c06d" + }, + "element_should_not_be_visible": { + "name": "element_should_not_be_visible", + "doc": "Verifies that the element identified by ``locator`` is NOT visible.\n\n Passes if the element does not exists. See `Element Should Be Visible`\n for more information about visibility and supported arguments.\n ", + "sha256": "811779774da3cf876101661d4c15a6e89ea0568493be61b19fded7a0bd40f0c4" + }, + "element_should_not_contain": { + "name": "element_should_not_contain", + "doc": "Verifies that element ``locator`` does not contain text ``expected``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n The ``message`` argument can be used to override the default error\n message.\n\n The ``ignore_case`` argument can be set to True to compare case\n insensitive, default is False.\n\n ``ignore_case`` argument new in SeleniumLibrary 3.1.\n ", + "sha256": "ef9492bae813b1597fabc9d6f02a21c05ff736a18fb6eb20fb81e6ca40011437" + }, + "element_text_should_be": { + "name": "element_text_should_be", + "doc": "Verifies that element ``locator`` contains exact the text ``expected``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n The ``message`` argument can be used to override the default error\n message.\n\n The ``ignore_case`` argument can be set to True to compare case\n insensitive, default is False.\n\n ``ignore_case`` argument is new in SeleniumLibrary 3.1.\n\n Use `Element Should Contain` if a substring match is desired.\n ", + "sha256": "4036c0bb4fe36085fcab4421f3ffb65265d70d8cb852106ea13a983438a77723" + }, + "element_text_should_not_be": { + "name": "element_text_should_not_be", + "doc": "Verifies that element ``locator`` does not contain exact the text ``not_expected``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n The ``message`` argument can be used to override the default error\n message.\n\n The ``ignore_case`` argument can be set to True to compare case\n insensitive, default is False.\n\n New in SeleniumLibrary 3.1.1\n ", + "sha256": "67821af845f34ba19ebffb38fa558c375f7261e3d9c9f04cb653bad828e99cf4" + }, + "get_all_links": { + "name": "get_all_links", + "doc": "Returns a list containing ids of all links found in current page.\n\n If a link has no id, an empty string will be in the list instead.\n ", + "sha256": "f17319af1acc205f3ee5fe01b5e8960bba45ff05629b4b1d2e4fdec770163c1a" + }, + "get_dom_attribute": { + "name": "get_dom_attribute", + "doc": "Returns the value of ``attribute`` from the element ``locator``. `Get DOM Attribute` keyword\n only returns attributes declared within the element's HTML markup. If the requested attribute\n is not there, the keyword returns ${None}.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n Example:\n | ${id}= | `Get DOM Attribute` | css:h1 | id |\n\n ", + "sha256": "1337e3b21fae3759b85da9dba5fda08378fd8ea4ff16b9d9a03fa54f1d75853f" + }, + "get_element_attribute": { + "name": "get_element_attribute", + "doc": "Returns the value of ``attribute`` from the element ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n Example:\n | ${id}= | `Get Element Attribute` | css:h1 | id |\n\n Passing attribute name as part of the ``locator`` was removed\n in SeleniumLibrary 3.2. The explicit ``attribute`` argument\n should be used instead.\n ", + "sha256": "3325a9affcfb67bbb11b250a7479d125f3a7c0ca3e6b4772b35f873c6942a300" + }, + "get_element_count": { + "name": "get_element_count", + "doc": "Returns the number of elements matching ``locator``.\n\n If you wish to assert the number of matching elements, use\n `Page Should Contain Element` with ``limit`` argument. Keyword will\n always return an integer.\n\n Example:\n | ${count} = | `Get Element Count` | name:div_name |\n | `Should Be True` | ${count} > 2 | |\n\n New in SeleniumLibrary 3.0.\n ", + "sha256": "edc00542de29af7b4b11d459c21c6a8f87fd21233f49c1b9a5b4d8e06d0128f8" + }, + "get_element_size": { + "name": "get_element_size", + "doc": "Returns width and height of the element identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n Both width and height are returned as integers.\n\n Example:\n | ${width} | ${height} = | `Get Element Size` | css:div#container |\n ", + "sha256": "d1dc235938760fc871c68838032587be56a8ebb13dc295f68e9df6a03c72d266" + }, + "get_horizontal_position": { + "name": "get_horizontal_position", + "doc": "Returns the horizontal position of the element identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n The position is returned in pixels off the left side of the page,\n as an integer.\n\n See also `Get Vertical Position`.\n ", + "sha256": "7b81ffe406d7708e72861971ec879a7cdb3adff3cf3a6ad4c816c0b36de84a79" + }, + "get_property": { + "name": "get_property", + "doc": "Returns the value of ``property`` from the element ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n Example:\n | ${text_length}= | `Get Property` | css:h1 | text_length |\n\n ", + "sha256": "6335a05f73d42212f78d4285872595fec96dbb4e669b8026b2e9bdab4f3284eb" + }, + "get_text": { + "name": "get_text", + "doc": "Returns the text value of the element identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "c5df21cb13fca76338626c63ce4e0e83be2e5563eb296833f55678c3424ad333" + }, + "get_value": { + "name": "get_value", + "doc": "Returns the value attribute of the element identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "5856fe53c0581268a5a395418f08aedb118762d5ec8fbd553cf2d44b82aa27c6" + }, + "get_vertical_position": { + "name": "get_vertical_position", + "doc": "Returns the vertical position of the element identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n The position is returned in pixels off the top of the page,\n as an integer.\n\n See also `Get Horizontal Position`.\n ", + "sha256": "a1f1cc8075b6323bf4b900ea52357586f28721239e45ec11fb1a130faa9246c0" + }, + "get_webelement": { + "name": "get_webelement", + "doc": "Returns the first WebElement matching the given ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "5deaaabc9162680121dbe744d4e476e40c7eacba17922459c209f211ba74b5cd" + }, + "get_webelements": { + "name": "get_webelements", + "doc": "Returns a list of WebElement objects matching the ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n Starting from SeleniumLibrary 3.0, the keyword returns an empty\n list if there are no matching elements. In previous releases, the\n keyword failed in this case.\n ", + "sha256": "ab7b4634b7c54b2b17daf4c290704fe45af948eeff41f9dbc1c01fab33273496" + }, + "mouse_down": { + "name": "mouse_down", + "doc": "Simulates pressing the left mouse button on the element ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n The element is pressed without releasing the mouse button.\n\n See also the more specific keywords `Mouse Down On Image` and\n `Mouse Down On Link`.\n ", + "sha256": "c0e5431b9b9eb6875830eadccc1ed0f9a9d34781ecef40ab059194054eeae9e4" + }, + "mouse_down_on_image": { + "name": "mouse_down_on_image", + "doc": "Simulates a mouse down event on an image identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax. When using the default locator strategy, images are searched\n using ``id``, ``name``, ``src`` and ``alt``.\n ", + "sha256": "3b7c0b9a83908e60012f095acc71305c853dd07864497077420f1a3930ea144c" + }, + "mouse_down_on_link": { + "name": "mouse_down_on_link", + "doc": "Simulates a mouse down event on a link identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax. When using the default locator strategy, links are searched\n using ``id``, ``name``, ``href`` and the link text.\n ", + "sha256": "8ef3134ef374ebc89f76985b09abd2caac10f603e8db38cf78dcbac9c826cc3e" + }, + "mouse_out": { + "name": "mouse_out", + "doc": "Simulates moving the mouse away from the element ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "835368b635d5d1c5c50250595a8e7cb2feb9eb4af4fa14753c561a9c35894db1" + }, + "mouse_over": { + "name": "mouse_over", + "doc": "Simulates hovering the mouse over the element ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "b4c14a2a10cfddb07d7748630ba6546991d3da2311a20aa146685a0f78e41241" + }, + "mouse_up": { + "name": "mouse_up", + "doc": "Simulates releasing the left mouse button on the element ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "47c3666126bc84aa9104f6137fd51817efcd1804aaf7c965df143a6aad71895a" + }, + "open_context_menu": { + "name": "open_context_menu", + "doc": "Opens the context menu on the element identified by ``locator``.", + "sha256": "8cb9023a05753eb5cc230116dec98188b5bdfac0b94955b69957726131189493" + }, + "page_should_contain": { + "name": "page_should_contain", + "doc": "Verifies that current page contains ``text``.\n\n If this keyword fails, it automatically logs the page source\n using the log level specified with the optional ``loglevel``\n argument. Valid log levels are ``TRACE`` (default), ``DEBUG``,\n ``INFO``, ``WARN``, and ``NONE``. If the log level is ``NONE``\n or below the current active log level the source will not be logged.\n\n !! WARNING !! If you have an iframe selected, `Page Should Contain`\n will reset the frame reference back to the main frame. This is due\n to the fact that is searches for the ``text`` in all frames. To locate\n an element in an iframe after calling `Page Should Contian` one needs\n to (re)select the frame.\n ", + "sha256": "bb1186dbfae09e52cad4cad8def5bf2980085e48f75b6af2330bcd4da67477af" + }, + "page_should_contain_element": { + "name": "page_should_contain_element", + "doc": "Verifies that element ``locator`` is found on the current page.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n The ``message`` argument can be used to override the default error\n message.\n\n The ``limit`` argument can used to define how many elements the\n page should contain. When ``limit`` is ``None`` (default) page can\n contain one or more elements. When limit is a number, page must\n contain same number of elements.\n\n See `Page Should Contain` for an explanation about the ``loglevel``\n argument.\n\n Examples assumes that locator matches to two elements.\n | `Page Should Contain Element` | div_name | limit=1 | # Keyword fails. |\n | `Page Should Contain Element` | div_name | limit=2 | # Keyword passes. |\n | `Page Should Contain Element` | div_name | limit=none | # None is considered one or more. |\n | `Page Should Contain Element` | div_name | | # Same as above. |\n\n The ``limit`` argument is new in SeleniumLibrary 3.0.\n ", + "sha256": "d2c24d9ce997c94b3cd391306893b9d864c389a047c274ca1ab323e51f960f8e" + }, + "page_should_contain_image": { + "name": "page_should_contain_image", + "doc": "Verifies image identified by ``locator`` is found from current page.\n\n See the `Locating elements` section for details about the locator\n syntax. When using the default locator strategy, images are searched\n using ``id``, ``name``, ``src`` and ``alt``.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n ", + "sha256": "84ab3a648d3b18c5e266ba075408f3cb2ac3b736e1e2009a6cca125de5d07a50" + }, + "page_should_contain_link": { + "name": "page_should_contain_link", + "doc": "Verifies link identified by ``locator`` is found from current page.\n\n See the `Locating elements` section for details about the locator\n syntax. When using the default locator strategy, links are searched\n using ``id``, ``name``, ``href`` and the link text.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n ", + "sha256": "005f6565f4fcd9b91f87a2274c32fae7545619549be26f23b2cc06856e44ecba" + }, + "page_should_not_contain": { + "name": "page_should_not_contain", + "doc": "Verifies the current page does not contain ``text``.\n\n See `Page Should Contain` for an explanation about the ``loglevel``\n argument.\n ", + "sha256": "72389be32f084ed5a3716a32e833e117c419bc2c6ebfa525a79e69054bb2a8cc" + }, + "page_should_not_contain_element": { + "name": "page_should_not_contain_element", + "doc": "Verifies that element ``locator`` is not found on the current page.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n See `Page Should Contain` for an explanation about ``message`` and\n ``loglevel`` arguments.\n ", + "sha256": "3939f5d1fce87d85f013ae3e4327b50404cf832231d4ca2e677013808ee8ff92" + }, + "page_should_not_contain_image": { + "name": "page_should_not_contain_image", + "doc": "Verifies image identified by ``locator`` is not found from current page.\n\n See the `Locating elements` section for details about the locator\n syntax. When using the default locator strategy, images are searched\n using ``id``, ``name``, ``src`` and ``alt``.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n ", + "sha256": "7367c4581992c47a2fbd74fd0beccc254e883879f6b93f206242d0ecb6397448" + }, + "page_should_not_contain_link": { + "name": "page_should_not_contain_link", + "doc": "Verifies link identified by ``locator`` is not found from current page.\n\n See the `Locating elements` section for details about the locator\n syntax. When using the default locator strategy, links are searched\n using ``id``, ``name``, ``href`` and the link text.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n ", + "sha256": "61fca3076c7b671f21528f5d141ee7b43ecc1acada608b4157d08ecb38fae0e1" + }, + "press_key": { + "name": "press_key", + "doc": "Simulates user pressing key on element identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n ``key`` is either a single character, a string, or a numerical ASCII\n code of the key lead by '\\'.\n\n Examples:\n | `Press Key` | text_field | q |\n | `Press Key` | text_field | abcde |\n | `Press Key` | login_button | \\13 | # ASCII code for enter key |\n\n `Press Key` and `Press Keys` differ in the methods to simulate key\n presses. `Press Key` uses the WebDriver `SEND_KEYS_TO_ELEMENT` command\n using the selenium send_keys method. Although one is not recommended\n over the other if `Press Key` does not work we recommend trying\n `Press Keys`.\n send_\n ", + "sha256": "fd4035762f6f532aed3cd2b93ad24002a51503e8a86cd7da956a3e2cf8a1038d" + }, + "press_keys": { + "name": "press_keys", + "doc": "Simulates the user pressing key(s) to an element or on the active browser.\n\n If ``locator`` evaluates as false, see `Boolean arguments` for more\n details, then the ``keys`` are sent to the currently active browser.\n Otherwise element is searched and ``keys`` are send to the element\n identified by the ``locator``. In later case, keyword fails if element\n is not found. See the `Locating elements` section for details about\n the locator syntax.\n\n ``keys`` arguments can contain one or many strings, but it can not\n be empty. ``keys`` can also be a combination of\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver/selenium.webdriver.common.keys.html|Selenium Keys]\n and strings or a single Selenium Key. If Selenium Key is combined\n with strings, Selenium key and strings must be separated by the\n `+` character, like in `CONTROL+c`. Selenium Keys\n are space and case sensitive and Selenium Keys are not parsed\n inside of the string. Example AALTO, would send string `AALTO`\n and `ALT` not parsed inside of the string. But `A+ALT+O` would\n found Selenium ALT key from the ``keys`` argument. It also possible\n to press many Selenium Keys down at the same time, example\n 'ALT+ARROW_DOWN`.\n\n If Selenium Keys are detected in the ``keys`` argument, keyword\n will press the Selenium Key down, send the strings and\n then release the Selenium Key. If keyword needs to send a Selenium\n Key as a string, then each character must be separated with\n `+` character, example `E+N+D`.\n\n `CTRL` is alias for\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver/selenium.webdriver.common.keys.html#selenium.webdriver.common.keys.Keys.CONTROL|Selenium CONTROL]\n and ESC is alias for\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver/selenium.webdriver.common.keys.html#selenium.webdriver.common.keys.Keys.ESCAPE|Selenium ESCAPE]\n\n New in SeleniumLibrary 3.3\n\n Examples:\n | `Press Keys` | text_field | AAAAA | | # Sends string \"AAAAA\" to element. |\n | `Press Keys` | None | BBBBB | | # Sends string \"BBBBB\" to currently active browser. |\n | `Press Keys` | text_field | E+N+D | | # Sends string \"END\" to element. |\n | `Press Keys` | text_field | XXX | YY | # Sends strings \"XXX\" and \"YY\" to element. |\n | `Press Keys` | text_field | XXX+YY | | # Same as above. |\n | `Press Keys` | text_field | ALT+ARROW_DOWN | | # Pressing \"ALT\" key down, then pressing ARROW_DOWN and then releasing both keys. |\n | `Press Keys` | text_field | ALT | ARROW_DOWN | # Pressing \"ALT\" key and then pressing ARROW_DOWN. |\n | `Press Keys` | text_field | CTRL+c | | # Pressing CTRL key down, sends string \"c\" and then releases CTRL key. |\n | `Press Keys` | button | RETURN | | # Pressing \"ENTER\" key to element. |\n\n `Press Key` and `Press Keys` differ in the methods to simulate key\n presses. `Press Keys` uses the Selenium/WebDriver Actions.\n `Press Keys` also has a more extensive syntax for describing keys,\n key combinations, and key actions. Although one is not recommended\n over the other if `Press Keys` does not work we recommend trying\n `Press Key`.\n ", + "sha256": "549b119394b8f48407c11208e1f38c3f2c753e9a40b5c6f1f47b3320df3f3612" + }, + "remove_location_strategy": { + "name": "remove_location_strategy", + "doc": "Removes a previously added custom location strategy.\n\n See `Custom locators` for information on how to create and use\n custom strategies.\n ", + "sha256": "827184ef194cec97d793297edbc6544d2e6774a80a14136ccfa0d5cc04fbc09e" + }, + "scroll_element_into_view": { + "name": "scroll_element_into_view", + "doc": "Scrolls the element identified by ``locator`` into view.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n New in SeleniumLibrary 3.2.0\n ", + "sha256": "0d567a31d5b64fcfb38b47c2f5f452de4fbe3d08aa0c0547644d4c59b243ef60" + }, + "set_focus_to_element": { + "name": "set_focus_to_element", + "doc": "Sets the focus to the element identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n Prior to SeleniumLibrary 3.0 this keyword was named `Focus`.\n ", + "sha256": "0b02399995113cd6ac38557106b4697e4d86f9874173ed593a8853e63362c74f" + }, + "simulate_event": { + "name": "simulate_event", + "doc": "Simulates ``event`` on the element identified by ``locator``.\n\n This keyword is useful if element has ``OnEvent`` handler that\n needs to be explicitly invoked.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n Prior to SeleniumLibrary 3.0 this keyword was named `Simulate`.\n ", + "sha256": "49cd268150ae4f3170f13d6b5a25809f41080efa3f3b5ca0fa2e2d8cd3ea7795" + }, + "wait_for_expected_condition": { + "name": "wait_for_expected_condition", + "doc": "Waits until ``condition`` is true or ``timeout`` expires.\n\n The condition must be one of selenium's expected condition which\n can be found within the selenium\n [https://www.selenium.dev/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.expected_conditions.html#module-selenium.webdriver.support.expected_conditions|Python API]\n documentation. The expected condition can written as snake_case\n (ex title_is) or it can be space delimited (ex Title Is). Some\n conditions require additional arguments or ``args`` which should\n be passed along after the expected condition.\n\n Fails if the timeout expires before the condition becomes true.\n The default value is 10 seconds.\n\n Examples:\n | `Wait For Expected Condition` | alert_is_present |\n | `Wait For Expected Condition` | Title Is | New Title |\n\n If the expected condition expects a locator then one can pass\n as arguments a tuple containing the selenium locator strategies\n and the locator.\n\n Example of expected condition expecting locator:\n | ${byElem}= | Evaluate (\"id\",\"added_btn\")\n | `Wait For Expected Condition` | Presence Of Element Located | ${byElem}\n ", + "sha256": "7e512f1e3c97525aa828d624627aaf3f8b76ac0ec1aaa507b36ff9c8fff34d5a" + }, + "checkbox_should_be_selected": { + "name": "checkbox_should_be_selected", + "doc": "Verifies checkbox ``locator`` is selected/checked.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "e50bf6856c0f0c3f373adb3bcc3b7d677738088632055f507797887c9f822136" + }, + "checkbox_should_not_be_selected": { + "name": "checkbox_should_not_be_selected", + "doc": "Verifies checkbox ``locator`` is not selected/checked.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "8488752a0365d5c94b3a7885d53b67f99d92ccc5687fdc59411b42a40fa95443" + }, + "choose_file": { + "name": "choose_file", + "doc": "Inputs the ``file_path`` into the file input field ``locator``.\n\n This keyword is most often used to input files into upload forms.\n The keyword does not check ``file_path`` is the file or folder\n available on the machine where tests are executed. If the ``file_path``\n points at a file and when using Selenium Grid, Selenium will\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_remote/selenium.webdriver.remote.command.html?highlight=upload#selenium.webdriver.remote.command.Command.UPLOAD_FILE|magically],\n transfer the file from the machine where the tests are executed\n to the Selenium Grid node where the browser is running.\n Then Selenium will send the file path, from the nodes file\n system, to the browser.\n\n That ``file_path`` is not checked, is new in SeleniumLibrary 4.0.\n\n Example:\n | `Choose File` | my_upload_field | ${CURDIR}/trades.csv |\n ", + "sha256": "244543282ef6c62ec448fb42ed37706978ecf84aec27a9c7774fdd39bc84697c" + }, + "input_password": { + "name": "input_password", + "doc": "Types the given password into the text field identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax. See `Input Text` for ``clear`` argument details.\n\n Difference compared to `Input Text` is that this keyword does not\n log the given password on the INFO level. Notice that if you use\n the keyword like\n\n | Input Password | password_field | password |\n\n the password is shown as a normal keyword argument. A way to avoid\n that is using variables like\n\n | Input Password | password_field | ${PASSWORD} |\n\n Please notice that Robot Framework logs all arguments using\n the TRACE level and tests must not be executed using level below\n DEBUG if the password should not be logged in any format.\n\n The `clear` argument is new in SeleniumLibrary 4.0. Hiding password\n logging from Selenium logs is new in SeleniumLibrary 4.2.\n ", + "sha256": "2471a62ea46d3d4815fe3700c92b61bd4abee39926bc4dadeb072bb88ba69fd5" + }, + "input_text": { + "name": "input_text", + "doc": "Types the given ``text`` into the text field identified by ``locator``.\n\n When ``clear`` is true, the input element is cleared before\n the text is typed into the element. When false, the previous text\n is not cleared from the element. Use `Input Password` if you\n do not want the given ``text`` to be logged.\n\n If [https://github.com/SeleniumHQ/selenium/wiki/Grid2|Selenium Grid]\n is used and the ``text`` argument points to a file in the file system,\n then this keyword prevents the Selenium to transfer the file to the\n Selenium Grid hub. Instead, this keyword will send the ``text`` string\n as is to the element. If a file should be transferred to the hub and\n upload should be performed, please use `Choose File` keyword.\n\n See the `Locating elements` section for details about the locator\n syntax. See the `Boolean arguments` section how Boolean values are\n handled.\n\n Disabling the file upload the Selenium Grid node and the `clear`\n argument are new in SeleniumLibrary 4.0\n ", + "sha256": "77be02dfff6bb6cc9d97af190e48a4c333913ca5058e67c85a4055bb84a9f494" + }, + "page_should_contain_button": { + "name": "page_should_contain_button", + "doc": "Verifies button ``locator`` is found from current page.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n\n See the `Locating elements` section for details about the locator\n syntax. When using the default locator strategy, buttons are\n searched using ``id``, ``name``, and ``value``.\n ", + "sha256": "f5fdc2763607b8a19e0dcbc2c8bc0512959193b4312232d89bdf5e3c1287ee25" + }, + "page_should_contain_checkbox": { + "name": "page_should_contain_checkbox", + "doc": "Verifies checkbox ``locator`` is found from the current page.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "827b0517772c7f3d0a8c9c41a1557892b98f0c9ee7228aa80a17df7d1766b338" + }, + "page_should_contain_radio_button": { + "name": "page_should_contain_radio_button", + "doc": "Verifies radio button ``locator`` is found from current page.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n\n See the `Locating elements` section for details about the locator\n syntax. When using the default locator strategy, radio buttons are\n searched using ``id``, ``name`` and ``value``.\n ", + "sha256": "a1bd5c4a731ebb21b599006d59a7c7d163da5fb64ca87ac20d853559ff948a95" + }, + "page_should_contain_textfield": { + "name": "page_should_contain_textfield", + "doc": "Verifies text field ``locator`` is found from current page.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "7b7414371c1321271f8616d6668e9b94001ab4443df27f26fe10c5e968be00c5" + }, + "page_should_not_contain_button": { + "name": "page_should_not_contain_button", + "doc": "Verifies button ``locator`` is not found from current page.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n\n See the `Locating elements` section for details about the locator\n syntax. When using the default locator strategy, buttons are\n searched using ``id``, ``name``, and ``value``.\n ", + "sha256": "c8b007d236e708e3d637b414d88b333f31bc64f396fe9034bc79be14288666ed" + }, + "page_should_not_contain_checkbox": { + "name": "page_should_not_contain_checkbox", + "doc": "Verifies checkbox ``locator`` is not found from the current page.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "88204d5dcc80e3fed6bfc74f5b2e02a3507d9ac290faf29c5818f54fc7c7109d" + }, + "page_should_not_contain_radio_button": { + "name": "page_should_not_contain_radio_button", + "doc": "Verifies radio button ``locator`` is not found from current page.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n\n See the `Locating elements` section for details about the locator\n syntax. When using the default locator strategy, radio buttons are\n searched using ``id``, ``name`` and ``value``.\n ", + "sha256": "f2310d4b57e4303ef5f38cc2cdc705ca95582a56ced04899d806beab1a63cef0" + }, + "page_should_not_contain_textfield": { + "name": "page_should_not_contain_textfield", + "doc": "Verifies text field ``locator`` is not found from current page.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "2d91d04a7f6bb6ffd6fb86459718e337880326ddbba3a1631de12737ecab5339" + }, + "radio_button_should_be_set_to": { + "name": "radio_button_should_be_set_to", + "doc": "Verifies radio button group ``group_name`` is set to ``value``.\n\n ``group_name`` is the ``name`` of the radio button group.\n ", + "sha256": "baedeb274f24cfa1951591b65fd654551c128c26db397414fce039f3c2ef68cc" + }, + "radio_button_should_not_be_selected": { + "name": "radio_button_should_not_be_selected", + "doc": "Verifies radio button group ``group_name`` has no selection.\n\n ``group_name`` is the ``name`` of the radio button group.\n ", + "sha256": "552945bd4776a7545990b26941784cf5a8bd5d1725fb1ccd6241d7f4404dea0e" + }, + "select_checkbox": { + "name": "select_checkbox", + "doc": "Selects the checkbox identified by ``locator``.\n\n Does nothing if checkbox is already selected.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "a864b4289721b7356ee6cc8f51612cdb5b91f5e439a264380665dd3c359cf09a" + }, + "select_radio_button": { + "name": "select_radio_button", + "doc": "Sets the radio button group ``group_name`` to ``value``.\n\n The radio button to be selected is located by two arguments:\n - ``group_name`` is the name of the radio button group.\n - ``value`` is the ``id`` or ``value`` attribute of the actual\n radio button.\n\n Examples:\n | `Select Radio Button` | size | XL |\n | `Select Radio Button` | contact | email |\n ", + "sha256": "ffbddc133ea67fa89fc81c47e311a5c1c0d17de62b307fb25cb0811ebf995909" + }, + "submit_form": { + "name": "submit_form", + "doc": "Submits a form identified by ``locator``.\n\n If ``locator`` is not given, first form on the page is submitted.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "19787cfd196cb398177f114d219b7047839b1b875ad44e4741c02be1f2219fb7" + }, + "textarea_should_contain": { + "name": "textarea_should_contain", + "doc": "Verifies text area ``locator`` contains text ``expected``.\n\n ``message`` can be used to override default error message.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "1f0212530a7318d4b84aab2f76e6a786698c18553eb45f6d7b5ce1526aa8806a" + }, + "textarea_value_should_be": { + "name": "textarea_value_should_be", + "doc": "Verifies text area ``locator`` has exactly text ``expected``.\n\n ``message`` can be used to override default error message.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "351e1fbde625caa68c16d8203c380853b86f12203e2a58fe32fed5154779df55" + }, + "textfield_should_contain": { + "name": "textfield_should_contain", + "doc": "Verifies text field ``locator`` contains text ``expected``.\n\n ``message`` can be used to override the default error message.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "8d542b446cce4ae3a59f57d2492144fa0264dc10bcc29a7a75e210368e7b24a9" + }, + "textfield_value_should_be": { + "name": "textfield_value_should_be", + "doc": "Verifies text field ``locator`` has exactly text ``expected``.\n\n ``message`` can be used to override default error message.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "bf88210c7d1673f6f28e6a5af94ecca2f23d655f0da09f31557b5d619ca4bb83" + }, + "unselect_checkbox": { + "name": "unselect_checkbox", + "doc": "Removes the selection of checkbox identified by ``locator``.\n\n Does nothing if the checkbox is not selected.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "73e850a91f88669d5f169f1da487263b966b34b9d5979fa7eacc353b9af6d3ad" + }, + "current_frame_should_contain": { + "name": "current_frame_should_contain", + "doc": "Verifies that the current frame contains ``text``.\n\n See `Page Should Contain` for an explanation about the ``loglevel``\n argument.\n\n Prior to SeleniumLibrary 3.0 this keyword was named\n `Current Frame Contains`.\n ", + "sha256": "d42932ad52a7f5a80466c5fc70cde1994b5dc91e42d5a92d5a4c84c5952106bc" + }, + "current_frame_should_not_contain": { + "name": "current_frame_should_not_contain", + "doc": "Verifies that the current frame does not contain ``text``.\n\n See `Page Should Contain` for an explanation about the ``loglevel``\n argument.\n ", + "sha256": "39c919106caf859d8c436e8334ba7dbfbaaadc761810034f9c24433ef930029d" + }, + "frame_should_contain": { + "name": "frame_should_contain", + "doc": "Verifies that frame identified by ``locator`` contains ``text``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n See `Page Should Contain` for an explanation about the ``loglevel``\n argument.\n ", + "sha256": "e7cf02e4cd77e7196d87f875db7285146a629fe895b3576c9dbd33ae4ab362fd" + }, + "select_frame": { + "name": "select_frame", + "doc": "Sets frame identified by ``locator`` as the current frame.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n Works both with frames and iframes. Use `Unselect Frame` to cancel\n the frame selection and return to the main frame.\n\n Example:\n | `Select Frame` | top-frame | # Select frame with id or name 'top-frame' |\n | `Click Link` | example | # Click link 'example' in the selected frame |\n | `Unselect Frame` | | # Back to main frame. |\n | `Select Frame` | //iframe[@name='xxx'] | # Select frame using xpath |\n ", + "sha256": "c2c67edf46d18644488c6395a750e293ab150011cdcdfe0741481328e01163f6" + }, + "unselect_frame": { + "name": "unselect_frame", + "doc": "Sets the main frame as the current frame.\n\n In practice cancels the previous `Select Frame` call.\n ", + "sha256": "9fc68af60f0d437e37ccc1fccb858b2c6554427f3f269518d4e7f849df3c43ec" + }, + "execute_async_javascript": { + "name": "execute_async_javascript", + "doc": "Executes asynchronous JavaScript code with possible arguments.\n\n Similar to `Execute Javascript` except that scripts executed with\n this keyword must explicitly signal they are finished by invoking the\n provided callback. This callback is always injected into the executed\n function as the last argument.\n\n Scripts must complete within the script timeout or this keyword will\n fail. See the `Timeout` section for more information.\n\n Starting from SeleniumLibrary 3.2 it is possible to provide JavaScript\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_remote/selenium.webdriver.remote.webdriver.html#selenium.webdriver.remote.webdriver.WebDriver.execute_async_script|\n arguments] as part of ``code`` argument. See `Execute Javascript` for\n more details.\n\n Examples:\n | `Execute Async JavaScript` | var callback = arguments[arguments.length - 1]; window.setTimeout(callback, 2000); |\n | `Execute Async JavaScript` | ${CURDIR}/async_js_to_execute.js |\n | ${result} = | `Execute Async JavaScript` |\n | ... | var callback = arguments[arguments.length - 1]; |\n | ... | function answer(){callback(\"text\");}; |\n | ... | window.setTimeout(answer, 2000); |\n | `Should Be Equal` | ${result} | text |\n ", + "sha256": "a67bddb89758620a690da6f26a06985d8a546d32da40a6509296e93dc1f68c51" + }, + "execute_javascript": { + "name": "execute_javascript", + "doc": "Executes the given JavaScript code with possible arguments.\n\n ``code`` may be divided into multiple cells in the test data and\n ``code`` may contain multiple lines of code and arguments. In that case,\n the JavaScript code parts are concatenated together without adding\n spaces and optional arguments are separated from ``code``.\n\n If ``code`` is a path to an existing file, the JavaScript\n to execute will be read from that file. Forward slashes work as\n a path separator on all operating systems.\n\n The JavaScript executes in the context of the currently selected\n frame or window as the body of an anonymous function. Use ``window``\n to refer to the window of your application and ``document`` to refer\n to the document object of the current frame or window, e.g.\n ``document.getElementById('example')``.\n\n This keyword returns whatever the executed JavaScript code returns.\n Return values are converted to the appropriate Python types.\n\n Starting from SeleniumLibrary 3.2 it is possible to provide JavaScript\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_remote/selenium.webdriver.remote.webdriver.html#selenium.webdriver.remote.webdriver.WebDriver.execute_script|\n arguments] as part of ``code`` argument. The JavaScript code and\n arguments must be separated with `JAVASCRIPT` and `ARGUMENTS` markers\n and must be used exactly with this format. If the Javascript code is\n first, then the `JAVASCRIPT` marker is optional. The order of\n `JAVASCRIPT` and `ARGUMENTS` markers can be swapped, but if `ARGUMENTS`\n is the first marker, then `JAVASCRIPT` marker is mandatory. It is only\n allowed to use `JAVASCRIPT` and `ARGUMENTS` markers only one time in the\n ``code`` argument.\n\n Examples:\n | `Execute JavaScript` | window.myFunc('arg1', 'arg2') |\n | `Execute JavaScript` | ${CURDIR}/js_to_execute.js |\n | `Execute JavaScript` | alert(arguments[0]); | ARGUMENTS | 123 |\n | `Execute JavaScript` | ARGUMENTS | 123 | JAVASCRIPT | alert(arguments[0]); |\n ", + "sha256": "5037e85a542b11eebcf4a3fd0b9eae560f17cd117b7fdfc9c7148c9091b44cc4" + }, + "register_keyword_to_run_on_failure": { + "name": "register_keyword_to_run_on_failure", + "doc": "Sets the keyword to execute, when a SeleniumLibrary keyword fails.\n\n ``keyword`` is the name of a keyword that will be executed if a\n SeleniumLibrary keyword fails. It is possible to use any available\n keyword, including user keywords or keywords from other libraries,\n but the keyword must not take any arguments.\n\n The initial keyword to use is set when `importing` the library, and\n the keyword that is used by default is `Capture Page Screenshot`.\n Taking a screenshot when something failed is a very useful\n feature, but notice that it can slow down the execution.\n\n It is possible to use string ``NOTHING`` or ``NONE``,\n case-insensitively, as well as Python ``None`` to disable this\n feature altogether.\n\n This keyword returns the name of the previously registered\n failure keyword or Python ``None`` if this functionality was\n previously disabled. The return value can be always used to\n restore the original value later.\n\n Example:\n | `Register Keyword To Run On Failure` | Log Source |\n | ${previous kw}= | `Register Keyword To Run On Failure` | NONE |\n | `Register Keyword To Run On Failure` | ${previous kw} |\n\n Changes in SeleniumLibrary 3.0:\n - Possible to use string ``NONE`` or Python ``None`` to disable the\n functionality.\n - Return Python ``None`` when the functionality was disabled earlier.\n In previous versions special value ``No Keyword`` was returned and\n it could not be used to restore the original state.\n ", + "sha256": "9eaadf25a89adfb670897301330147203808d9cec135d82015215fe7a14c7313" + }, + "capture_element_screenshot": { + "name": "capture_element_screenshot", + "doc": "Captures a screenshot from the element identified by ``locator`` and embeds it into log file.\n\n See `Capture Page Screenshot` for details about ``filename`` argument.\n See the `Locating elements` section for details about the locator\n syntax.\n\n An absolute path to the created element screenshot is returned.\n\n Support for capturing the screenshot from an element has limited support\n among browser vendors. Please check the browser vendor driver documentation\n does the browser support capturing a screenshot from an element.\n\n New in SeleniumLibrary 3.3. Support for EMBED is new in SeleniumLibrary 4.2.\n\n Examples:\n | `Capture Element Screenshot` | id:image_id | |\n | `Capture Element Screenshot` | id:image_id | ${OUTPUTDIR}/id_image_id-1.png |\n | `Capture Element Screenshot` | id:image_id | EMBED |\n ", + "sha256": "a5dabc5a6525bca9796834b47e1fff61557439b12dd78240701233af0b95c73f" + }, + "capture_page_screenshot": { + "name": "capture_page_screenshot", + "doc": "Takes a screenshot of the current page and embeds it into a log file.\n\n ``filename`` argument specifies the name of the file to write the\n screenshot into. The directory where screenshots are saved can be\n set when `importing` the library or by using the `Set Screenshot\n Directory` keyword. If the directory is not configured, screenshots\n are saved to the same directory where Robot Framework's log file is\n written.\n\n If ``filename`` equals to EMBED (case insensitive), then screenshot\n is embedded as Base64 image to the log.html. In this case file is not\n created in the filesystem.\n\n Starting from SeleniumLibrary 1.8, if ``filename`` contains marker\n ``{index}``, it will be automatically replaced with an unique running\n index, preventing files to be overwritten. Indices start from 1,\n and how they are represented can be customized using Python's\n [https://docs.python.org/3/library/string.html#format-string-syntax|\n format string syntax].\n\n An absolute path to the created screenshot file is returned or if\n ``filename`` equals to EMBED, word `EMBED` is returned.\n\n Support for EMBED is new in SeleniumLibrary 4.2\n\n Examples:\n | `Capture Page Screenshot` | |\n | `File Should Exist` | ${OUTPUTDIR}/selenium-screenshot-1.png |\n | ${path} = | `Capture Page Screenshot` |\n | `File Should Exist` | ${OUTPUTDIR}/selenium-screenshot-2.png |\n | `File Should Exist` | ${path} |\n | `Capture Page Screenshot` | custom_name.png |\n | `File Should Exist` | ${OUTPUTDIR}/custom_name.png |\n | `Capture Page Screenshot` | custom_with_index_{index}.png |\n | `File Should Exist` | ${OUTPUTDIR}/custom_with_index_1.png |\n | `Capture Page Screenshot` | formatted_index_{index:03}.png |\n | `File Should Exist` | ${OUTPUTDIR}/formatted_index_001.png |\n | `Capture Page Screenshot` | EMBED |\n | `File Should Not Exist` | EMBED |\n ", + "sha256": "271132ea5ad25ba3e6182db7560e7eaf512df0bae8f437f756419b9611a4bebe" + }, + "set_screenshot_directory": { + "name": "set_screenshot_directory", + "doc": "Sets the directory for captured screenshots.\n\n ``path`` argument specifies the absolute path to a directory where\n the screenshots should be written to. If the directory does not\n exist, it will be created. The directory can also be set when\n `importing` the library. If it is not configured anywhere,\n screenshots are saved to the same directory where Robot Framework's\n log file is written.\n\n If ``path`` equals to EMBED (case insensitive) and\n `Capture Page Screenshot` or `capture Element Screenshot` keywords\n filename argument is not changed from the default value, then\n the page or element screenshot is embedded as Base64 image to\n the log.html.\n\n The previous value is returned and can be used to restore\n the original value later if needed.\n\n Returning the previous value is new in SeleniumLibrary 3.0.\n The persist argument was removed in SeleniumLibrary 3.2 and\n EMBED is new in SeleniumLibrary 4.2.\n ", + "sha256": "c8241dd4f1113b3db620de1f45f2390c227b081400b04e0178561dde2c38748e" + }, + "get_list_items": { + "name": "get_list_items", + "doc": "Returns all labels or values of selection list ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n Returns visible labels by default, but values can be returned by\n setting the ``values`` argument to a true value (see `Boolean\n arguments`).\n\n Example:\n | ${labels} = | `Get List Items` | mylist | |\n | ${values} = | `Get List Items` | css:#example select | values=True |\n\n Support to return values is new in SeleniumLibrary 3.0.\n ", + "sha256": "60f7293239f288f08276b8fa63d98a6be52ff42a0627b9b0da14ba6dab51bd94" + }, + "get_selected_list_label": { + "name": "get_selected_list_label", + "doc": "Returns the label of selected option from selection list ``locator``.\n\n If there are multiple selected options, the label of the first option\n is returned.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "f9281509d3c4ac39f4b98d9d9d4f0f2dd6b579c37204b33ec7d47b6bef999672" + }, + "get_selected_list_labels": { + "name": "get_selected_list_labels", + "doc": "Returns labels of selected options from selection list ``locator``.\n\n Starting from SeleniumLibrary 3.0, returns an empty list if there\n are no selections. In earlier versions, this caused an error.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "e3bf2c1db04dbb52c99c7397065da52699bb4b7bdc5ceaeb45d525e8176acb48" + }, + "get_selected_list_value": { + "name": "get_selected_list_value", + "doc": "Returns the value of selected option from selection list ``locator``.\n\n If there are multiple selected options, the value of the first option\n is returned.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "2b935dd4627ca62d92a311569036b2978032aa67e542f5b7ef91a514f01f323d" + }, + "get_selected_list_values": { + "name": "get_selected_list_values", + "doc": "Returns values of selected options from selection list ``locator``.\n\n Starting from SeleniumLibrary 3.0, returns an empty list if there\n are no selections. In earlier versions, this caused an error.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "83b79c56056a6d51529e36a093ba14ec0b805a96bdb9e6870214eb4de987bea6" + }, + "list_selection_should_be": { + "name": "list_selection_should_be", + "doc": "Verifies selection list ``locator`` has ``expected`` options selected.\n\n It is possible to give expected options both as visible labels and\n as values. Starting from SeleniumLibrary 3.0, mixing labels and\n values is not possible. Order of the selected options is not\n validated.\n\n If no expected options are given, validates that the list has\n no selections. A more explicit alternative is using `List Should\n Have No Selections`.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n Examples:\n | `List Selection Should Be` | gender | Female | |\n | `List Selection Should Be` | interests | Test Automation | Python |\n ", + "sha256": "1d70ccc8a2dc868e265fc29e9cbc2317799eb12d0dd3f21d61fa4ffea7a7e4c2" + }, + "list_should_have_no_selections": { + "name": "list_should_have_no_selections", + "doc": "Verifies selection list ``locator`` has no options selected.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "429fc50c47319d8267bc5c2306a7d1d191a124d457a6f6655bb4ff5d64d71def" + }, + "page_should_contain_list": { + "name": "page_should_contain_list", + "doc": "Verifies selection list ``locator`` is found from current page.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "9ad2d87bd51bee3365d5ca32153adae2ea4b137f916f07fc39416a54aa117bf6" + }, + "page_should_not_contain_list": { + "name": "page_should_not_contain_list", + "doc": "Verifies selection list ``locator`` is not found from current page.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "2f2e58b399f73b2ab4dc795368b0b18b9a63c37e2764de722d897039d6e7881c" + }, + "select_all_from_list": { + "name": "select_all_from_list", + "doc": "Selects all options from multi-selection list ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "7113bdf3faec639e3bdb3b1beb09c526dec522a0181ae11fd94398fdfb3f6fd2" + }, + "select_from_list_by_index": { + "name": "select_from_list_by_index", + "doc": "Selects options from selection list ``locator`` by ``indexes``.\n\n Indexes of list options start from 0.\n\n If more than one option is given for a single-selection list,\n the last value will be selected. With multi-selection lists all\n specified options are selected, but possible old selections are\n not cleared.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "220f77e512662cfff307efa29f5b46dba2e0d1b04760707cface96f63ff87e7c" + }, + "select_from_list_by_label": { + "name": "select_from_list_by_label", + "doc": "Selects options from selection list ``locator`` by ``labels``.\n\n If more than one option is given for a single-selection list,\n the last value will be selected. With multi-selection lists all\n specified options are selected, but possible old selections are\n not cleared.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "12c2af99cb8c78b6edd06ee17d902a575d1a2a4932d21bb67b040233a5a80318" + }, + "select_from_list_by_value": { + "name": "select_from_list_by_value", + "doc": "Selects options from selection list ``locator`` by ``values``.\n\n If more than one option is given for a single-selection list,\n the last value will be selected. With multi-selection lists all\n specified options are selected, but possible old selections are\n not cleared.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "9989cd962aeddb746a6ac8c632023bb9fbbe1ae832ae618635fb1c072049d7ab" + }, + "unselect_all_from_list": { + "name": "unselect_all_from_list", + "doc": "Unselects all options from multi-selection list ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n New in SeleniumLibrary 3.0.\n ", + "sha256": "e273c674b217707452b897e66ccfa2ff12ef2279198364b4f95350b0cc557c4c" + }, + "unselect_from_list_by_index": { + "name": "unselect_from_list_by_index", + "doc": "Unselects options from selection list ``locator`` by ``indexes``.\n\n Indexes of list options start from 0. This keyword works only with\n multi-selection lists.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "5aac4cc2fa0bec90621d29b2eac7064d18510c447b7357d8eb5948d2cd459cef" + }, + "unselect_from_list_by_label": { + "name": "unselect_from_list_by_label", + "doc": "Unselects options from selection list ``locator`` by ``labels``.\n\n This keyword works only with multi-selection lists.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "3dfe87450d9a1a8cad3f8cad3e159b8bd4c3e25f25f91dd747aeb23403b18ab5" + }, + "unselect_from_list_by_value": { + "name": "unselect_from_list_by_value", + "doc": "Unselects options from selection list ``locator`` by ``values``.\n\n This keyword works only with multi-selection lists.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "7ee06a01319ea95e02d4ba34cfbc0d845cf5dbaf58244d93338760609a67ec02" + }, + "get_table_cell": { + "name": "get_table_cell", + "doc": "Returns contents of a table cell.\n\n The table is located using the ``locator`` argument and its cell\n found using ``row`` and ``column``. See the `Locating elements`\n section for details about the locator syntax.\n\n Both row and column indexes start from 1, and header and footer\n rows are included in the count. It is possible to refer to rows\n and columns from the end by using negative indexes so that -1\n is the last row/column, -2 is the second last, and so on.\n\n All ```` and ```` elements anywhere in the table are\n considered to be cells.\n\n See `Page Should Contain` for an explanation about the ``loglevel``\n argument.\n ", + "sha256": "616f2d925fbd431f1cdde9427ff865b4f402806b2f15b99dfd033a96e0d0a42e" + }, + "table_cell_should_contain": { + "name": "table_cell_should_contain", + "doc": "Verifies table cell contains text ``expected``.\n\n See `Get Table Cell` that this keyword uses internally for\n an explanation about accepted arguments.\n ", + "sha256": "628c09aa35b649beda7c500e914fa906cf91f9eb30afad19973809784ee1f8d6" + }, + "table_column_should_contain": { + "name": "table_column_should_contain", + "doc": "Verifies table column contains text ``expected``.\n\n The table is located using the ``locator`` argument and its column\n found using ``column``. See the `Locating elements` section for\n details about the locator syntax.\n\n Column indexes start from 1. It is possible to refer to columns\n from the end by using negative indexes so that -1 is the last column,\n -2 is the second last, and so on.\n\n If a table contains cells that span multiple columns, those merged\n cells count as a single column.\n\n See `Page Should Contain Element` for an explanation about the\n ``loglevel`` argument.\n ", + "sha256": "e0f898ce00b22cd66e2f4c5ab1cdcbea733f294d53bc210ec33667dfcd1963de" + }, + "table_footer_should_contain": { + "name": "table_footer_should_contain", + "doc": "Verifies table footer contains text ``expected``.\n\n Any ```` element inside ```` element is considered to\n be part of the footer.\n\n The table is located using the ``locator`` argument. See the\n `Locating elements` section for details about the locator syntax.\n\n See `Page Should Contain Element` for an explanation about the\n ``loglevel`` argument.\n ", + "sha256": "454fb3be070acb378460038572ed4268de8b18b96b3aaa903d3a1f0093147691" + }, + "table_header_should_contain": { + "name": "table_header_should_contain", + "doc": "Verifies table header contains text ``expected``.\n\n Any ```` element anywhere in the table is considered to be\n part of the header.\n\n The table is located using the ``locator`` argument. See the\n `Locating elements` section for details about the locator syntax.\n\n See `Page Should Contain Element` for an explanation about the\n ``loglevel`` argument.\n ", + "sha256": "66208e9741c9d18d1c09645bfcb9b54b4ffe2c104e5402c86f2cf54feb02de79" + }, + "table_row_should_contain": { + "name": "table_row_should_contain", + "doc": "Verifies that table row contains text ``expected``.\n\n The table is located using the ``locator`` argument and its column\n found using ``column``. See the `Locating elements` section for\n details about the locator syntax.\n\n Row indexes start from 1. It is possible to refer to rows\n from the end by using negative indexes so that -1 is the last row,\n -2 is the second last, and so on.\n\n If a table contains cells that span multiple rows, a match\n only occurs for the uppermost row of those merged cells.\n\n See `Page Should Contain Element` for an explanation about the\n ``loglevel`` argument.\n ", + "sha256": "2ad4f79443748abaa86e768fb0994f32a2d1386c435688727093fb0c1034d23f" + }, + "table_should_contain": { + "name": "table_should_contain", + "doc": "Verifies table contains text ``expected``.\n\n The table is located using the ``locator`` argument. See the\n `Locating elements` section for details about the locator syntax.\n\n See `Page Should Contain Element` for an explanation about the\n ``loglevel`` argument.\n ", + "sha256": "ea4dc362f588ab33332b985ea6ff059499de1e4c25bdbfceb6e6517cd36b24fc" + }, + "wait_for_condition": { + "name": "wait_for_condition", + "doc": "Waits until ``condition`` is true or ``timeout`` expires.\n\n The condition can be arbitrary JavaScript expression but it\n must return a value to be evaluated. See `Execute JavaScript` for\n information about accessing content on pages.\n\n Fails if the timeout expires before the condition becomes true. See\n the `Timeouts` section for more information about using timeouts\n and their default value.\n\n ``error`` can be used to override the default error message.\n\n Examples:\n | `Wait For Condition` | return document.title == \"New Title\" |\n | `Wait For Condition` | return jQuery.active == 0 |\n | `Wait For Condition` | style = document.querySelector('h1').style; return style.background == \"red\" && style.color == \"white\" |\n ", + "sha256": "4998ab3cee46a578df2b064d390401d2ec0268454607ef194db5c0d3d73c81db" + }, + "wait_until_element_contains": { + "name": "wait_until_element_contains", + "doc": "Waits until the element ``locator`` contains ``text``.\n\n Fails if ``timeout`` expires before the text appears. See\n the `Timeouts` section for more information about using timeouts and\n their default value and the `Locating elements` section for details\n about the locator syntax.\n\n ``error`` can be used to override the default error message.\n ", + "sha256": "982c68220bb622a3d985c04b39ea3bc11b20437e73bcf8e38d51ed7e2032852c" + }, + "wait_until_element_does_not_contain": { + "name": "wait_until_element_does_not_contain", + "doc": "Waits until the element ``locator`` does not contain ``text``.\n\n Fails if ``timeout`` expires before the text disappears. See\n the `Timeouts` section for more information about using timeouts and\n their default value and the `Locating elements` section for details\n about the locator syntax.\n\n ``error`` can be used to override the default error message.\n ", + "sha256": "a2b8bc5ee7de21f06e79317935026beddee2105ae645c22b322446dd5a8be0ad" + }, + "wait_until_element_is_enabled": { + "name": "wait_until_element_is_enabled", + "doc": "Waits until the element ``locator`` is enabled.\n\n Element is considered enabled if it is not disabled nor read-only.\n\n Fails if ``timeout`` expires before the element is enabled. See\n the `Timeouts` section for more information about using timeouts and\n their default value and the `Locating elements` section for details\n about the locator syntax.\n\n ``error`` can be used to override the default error message.\n\n Considering read-only elements to be disabled is a new feature\n in SeleniumLibrary 3.0.\n ", + "sha256": "6202e0635b377e2e7d5eaa091eb6a582b64bc49f9d5edf6ddeb7754723015543" + }, + "wait_until_element_is_not_visible": { + "name": "wait_until_element_is_not_visible", + "doc": "Waits until the element ``locator`` is not visible.\n\n Fails if ``timeout`` expires before the element is not visible. See\n the `Timeouts` section for more information about using timeouts and\n their default value and the `Locating elements` section for details\n about the locator syntax.\n\n ``error`` can be used to override the default error message.\n ", + "sha256": "e112e160d739b0cd0f8730703738cc0692e1c0d57e42308b6d50206db23e6d52" + }, + "wait_until_element_is_visible": { + "name": "wait_until_element_is_visible", + "doc": "Waits until the element ``locator`` is visible.\n\n Fails if ``timeout`` expires before the element is visible. See\n the `Timeouts` section for more information about using timeouts and\n their default value and the `Locating elements` section for details\n about the locator syntax.\n\n ``error`` can be used to override the default error message.\n ", + "sha256": "90878c583a727db5da943e7f532efa4e73c59a525a0107233fd59740bb9dd116" + }, + "wait_until_location_contains": { + "name": "wait_until_location_contains", + "doc": "Waits until the current URL contains ``expected``.\n\n The ``expected`` argument contains the expected value in url.\n\n Fails if ``timeout`` expires before the location contains. See\n the `Timeouts` section for more information about using timeouts\n and their default value.\n\n The ``message`` argument can be used to override the default error\n message.\n\n New in SeleniumLibrary 4.0\n ", + "sha256": "33b91c79fe956c37284bccdb56d318e679ec774ca1565db5e2140250b6b46fb5" + }, + "wait_until_location_does_not_contain": { + "name": "wait_until_location_does_not_contain", + "doc": "Waits until the current URL does not contains ``location``.\n\n The ``location`` argument contains value not expected in url.\n\n Fails if ``timeout`` expires before the location not contains. See\n the `Timeouts` section for more information about using timeouts\n and their default value.\n\n The ``message`` argument can be used to override the default error\n message.\n\n New in SeleniumLibrary 4.3\n ", + "sha256": "5ea0b9da22370c90d509d3e4a8aad47b69652b2bd0ce5b29a9264508d4bea432" + }, + "wait_until_location_is": { + "name": "wait_until_location_is", + "doc": "Waits until the current URL is ``expected``.\n\n The ``expected`` argument is the expected value in url.\n\n Fails if ``timeout`` expires before the location is. See\n the `Timeouts` section for more information about using timeouts\n and their default value.\n\n The ``message`` argument can be used to override the default error\n message.\n\n New in SeleniumLibrary 4.0\n ", + "sha256": "2a0604e9e096908cda4caef1486d56310d6f10d0d974804c96a32a0492eb1f82" + }, + "wait_until_location_is_not": { + "name": "wait_until_location_is_not", + "doc": "Waits until the current URL is not ``location``.\n\n The ``location`` argument is the unexpected value in url.\n\n Fails if ``timeout`` expires before the location is not. See\n the `Timeouts` section for more information about using timeouts\n and their default value.\n\n The ``message`` argument can be used to override the default error\n message.\n\n New in SeleniumLibrary 4.3\n ", + "sha256": "96f19cceb6f263cde977b3dfd4b90d06691a1533ebef77c9c5ef1f0e0925e228" + }, + "wait_until_page_contains": { + "name": "wait_until_page_contains", + "doc": "Waits until ``text`` appears on the current page.\n\n Fails if ``timeout`` expires before the text appears. See\n the `Timeouts` section for more information about using timeouts\n and their default value.\n\n ``error`` can be used to override the default error message.\n ", + "sha256": "2e6b9f7e424ed5ba676c82ce9b6ae964050a5fb7b47baa35a3f94125107d9e57" + }, + "wait_until_page_contains_element": { + "name": "wait_until_page_contains_element", + "doc": "Waits until the element ``locator`` appears on the current page.\n\n Fails if ``timeout`` expires before the element appears. See\n the `Timeouts` section for more information about using timeouts and\n their default value and the `Locating elements` section for details\n about the locator syntax.\n\n ``error`` can be used to override the default error message.\n\n The ``limit`` argument can used to define how many elements the\n page should contain. When ``limit`` is `None` (default) page can\n contain one or more elements. When limit is a number, page must\n contain same number of elements.\n\n ``limit`` is new in SeleniumLibrary 4.4\n ", + "sha256": "712da49e8aff630cb2843522331935693ce334aea9ccb2aacb6c015af9c921b5" + }, + "wait_until_page_does_not_contain": { + "name": "wait_until_page_does_not_contain", + "doc": "Waits until ``text`` disappears from the current page.\n\n Fails if ``timeout`` expires before the text disappears. See\n the `Timeouts` section for more information about using timeouts\n and their default value.\n\n ``error`` can be used to override the default error message.\n ", + "sha256": "96c2f8840c677afdb9f207107bf3f7bbdfb9d1b56e3ce887cf34a88e3e273974" + }, + "wait_until_page_does_not_contain_element": { + "name": "wait_until_page_does_not_contain_element", + "doc": "Waits until the element ``locator`` disappears from the current page.\n\n Fails if ``timeout`` expires before the element disappears. See\n the `Timeouts` section for more information about using timeouts and\n their default value and the `Locating elements` section for details\n about the locator syntax.\n\n ``error`` can be used to override the default error message.\n\n The ``limit`` argument can used to define how many elements the\n page should not contain. When ``limit`` is `None` (default) page can`t\n contain any elements. When limit is a number, page must not\n contain same number of elements.\n\n ``limit`` is new in SeleniumLibrary 4.4\n ", + "sha256": "081d0393a8d8f100d9db65f81170222f4a6678fcc2703a3e123c907ef5ade430" + }, + "close_window": { + "name": "close_window", + "doc": "Closes currently opened and selected browser window/tab. ", + "sha256": "8d00f3bcf62126a5fcc61ca14d62631ad918c2993ee9e8f2641cb57595b591bb" + }, + "get_locations": { + "name": "get_locations", + "doc": "Returns and logs URLs of all windows of the selected browser.\n\n *Browser Scope:*\n\n The ``browser`` argument specifies the browser that shall return\n its windows information.\n\n - ``browser`` can be ``index_or_alias`` like in `Switch Browser`.\n\n - If ``browser`` is ``CURRENT`` (default, case-insensitive)\n the currently active browser is selected.\n\n - If ``browser`` is ``ALL`` (case-insensitive)\n the window information of all windows of all opened browsers are returned.", + "sha256": "3e73811fa673371891cffa16aa99f24fa6dbc87ff826d0d84be6d54fc937163c" + }, + "get_window_handles": { + "name": "get_window_handles", + "doc": "Returns all child window handles of the selected browser as a list.\n\n Can be used as a list of windows to exclude with `Select Window`.\n\n How to select the ``browser`` scope of this keyword, see `Get Locations`.\n\n Prior to SeleniumLibrary 3.0, this keyword was named `List Windows`.\n ", + "sha256": "b051b51a36766e2a3c748a2ecbb76ed6516a20cec807a38d29a96f95c5ea7efa" + }, + "get_window_identifiers": { + "name": "get_window_identifiers", + "doc": "Returns and logs id attributes of all windows of the selected browser.\n\n How to select the ``browser`` scope of this keyword, see `Get Locations`.", + "sha256": "9342df3471d9923e299c60511d11006762b1797802153c97ac0451adcdd5e0bf" + }, + "get_window_names": { + "name": "get_window_names", + "doc": "Returns and logs names of all windows of the selected browser.\n\n How to select the ``browser`` scope of this keyword, see `Get Locations`.", + "sha256": "557778bcbb2b4be2e575416f5422c8077397f2e7d7614e3b064fe3f222bf3225" + }, + "get_window_position": { + "name": "get_window_position", + "doc": "Returns current window position.\n\n The position is relative to the top left corner of the screen. Returned\n values are integers. See also `Set Window Position`.\n\n Example:\n | ${x} | ${y}= | `Get Window Position` |\n ", + "sha256": "c9f1ab8ee31517bc91a6ae9f3dd3782c695f0c3c64adf1639fc3e34ea85e7d9c" + }, + "get_window_size": { + "name": "get_window_size", + "doc": "Returns current window width and height as integers.\n\n See also `Set Window Size`.\n\n If ``inner`` parameter is set to True, keyword returns\n HTML DOM window.innerWidth and window.innerHeight properties.\n See `Boolean arguments` for more details on how to set boolean\n arguments. The ``inner`` is new in SeleniumLibrary 4.0.\n\n Example:\n | ${width} | ${height}= | `Get Window Size` | |\n | ${width} | ${height}= | `Get Window Size` | True |\n ", + "sha256": "d9fc8a6bc4dd38749c761722027b783dfd74ff3c69d16ad3e4ceceb162f2ed64" + }, + "get_window_titles": { + "name": "get_window_titles", + "doc": "Returns and logs titles of all windows of the selected browser.\n\n How to select the ``browser`` scope of this keyword, see `Get Locations`.", + "sha256": "7b2a62a9e808f584ec9674faae954855135aec5ac168ec0b929b11ac73f7fcec" + }, + "maximize_browser_window": { + "name": "maximize_browser_window", + "doc": "Maximizes current browser window.", + "sha256": "de016b8b98dc0a25f624060424c8ae449cc680990baf8789da09181b2643d77b" + }, + "minimize_browser_window": { + "name": "minimize_browser_window", + "doc": "Minimizes current browser window.", + "sha256": "6a99ddaa41cde69ae82c33df6d43976d9ad76a358be5d4e35f065895e94e95db" + }, + "set_window_position": { + "name": "set_window_position", + "doc": "Sets window position using ``x`` and ``y`` coordinates.\n\n The position is relative to the top left corner of the screen,\n but some browsers exclude possible task bar set by the operating\n system from the calculation. The actual position may thus be\n different with different browsers.\n\n Values can be given using strings containing numbers or by using\n actual numbers. See also `Get Window Position`.\n\n Example:\n | `Set Window Position` | 100 | 200 |\n ", + "sha256": "d9c3d6dc138cd350941a1660e5601dbc4441ee6c0a7df08902c76dd15953017c" + }, + "set_window_size": { + "name": "set_window_size", + "doc": "Sets current windows size to given ``width`` and ``height``.\n\n Values can be given using strings containing numbers or by using\n actual numbers. See also `Get Window Size`.\n\n Browsers have a limit on their minimum size. Trying to set them\n smaller will cause the actual size to be bigger than the requested\n size.\n\n If ``inner`` parameter is set to True, keyword sets the necessary\n window width and height to have the desired HTML DOM _window.innerWidth_\n and _window.innerHeight_. See `Boolean arguments` for more details on how to set boolean\n arguments.\n\n The ``inner`` argument is new since SeleniumLibrary 4.0.\n\n This ``inner`` argument does not support Frames. If a frame is selected,\n switch to default before running this.\n\n Example:\n | `Set Window Size` | 800 | 600 | |\n | `Set Window Size` | 800 | 600 | True |\n ", + "sha256": "31b5febddcb935b20320728accc28a892b8a0956301646827aa8c7c74e1cdfec" + }, + "switch_window": { + "name": "switch_window", + "doc": "Switches to browser window matching ``locator``.\n\n If the window is found, all subsequent commands use the selected\n window, until this keyword is used again. If the window is not\n found, this keyword fails. The previous windows handle is returned\n and can be used to switch back to it later.\n\n Notice that alerts should be handled with\n `Handle Alert` or other alert related keywords.\n\n The ``locator`` can be specified using different strategies somewhat\n similarly as when `locating elements` on pages.\n\n - By default, the ``locator`` is matched against window handle, name,\n title, and URL. Matching is done in that order and the first\n matching window is selected.\n\n - The ``locator`` can specify an explicit strategy by using the format\n ``strategy:value`` (recommended) or ``strategy=value``. Supported\n strategies are ``name``, ``title``, and ``url``. These matches windows\n using their name, title, or URL, respectively. Additionally, ``default``\n can be used to explicitly use the default strategy explained above.\n\n - If the ``locator`` is ``NEW`` (case-insensitive), the latest\n opened window is selected. It is an error if this is the same\n as the current window.\n\n - If the ``locator`` is ``MAIN`` (default, case-insensitive),\n the main window is selected.\n\n - If the ``locator`` is ``CURRENT`` (case-insensitive), nothing is\n done. This effectively just returns the current window handle.\n\n - If the ``locator`` is not a string, it is expected to be a list\n of window handles _to exclude_. Such a list of excluded windows\n can be got from `Get Window Handles` before doing an action that\n opens a new window.\n\n The ``timeout`` is used to specify how long keyword will poll to select\n the new window. The ``timeout`` is new in SeleniumLibrary 3.2.\n\n Example:\n | `Click Link` | popup1 | | # Open new window |\n | `Switch Window` | example | | # Select window using default strategy |\n | `Title Should Be` | Pop-up 1 | |\n | `Click Button` | popup2 | | # Open another window |\n | ${handle} = | `Switch Window` | NEW | # Select latest opened window |\n | `Title Should Be` | Pop-up 2 | |\n | `Switch Window` | ${handle} | | # Select window using handle |\n | `Title Should Be` | Pop-up 1 | |\n | `Switch Window` | MAIN | | # Select the main window |\n | `Title Should Be` | Main | |\n | ${excludes} = | `Get Window Handles` | | # Get list of current windows |\n | `Click Link` | popup3 | | # Open one more window |\n | `Switch Window` | ${excludes} | | # Select window using excludes |\n | `Title Should Be` | Pop-up 3 | |\n\n The ``browser`` argument allows with ``index_or_alias`` to implicitly switch to\n a specific browser when switching to a window. See `Switch Browser`\n\n - If the ``browser`` is ``CURRENT`` (case-insensitive), no other browser is\n selected.\n\n *NOTE:*\n\n - The ``strategy:value`` syntax is only supported by SeleniumLibrary\n 3.0 and newer.\n - Prior to SeleniumLibrary 3.0 matching windows by name, title\n and URL was case-insensitive.\n - Earlier versions supported aliases ``None``, ``null`` and the\n empty string for selecting the main window, and alias ``self``\n for selecting the current window. Support for these aliases was\n removed in SeleniumLibrary 3.2.\n ", + "sha256": "2ae583a5179810f31a4f7ae665918443d1f068c53e255c552b51bd1f5205c608" + }, + "__init__": { + "name": "__init__", + "doc": "1 SeleniumLibrary is a web testing library for Robot Framework.\n\nThis document explains how to use keywords provided by SeleniumLibrary.\nFor information about installation, support, and more, please visit the\n[https://github.com/robotframework/SeleniumLibrary|project pages].\nFor more information about Robot Framework, see http://robotframework.org.\n\nSeleniumLibrary uses the Selenium WebDriver modules internally to\ncontrol a web browser. See http://seleniumhq.org for more information\nabout Selenium in general and SeleniumLibrary README.rst\n[https://github.com/robotframework/SeleniumLibrary#browser-drivers|Browser drivers chapter]\nfor more details about WebDriver binary installation.\n\n%TOC%\n\n= Locating elements =\n\nAll keywords in SeleniumLibrary that need to interact with an element\non a web page take an argument typically named ``locator`` that specifies\nhow to find the element. Most often the locator is given as a string\nusing the locator syntax described below, but `using WebElements` is\npossible too.\n\n== Locator syntax ==\n\nSeleniumLibrary supports finding elements based on different strategies\nsuch as the element id, XPath expressions, or CSS selectors. The strategy\ncan either be explicitly specified with a prefix or the strategy can be\nimplicit.\n\n=== Default locator strategy ===\n\nBy default, locators are considered to use the keyword specific default\nlocator strategy. All keywords support finding elements based on ``id``\nand ``name`` attributes, but some keywords support additional attributes\nor other values that make sense in their context. For example, `Click\nLink` supports the ``href`` attribute and the link text and addition\nto the normal ``id`` and ``name``.\n\nExamples:\n\n| `Click Element` | example | # Match based on ``id`` or ``name``. |\n| `Click Link` | example | # Match also based on link text and ``href``. |\n| `Click Button` | example | # Match based on ``id``, ``name`` or ``value``. |\n\nIf a locator accidentally starts with a prefix recognized as `explicit\nlocator strategy` or `implicit XPath strategy`, it is possible to use\nthe explicit ``default`` prefix to enable the default strategy.\n\nExamples:\n\n| `Click Element` | name:foo | # Find element with name ``foo``. |\n| `Click Element` | default:name:foo | # Use default strategy with value ``name:foo``. |\n| `Click Element` | //foo | # Find element using XPath ``//foo``. |\n| `Click Element` | default: //foo | # Use default strategy with value ``//foo``. |\n\n=== Explicit locator strategy ===\n\nThe explicit locator strategy is specified with a prefix using either\nsyntax ``strategy:value`` or ``strategy=value``. The former syntax\nis preferred because the latter is identical to Robot Framework's\n[http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#named-argument-syntax|\nnamed argument syntax] and that can cause problems. Spaces around\nthe separator are ignored, so ``id:foo``, ``id: foo`` and ``id : foo``\nare all equivalent.\n\nLocator strategies that are supported by default are listed in the table\nbelow. In addition to them, it is possible to register `custom locators`.\n\n| = Strategy = | = Match based on = | = Example = |\n| id | Element ``id``. | ``id:example`` |\n| name | ``name`` attribute. | ``name:example`` |\n| identifier | Either ``id`` or ``name``. | ``identifier:example`` |\n| class | Element ``class``. | ``class:example`` |\n| tag | Tag name. | ``tag:div`` |\n| xpath | XPath expression. | ``xpath://div[@id=\"example\"]`` |\n| css | CSS selector. | ``css:div#example`` |\n| dom | DOM expression. | ``dom:document.images[5]`` |\n| link | Exact text a link has. | ``link:The example`` |\n| partial link | Partial link text. | ``partial link:he ex`` |\n| sizzle | Sizzle selector deprecated. | ``sizzle:div.example`` |\n| data | Element ``data-*`` attribute | ``data:id:my_id`` |\n| jquery | jQuery expression. | ``jquery:div.example`` |\n| default | Keyword specific default behavior. | ``default:example`` |\n\nSee the `Default locator strategy` section below for more information\nabout how the default strategy works. Using the explicit ``default``\nprefix is only necessary if the locator value itself accidentally\nmatches some of the explicit strategies.\n\nDifferent locator strategies have different pros and cons. Using ids,\neither explicitly like ``id:foo`` or by using the `default locator\nstrategy` simply like ``foo``, is recommended when possible, because\nthe syntax is simple and locating elements by id is fast for browsers.\nIf an element does not have an id or the id is not stable, other\nsolutions need to be used. If an element has a unique tag name or class,\nusing ``tag``, ``class`` or ``css`` strategy like ``tag:h1``,\n``class:example`` or ``css:h1.example`` is often an easy solution. In\nmore complex cases using XPath expressions is typically the best\napproach. They are very powerful but a downside is that they can also\nget complex.\n\nExamples:\n\n| `Click Element` | id:foo | # Element with id 'foo'. |\n| `Click Element` | css:div#foo h1 | # h1 element under div with id 'foo'. |\n| `Click Element` | xpath: //div[@id=\"foo\"]//h1 | # Same as the above using XPath, not CSS. |\n| `Click Element` | xpath: //*[contains(text(), \"example\")] | # Element containing text 'example'. |\n\n*NOTE:*\n\n- The ``strategy:value`` syntax is only supported by SeleniumLibrary 3.0\n and newer.\n- Using the ``sizzle`` strategy or its alias ``jquery`` requires that\n the system under test contains the jQuery library.\n- Prior to SeleniumLibrary 3.0, table related keywords only supported\n ``xpath``, ``css`` and ``sizzle/jquery`` strategies.\n- ``data`` strategy is conveniance locator that will construct xpath from the parameters.\n If you have element like `
`, you locate the element via\n ``data:automation:automation-id-2``. This feature was added in SeleniumLibrary 5.2.0\n\n=== Implicit XPath strategy ===\n\nIf the locator starts with ``//`` or multiple opening parenthesis in front\nof the ``//``, the locator is considered to be an XPath expression. In other\nwords, using ``//div`` is equivalent to using explicit ``xpath://div`` and\n``((//div))`` is equivalent to using explicit ``xpath:((//div))``\n\nExamples:\n\n| `Click Element` | //div[@id=\"foo\"]//h1 |\n| `Click Element` | (//div)[2] |\n\nThe support for the ``(//`` prefix is new in SeleniumLibrary 3.0.\nSupporting multiple opening parenthesis is new in SeleniumLibrary 5.0.\n\n=== Chaining locators ===\n\nIt is possible chain multiple locators together as single locator. Each chained locator must start with locator\nstrategy. Chained locators must be separated with single space, two greater than characters and followed with\nspace. It is also possible mix different locator strategies, example css or xpath. Also a list can also be\nused to specify multiple locators. This is useful, is some part of locator would match as the locator separator\nbut it should not. Or if there is need to existing WebElement as locator.\n\nAlthough all locators support chaining, some locator strategies do not abey the chaining. This is because\nsome locator strategies use JavaScript to find elements and JavaScript is executed for the whole browser context\nand not for the element found be the previous locator. Chaining is supported by locator strategies which\nare based on Selenium API, like `xpath` or `css`, but example chaining is not supported by `sizzle` or `jquery\n\nExamples:\n| `Click Element` | css:.bar >> xpath://a | # To find a link which is present after an element with class \"bar\" |\n\nList examples:\n| ${locator_list} = | `Create List` | css:div#div_id | xpath://*[text(), \" >> \"] |\n| `Page Should Contain Element` | ${locator_list} | | |\n| ${element} = | Get WebElement | xpath://*[text(), \" >> \"] | |\n| ${locator_list} = | `Create List` | css:div#div_id | ${element} |\n| `Page Should Contain Element` | ${locator_list} | | |\n\nChaining locators in new in SeleniumLibrary 5.0\n\n== Using WebElements ==\n\nIn addition to specifying a locator as a string, it is possible to use\nSelenium's WebElement objects. This requires first getting a WebElement,\nfor example, by using the `Get WebElement` keyword.\n\n| ${elem} = | `Get WebElement` | id:example |\n| `Click Element` | ${elem} | |\n\n== Custom locators ==\n\nIf more complex lookups are required than what is provided through the\ndefault locators, custom lookup strategies can be created. Using custom\nlocators is a two part process. First, create a keyword that returns\na WebElement that should be acted on:\n\n| Custom Locator Strategy | [Arguments] | ${browser} | ${locator} | ${tag} | ${constraints} |\n| | ${element}= | Execute Javascript | return window.document.getElementById('${locator}'); |\n| | [Return] | ${element} |\n\nThis keyword is a reimplementation of the basic functionality of the\n``id`` locator where ``${browser}`` is a reference to a WebDriver\ninstance and ``${locator}`` is the name of the locator strategy. To use\nthis locator, it must first be registered by using the\n`Add Location Strategy` keyword:\n\n| `Add Location Strategy` | custom | Custom Locator Strategy |\n\nThe first argument of `Add Location Strategy` specifies the name of\nthe strategy and it must be unique. After registering the strategy,\nthe usage is the same as with other locators:\n\n| `Click Element` | custom:example |\n\nSee the `Add Location Strategy` keyword for more details.\n\n= Browser and Window =\n\nThere is different conceptual meaning when SeleniumLibrary talks\nabout windows or browsers. This chapter explains those differences.\n\n== Browser ==\n\nWhen `Open Browser` or `Create WebDriver` keyword is called, it\nwill create a new Selenium WebDriver instance by using the\n[https://www.seleniumhq.org/docs/03_webdriver.jsp|Selenium WebDriver]\nAPI. In SeleniumLibrary terms, a new browser is created. It is\npossible to start multiple independent browsers (Selenium Webdriver\ninstances) at the same time, by calling `Open Browser` or\n`Create WebDriver` multiple times. These browsers are usually\nindependent of each other and do not share data like cookies,\nsessions or profiles. Typically when the browser starts, it\ncreates a single window which is shown to the user.\n\n== Window ==\n\nWindows are the part of a browser that loads the web site and presents\nit to the user. All content of the site is the content of the window.\nWindows are children of a browser. In SeleniumLibrary browser is a\nsynonym for WebDriver instance. One browser may have multiple\nwindows. Windows can appear as tabs, as separate windows or pop-ups with\ndifferent position and size. Windows belonging to the same browser\ntypically share the sessions detail, like cookies. If there is a\nneed to separate sessions detail, example login with two different\nusers, two browsers (Selenium WebDriver instances) must be created.\nNew windows can be opened example by the application under test or\nby example `Execute Javascript` keyword:\n\n| `Execute Javascript` window.open() # Opens a new window with location about:blank\n\nThe example below opens multiple browsers and windows,\nto demonstrate how the different keywords can be used to interact\nwith browsers, and windows attached to these browsers.\n\nStructure:\n| BrowserA\n| Window 1 (location=https://robotframework.org/)\n| Window 2 (location=https://robocon.io/)\n| Window 3 (location=https://github.com/robotframework/)\n|\n| BrowserB\n| Window 1 (location=https://github.com/)\n\nExample:\n| `Open Browser` | https://robotframework.org | ${BROWSER} | alias=BrowserA | # BrowserA with first window is opened. |\n| `Execute Javascript` | window.open() | | | # In BrowserA second window is opened. |\n| `Switch Window` | locator=NEW | | | # Switched to second window in BrowserA |\n| `Go To` | https://robocon.io | | | # Second window navigates to robocon site. |\n| `Execute Javascript` | window.open() | | | # In BrowserA third window is opened. |\n| ${handle} | `Switch Window` | locator=NEW | | # Switched to third window in BrowserA |\n| `Go To` | https://github.com/robotframework/ | | | # Third windows goes to robot framework github site. |\n| `Open Browser` | https://github.com | ${BROWSER} | alias=BrowserB | # BrowserB with first windows is opened. |\n| ${location} | `Get Location` | | | # ${location} is: https://www.github.com |\n| `Switch Window` | ${handle} | browser=BrowserA | | # BrowserA second windows is selected. |\n| ${location} | `Get Location` | | | # ${location} = https://robocon.io/ |\n| @{locations 1} | `Get Locations` | | | # By default, lists locations under the currectly active browser (BrowserA). |\n| @{locations 2} | `Get Locations` | browser=ALL | | # By using browser=ALL argument keyword list all locations from all browsers. |\n\nThe above example, @{locations 1} contains the following items:\nhttps://robotframework.org/, https://robocon.io/ and\nhttps://github.com/robotframework/'. The @{locations 2}\ncontains the following items: https://robotframework.org/,\nhttps://robocon.io/, https://github.com/robotframework/'\nand 'https://github.com/.\n\n= Timeouts, waits, and delays =\n\nThis section discusses different ways how to wait for elements to\nappear on web pages and to slow down execution speed otherwise.\nIt also explains the `time format` that can be used when setting various\ntimeouts, waits, and delays.\n\n== Timeout ==\n\nSeleniumLibrary contains various keywords that have an optional\n``timeout`` argument that specifies how long these keywords should\nwait for certain events or actions. These keywords include, for example,\n``Wait ...`` keywords and keywords related to alerts. Additionally\n`Execute Async Javascript`. Although it does not have ``timeout``,\nargument, uses a timeout to define how long asynchronous JavaScript\ncan run.\n\nThe default timeout these keywords use can be set globally either by\nusing the `Set Selenium Timeout` keyword or with the ``timeout`` argument\nwhen `importing` the library. If no default timeout is set globally, the\ndefault is 5 seconds. If None is specified for the timeout argument in the\nkeywords, the default is used. See `time format` below for supported\ntimeout syntax.\n\n== Implicit wait ==\n\nImplicit wait specifies the maximum time how long Selenium waits when\nsearching for elements. It can be set by using the `Set Selenium Implicit\nWait` keyword or with the ``implicit_wait`` argument when `importing`\nthe library. See [https://www.seleniumhq.org/docs/04_webdriver_advanced.jsp|\nSelenium documentation] for more information about this functionality.\n\nSee `time format` below for supported syntax.\n\n== Page load ==\nPage load timeout is the amount of time to wait for page load to complete\nuntil a timeout exception is raised.\n\nThe default page load timeout can be set globally\nwhen `importing` the library with the ``page_load_timeout`` argument\nor by using the `Set Selenium Page Load Timeout` keyword.\n\nSee `time format` below for supported timeout syntax.\n\nSupport for page load is new in SeleniumLibrary 6.1\n\n== Selenium speed ==\n\nSelenium execution speed can be slowed down globally by using `Set\nSelenium speed` keyword. This functionality is designed to be used for\ndemonstrating or debugging purposes. Using it to make sure that elements\nappear on a page is not a good idea. The above-explained timeouts\nand waits should be used instead.\n\nSee `time format` below for supported syntax.\n\n== Time format ==\n\nAll timeouts and waits can be given as numbers considered seconds\n(e.g. ``0.5`` or ``42``) or in Robot Framework's time syntax\n(e.g. ``1.5 seconds`` or ``1 min 30 s``). For more information about\nthe time syntax see the\n[http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#time-format|Robot Framework User Guide].\n\n= Run-on-failure functionality =\n\nSeleniumLibrary has a handy feature that it can automatically execute\na keyword if any of its own keywords fails. By default, it uses the\n`Capture Page Screenshot` keyword, but this can be changed either by\nusing the `Register Keyword To Run On Failure` keyword or with the\n``run_on_failure`` argument when `importing` the library. It is\npossible to use any keyword from any imported library or resource file.\n\nThe run-on-failure functionality can be disabled by using a special value\n``NOTHING`` or anything considered false (see `Boolean arguments`)\nsuch as ``NONE``.\n\n= Boolean arguments =\n\nStarting from 5.0 SeleniumLibrary relies on Robot Framework to perform the\nboolean conversion based on keyword arguments [https://docs.python.org/3/library/typing.html|type hint].\nMore details in Robot Framework\n[http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#supported-conversions|user guide]\n\nPlease note SeleniumLibrary 3 and 4 did have own custom methods to covert\narguments to boolean values.\n\n= EventFiringWebDriver =\n\nThe SeleniumLibrary offers support for\n[https://seleniumhq.github.io/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.event_firing_webdriver.html#module-selenium.webdriver.support.event_firing_webdriver|EventFiringWebDriver].\nSee the Selenium and SeleniumLibrary\n[https://github.com/robotframework/SeleniumLibrary/blob/master/docs/extending/extending.rst#EventFiringWebDriver|EventFiringWebDriver support]\ndocumentation for further details.\n\nEventFiringWebDriver is new in SeleniumLibrary 4.0\n\n= Thread support =\n\nSeleniumLibrary is not thread-safe. This is mainly due because the underlying\n[https://github.com/SeleniumHQ/selenium/wiki/Frequently-Asked-Questions#q-is-webdriver-thread-safe|\nSelenium tool is not thread-safe] within one browser/driver instance.\nBecause of the limitation in the Selenium side, the keywords or the\nAPI provided by the SeleniumLibrary is not thread-safe.\n\n= Plugins =\n\nSeleniumLibrary offers plugins as a way to modify and add library keywords and modify some of the internal\nfunctionality without creating a new library or hacking the source code. See\n[https://github.com/robotframework/SeleniumLibrary/blob/master/docs/extending/extending.rst#Plugins|plugin API]\ndocumentation for further details.\n\nPlugin API is new SeleniumLibrary 4.0", + "sha256": "3d660b78fb0d75d9f2f8265fa6f29967ae30b712f545661d64de0f05f2c1b913" + }, + "__intro__": { + "name": "__intro__", + "doc": "1 SeleniumLibrary is a web testing library for Robot Framework.\n\n This document explains how to use keywords provided by SeleniumLibrary.\n For information about installation, support, and more, please visit the\n [https://github.com/robotframework/SeleniumLibrary|project pages].\n For more information about Robot Framework, see http://robotframework.org.\n\n SeleniumLibrary uses the Selenium WebDriver modules internally to\n control a web browser. See http://seleniumhq.org for more information\n about Selenium in general and SeleniumLibrary README.rst\n [https://github.com/robotframework/SeleniumLibrary#browser-drivers|Browser drivers chapter]\n for more details about WebDriver binary installation.\n\n %TOC%\n\n = Locating elements =\n\n All keywords in SeleniumLibrary that need to interact with an element\n on a web page take an argument typically named ``locator`` that specifies\n how to find the element. Most often the locator is given as a string\n using the locator syntax described below, but `using WebElements` is\n possible too.\n\n == Locator syntax ==\n\n SeleniumLibrary supports finding elements based on different strategies\n such as the element id, XPath expressions, or CSS selectors. The strategy\n can either be explicitly specified with a prefix or the strategy can be\n implicit.\n\n === Default locator strategy ===\n\n By default, locators are considered to use the keyword specific default\n locator strategy. All keywords support finding elements based on ``id``\n and ``name`` attributes, but some keywords support additional attributes\n or other values that make sense in their context. For example, `Click\n Link` supports the ``href`` attribute and the link text and addition\n to the normal ``id`` and ``name``.\n\n Examples:\n\n | `Click Element` | example | # Match based on ``id`` or ``name``. |\n | `Click Link` | example | # Match also based on link text and ``href``. |\n | `Click Button` | example | # Match based on ``id``, ``name`` or ``value``. |\n\n If a locator accidentally starts with a prefix recognized as `explicit\n locator strategy` or `implicit XPath strategy`, it is possible to use\n the explicit ``default`` prefix to enable the default strategy.\n\n Examples:\n\n | `Click Element` | name:foo | # Find element with name ``foo``. |\n | `Click Element` | default:name:foo | # Use default strategy with value ``name:foo``. |\n | `Click Element` | //foo | # Find element using XPath ``//foo``. |\n | `Click Element` | default: //foo | # Use default strategy with value ``//foo``. |\n\n === Explicit locator strategy ===\n\n The explicit locator strategy is specified with a prefix using either\n syntax ``strategy:value`` or ``strategy=value``. The former syntax\n is preferred because the latter is identical to Robot Framework's\n [http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#named-argument-syntax|\n named argument syntax] and that can cause problems. Spaces around\n the separator are ignored, so ``id:foo``, ``id: foo`` and ``id : foo``\n are all equivalent.\n\n Locator strategies that are supported by default are listed in the table\n below. In addition to them, it is possible to register `custom locators`.\n\n | = Strategy = | = Match based on = | = Example = |\n | id | Element ``id``. | ``id:example`` |\n | name | ``name`` attribute. | ``name:example`` |\n | identifier | Either ``id`` or ``name``. | ``identifier:example`` |\n | class | Element ``class``. | ``class:example`` |\n | tag | Tag name. | ``tag:div`` |\n | xpath | XPath expression. | ``xpath://div[@id=\"example\"]`` |\n | css | CSS selector. | ``css:div#example`` |\n | dom | DOM expression. | ``dom:document.images[5]`` |\n | link | Exact text a link has. | ``link:The example`` |\n | partial link | Partial link text. | ``partial link:he ex`` |\n | sizzle | Sizzle selector deprecated. | ``sizzle:div.example`` |\n | data | Element ``data-*`` attribute | ``data:id:my_id`` |\n | jquery | jQuery expression. | ``jquery:div.example`` |\n | default | Keyword specific default behavior. | ``default:example`` |\n\n See the `Default locator strategy` section below for more information\n about how the default strategy works. Using the explicit ``default``\n prefix is only necessary if the locator value itself accidentally\n matches some of the explicit strategies.\n\n Different locator strategies have different pros and cons. Using ids,\n either explicitly like ``id:foo`` or by using the `default locator\n strategy` simply like ``foo``, is recommended when possible, because\n the syntax is simple and locating elements by id is fast for browsers.\n If an element does not have an id or the id is not stable, other\n solutions need to be used. If an element has a unique tag name or class,\n using ``tag``, ``class`` or ``css`` strategy like ``tag:h1``,\n ``class:example`` or ``css:h1.example`` is often an easy solution. In\n more complex cases using XPath expressions is typically the best\n approach. They are very powerful but a downside is that they can also\n get complex.\n\n Examples:\n\n | `Click Element` | id:foo | # Element with id 'foo'. |\n | `Click Element` | css:div#foo h1 | # h1 element under div with id 'foo'. |\n | `Click Element` | xpath: //div[@id=\"foo\"]//h1 | # Same as the above using XPath, not CSS. |\n | `Click Element` | xpath: //*[contains(text(), \"example\")] | # Element containing text 'example'. |\n\n *NOTE:*\n\n - The ``strategy:value`` syntax is only supported by SeleniumLibrary 3.0\n and newer.\n - Using the ``sizzle`` strategy or its alias ``jquery`` requires that\n the system under test contains the jQuery library.\n - Prior to SeleniumLibrary 3.0, table related keywords only supported\n ``xpath``, ``css`` and ``sizzle/jquery`` strategies.\n - ``data`` strategy is conveniance locator that will construct xpath from the parameters.\n If you have element like `
`, you locate the element via\n ``data:automation:automation-id-2``. This feature was added in SeleniumLibrary 5.2.0\n\n === Implicit XPath strategy ===\n\n If the locator starts with ``//`` or multiple opening parenthesis in front\n of the ``//``, the locator is considered to be an XPath expression. In other\n words, using ``//div`` is equivalent to using explicit ``xpath://div`` and\n ``((//div))`` is equivalent to using explicit ``xpath:((//div))``\n\n Examples:\n\n | `Click Element` | //div[@id=\"foo\"]//h1 |\n | `Click Element` | (//div)[2] |\n\n The support for the ``(//`` prefix is new in SeleniumLibrary 3.0.\n Supporting multiple opening parenthesis is new in SeleniumLibrary 5.0.\n\n === Chaining locators ===\n\n It is possible chain multiple locators together as single locator. Each chained locator must start with locator\n strategy. Chained locators must be separated with single space, two greater than characters and followed with\n space. It is also possible mix different locator strategies, example css or xpath. Also a list can also be\n used to specify multiple locators. This is useful, is some part of locator would match as the locator separator\n but it should not. Or if there is need to existing WebElement as locator.\n\n Although all locators support chaining, some locator strategies do not abey the chaining. This is because\n some locator strategies use JavaScript to find elements and JavaScript is executed for the whole browser context\n and not for the element found be the previous locator. Chaining is supported by locator strategies which\n are based on Selenium API, like `xpath` or `css`, but example chaining is not supported by `sizzle` or `jquery\n\n Examples:\n | `Click Element` | css:.bar >> xpath://a | # To find a link which is present after an element with class \"bar\" |\n\n List examples:\n | ${locator_list} = | `Create List` | css:div#div_id | xpath://*[text(), \" >> \"] |\n | `Page Should Contain Element` | ${locator_list} | | |\n | ${element} = | Get WebElement | xpath://*[text(), \" >> \"] | |\n | ${locator_list} = | `Create List` | css:div#div_id | ${element} |\n | `Page Should Contain Element` | ${locator_list} | | |\n\n Chaining locators in new in SeleniumLibrary 5.0\n\n == Using WebElements ==\n\n In addition to specifying a locator as a string, it is possible to use\n Selenium's WebElement objects. This requires first getting a WebElement,\n for example, by using the `Get WebElement` keyword.\n\n | ${elem} = | `Get WebElement` | id:example |\n | `Click Element` | ${elem} | |\n\n == Custom locators ==\n\n If more complex lookups are required than what is provided through the\n default locators, custom lookup strategies can be created. Using custom\n locators is a two part process. First, create a keyword that returns\n a WebElement that should be acted on:\n\n | Custom Locator Strategy | [Arguments] | ${browser} | ${locator} | ${tag} | ${constraints} |\n | | ${element}= | Execute Javascript | return window.document.getElementById('${locator}'); |\n | | [Return] | ${element} |\n\n This keyword is a reimplementation of the basic functionality of the\n ``id`` locator where ``${browser}`` is a reference to a WebDriver\n instance and ``${locator}`` is the name of the locator strategy. To use\n this locator, it must first be registered by using the\n `Add Location Strategy` keyword:\n\n | `Add Location Strategy` | custom | Custom Locator Strategy |\n\n The first argument of `Add Location Strategy` specifies the name of\n the strategy and it must be unique. After registering the strategy,\n the usage is the same as with other locators:\n\n | `Click Element` | custom:example |\n\n See the `Add Location Strategy` keyword for more details.\n\n = Browser and Window =\n\n There is different conceptual meaning when SeleniumLibrary talks\n about windows or browsers. This chapter explains those differences.\n\n == Browser ==\n\n When `Open Browser` or `Create WebDriver` keyword is called, it\n will create a new Selenium WebDriver instance by using the\n [https://www.seleniumhq.org/docs/03_webdriver.jsp|Selenium WebDriver]\n API. In SeleniumLibrary terms, a new browser is created. It is\n possible to start multiple independent browsers (Selenium Webdriver\n instances) at the same time, by calling `Open Browser` or\n `Create WebDriver` multiple times. These browsers are usually\n independent of each other and do not share data like cookies,\n sessions or profiles. Typically when the browser starts, it\n creates a single window which is shown to the user.\n\n == Window ==\n\n Windows are the part of a browser that loads the web site and presents\n it to the user. All content of the site is the content of the window.\n Windows are children of a browser. In SeleniumLibrary browser is a\n synonym for WebDriver instance. One browser may have multiple\n windows. Windows can appear as tabs, as separate windows or pop-ups with\n different position and size. Windows belonging to the same browser\n typically share the sessions detail, like cookies. If there is a\n need to separate sessions detail, example login with two different\n users, two browsers (Selenium WebDriver instances) must be created.\n New windows can be opened example by the application under test or\n by example `Execute Javascript` keyword:\n\n | `Execute Javascript` window.open() # Opens a new window with location about:blank\n\n The example below opens multiple browsers and windows,\n to demonstrate how the different keywords can be used to interact\n with browsers, and windows attached to these browsers.\n\n Structure:\n | BrowserA\n | Window 1 (location=https://robotframework.org/)\n | Window 2 (location=https://robocon.io/)\n | Window 3 (location=https://github.com/robotframework/)\n |\n | BrowserB\n | Window 1 (location=https://github.com/)\n\n Example:\n | `Open Browser` | https://robotframework.org | ${BROWSER} | alias=BrowserA | # BrowserA with first window is opened. |\n | `Execute Javascript` | window.open() | | | # In BrowserA second window is opened. |\n | `Switch Window` | locator=NEW | | | # Switched to second window in BrowserA |\n | `Go To` | https://robocon.io | | | # Second window navigates to robocon site. |\n | `Execute Javascript` | window.open() | | | # In BrowserA third window is opened. |\n | ${handle} | `Switch Window` | locator=NEW | | # Switched to third window in BrowserA |\n | `Go To` | https://github.com/robotframework/ | | | # Third windows goes to robot framework github site. |\n | `Open Browser` | https://github.com | ${BROWSER} | alias=BrowserB | # BrowserB with first windows is opened. |\n | ${location} | `Get Location` | | | # ${location} is: https://www.github.com |\n | `Switch Window` | ${handle} | browser=BrowserA | | # BrowserA second windows is selected. |\n | ${location} | `Get Location` | | | # ${location} = https://robocon.io/ |\n | @{locations 1} | `Get Locations` | | | # By default, lists locations under the currectly active browser (BrowserA). |\n | @{locations 2} | `Get Locations` | browser=ALL | | # By using browser=ALL argument keyword list all locations from all browsers. |\n\n The above example, @{locations 1} contains the following items:\n https://robotframework.org/, https://robocon.io/ and\n https://github.com/robotframework/'. The @{locations 2}\n contains the following items: https://robotframework.org/,\n https://robocon.io/, https://github.com/robotframework/'\n and 'https://github.com/.\n\n = Timeouts, waits, and delays =\n\n This section discusses different ways how to wait for elements to\n appear on web pages and to slow down execution speed otherwise.\n It also explains the `time format` that can be used when setting various\n timeouts, waits, and delays.\n\n == Timeout ==\n\n SeleniumLibrary contains various keywords that have an optional\n ``timeout`` argument that specifies how long these keywords should\n wait for certain events or actions. These keywords include, for example,\n ``Wait ...`` keywords and keywords related to alerts. Additionally\n `Execute Async Javascript`. Although it does not have ``timeout``,\n argument, uses a timeout to define how long asynchronous JavaScript\n can run.\n\n The default timeout these keywords use can be set globally either by\n using the `Set Selenium Timeout` keyword or with the ``timeout`` argument\n when `importing` the library. If no default timeout is set globally, the\n default is 5 seconds. If None is specified for the timeout argument in the\n keywords, the default is used. See `time format` below for supported\n timeout syntax.\n\n == Implicit wait ==\n\n Implicit wait specifies the maximum time how long Selenium waits when\n searching for elements. It can be set by using the `Set Selenium Implicit\n Wait` keyword or with the ``implicit_wait`` argument when `importing`\n the library. See [https://www.seleniumhq.org/docs/04_webdriver_advanced.jsp|\n Selenium documentation] for more information about this functionality.\n\n See `time format` below for supported syntax.\n\n == Page load ==\n Page load timeout is the amount of time to wait for page load to complete\n until a timeout exception is raised.\n\n The default page load timeout can be set globally\n when `importing` the library with the ``page_load_timeout`` argument\n or by using the `Set Selenium Page Load Timeout` keyword.\n\n See `time format` below for supported timeout syntax.\n\n Support for page load is new in SeleniumLibrary 6.1\n\n == Selenium speed ==\n\n Selenium execution speed can be slowed down globally by using `Set\n Selenium speed` keyword. This functionality is designed to be used for\n demonstrating or debugging purposes. Using it to make sure that elements\n appear on a page is not a good idea. The above-explained timeouts\n and waits should be used instead.\n\n See `time format` below for supported syntax.\n\n == Time format ==\n\n All timeouts and waits can be given as numbers considered seconds\n (e.g. ``0.5`` or ``42``) or in Robot Framework's time syntax\n (e.g. ``1.5 seconds`` or ``1 min 30 s``). For more information about\n the time syntax see the\n [http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#time-format|Robot Framework User Guide].\n\n = Run-on-failure functionality =\n\n SeleniumLibrary has a handy feature that it can automatically execute\n a keyword if any of its own keywords fails. By default, it uses the\n `Capture Page Screenshot` keyword, but this can be changed either by\n using the `Register Keyword To Run On Failure` keyword or with the\n ``run_on_failure`` argument when `importing` the library. It is\n possible to use any keyword from any imported library or resource file.\n\n The run-on-failure functionality can be disabled by using a special value\n ``NOTHING`` or anything considered false (see `Boolean arguments`)\n such as ``NONE``.\n\n = Boolean arguments =\n\n Starting from 5.0 SeleniumLibrary relies on Robot Framework to perform the\n boolean conversion based on keyword arguments [https://docs.python.org/3/library/typing.html|type hint].\n More details in Robot Framework\n [http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#supported-conversions|user guide]\n\n Please note SeleniumLibrary 3 and 4 did have own custom methods to covert\n arguments to boolean values.\n\n = EventFiringWebDriver =\n\n The SeleniumLibrary offers support for\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.event_firing_webdriver.html#module-selenium.webdriver.support.event_firing_webdriver|EventFiringWebDriver].\n See the Selenium and SeleniumLibrary\n [https://github.com/robotframework/SeleniumLibrary/blob/master/docs/extending/extending.rst#EventFiringWebDriver|EventFiringWebDriver support]\n documentation for further details.\n\n EventFiringWebDriver is new in SeleniumLibrary 4.0\n\n = Thread support =\n\n SeleniumLibrary is not thread-safe. This is mainly due because the underlying\n [https://github.com/SeleniumHQ/selenium/wiki/Frequently-Asked-Questions#q-is-webdriver-thread-safe|\n Selenium tool is not thread-safe] within one browser/driver instance.\n Because of the limitation in the Selenium side, the keywords or the\n API provided by the SeleniumLibrary is not thread-safe.\n\n = Plugins =\n\n SeleniumLibrary offers plugins as a way to modify and add library keywords and modify some of the internal\n functionality without creating a new library or hacking the source code. See\n [https://github.com/robotframework/SeleniumLibrary/blob/master/docs/extending/extending.rst#Plugins|plugin API]\n documentation for further details.\n\n Plugin API is new SeleniumLibrary 4.0\n ", + "sha256": "59c13272c5a498ee00aa6f3e5e2d1f9cec5c355267e1b03f88c604f15dab6c4e" + } +} \ No newline at end of file diff --git a/utest/test/robotframework_seleniumlibrary_translation_list/translate2.json b/utest/test/robotframework_seleniumlibrary_translation_list/translate2.json new file mode 100644 index 000000000..f5698eed2 --- /dev/null +++ b/utest/test/robotframework_seleniumlibrary_translation_list/translate2.json @@ -0,0 +1,917 @@ +{ + "alert_should_be_present": { + "name": "2 alert_should_be_present", + "doc": "2 Verifies that an alert is present and by default, accepts it.\n\n Fails if no alert is present. If ``text`` is a non-empty string,\n then it is used to verify alert's message. The alert is accepted\n by default, but that behavior can be controlled by using the\n ``action`` argument same way as with `Handle Alert`.\n\n ``timeout`` specifies how long to wait for the alert to appear.\n If it is not given, the global default `timeout` is used instead.\n\n ``action`` and ``timeout`` arguments are new in SeleniumLibrary 3.0.\n In earlier versions, the alert was always accepted and a timeout was\n hardcoded to one second.\n ", + "sha256": "c2389ab996f30509c4a5951f32dcfe2c8630040e00cedba19e19faa76a15299d" + }, + "alert_should_not_be_present": { + "name": "alert_should_not_be_present", + "doc": "Verifies that no alert is present.\n\n If the alert actually exists, the ``action`` argument determines\n how it should be handled. By default, the alert is accepted, but\n it can be also dismissed or left open the same way as with the\n `Handle Alert` keyword.\n\n ``timeout`` specifies how long to wait for the alert to appear.\n By default, is not waited for the alert at all, but a custom time can\n be given if alert may be delayed. See the `time format` section\n for information about the syntax.\n\n New in SeleniumLibrary 3.0.\n ", + "sha256": "75343dfda0a68c40607e961ead1e104553ba074110f33627131125e8c11ecef0" + }, + "handle_alert": { + "name": "hallinnoi_hälytys", + "doc": "Hallinnoi hälytyksen uusi dokkari\n\nToinen rivi", + "sha256": "7620b9059b37d2cb1d5823256d0f71d32d3f66af153d6be8ff5100219d4270d6" + }, + "input_text_into_alert": { + "name": "input_text_into_alert", + "doc": "Types the given ``text`` into an input field in an alert.\n\n The alert is accepted by default, but that behavior can be controlled\n by using the ``action`` argument same way as with `Handle Alert`.\n\n ``timeout`` specifies how long to wait for the alert to appear.\n If it is not given, the global default `timeout` is used instead.\n\n New in SeleniumLibrary 3.0.\n ", + "sha256": "77f522107ebbde4fbcca0e9d1f1e31911dad7f3256ea39d078ed3365cfefbc46" + }, + "close_all_browsers": { + "name": "close_all_browsers", + "doc": "Closes all open browsers and resets the browser cache.\n\n After this keyword, new indexes returned from `Open Browser` keyword\n are reset to 1.\n\n This keyword should be used in test or suite teardown to make sure\n all browsers are closed.\n ", + "sha256": "34bfcab8a0c99c9fc0ebeeaec4432664ab8fbcc99673bd4bb3f9be2e897dbb5b" + }, + "close_browser": { + "name": "close_browser", + "doc": "Closes the current browser.", + "sha256": "a13d34e21bad1e0a76dab6f27c3f8b803825b8996c989f5b106918e27f0d0eb1" + }, + "create_webdriver": { + "name": "create_webdriver", + "doc": "Creates an instance of Selenium WebDriver.\n\n Like `Open Browser`, but allows passing arguments to the created\n WebDriver instance directly. This keyword should only be used if\n the functionality provided by `Open Browser` is not adequate.\n\n ``driver_name`` must be a WebDriver implementation name like Firefox,\n Chrome, Ie, Edge, Safari, or Remote.\n\n The initialized WebDriver can be configured either with a Python\n dictionary ``kwargs`` or by using keyword arguments ``**init_kwargs``.\n These arguments are passed directly to WebDriver without any\n processing. See [https://seleniumhq.github.io/selenium/docs/api/py/api.html|\n Selenium API documentation] for details about the supported arguments.\n\n Examples:\n | # Use proxy with Firefox | | | |\n | ${proxy}= | `Evaluate` | selenium.webdriver.Proxy() | modules=selenium, selenium.webdriver |\n | ${proxy.http_proxy}= | `Set Variable` | localhost:8888 | |\n | `Create Webdriver` | Firefox | proxy=${proxy} | |\n\n Returns the index of this browser instance which can be used later to\n switch back to it. Index starts from 1 and is reset back to it when\n `Close All Browsers` keyword is used. See `Switch Browser` for an\n example.\n ", + "sha256": "c7efa8a6295acc8336de8f8fdccec61b8a19cfc1b091382753929f9d86d2e292" + }, + "get_action_chain_delay": { + "name": "get_action_chain_delay", + "doc": "Gets the currently stored value for chain_delay_value in timestr format.\n ", + "sha256": "167a6689441f92c4099130c03e41a6c1595bcc1a37a207ac0f970b08b1591fdf" + }, + "get_browser_aliases": { + "name": "get_browser_aliases", + "doc": "Returns aliases of all active browser that has an alias as NormalizedDict.\n The dictionary contains the aliases as keys and the index as value.\n This can be accessed as dictionary ``${aliases.key}`` or as list ``@{aliases}[0]``.\n\n Example:\n | `Open Browser` | https://example.com | alias=BrowserA | |\n | `Open Browser` | https://example.com | alias=BrowserB | |\n | &{aliases} | `Get Browser Aliases` | | # &{aliases} = { BrowserA=1|BrowserB=2 } |\n | `Log` | ${aliases.BrowserA} | | # logs ``1`` |\n | FOR | ${alias} | IN | @{aliases} |\n | | `Log` | ${alias} | # logs ``BrowserA`` and ``BrowserB`` |\n | END | | | |\n\n See `Switch Browser` for more information and examples.\n\n New in SeleniumLibrary 4.0\n ", + "sha256": "defef82080de396568467a48c850a3db67484a7b786d8ebd76a3f3ba02c71dff" + }, + "get_browser_ids": { + "name": "get_browser_ids", + "doc": "Returns index of all active browser as list.\n\n Example:\n | @{browser_ids}= | Get Browser Ids | | |\n | FOR | ${id} | IN | @{browser_ids} |\n | | @{window_titles}= | Get Window Titles | browser=${id} |\n | | Log | Browser ${id} has these windows: ${window_titles} | |\n | END | | | |\n\n See `Switch Browser` for more information and examples.\n\n New in SeleniumLibrary 4.0\n ", + "sha256": "c320152b2a66ba066b100fb8c729f3d36c04a5b72ed753b09d29b6e13613a004" + }, + "get_location": { + "name": "get_location", + "doc": "Returns the current browser window URL.", + "sha256": "3dda250c7af426a85b6ec9c6be5ec5b4a4df41d4b2c72f0fa53b905384c29fc1" + }, + "get_selenium_implicit_wait": { + "name": "get_selenium_implicit_wait", + "doc": "Gets the implicit wait value used by Selenium.\n\n The value is returned as a human-readable string like ``1 second``.\n\n See the `Implicit wait` section above for more information.\n ", + "sha256": "f506381005ec3abf34b359df073e602f6589fac8d030a5369156016bbfacfde2" + }, + "get_selenium_page_load_timeout": { + "name": "get_selenium_page_load_timeout", + "doc": "Gets the time to wait for a page load to complete\n before raising a timeout exception.\n\n The value is returned as a human-readable string like ``1 second``.\n\n See the `Page load` section above for more information.\n\n New in SeleniumLibrary 6.1\n ", + "sha256": "18d82c9e55e7d06156a7fcccd2f96ddd6185a4c3625c344073a3f3e33d6e1e72" + }, + "get_selenium_speed": { + "name": "get_selenium_speed", + "doc": "Gets the delay that is waited after each Selenium command.\n\n The value is returned as a human-readable string like ``1 second``.\n\n See the `Selenium Speed` section above for more information.\n ", + "sha256": "e310cfaddced1d3088b673df4c7c469f10d3992116e2fabe048be986462febc5" + }, + "get_selenium_timeout": { + "name": "get_selenium_timeout", + "doc": "Gets the timeout that is used by various keywords.\n\n The value is returned as a human-readable string like ``1 second``.\n\n See the `Timeout` section above for more information.\n ", + "sha256": "9ebe70c2d1751c70d0f646c8c0e91e3c924ae6062c4c961432405b1fa2e0efe3" + }, + "get_session_id": { + "name": "get_session_id", + "doc": "Returns the currently active browser session id.\n\n New in SeleniumLibrary 3.2\n ", + "sha256": "26f4581c49c3930c0bbc7ff188330eff3bdb9822556ed029c8b47e5cb75949d2" + }, + "get_source": { + "name": "get_source", + "doc": "Returns the entire HTML source of the current page or frame.", + "sha256": "186bf0854602fddcbf9400b50a6db19549cfa23171c01e4708702cbfeaf4a921" + }, + "get_title": { + "name": "get_title", + "doc": "Returns the title of the current page.", + "sha256": "15ca2c42f74a7447ac29d6431219afa7b827245f9bd45e8d220c597c8c76ea72" + }, + "go_back": { + "name": "go_back", + "doc": "Simulates the user clicking the back button on their browser.", + "sha256": "c1ad3668ded03441f5e9019fe3e6417d6c0786fad522ef2d126b233112436ae7" + }, + "go_to": { + "name": "go_to", + "doc": "Navigates the current browser window to the provided ``url``.", + "sha256": "c7db5e459ba7a16a1e895bd0a948765b75bfc536284a2a50ac02e7153ccb0450" + }, + "location_should_be": { + "name": "location_should_be", + "doc": "Verifies that the current URL is exactly ``url``.\n\n The ``url`` argument contains the exact url that should exist in browser.\n\n The ``message`` argument can be used to override the default error\n message.\n\n ``message`` argument is new in SeleniumLibrary 3.2.0.\n ", + "sha256": "ea4b77e8386a52d7881a76cc42cf6c7754da4c44f1b54aa8d71467770a919839" + }, + "location_should_contain": { + "name": "location_should_contain", + "doc": "Verifies that the current URL contains ``expected``.\n\n The ``expected`` argument contains the expected value in url.\n\n The ``message`` argument can be used to override the default error\n message.\n\n ``message`` argument is new in SeleniumLibrary 3.2.0.\n ", + "sha256": "be7e648ca2a1f5a7d83f5fe99d0e9aef696f0c645b57985059179476c4d1d0ed" + }, + "log_location": { + "name": "log_location", + "doc": "Logs and returns the current browser window URL.", + "sha256": "ecdeee422f6587f42650730b5d1510d9f207cda56a2346fa3f6245ad62f4bac5" + }, + "log_source": { + "name": "log_source", + "doc": "Logs and returns the HTML source of the current page or frame.\n\n The ``loglevel`` argument defines the used log level. Valid log\n levels are ``WARN``, ``INFO`` (default), ``DEBUG``, ``TRACE``\n and ``NONE`` (no logging).\n ", + "sha256": "ccfb24c918224eb021f3f020cd9dd1375b128835d8295fc0a40d7f76c628d0b7" + }, + "log_title": { + "name": "log_title", + "doc": "Logs and returns the title of the current page.", + "sha256": "3722f0e150770d3b876af7a430c3a0e22f09a3b847c61b467cce146ed64ceea5" + }, + "open_browser": { + "name": "open_browser", + "doc": "Opens a new browser instance to the optional ``url``.\n\n The ``browser`` argument specifies which browser to use. The\n supported browsers are listed in the table below. The browser names\n are case-insensitive and some browsers have multiple supported names.\n\n | = Browser = | = Name(s) = |\n | Firefox | firefox, ff |\n | Google Chrome | googlechrome, chrome, gc |\n | Headless Firefox | headlessfirefox |\n | Headless Chrome | headlesschrome |\n | Internet Explorer | internetexplorer, ie |\n | Edge | edge |\n | Safari | safari |\n\n To be able to actually use one of these browsers, you need to have\n a matching Selenium browser driver available. See the\n [https://github.com/robotframework/SeleniumLibrary#browser-drivers|\n project documentation] for more details. Headless Firefox and\n Headless Chrome are new additions in SeleniumLibrary 3.1.0\n and require Selenium 3.8.0 or newer.\n\n After opening the browser, it is possible to use optional\n ``url`` to navigate the browser to the desired address.\n\n Optional ``alias`` is an alias given for this browser instance and\n it can be used for switching between browsers. When same ``alias``\n is given with two `Open Browser` keywords, the first keyword will\n open a new browser, but the second one will switch to the already\n opened browser and will not open a new browser. The ``alias``\n definition overrules ``browser`` definition. When same ``alias``\n is used but a different ``browser`` is defined, then switch to\n a browser with same alias is done and new browser is not opened.\n An alternative approach for switching is using an index returned\n by this keyword. These indices start from 1, are incremented when new\n browsers are opened, and reset back to 1 when `Close All Browsers`\n is called. See `Switch Browser` for more information and examples.\n\n Optional ``remote_url`` is the URL for a\n [https://github.com/SeleniumHQ/selenium/wiki/Grid2|Selenium Grid].\n\n Optional ``desired_capabilities`` is deprecated and will be ignored. Capabilities of each\n individual browser is now done through options or services. Please refer to those arguments\n for configuring specific browsers.\n\n Optional ``ff_profile_dir`` is the path to the Firefox profile\n directory if you wish to overwrite the default profile Selenium\n uses. Notice that prior to SeleniumLibrary 3.0, the library\n contained its own profile that was used by default. The\n ``ff_profile_dir`` can also be an instance of the\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_firefox/selenium.webdriver.firefox.firefox_profile.html|selenium.webdriver.FirefoxProfile]\n . As a third option, it is possible to use `FirefoxProfile` methods\n and attributes to define the profile using methods and attributes\n in the same way as with ``options`` argument. Example: It is possible\n to use FirefoxProfile `set_preference` to define different\n profile settings. See ``options`` argument documentation in below\n how to handle backslash escaping.\n\n Optional ``options`` argument allows defining browser specific\n Selenium options. Example for Chrome, the ``options`` argument\n allows defining the following\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_chrome/selenium.webdriver.chrome.options.html#selenium.webdriver.chrome.options.Options|methods and attributes]\n and for Firefox these\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_firefox/selenium.webdriver.firefox.options.html?highlight=firefox#selenium.webdriver.firefox.options.Options|methods and attributes]\n are available. Please note that not all browsers, supported by the\n SeleniumLibrary, have Selenium options available. Therefore please\n consult the Selenium documentation which browsers do support\n the Selenium options. Selenium options are also supported, when ``remote_url``\n argument is used.\n\n The SeleniumLibrary ``options`` argument accepts Selenium\n options in two different formats: as a string and as Python object\n which is an instance of the Selenium options class.\n\n The string format allows defining Selenium options methods\n or attributes and their arguments in Robot Framework test data.\n The method and attributes names are case and space sensitive and\n must match to the Selenium options methods and attributes names.\n When defining a method, it must be defined in a similar way as in\n python: method name, opening parenthesis, zero to many arguments\n and closing parenthesis. If there is a need to define multiple\n arguments for a single method, arguments must be separated with\n comma, just like in Python. Example: `add_argument(\"--headless\")`\n or `add_experimental_option(\"key\", \"value\")`. Attributes are\n defined in a similar way as in Python: attribute name, equal sign,\n and attribute value. Example, `headless=True`. Multiple methods\n and attributes must be separated by a semicolon. Example:\n `add_argument(\"--headless\");add_argument(\"--start-maximized\")`.\n\n Arguments allow defining Python data types and arguments are\n evaluated by using Python\n [https://docs.python.org/3/library/ast.html#ast.literal_eval|ast.literal_eval].\n Strings must be quoted with single or double quotes, example \"value\"\n or 'value'. It is also possible to define other Python builtin\n data types, example `True` or `None`, by not using quotes\n around the arguments.\n\n The string format is space friendly. Usually, spaces do not alter\n the defining methods or attributes. There are two exceptions.\n In some Robot Framework test data formats, two or more spaces are\n considered as cell separator and instead of defining a single\n argument, two or more arguments may be defined. Spaces in string\n arguments are not removed and are left as is. Example\n `add_argument ( \"--headless\" )` is same as\n `add_argument(\"--headless\")`. But `add_argument(\" --headless \")` is\n not same same as `add_argument ( \"--headless\" )`, because\n spaces inside of quotes are not removed. Please note that if\n options string contains backslash, example a Windows OS path,\n the backslash needs escaping both in Robot Framework data and\n in Python side. This means single backslash must be writen using\n four backslash characters. Example, Windows path:\n \"C:\\path\\to\\profile\" must be written as\n \"C:\\\\\\\\path\\\\\\to\\\\\\\\profile\". Another way to write\n backslash is use Python\n [https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals|raw strings]\n and example write: r\"C:\\\\path\\\\to\\\\profile\".\n\n As last format, ``options`` argument also supports receiving\n the Selenium options as Python class instance. In this case, the\n instance is used as-is and the SeleniumLibrary will not convert\n the instance to other formats.\n For example, if the following code return value is saved to\n `${options}` variable in the Robot Framework data:\n | options = webdriver.ChromeOptions()\n | options.add_argument('--disable-dev-shm-usage')\n | return options\n\n Then the `${options}` variable can be used as an argument to\n ``options``.\n\n Example the ``options`` argument can be used to launch Chomium-based\n applications which utilize the\n [https://bitbucket.org/chromiumembedded/cef/wiki/UsingChromeDriver|Chromium Embedded Framework]\n . To lauch Chomium-based application, use ``options`` to define\n `binary_location` attribute and use `add_argument` method to define\n `remote-debugging-port` port for the application. Once the browser\n is opened, the test can interact with the embedded web-content of\n the system under test.\n\n Optional ``service_log_path`` argument defines the name of the\n file where to write the browser driver logs. If the\n ``service_log_path`` argument contain a marker ``{index}``, it\n will be automatically replaced with unique running\n index preventing files to be overwritten. Indices start's from 1,\n and how they are represented can be customized using Python's\n [https://docs.python.org/3/library/string.html#format-string-syntax|\n format string syntax].\n\n Optional ``executable_path`` argument defines the path to the driver\n executable, example to a chromedriver or a geckodriver. If not defined\n it is assumed the executable is in the\n [https://en.wikipedia.org/wiki/PATH_(variable)|$PATH].\n\n Examples:\n | `Open Browser` | http://example.com | Chrome | |\n | `Open Browser` | http://example.com | Firefox | alias=Firefox |\n | `Open Browser` | http://example.com | Edge | remote_url=http://127.0.0.1:4444/wd/hub |\n | `Open Browser` | about:blank | | |\n | `Open Browser` | browser=Chrome | | |\n\n Alias examples:\n | ${1_index} = | `Open Browser` | http://example.com | Chrome | alias=Chrome | # Opens new browser because alias is new. |\n | ${2_index} = | `Open Browser` | http://example.com | Firefox | | # Opens new browser because alias is not defined. |\n | ${3_index} = | `Open Browser` | http://example.com | Chrome | alias=Chrome | # Switches to the browser with Chrome alias. |\n | ${4_index} = | `Open Browser` | http://example.com | Chrome | alias=${1_index} | # Switches to the browser with Chrome alias. |\n | Should Be Equal | ${1_index} | ${3_index} | | | |\n | Should Be Equal | ${1_index} | ${4_index} | | | |\n | Should Be Equal | ${2_index} | ${2} | | | |\n\n Example when using\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_chrome/selenium.webdriver.chrome.options.html#selenium.webdriver.chrome.options.Options|Chrome options]\n method:\n | `Open Browser` | http://example.com | Chrome | options=add_argument(\"--disable-popup-blocking\"); add_argument(\"--ignore-certificate-errors\") | # Sting format. |\n | ${options} = | Get Options | | | # Selenium options instance. |\n | `Open Browser` | http://example.com | Chrome | options=${options} | |\n | `Open Browser` | None | Chrome | options=binary_location=\"/path/to/binary\";add_argument(\"remote-debugging-port=port\") | # Start Chomium-based application. |\n | `Open Browser` | None | Chrome | options=binary_location=r\"C:\\\\path\\\\to\\\\binary\" | # Windows OS path escaping. |\n\n Example for FirefoxProfile\n | `Open Browser` | http://example.com | Firefox | ff_profile_dir=/path/to/profile | # Using profile from disk. |\n | `Open Browser` | http://example.com | Firefox | ff_profile_dir=${FirefoxProfile_instance} | # Using instance of FirefoxProfile. |\n | `Open Browser` | http://example.com | Firefox | ff_profile_dir=set_preference(\"key\", \"value\");set_preference(\"other\", \"setting\") | # Defining profile using FirefoxProfile mehtods. |\n\n If the provided configuration options are not enough, it is possible\n to use `Create Webdriver` to customize browser initialization even\n more.\n\n Applying ``desired_capabilities`` argument also for local browser is\n new in SeleniumLibrary 3.1.\n\n Using ``alias`` to decide, is the new browser opened is new\n in SeleniumLibrary 4.0. The ``options`` and ``service_log_path``\n are new in SeleniumLibrary 4.0. Support for ``ff_profile_dir``\n accepting an instance of the `selenium.webdriver.FirefoxProfile`\n and support defining FirefoxProfile with methods and\n attributes are new in SeleniumLibrary 4.0.\n\n Making ``url`` optional is new in SeleniumLibrary 4.1.\n\n The ``executable_path`` argument is new in SeleniumLibrary 4.2.\n ", + "sha256": "0c3f6191eb0bb2f557a3f93ab0c99c6137361091c73d09186c3846208a9ad7ff" + }, + "reload_page": { + "name": "reload_page", + "doc": "Simulates user reloading page.", + "sha256": "29308a1588c11a36ee1e46274959c9fb83b01fa628d38f7d1e60615cfa3c1d54" + }, + "set_action_chain_delay": { + "name": "set_action_chain_delay", + "doc": "Sets the duration of delay in ActionChains() used by SeleniumLibrary.\n\n The value can be given as a number that is considered to be\n seconds or as a human-readable string like ``1 second``.\n\n Value is always stored as milliseconds internally.\n\n The previous value is returned and can be used to restore\n the original value later if needed.\n ", + "sha256": "30a861e88589e077326d025611cd558432a5426b6b002aface8b8367286eca24" + }, + "set_browser_implicit_wait": { + "name": "set_browser_implicit_wait", + "doc": "Sets the implicit wait value used by Selenium.\n\n Same as `Set Selenium Implicit Wait` but only affects the current\n browser.\n ", + "sha256": "a5097a7357967bebd69e46c700917daaa41994d0235b77da90ce0b88d1bd3518" + }, + "set_selenium_implicit_wait": { + "name": "set_selenium_implicit_wait", + "doc": "Sets the implicit wait value used by Selenium.\n\n The value can be given as a number that is considered to be\n seconds or as a human-readable string like ``1 second``.\n The previous value is returned and can be used to restore\n the original value later if needed.\n\n This keyword sets the implicit wait for all opened browsers.\n Use `Set Browser Implicit Wait` to set it only to the current\n browser.\n\n See the `Implicit wait` section above for more information.\n\n Example:\n | ${orig wait} = | `Set Selenium Implicit Wait` | 10 seconds |\n | `Perform AJAX call that is slow` |\n | `Set Selenium Implicit Wait` | ${orig wait} |\n ", + "sha256": "1df9421daaba885bd06552d7b62030b285ac8472b98e09e0719554fd2448547c" + }, + "set_selenium_page_load_timeout": { + "name": "set_selenium_page_load_timeout", + "doc": "Sets the page load timeout value used by Selenium.\n\n The value can be given as a number that is considered to be\n seconds or as a human-readable string like ``1 second``.\n The previous value is returned and can be used to restore\n the original value later if needed.\n\n In contrast to `Set Selenium Timeout` and `Set Selenium Implicit Wait`,\n this keywords sets the time for the Webdriver to wait until the page\n is loaded before raising a timeout exception.\n\n See the `Page load` section above for more information.\n\n Example:\n | ${orig page load timeout} = | `Set Selenium Page Load Timeout` | 30 seconds |\n | `Open page that loads slowly` |\n | `Set Selenium Page Load Timeout` | ${orig page load timeout} |\n\n New in SeleniumLibrary 6.1\n ", + "sha256": "37e2b5f6af58ce3b2e1d520c0c2d56b99cadf175dd31f1ccfb05de36c8cfdab0" + }, + "set_selenium_speed": { + "name": "set_selenium_speed", + "doc": "Sets the delay that is waited after each Selenium command.\n\n The value can be given as a number that is considered to be\n seconds or as a human-readable string like ``1 second``.\n The previous value is returned and can be used to restore\n the original value later if needed.\n\n See the `Selenium Speed` section above for more information.\n\n Example:\n | `Set Selenium Speed` | 0.5 seconds |\n ", + "sha256": "143bd7c58689c676a711dcf2571cfdd8ee609325264bd632db2945dce3300ae5" + }, + "set_selenium_timeout": { + "name": "set_selenium_timeout", + "doc": "Sets the timeout that is used by various keywords.\n\n The value can be given as a number that is considered to be\n seconds or as a human-readable string like ``1 second``.\n The previous value is returned and can be used to restore\n the original value later if needed.\n\n See the `Timeout` section above for more information.\n\n Example:\n | ${orig timeout} = | `Set Selenium Timeout` | 15 seconds |\n | `Open page that loads slowly` |\n | `Set Selenium Timeout` | ${orig timeout} |\n ", + "sha256": "6e78114e0e60f0148629589b897d6a67b1c492317eb883b2ca4f3c6457a5d01b" + }, + "switch_browser": { + "name": "switch_browser", + "doc": "Switches between active browsers using ``index_or_alias``.\n\n Indices are returned by the `Open Browser` keyword and aliases can\n be given to it explicitly. Indices start from 1.\n\n Example:\n | `Open Browser` | http://google.com | ff |\n | `Location Should Be` | http://google.com | |\n | `Open Browser` | http://yahoo.com | ie | alias=second |\n | `Location Should Be` | http://yahoo.com | |\n | `Switch Browser` | 1 | # index |\n | `Page Should Contain` | I'm feeling lucky | |\n | `Switch Browser` | second | # alias |\n | `Page Should Contain` | More Yahoo! | |\n | `Close All Browsers` | | |\n\n Above example expects that there was no other open browsers when\n opening the first one because it used index ``1`` when switching to\n it later. If you are not sure about that, you can store the index\n into a variable as below.\n\n | ${index} = | `Open Browser` | http://google.com |\n | # Do something ... | | |\n | `Switch Browser` | ${index} | |\n ", + "sha256": "de918f9e83ebecafb37ba3704649efb39dfbf405960597e1e99dddffdf69c1fb" + }, + "title_should_be": { + "name": "title_should_be", + "doc": "Verifies that the current page title equals ``title``.\n\n The ``message`` argument can be used to override the default error\n message.\n\n ``message`` argument is new in SeleniumLibrary 3.1.\n ", + "sha256": "f3ed755ed3bdbb8e7b334bce951620ceb83c3aca1cad51a31b2eea42260e1199" + }, + "add_cookie": { + "name": "add_cookie", + "doc": "Adds a cookie to your current session.\n\n ``name`` and ``value`` are required, ``path``, ``domain``, ``secure``\n and ``expiry`` are optional. Expiry supports the same formats as\n the [http://robotframework.org/robotframework/latest/libraries/DateTime.html|DateTime]\n library or an epoch timestamp.\n\n Example:\n | `Add Cookie` | foo | bar | |\n | `Add Cookie` | foo | bar | domain=example.com |\n | `Add Cookie` | foo | bar | expiry=2027-09-28 16:21:35 | # Expiry as timestamp. |\n | `Add Cookie` | foo | bar | expiry=1822137695 | # Expiry as epoch seconds. |\n\n Prior to SeleniumLibrary 3.0 setting expiry did not work.\n ", + "sha256": "4824fdf8e69148f3f74ed2a177fc4417caa1b7d24b5fd55378e8cdbd3ace04a5" + }, + "delete_all_cookies": { + "name": "delete_all_cookies", + "doc": "Deletes all cookies.", + "sha256": "3300bc6758bd113107fb425664eacbda4143514393c4d4197ac28626592b77c5" + }, + "delete_cookie": { + "name": "delete_cookie", + "doc": "Deletes the cookie matching ``name``.\n\n If the cookie is not found, nothing happens.\n ", + "sha256": "9f69becc9575a4dc10a09bebdcb7405fbfba883c8268c889baca4659ba549d04" + }, + "get_cookie": { + "name": "get_cookie", + "doc": "Returns information of cookie with ``name`` as an object.\n\n If no cookie is found with ``name``, keyword fails. The cookie object\n contains details about the cookie. Attributes available in the object\n are documented in the table below.\n\n | = Attribute = | = Explanation = |\n | name | The name of a cookie. |\n | value | Value of the cookie. |\n | path | Indicates a URL path, for example ``/``. |\n | domain | The domain, the cookie is visible to. |\n | secure | When true, the cookie is only used with HTTPS connections. |\n | httpOnly | When true, the cookie is not accessible via JavaScript. |\n | expiry | Python datetime object indicating when the cookie expires. |\n | extra | Possible attributes outside of the WebDriver specification |\n\n See the\n [https://w3c.github.io/webdriver/#cookies|WebDriver specification]\n for details about the cookie information.\n Notice that ``expiry`` is specified as a\n [https://docs.python.org/3/library/datetime.html#datetime.datetime|datetime object],\n not as seconds since Unix Epoch like WebDriver natively does.\n\n In some cases, example when running a browser in the cloud, it is possible that\n the cookie contains other attributes than is defined in the\n [https://w3c.github.io/webdriver/#cookies|WebDriver specification].\n These other attributes are available in an ``extra`` attribute in the cookie\n object and it contains a dictionary of the other attributes. The ``extra``\n attribute is new in SeleniumLibrary 4.0.\n\n Example:\n | `Add Cookie` | foo | bar |\n | ${cookie} = | `Get Cookie` | foo |\n | `Should Be Equal` | ${cookie.name} | foo |\n | `Should Be Equal` | ${cookie.value} | bar |\n | `Should Be True` | ${cookie.expiry.year} > 2017 |\n\n New in SeleniumLibrary 3.0.\n ", + "sha256": "747951f772be34600739a36f99d276499abc5137ddb8994e1773b68cc7c2e05b" + }, + "get_cookies": { + "name": "get_cookies", + "doc": "Returns all cookies of the current page.\n\n If ``as_dict`` argument evaluates as false, see `Boolean arguments`\n for more details, then cookie information is returned as\n a single string in format ``name1=value1; name2=value2; name3=value3``.\n When ``as_dict`` argument evaluates as true, cookie information\n is returned as Robot Framework dictionary format. The string format\n can be used, for example, for logging purposes or in headers when\n sending HTTP requests. The dictionary format is helpful when\n the result can be passed to requests library's Create Session\n keyword's optional cookies parameter.\n\n The `` as_dict`` argument is new in SeleniumLibrary 3.3\n ", + "sha256": "7a9bda6590cdb1aa8825e385ffefc087a7ca087936dd11350d6234e6e2c05e6c" + }, + "add_location_strategy": { + "name": "add_location_strategy", + "doc": "Adds a custom location strategy.\n\n See `Custom locators` for information on how to create and use\n custom strategies. `Remove Location Strategy` can be used to\n remove a registered strategy.\n\n Location strategies are automatically removed after leaving the\n current scope by default. Setting ``persist`` to a true value (see\n `Boolean arguments`) will cause the location strategy to stay\n registered throughout the life of the test.\n ", + "sha256": "046e816fd4d028592aaa9146fd815aec20809f88d4160fdf166fb19d5fdcfa0c" + }, + "assign_id_to_element": { + "name": "assign_id_to_element", + "doc": "Assigns a temporary ``id`` to the element specified by ``locator``.\n\n This is mainly useful if the locator is complicated and/or slow XPath\n expression and it is needed multiple times. Identifier expires when\n the page is reloaded.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n Example:\n | `Assign ID to Element` | //ul[@class='example' and ./li[contains(., 'Stuff')]] | my id |\n | `Page Should Contain Element` | my id |\n ", + "sha256": "2ce9ab7a44154be53f32d6d6e8b1b6e9dd8bbff880048c99ed4b62763a0b522c" + }, + "clear_element_text": { + "name": "clear_element_text", + "doc": "Clears the value of the text-input-element identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "31d7803b76e63ff90ff333f06e323aba4f820632b8795d51d24242fb65f4e7d2" + }, + "click_button": { + "name": "click_button", + "doc": "Clicks the button identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax. When using the default locator strategy, buttons are\n searched using ``id``, ``name``, and ``value``.\n\n See the `Click Element` keyword for details about the\n ``modifier`` argument.\n\n The ``modifier`` argument is new in SeleniumLibrary 3.3\n ", + "sha256": "72dcaeaa3bc1a4e14c596d72a19cbd82e0881732440153cbfb27272b2066dd77" + }, + "click_element": { + "name": "click_element", + "doc": "Click the element identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n The ``modifier`` argument can be used to pass\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver/selenium.webdriver.common.keys.html#selenium.webdriver.common.keys.Keys|Selenium Keys]\n when clicking the element. The `+` can be used as a separator\n for different Selenium Keys. The `CTRL` is internally translated to\n the `CONTROL` key. The ``modifier`` is space and case insensitive, example\n \"alt\" and \" aLt \" are supported formats to\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver/selenium.webdriver.common.keys.html#selenium.webdriver.common.keys.Keys.ALT|ALT key]\n . If ``modifier`` does not match to Selenium Keys, keyword fails.\n\n If ``action_chain`` argument is true, see `Boolean arguments` for more\n details on how to set boolean argument, then keyword uses ActionChain\n based click instead of the .click() function. If both\n ``action_chain`` and ``modifier`` are defined, the click will be\n performed using ``modifier`` and ``action_chain`` will be ignored.\n\n Example:\n | Click Element | id:button | | # Would click element without any modifiers. |\n | Click Element | id:button | CTRL | # Would click element with CTLR key pressed down. |\n | Click Element | id:button | CTRL+ALT | # Would click element with CTLR and ALT keys pressed down. |\n | Click Element | id:button | action_chain=True | # Clicks the button using an Selenium ActionChains |\n\n The ``modifier`` argument is new in SeleniumLibrary 3.2\n The ``action_chain`` argument is new in SeleniumLibrary 4.1\n ", + "sha256": "5099da1ff98ae3351fb740f301498066e1f86b8f9a6ef7f178e2b29d5d5afb35" + }, + "click_element_at_coordinates": { + "name": "click_element_at_coordinates", + "doc": "Click the element ``locator`` at ``xoffset/yoffset``.\n\n The Cursor is moved and the center of the element and x/y coordinates are\n calculated from that point.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "6c9be5ef41acf068a8ecf3972fe88f5f9c5257cf843d014dd9a76f7b4a3719c7" + }, + "click_image": { + "name": "click_image", + "doc": "Clicks an image identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax. When using the default locator strategy, images are searched\n using ``id``, ``name``, ``src`` and ``alt``.\n\n See the `Click Element` keyword for details about the\n ``modifier`` argument.\n\n The ``modifier`` argument is new in SeleniumLibrary 3.3\n ", + "sha256": "a83623f5affb23d6a089b6cab14e9983dd55eba3b11deedf672c6d2c3d387cf4" + }, + "click_link": { + "name": "click_link", + "doc": "Clicks a link identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax. When using the default locator strategy, links are searched\n using ``id``, ``name``, ``href`` and the link text.\n\n See the `Click Element` keyword for details about the\n ``modifier`` argument.\n\n The ``modifier`` argument is new in SeleniumLibrary 3.3\n ", + "sha256": "d8c5ec4c5359fed7c6a5094f5d18e8766b4dfb6f4e4d5ea1d61d50b7b09e7c31" + }, + "cover_element": { + "name": "cover_element", + "doc": "Will cover elements identified by ``locator`` with a blue div without breaking page layout.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n New in SeleniumLibrary 3.3.0\n\n Example:\n |`Cover Element` | css:div#container |\n ", + "sha256": "0dd30bea744e70b71f3e5fc5358833c291d404cdfa23970d09ece25f2380fb28" + }, + "double_click_element": { + "name": "double_click_element", + "doc": "Double clicks the element identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "c7b11722014178d683d80e276fcea367307d1d4cbe3b93b17cbbbe30b35b7174" + }, + "drag_and_drop": { + "name": "drag_and_drop", + "doc": "Drags the element identified by ``locator`` into the ``target`` element.\n\n The ``locator`` argument is the locator of the dragged element\n and the ``target`` is the locator of the target. See the\n `Locating elements` section for details about the locator syntax.\n\n Example:\n | `Drag And Drop` | css:div#element | css:div.target |\n ", + "sha256": "af13a511a462a2540dc93baf3bc42d05143aaf0de6ce9771029044a25b40bd64" + }, + "drag_and_drop_by_offset": { + "name": "drag_and_drop_by_offset", + "doc": "Drags the element identified with ``locator`` by ``xoffset/yoffset``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n The element will be moved by ``xoffset`` and ``yoffset``, each of which\n is a negative or positive number specifying the offset.\n\n Example:\n | `Drag And Drop By Offset` | myElem | 50 | -35 | # Move myElem 50px right and 35px down |\n ", + "sha256": "89750f538dc14ca0c04fbe1a3aba732352f9723d658bbd971905003ee9c351f6" + }, + "element_attribute_value_should_be": { + "name": "element_attribute_value_should_be", + "doc": "Verifies element identified by ``locator`` contains expected attribute value.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n Example:\n `Element Attribute Value Should Be` | css:img | href | value\n\n New in SeleniumLibrary 3.2.\n ", + "sha256": "330701ee8d3307c6543bdfeafa649d14689f639f2e139e499aae8ec495d7d015" + }, + "element_should_be_disabled": { + "name": "element_should_be_disabled", + "doc": "Verifies that element identified by ``locator`` is disabled.\n\n This keyword considers also elements that are read-only to be\n disabled.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "6f34019f6e68805c2b73ef5207b424743c9461dfd30061f163d21948304bb012" + }, + "element_should_be_enabled": { + "name": "element_should_be_enabled", + "doc": "Verifies that element identified by ``locator`` is enabled.\n\n This keyword considers also elements that are read-only to be\n disabled.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "014f8538093bdcef0ed8c7a13020ae513a4a14bd2d0b71f1843de951f5c7b5d3" + }, + "element_should_be_focused": { + "name": "element_should_be_focused", + "doc": "Verifies that element identified by ``locator`` is focused.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n New in SeleniumLibrary 3.0.\n ", + "sha256": "f327420520f06421e0a11062af115eaa7bb3eaf97a0ae4b6f02c0c82c9fa1f73" + }, + "element_should_be_visible": { + "name": "element_should_be_visible", + "doc": "Verifies that the element identified by ``locator`` is visible.\n\n Herein, visible means that the element is logically visible, not\n optically visible in the current browser viewport. For example,\n an element that carries ``display:none`` is not logically visible,\n so using this keyword on that element would fail.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n The ``message`` argument can be used to override the default error\n message.\n ", + "sha256": "98c4fb9d0b90e73c3d702b553aa6a30f027320463eb18e298cd5b9133f1cc36a" + }, + "element_should_contain": { + "name": "element_should_contain", + "doc": "Verifies that element ``locator`` contains text ``expected``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n The ``message`` argument can be used to override the default error\n message.\n\n The ``ignore_case`` argument can be set to True to compare case\n insensitive, default is False. New in SeleniumLibrary 3.1.\n\n ``ignore_case`` argument is new in SeleniumLibrary 3.1.\n\n Use `Element Text Should Be` if you want to match the exact text,\n not a substring.\n ", + "sha256": "998a924785fef84597b5e5fc866f4c5d7e4b0a753cba68d15be0f3b44588c06d" + }, + "element_should_not_be_visible": { + "name": "element_should_not_be_visible", + "doc": "Verifies that the element identified by ``locator`` is NOT visible.\n\n Passes if the element does not exists. See `Element Should Be Visible`\n for more information about visibility and supported arguments.\n ", + "sha256": "811779774da3cf876101661d4c15a6e89ea0568493be61b19fded7a0bd40f0c4" + }, + "element_should_not_contain": { + "name": "element_should_not_contain", + "doc": "Verifies that element ``locator`` does not contain text ``expected``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n The ``message`` argument can be used to override the default error\n message.\n\n The ``ignore_case`` argument can be set to True to compare case\n insensitive, default is False.\n\n ``ignore_case`` argument new in SeleniumLibrary 3.1.\n ", + "sha256": "ef9492bae813b1597fabc9d6f02a21c05ff736a18fb6eb20fb81e6ca40011437" + }, + "element_text_should_be": { + "name": "element_text_should_be", + "doc": "Verifies that element ``locator`` contains exact the text ``expected``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n The ``message`` argument can be used to override the default error\n message.\n\n The ``ignore_case`` argument can be set to True to compare case\n insensitive, default is False.\n\n ``ignore_case`` argument is new in SeleniumLibrary 3.1.\n\n Use `Element Should Contain` if a substring match is desired.\n ", + "sha256": "4036c0bb4fe36085fcab4421f3ffb65265d70d8cb852106ea13a983438a77723" + }, + "element_text_should_not_be": { + "name": "element_text_should_not_be", + "doc": "Verifies that element ``locator`` does not contain exact the text ``not_expected``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n The ``message`` argument can be used to override the default error\n message.\n\n The ``ignore_case`` argument can be set to True to compare case\n insensitive, default is False.\n\n New in SeleniumLibrary 3.1.1\n ", + "sha256": "67821af845f34ba19ebffb38fa558c375f7261e3d9c9f04cb653bad828e99cf4" + }, + "get_all_links": { + "name": "get_all_links", + "doc": "Returns a list containing ids of all links found in current page.\n\n If a link has no id, an empty string will be in the list instead.\n ", + "sha256": "f17319af1acc205f3ee5fe01b5e8960bba45ff05629b4b1d2e4fdec770163c1a" + }, + "get_dom_attribute": { + "name": "get_dom_attribute", + "doc": "Returns the value of ``attribute`` from the element ``locator``. `Get DOM Attribute` keyword\n only returns attributes declared within the element's HTML markup. If the requested attribute\n is not there, the keyword returns ${None}.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n Example:\n | ${id}= | `Get DOM Attribute` | css:h1 | id |\n\n ", + "sha256": "1337e3b21fae3759b85da9dba5fda08378fd8ea4ff16b9d9a03fa54f1d75853f" + }, + "get_element_attribute": { + "name": "get_element_attribute", + "doc": "Returns the value of ``attribute`` from the element ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n Example:\n | ${id}= | `Get Element Attribute` | css:h1 | id |\n\n Passing attribute name as part of the ``locator`` was removed\n in SeleniumLibrary 3.2. The explicit ``attribute`` argument\n should be used instead.\n ", + "sha256": "3325a9affcfb67bbb11b250a7479d125f3a7c0ca3e6b4772b35f873c6942a300" + }, + "get_element_count": { + "name": "get_element_count", + "doc": "Returns the number of elements matching ``locator``.\n\n If you wish to assert the number of matching elements, use\n `Page Should Contain Element` with ``limit`` argument. Keyword will\n always return an integer.\n\n Example:\n | ${count} = | `Get Element Count` | name:div_name |\n | `Should Be True` | ${count} > 2 | |\n\n New in SeleniumLibrary 3.0.\n ", + "sha256": "edc00542de29af7b4b11d459c21c6a8f87fd21233f49c1b9a5b4d8e06d0128f8" + }, + "get_element_size": { + "name": "get_element_size", + "doc": "Returns width and height of the element identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n Both width and height are returned as integers.\n\n Example:\n | ${width} | ${height} = | `Get Element Size` | css:div#container |\n ", + "sha256": "d1dc235938760fc871c68838032587be56a8ebb13dc295f68e9df6a03c72d266" + }, + "get_horizontal_position": { + "name": "get_horizontal_position", + "doc": "Returns the horizontal position of the element identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n The position is returned in pixels off the left side of the page,\n as an integer.\n\n See also `Get Vertical Position`.\n ", + "sha256": "7b81ffe406d7708e72861971ec879a7cdb3adff3cf3a6ad4c816c0b36de84a79" + }, + "get_property": { + "name": "get_property", + "doc": "Returns the value of ``property`` from the element ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n Example:\n | ${text_length}= | `Get Property` | css:h1 | text_length |\n\n ", + "sha256": "6335a05f73d42212f78d4285872595fec96dbb4e669b8026b2e9bdab4f3284eb" + }, + "get_text": { + "name": "get_text", + "doc": "Returns the text value of the element identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "c5df21cb13fca76338626c63ce4e0e83be2e5563eb296833f55678c3424ad333" + }, + "get_value": { + "name": "get_value", + "doc": "Returns the value attribute of the element identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "5856fe53c0581268a5a395418f08aedb118762d5ec8fbd553cf2d44b82aa27c6" + }, + "get_vertical_position": { + "name": "get_vertical_position", + "doc": "Returns the vertical position of the element identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n The position is returned in pixels off the top of the page,\n as an integer.\n\n See also `Get Horizontal Position`.\n ", + "sha256": "a1f1cc8075b6323bf4b900ea52357586f28721239e45ec11fb1a130faa9246c0" + }, + "get_webelement": { + "name": "get_webelement", + "doc": "Returns the first WebElement matching the given ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "5deaaabc9162680121dbe744d4e476e40c7eacba17922459c209f211ba74b5cd" + }, + "get_webelements": { + "name": "get_webelements", + "doc": "Returns a list of WebElement objects matching the ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n Starting from SeleniumLibrary 3.0, the keyword returns an empty\n list if there are no matching elements. In previous releases, the\n keyword failed in this case.\n ", + "sha256": "ab7b4634b7c54b2b17daf4c290704fe45af948eeff41f9dbc1c01fab33273496" + }, + "mouse_down": { + "name": "mouse_down", + "doc": "Simulates pressing the left mouse button on the element ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n The element is pressed without releasing the mouse button.\n\n See also the more specific keywords `Mouse Down On Image` and\n `Mouse Down On Link`.\n ", + "sha256": "c0e5431b9b9eb6875830eadccc1ed0f9a9d34781ecef40ab059194054eeae9e4" + }, + "mouse_down_on_image": { + "name": "mouse_down_on_image", + "doc": "Simulates a mouse down event on an image identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax. When using the default locator strategy, images are searched\n using ``id``, ``name``, ``src`` and ``alt``.\n ", + "sha256": "3b7c0b9a83908e60012f095acc71305c853dd07864497077420f1a3930ea144c" + }, + "mouse_down_on_link": { + "name": "mouse_down_on_link", + "doc": "Simulates a mouse down event on a link identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax. When using the default locator strategy, links are searched\n using ``id``, ``name``, ``href`` and the link text.\n ", + "sha256": "8ef3134ef374ebc89f76985b09abd2caac10f603e8db38cf78dcbac9c826cc3e" + }, + "mouse_out": { + "name": "mouse_out", + "doc": "Simulates moving the mouse away from the element ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "835368b635d5d1c5c50250595a8e7cb2feb9eb4af4fa14753c561a9c35894db1" + }, + "mouse_over": { + "name": "mouse_over", + "doc": "Simulates hovering the mouse over the element ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "b4c14a2a10cfddb07d7748630ba6546991d3da2311a20aa146685a0f78e41241" + }, + "mouse_up": { + "name": "mouse_up", + "doc": "Simulates releasing the left mouse button on the element ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "47c3666126bc84aa9104f6137fd51817efcd1804aaf7c965df143a6aad71895a" + }, + "open_context_menu": { + "name": "open_context_menu", + "doc": "Opens the context menu on the element identified by ``locator``.", + "sha256": "8cb9023a05753eb5cc230116dec98188b5bdfac0b94955b69957726131189493" + }, + "page_should_contain": { + "name": "page_should_contain", + "doc": "Verifies that current page contains ``text``.\n\n If this keyword fails, it automatically logs the page source\n using the log level specified with the optional ``loglevel``\n argument. Valid log levels are ``TRACE`` (default), ``DEBUG``,\n ``INFO``, ``WARN``, and ``NONE``. If the log level is ``NONE``\n or below the current active log level the source will not be logged.\n\n !! WARNING !! If you have an iframe selected, `Page Should Contain`\n will reset the frame reference back to the main frame. This is due\n to the fact that is searches for the ``text`` in all frames. To locate\n an element in an iframe after calling `Page Should Contian` one needs\n to (re)select the frame.\n ", + "sha256": "bb1186dbfae09e52cad4cad8def5bf2980085e48f75b6af2330bcd4da67477af" + }, + "page_should_contain_element": { + "name": "page_should_contain_element", + "doc": "Verifies that element ``locator`` is found on the current page.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n The ``message`` argument can be used to override the default error\n message.\n\n The ``limit`` argument can used to define how many elements the\n page should contain. When ``limit`` is ``None`` (default) page can\n contain one or more elements. When limit is a number, page must\n contain same number of elements.\n\n See `Page Should Contain` for an explanation about the ``loglevel``\n argument.\n\n Examples assumes that locator matches to two elements.\n | `Page Should Contain Element` | div_name | limit=1 | # Keyword fails. |\n | `Page Should Contain Element` | div_name | limit=2 | # Keyword passes. |\n | `Page Should Contain Element` | div_name | limit=none | # None is considered one or more. |\n | `Page Should Contain Element` | div_name | | # Same as above. |\n\n The ``limit`` argument is new in SeleniumLibrary 3.0.\n ", + "sha256": "d2c24d9ce997c94b3cd391306893b9d864c389a047c274ca1ab323e51f960f8e" + }, + "page_should_contain_image": { + "name": "page_should_contain_image", + "doc": "Verifies image identified by ``locator`` is found from current page.\n\n See the `Locating elements` section for details about the locator\n syntax. When using the default locator strategy, images are searched\n using ``id``, ``name``, ``src`` and ``alt``.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n ", + "sha256": "84ab3a648d3b18c5e266ba075408f3cb2ac3b736e1e2009a6cca125de5d07a50" + }, + "page_should_contain_link": { + "name": "page_should_contain_link", + "doc": "Verifies link identified by ``locator`` is found from current page.\n\n See the `Locating elements` section for details about the locator\n syntax. When using the default locator strategy, links are searched\n using ``id``, ``name``, ``href`` and the link text.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n ", + "sha256": "005f6565f4fcd9b91f87a2274c32fae7545619549be26f23b2cc06856e44ecba" + }, + "page_should_not_contain": { + "name": "page_should_not_contain", + "doc": "Verifies the current page does not contain ``text``.\n\n See `Page Should Contain` for an explanation about the ``loglevel``\n argument.\n ", + "sha256": "72389be32f084ed5a3716a32e833e117c419bc2c6ebfa525a79e69054bb2a8cc" + }, + "page_should_not_contain_element": { + "name": "page_should_not_contain_element", + "doc": "Verifies that element ``locator`` is not found on the current page.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n See `Page Should Contain` for an explanation about ``message`` and\n ``loglevel`` arguments.\n ", + "sha256": "3939f5d1fce87d85f013ae3e4327b50404cf832231d4ca2e677013808ee8ff92" + }, + "page_should_not_contain_image": { + "name": "page_should_not_contain_image", + "doc": "Verifies image identified by ``locator`` is not found from current page.\n\n See the `Locating elements` section for details about the locator\n syntax. When using the default locator strategy, images are searched\n using ``id``, ``name``, ``src`` and ``alt``.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n ", + "sha256": "7367c4581992c47a2fbd74fd0beccc254e883879f6b93f206242d0ecb6397448" + }, + "page_should_not_contain_link": { + "name": "page_should_not_contain_link", + "doc": "Verifies link identified by ``locator`` is not found from current page.\n\n See the `Locating elements` section for details about the locator\n syntax. When using the default locator strategy, links are searched\n using ``id``, ``name``, ``href`` and the link text.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n ", + "sha256": "61fca3076c7b671f21528f5d141ee7b43ecc1acada608b4157d08ecb38fae0e1" + }, + "press_key": { + "name": "press_key", + "doc": "Simulates user pressing key on element identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n ``key`` is either a single character, a string, or a numerical ASCII\n code of the key lead by '\\'.\n\n Examples:\n | `Press Key` | text_field | q |\n | `Press Key` | text_field | abcde |\n | `Press Key` | login_button | \\13 | # ASCII code for enter key |\n\n `Press Key` and `Press Keys` differ in the methods to simulate key\n presses. `Press Key` uses the WebDriver `SEND_KEYS_TO_ELEMENT` command\n using the selenium send_keys method. Although one is not recommended\n over the other if `Press Key` does not work we recommend trying\n `Press Keys`.\n send_\n ", + "sha256": "fd4035762f6f532aed3cd2b93ad24002a51503e8a86cd7da956a3e2cf8a1038d" + }, + "press_keys": { + "name": "press_keys", + "doc": "Simulates the user pressing key(s) to an element or on the active browser.\n\n If ``locator`` evaluates as false, see `Boolean arguments` for more\n details, then the ``keys`` are sent to the currently active browser.\n Otherwise element is searched and ``keys`` are send to the element\n identified by the ``locator``. In later case, keyword fails if element\n is not found. See the `Locating elements` section for details about\n the locator syntax.\n\n ``keys`` arguments can contain one or many strings, but it can not\n be empty. ``keys`` can also be a combination of\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver/selenium.webdriver.common.keys.html|Selenium Keys]\n and strings or a single Selenium Key. If Selenium Key is combined\n with strings, Selenium key and strings must be separated by the\n `+` character, like in `CONTROL+c`. Selenium Keys\n are space and case sensitive and Selenium Keys are not parsed\n inside of the string. Example AALTO, would send string `AALTO`\n and `ALT` not parsed inside of the string. But `A+ALT+O` would\n found Selenium ALT key from the ``keys`` argument. It also possible\n to press many Selenium Keys down at the same time, example\n 'ALT+ARROW_DOWN`.\n\n If Selenium Keys are detected in the ``keys`` argument, keyword\n will press the Selenium Key down, send the strings and\n then release the Selenium Key. If keyword needs to send a Selenium\n Key as a string, then each character must be separated with\n `+` character, example `E+N+D`.\n\n `CTRL` is alias for\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver/selenium.webdriver.common.keys.html#selenium.webdriver.common.keys.Keys.CONTROL|Selenium CONTROL]\n and ESC is alias for\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver/selenium.webdriver.common.keys.html#selenium.webdriver.common.keys.Keys.ESCAPE|Selenium ESCAPE]\n\n New in SeleniumLibrary 3.3\n\n Examples:\n | `Press Keys` | text_field | AAAAA | | # Sends string \"AAAAA\" to element. |\n | `Press Keys` | None | BBBBB | | # Sends string \"BBBBB\" to currently active browser. |\n | `Press Keys` | text_field | E+N+D | | # Sends string \"END\" to element. |\n | `Press Keys` | text_field | XXX | YY | # Sends strings \"XXX\" and \"YY\" to element. |\n | `Press Keys` | text_field | XXX+YY | | # Same as above. |\n | `Press Keys` | text_field | ALT+ARROW_DOWN | | # Pressing \"ALT\" key down, then pressing ARROW_DOWN and then releasing both keys. |\n | `Press Keys` | text_field | ALT | ARROW_DOWN | # Pressing \"ALT\" key and then pressing ARROW_DOWN. |\n | `Press Keys` | text_field | CTRL+c | | # Pressing CTRL key down, sends string \"c\" and then releases CTRL key. |\n | `Press Keys` | button | RETURN | | # Pressing \"ENTER\" key to element. |\n\n `Press Key` and `Press Keys` differ in the methods to simulate key\n presses. `Press Keys` uses the Selenium/WebDriver Actions.\n `Press Keys` also has a more extensive syntax for describing keys,\n key combinations, and key actions. Although one is not recommended\n over the other if `Press Keys` does not work we recommend trying\n `Press Key`.\n ", + "sha256": "549b119394b8f48407c11208e1f38c3f2c753e9a40b5c6f1f47b3320df3f3612" + }, + "remove_location_strategy": { + "name": "remove_location_strategy", + "doc": "Removes a previously added custom location strategy.\n\n See `Custom locators` for information on how to create and use\n custom strategies.\n ", + "sha256": "827184ef194cec97d793297edbc6544d2e6774a80a14136ccfa0d5cc04fbc09e" + }, + "scroll_element_into_view": { + "name": "scroll_element_into_view", + "doc": "Scrolls the element identified by ``locator`` into view.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n New in SeleniumLibrary 3.2.0\n ", + "sha256": "0d567a31d5b64fcfb38b47c2f5f452de4fbe3d08aa0c0547644d4c59b243ef60" + }, + "set_focus_to_element": { + "name": "set_focus_to_element", + "doc": "Sets the focus to the element identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n Prior to SeleniumLibrary 3.0 this keyword was named `Focus`.\n ", + "sha256": "0b02399995113cd6ac38557106b4697e4d86f9874173ed593a8853e63362c74f" + }, + "simulate_event": { + "name": "simulate_event", + "doc": "Simulates ``event`` on the element identified by ``locator``.\n\n This keyword is useful if element has ``OnEvent`` handler that\n needs to be explicitly invoked.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n Prior to SeleniumLibrary 3.0 this keyword was named `Simulate`.\n ", + "sha256": "49cd268150ae4f3170f13d6b5a25809f41080efa3f3b5ca0fa2e2d8cd3ea7795" + }, + "wait_for_expected_condition": { + "name": "wait_for_expected_condition", + "doc": "Waits until ``condition`` is true or ``timeout`` expires.\n\n The condition must be one of selenium's expected condition which\n can be found within the selenium\n [https://www.selenium.dev/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.expected_conditions.html#module-selenium.webdriver.support.expected_conditions|Python API]\n documentation. The expected condition can written as snake_case\n (ex title_is) or it can be space delimited (ex Title Is). Some\n conditions require additional arguments or ``args`` which should\n be passed along after the expected condition.\n\n Fails if the timeout expires before the condition becomes true.\n The default value is 10 seconds.\n\n Examples:\n | `Wait For Expected Condition` | alert_is_present |\n | `Wait For Expected Condition` | Title Is | New Title |\n\n If the expected condition expects a locator then one can pass\n as arguments a tuple containing the selenium locator strategies\n and the locator.\n\n Example of expected condition expecting locator:\n | ${byElem}= | Evaluate (\"id\",\"added_btn\")\n | `Wait For Expected Condition` | Presence Of Element Located | ${byElem}\n ", + "sha256": "7e512f1e3c97525aa828d624627aaf3f8b76ac0ec1aaa507b36ff9c8fff34d5a" + }, + "checkbox_should_be_selected": { + "name": "checkbox_should_be_selected", + "doc": "Verifies checkbox ``locator`` is selected/checked.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "e50bf6856c0f0c3f373adb3bcc3b7d677738088632055f507797887c9f822136" + }, + "checkbox_should_not_be_selected": { + "name": "checkbox_should_not_be_selected", + "doc": "Verifies checkbox ``locator`` is not selected/checked.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "8488752a0365d5c94b3a7885d53b67f99d92ccc5687fdc59411b42a40fa95443" + }, + "choose_file": { + "name": "choose_file", + "doc": "Inputs the ``file_path`` into the file input field ``locator``.\n\n This keyword is most often used to input files into upload forms.\n The keyword does not check ``file_path`` is the file or folder\n available on the machine where tests are executed. If the ``file_path``\n points at a file and when using Selenium Grid, Selenium will\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_remote/selenium.webdriver.remote.command.html?highlight=upload#selenium.webdriver.remote.command.Command.UPLOAD_FILE|magically],\n transfer the file from the machine where the tests are executed\n to the Selenium Grid node where the browser is running.\n Then Selenium will send the file path, from the nodes file\n system, to the browser.\n\n That ``file_path`` is not checked, is new in SeleniumLibrary 4.0.\n\n Example:\n | `Choose File` | my_upload_field | ${CURDIR}/trades.csv |\n ", + "sha256": "244543282ef6c62ec448fb42ed37706978ecf84aec27a9c7774fdd39bc84697c" + }, + "input_password": { + "name": "input_password", + "doc": "Types the given password into the text field identified by ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax. See `Input Text` for ``clear`` argument details.\n\n Difference compared to `Input Text` is that this keyword does not\n log the given password on the INFO level. Notice that if you use\n the keyword like\n\n | Input Password | password_field | password |\n\n the password is shown as a normal keyword argument. A way to avoid\n that is using variables like\n\n | Input Password | password_field | ${PASSWORD} |\n\n Please notice that Robot Framework logs all arguments using\n the TRACE level and tests must not be executed using level below\n DEBUG if the password should not be logged in any format.\n\n The `clear` argument is new in SeleniumLibrary 4.0. Hiding password\n logging from Selenium logs is new in SeleniumLibrary 4.2.\n ", + "sha256": "2471a62ea46d3d4815fe3700c92b61bd4abee39926bc4dadeb072bb88ba69fd5" + }, + "input_text": { + "name": "input_text", + "doc": "Types the given ``text`` into the text field identified by ``locator``.\n\n When ``clear`` is true, the input element is cleared before\n the text is typed into the element. When false, the previous text\n is not cleared from the element. Use `Input Password` if you\n do not want the given ``text`` to be logged.\n\n If [https://github.com/SeleniumHQ/selenium/wiki/Grid2|Selenium Grid]\n is used and the ``text`` argument points to a file in the file system,\n then this keyword prevents the Selenium to transfer the file to the\n Selenium Grid hub. Instead, this keyword will send the ``text`` string\n as is to the element. If a file should be transferred to the hub and\n upload should be performed, please use `Choose File` keyword.\n\n See the `Locating elements` section for details about the locator\n syntax. See the `Boolean arguments` section how Boolean values are\n handled.\n\n Disabling the file upload the Selenium Grid node and the `clear`\n argument are new in SeleniumLibrary 4.0\n ", + "sha256": "77be02dfff6bb6cc9d97af190e48a4c333913ca5058e67c85a4055bb84a9f494" + }, + "page_should_contain_button": { + "name": "page_should_contain_button", + "doc": "Verifies button ``locator`` is found from current page.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n\n See the `Locating elements` section for details about the locator\n syntax. When using the default locator strategy, buttons are\n searched using ``id``, ``name``, and ``value``.\n ", + "sha256": "f5fdc2763607b8a19e0dcbc2c8bc0512959193b4312232d89bdf5e3c1287ee25" + }, + "page_should_contain_checkbox": { + "name": "page_should_contain_checkbox", + "doc": "Verifies checkbox ``locator`` is found from the current page.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "827b0517772c7f3d0a8c9c41a1557892b98f0c9ee7228aa80a17df7d1766b338" + }, + "page_should_contain_radio_button": { + "name": "page_should_contain_radio_button", + "doc": "Verifies radio button ``locator`` is found from current page.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n\n See the `Locating elements` section for details about the locator\n syntax. When using the default locator strategy, radio buttons are\n searched using ``id``, ``name`` and ``value``.\n ", + "sha256": "a1bd5c4a731ebb21b599006d59a7c7d163da5fb64ca87ac20d853559ff948a95" + }, + "page_should_contain_textfield": { + "name": "page_should_contain_textfield", + "doc": "Verifies text field ``locator`` is found from current page.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "7b7414371c1321271f8616d6668e9b94001ab4443df27f26fe10c5e968be00c5" + }, + "page_should_not_contain_button": { + "name": "page_should_not_contain_button", + "doc": "Verifies button ``locator`` is not found from current page.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n\n See the `Locating elements` section for details about the locator\n syntax. When using the default locator strategy, buttons are\n searched using ``id``, ``name``, and ``value``.\n ", + "sha256": "c8b007d236e708e3d637b414d88b333f31bc64f396fe9034bc79be14288666ed" + }, + "page_should_not_contain_checkbox": { + "name": "page_should_not_contain_checkbox", + "doc": "Verifies checkbox ``locator`` is not found from the current page.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "88204d5dcc80e3fed6bfc74f5b2e02a3507d9ac290faf29c5818f54fc7c7109d" + }, + "page_should_not_contain_radio_button": { + "name": "page_should_not_contain_radio_button", + "doc": "Verifies radio button ``locator`` is not found from current page.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n\n See the `Locating elements` section for details about the locator\n syntax. When using the default locator strategy, radio buttons are\n searched using ``id``, ``name`` and ``value``.\n ", + "sha256": "f2310d4b57e4303ef5f38cc2cdc705ca95582a56ced04899d806beab1a63cef0" + }, + "page_should_not_contain_textfield": { + "name": "page_should_not_contain_textfield", + "doc": "Verifies text field ``locator`` is not found from current page.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "2d91d04a7f6bb6ffd6fb86459718e337880326ddbba3a1631de12737ecab5339" + }, + "radio_button_should_be_set_to": { + "name": "radio_button_should_be_set_to", + "doc": "Verifies radio button group ``group_name`` is set to ``value``.\n\n ``group_name`` is the ``name`` of the radio button group.\n ", + "sha256": "baedeb274f24cfa1951591b65fd654551c128c26db397414fce039f3c2ef68cc" + }, + "radio_button_should_not_be_selected": { + "name": "radio_button_should_not_be_selected", + "doc": "Verifies radio button group ``group_name`` has no selection.\n\n ``group_name`` is the ``name`` of the radio button group.\n ", + "sha256": "552945bd4776a7545990b26941784cf5a8bd5d1725fb1ccd6241d7f4404dea0e" + }, + "select_checkbox": { + "name": "select_checkbox", + "doc": "Selects the checkbox identified by ``locator``.\n\n Does nothing if checkbox is already selected.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "a864b4289721b7356ee6cc8f51612cdb5b91f5e439a264380665dd3c359cf09a" + }, + "select_radio_button": { + "name": "select_radio_button", + "doc": "Sets the radio button group ``group_name`` to ``value``.\n\n The radio button to be selected is located by two arguments:\n - ``group_name`` is the name of the radio button group.\n - ``value`` is the ``id`` or ``value`` attribute of the actual\n radio button.\n\n Examples:\n | `Select Radio Button` | size | XL |\n | `Select Radio Button` | contact | email |\n ", + "sha256": "ffbddc133ea67fa89fc81c47e311a5c1c0d17de62b307fb25cb0811ebf995909" + }, + "submit_form": { + "name": "submit_form", + "doc": "Submits a form identified by ``locator``.\n\n If ``locator`` is not given, first form on the page is submitted.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "19787cfd196cb398177f114d219b7047839b1b875ad44e4741c02be1f2219fb7" + }, + "textarea_should_contain": { + "name": "textarea_should_contain", + "doc": "Verifies text area ``locator`` contains text ``expected``.\n\n ``message`` can be used to override default error message.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "1f0212530a7318d4b84aab2f76e6a786698c18553eb45f6d7b5ce1526aa8806a" + }, + "textarea_value_should_be": { + "name": "textarea_value_should_be", + "doc": "Verifies text area ``locator`` has exactly text ``expected``.\n\n ``message`` can be used to override default error message.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "351e1fbde625caa68c16d8203c380853b86f12203e2a58fe32fed5154779df55" + }, + "textfield_should_contain": { + "name": "textfield_should_contain", + "doc": "Verifies text field ``locator`` contains text ``expected``.\n\n ``message`` can be used to override the default error message.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "8d542b446cce4ae3a59f57d2492144fa0264dc10bcc29a7a75e210368e7b24a9" + }, + "textfield_value_should_be": { + "name": "textfield_value_should_be", + "doc": "Verifies text field ``locator`` has exactly text ``expected``.\n\n ``message`` can be used to override default error message.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "bf88210c7d1673f6f28e6a5af94ecca2f23d655f0da09f31557b5d619ca4bb83" + }, + "unselect_checkbox": { + "name": "unselect_checkbox", + "doc": "Removes the selection of checkbox identified by ``locator``.\n\n Does nothing if the checkbox is not selected.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "73e850a91f88669d5f169f1da487263b966b34b9d5979fa7eacc353b9af6d3ad" + }, + "current_frame_should_contain": { + "name": "current_frame_should_contain", + "doc": "Verifies that the current frame contains ``text``.\n\n See `Page Should Contain` for an explanation about the ``loglevel``\n argument.\n\n Prior to SeleniumLibrary 3.0 this keyword was named\n `Current Frame Contains`.\n ", + "sha256": "d42932ad52a7f5a80466c5fc70cde1994b5dc91e42d5a92d5a4c84c5952106bc" + }, + "current_frame_should_not_contain": { + "name": "current_frame_should_not_contain", + "doc": "Verifies that the current frame does not contain ``text``.\n\n See `Page Should Contain` for an explanation about the ``loglevel``\n argument.\n ", + "sha256": "39c919106caf859d8c436e8334ba7dbfbaaadc761810034f9c24433ef930029d" + }, + "frame_should_contain": { + "name": "frame_should_contain", + "doc": "Verifies that frame identified by ``locator`` contains ``text``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n See `Page Should Contain` for an explanation about the ``loglevel``\n argument.\n ", + "sha256": "e7cf02e4cd77e7196d87f875db7285146a629fe895b3576c9dbd33ae4ab362fd" + }, + "select_frame": { + "name": "select_frame", + "doc": "Sets frame identified by ``locator`` as the current frame.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n Works both with frames and iframes. Use `Unselect Frame` to cancel\n the frame selection and return to the main frame.\n\n Example:\n | `Select Frame` | top-frame | # Select frame with id or name 'top-frame' |\n | `Click Link` | example | # Click link 'example' in the selected frame |\n | `Unselect Frame` | | # Back to main frame. |\n | `Select Frame` | //iframe[@name='xxx'] | # Select frame using xpath |\n ", + "sha256": "c2c67edf46d18644488c6395a750e293ab150011cdcdfe0741481328e01163f6" + }, + "unselect_frame": { + "name": "unselect_frame", + "doc": "Sets the main frame as the current frame.\n\n In practice cancels the previous `Select Frame` call.\n ", + "sha256": "9fc68af60f0d437e37ccc1fccb858b2c6554427f3f269518d4e7f849df3c43ec" + }, + "execute_async_javascript": { + "name": "execute_async_javascript", + "doc": "Executes asynchronous JavaScript code with possible arguments.\n\n Similar to `Execute Javascript` except that scripts executed with\n this keyword must explicitly signal they are finished by invoking the\n provided callback. This callback is always injected into the executed\n function as the last argument.\n\n Scripts must complete within the script timeout or this keyword will\n fail. See the `Timeout` section for more information.\n\n Starting from SeleniumLibrary 3.2 it is possible to provide JavaScript\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_remote/selenium.webdriver.remote.webdriver.html#selenium.webdriver.remote.webdriver.WebDriver.execute_async_script|\n arguments] as part of ``code`` argument. See `Execute Javascript` for\n more details.\n\n Examples:\n | `Execute Async JavaScript` | var callback = arguments[arguments.length - 1]; window.setTimeout(callback, 2000); |\n | `Execute Async JavaScript` | ${CURDIR}/async_js_to_execute.js |\n | ${result} = | `Execute Async JavaScript` |\n | ... | var callback = arguments[arguments.length - 1]; |\n | ... | function answer(){callback(\"text\");}; |\n | ... | window.setTimeout(answer, 2000); |\n | `Should Be Equal` | ${result} | text |\n ", + "sha256": "a67bddb89758620a690da6f26a06985d8a546d32da40a6509296e93dc1f68c51" + }, + "execute_javascript": { + "name": "execute_javascript", + "doc": "Executes the given JavaScript code with possible arguments.\n\n ``code`` may be divided into multiple cells in the test data and\n ``code`` may contain multiple lines of code and arguments. In that case,\n the JavaScript code parts are concatenated together without adding\n spaces and optional arguments are separated from ``code``.\n\n If ``code`` is a path to an existing file, the JavaScript\n to execute will be read from that file. Forward slashes work as\n a path separator on all operating systems.\n\n The JavaScript executes in the context of the currently selected\n frame or window as the body of an anonymous function. Use ``window``\n to refer to the window of your application and ``document`` to refer\n to the document object of the current frame or window, e.g.\n ``document.getElementById('example')``.\n\n This keyword returns whatever the executed JavaScript code returns.\n Return values are converted to the appropriate Python types.\n\n Starting from SeleniumLibrary 3.2 it is possible to provide JavaScript\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_remote/selenium.webdriver.remote.webdriver.html#selenium.webdriver.remote.webdriver.WebDriver.execute_script|\n arguments] as part of ``code`` argument. The JavaScript code and\n arguments must be separated with `JAVASCRIPT` and `ARGUMENTS` markers\n and must be used exactly with this format. If the Javascript code is\n first, then the `JAVASCRIPT` marker is optional. The order of\n `JAVASCRIPT` and `ARGUMENTS` markers can be swapped, but if `ARGUMENTS`\n is the first marker, then `JAVASCRIPT` marker is mandatory. It is only\n allowed to use `JAVASCRIPT` and `ARGUMENTS` markers only one time in the\n ``code`` argument.\n\n Examples:\n | `Execute JavaScript` | window.myFunc('arg1', 'arg2') |\n | `Execute JavaScript` | ${CURDIR}/js_to_execute.js |\n | `Execute JavaScript` | alert(arguments[0]); | ARGUMENTS | 123 |\n | `Execute JavaScript` | ARGUMENTS | 123 | JAVASCRIPT | alert(arguments[0]); |\n ", + "sha256": "5037e85a542b11eebcf4a3fd0b9eae560f17cd117b7fdfc9c7148c9091b44cc4" + }, + "register_keyword_to_run_on_failure": { + "name": "register_keyword_to_run_on_failure", + "doc": "Sets the keyword to execute, when a SeleniumLibrary keyword fails.\n\n ``keyword`` is the name of a keyword that will be executed if a\n SeleniumLibrary keyword fails. It is possible to use any available\n keyword, including user keywords or keywords from other libraries,\n but the keyword must not take any arguments.\n\n The initial keyword to use is set when `importing` the library, and\n the keyword that is used by default is `Capture Page Screenshot`.\n Taking a screenshot when something failed is a very useful\n feature, but notice that it can slow down the execution.\n\n It is possible to use string ``NOTHING`` or ``NONE``,\n case-insensitively, as well as Python ``None`` to disable this\n feature altogether.\n\n This keyword returns the name of the previously registered\n failure keyword or Python ``None`` if this functionality was\n previously disabled. The return value can be always used to\n restore the original value later.\n\n Example:\n | `Register Keyword To Run On Failure` | Log Source |\n | ${previous kw}= | `Register Keyword To Run On Failure` | NONE |\n | `Register Keyword To Run On Failure` | ${previous kw} |\n\n Changes in SeleniumLibrary 3.0:\n - Possible to use string ``NONE`` or Python ``None`` to disable the\n functionality.\n - Return Python ``None`` when the functionality was disabled earlier.\n In previous versions special value ``No Keyword`` was returned and\n it could not be used to restore the original state.\n ", + "sha256": "9eaadf25a89adfb670897301330147203808d9cec135d82015215fe7a14c7313" + }, + "capture_element_screenshot": { + "name": "capture_element_screenshot", + "doc": "Captures a screenshot from the element identified by ``locator`` and embeds it into log file.\n\n See `Capture Page Screenshot` for details about ``filename`` argument.\n See the `Locating elements` section for details about the locator\n syntax.\n\n An absolute path to the created element screenshot is returned.\n\n Support for capturing the screenshot from an element has limited support\n among browser vendors. Please check the browser vendor driver documentation\n does the browser support capturing a screenshot from an element.\n\n New in SeleniumLibrary 3.3. Support for EMBED is new in SeleniumLibrary 4.2.\n\n Examples:\n | `Capture Element Screenshot` | id:image_id | |\n | `Capture Element Screenshot` | id:image_id | ${OUTPUTDIR}/id_image_id-1.png |\n | `Capture Element Screenshot` | id:image_id | EMBED |\n ", + "sha256": "a5dabc5a6525bca9796834b47e1fff61557439b12dd78240701233af0b95c73f" + }, + "capture_page_screenshot": { + "name": "capture_page_screenshot", + "doc": "Takes a screenshot of the current page and embeds it into a log file.\n\n ``filename`` argument specifies the name of the file to write the\n screenshot into. The directory where screenshots are saved can be\n set when `importing` the library or by using the `Set Screenshot\n Directory` keyword. If the directory is not configured, screenshots\n are saved to the same directory where Robot Framework's log file is\n written.\n\n If ``filename`` equals to EMBED (case insensitive), then screenshot\n is embedded as Base64 image to the log.html. In this case file is not\n created in the filesystem.\n\n Starting from SeleniumLibrary 1.8, if ``filename`` contains marker\n ``{index}``, it will be automatically replaced with an unique running\n index, preventing files to be overwritten. Indices start from 1,\n and how they are represented can be customized using Python's\n [https://docs.python.org/3/library/string.html#format-string-syntax|\n format string syntax].\n\n An absolute path to the created screenshot file is returned or if\n ``filename`` equals to EMBED, word `EMBED` is returned.\n\n Support for EMBED is new in SeleniumLibrary 4.2\n\n Examples:\n | `Capture Page Screenshot` | |\n | `File Should Exist` | ${OUTPUTDIR}/selenium-screenshot-1.png |\n | ${path} = | `Capture Page Screenshot` |\n | `File Should Exist` | ${OUTPUTDIR}/selenium-screenshot-2.png |\n | `File Should Exist` | ${path} |\n | `Capture Page Screenshot` | custom_name.png |\n | `File Should Exist` | ${OUTPUTDIR}/custom_name.png |\n | `Capture Page Screenshot` | custom_with_index_{index}.png |\n | `File Should Exist` | ${OUTPUTDIR}/custom_with_index_1.png |\n | `Capture Page Screenshot` | formatted_index_{index:03}.png |\n | `File Should Exist` | ${OUTPUTDIR}/formatted_index_001.png |\n | `Capture Page Screenshot` | EMBED |\n | `File Should Not Exist` | EMBED |\n ", + "sha256": "271132ea5ad25ba3e6182db7560e7eaf512df0bae8f437f756419b9611a4bebe" + }, + "set_screenshot_directory": { + "name": "set_screenshot_directory", + "doc": "Sets the directory for captured screenshots.\n\n ``path`` argument specifies the absolute path to a directory where\n the screenshots should be written to. If the directory does not\n exist, it will be created. The directory can also be set when\n `importing` the library. If it is not configured anywhere,\n screenshots are saved to the same directory where Robot Framework's\n log file is written.\n\n If ``path`` equals to EMBED (case insensitive) and\n `Capture Page Screenshot` or `capture Element Screenshot` keywords\n filename argument is not changed from the default value, then\n the page or element screenshot is embedded as Base64 image to\n the log.html.\n\n The previous value is returned and can be used to restore\n the original value later if needed.\n\n Returning the previous value is new in SeleniumLibrary 3.0.\n The persist argument was removed in SeleniumLibrary 3.2 and\n EMBED is new in SeleniumLibrary 4.2.\n ", + "sha256": "c8241dd4f1113b3db620de1f45f2390c227b081400b04e0178561dde2c38748e" + }, + "get_list_items": { + "name": "get_list_items", + "doc": "Returns all labels or values of selection list ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n Returns visible labels by default, but values can be returned by\n setting the ``values`` argument to a true value (see `Boolean\n arguments`).\n\n Example:\n | ${labels} = | `Get List Items` | mylist | |\n | ${values} = | `Get List Items` | css:#example select | values=True |\n\n Support to return values is new in SeleniumLibrary 3.0.\n ", + "sha256": "60f7293239f288f08276b8fa63d98a6be52ff42a0627b9b0da14ba6dab51bd94" + }, + "get_selected_list_label": { + "name": "get_selected_list_label", + "doc": "Returns the label of selected option from selection list ``locator``.\n\n If there are multiple selected options, the label of the first option\n is returned.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "f9281509d3c4ac39f4b98d9d9d4f0f2dd6b579c37204b33ec7d47b6bef999672" + }, + "get_selected_list_labels": { + "name": "get_selected_list_labels", + "doc": "Returns labels of selected options from selection list ``locator``.\n\n Starting from SeleniumLibrary 3.0, returns an empty list if there\n are no selections. In earlier versions, this caused an error.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "e3bf2c1db04dbb52c99c7397065da52699bb4b7bdc5ceaeb45d525e8176acb48" + }, + "get_selected_list_value": { + "name": "get_selected_list_value", + "doc": "Returns the value of selected option from selection list ``locator``.\n\n If there are multiple selected options, the value of the first option\n is returned.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "2b935dd4627ca62d92a311569036b2978032aa67e542f5b7ef91a514f01f323d" + }, + "get_selected_list_values": { + "name": "get_selected_list_values", + "doc": "Returns values of selected options from selection list ``locator``.\n\n Starting from SeleniumLibrary 3.0, returns an empty list if there\n are no selections. In earlier versions, this caused an error.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "83b79c56056a6d51529e36a093ba14ec0b805a96bdb9e6870214eb4de987bea6" + }, + "list_selection_should_be": { + "name": "list_selection_should_be", + "doc": "Verifies selection list ``locator`` has ``expected`` options selected.\n\n It is possible to give expected options both as visible labels and\n as values. Starting from SeleniumLibrary 3.0, mixing labels and\n values is not possible. Order of the selected options is not\n validated.\n\n If no expected options are given, validates that the list has\n no selections. A more explicit alternative is using `List Should\n Have No Selections`.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n Examples:\n | `List Selection Should Be` | gender | Female | |\n | `List Selection Should Be` | interests | Test Automation | Python |\n ", + "sha256": "1d70ccc8a2dc868e265fc29e9cbc2317799eb12d0dd3f21d61fa4ffea7a7e4c2" + }, + "list_should_have_no_selections": { + "name": "list_should_have_no_selections", + "doc": "Verifies selection list ``locator`` has no options selected.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "429fc50c47319d8267bc5c2306a7d1d191a124d457a6f6655bb4ff5d64d71def" + }, + "page_should_contain_list": { + "name": "page_should_contain_list", + "doc": "Verifies selection list ``locator`` is found from current page.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "9ad2d87bd51bee3365d5ca32153adae2ea4b137f916f07fc39416a54aa117bf6" + }, + "page_should_not_contain_list": { + "name": "page_should_not_contain_list", + "doc": "Verifies selection list ``locator`` is not found from current page.\n\n See `Page Should Contain Element` for an explanation about ``message``\n and ``loglevel`` arguments.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "2f2e58b399f73b2ab4dc795368b0b18b9a63c37e2764de722d897039d6e7881c" + }, + "select_all_from_list": { + "name": "select_all_from_list", + "doc": "Selects all options from multi-selection list ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "7113bdf3faec639e3bdb3b1beb09c526dec522a0181ae11fd94398fdfb3f6fd2" + }, + "select_from_list_by_index": { + "name": "select_from_list_by_index", + "doc": "Selects options from selection list ``locator`` by ``indexes``.\n\n Indexes of list options start from 0.\n\n If more than one option is given for a single-selection list,\n the last value will be selected. With multi-selection lists all\n specified options are selected, but possible old selections are\n not cleared.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "220f77e512662cfff307efa29f5b46dba2e0d1b04760707cface96f63ff87e7c" + }, + "select_from_list_by_label": { + "name": "select_from_list_by_label", + "doc": "Selects options from selection list ``locator`` by ``labels``.\n\n If more than one option is given for a single-selection list,\n the last value will be selected. With multi-selection lists all\n specified options are selected, but possible old selections are\n not cleared.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "12c2af99cb8c78b6edd06ee17d902a575d1a2a4932d21bb67b040233a5a80318" + }, + "select_from_list_by_value": { + "name": "select_from_list_by_value", + "doc": "Selects options from selection list ``locator`` by ``values``.\n\n If more than one option is given for a single-selection list,\n the last value will be selected. With multi-selection lists all\n specified options are selected, but possible old selections are\n not cleared.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "9989cd962aeddb746a6ac8c632023bb9fbbe1ae832ae618635fb1c072049d7ab" + }, + "unselect_all_from_list": { + "name": "unselect_all_from_list", + "doc": "Unselects all options from multi-selection list ``locator``.\n\n See the `Locating elements` section for details about the locator\n syntax.\n\n New in SeleniumLibrary 3.0.\n ", + "sha256": "e273c674b217707452b897e66ccfa2ff12ef2279198364b4f95350b0cc557c4c" + }, + "unselect_from_list_by_index": { + "name": "unselect_from_list_by_index", + "doc": "Unselects options from selection list ``locator`` by ``indexes``.\n\n Indexes of list options start from 0. This keyword works only with\n multi-selection lists.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "5aac4cc2fa0bec90621d29b2eac7064d18510c447b7357d8eb5948d2cd459cef" + }, + "unselect_from_list_by_label": { + "name": "unselect_from_list_by_label", + "doc": "Unselects options from selection list ``locator`` by ``labels``.\n\n This keyword works only with multi-selection lists.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "3dfe87450d9a1a8cad3f8cad3e159b8bd4c3e25f25f91dd747aeb23403b18ab5" + }, + "unselect_from_list_by_value": { + "name": "unselect_from_list_by_value", + "doc": "Unselects options from selection list ``locator`` by ``values``.\n\n This keyword works only with multi-selection lists.\n\n See the `Locating elements` section for details about the locator\n syntax.\n ", + "sha256": "7ee06a01319ea95e02d4ba34cfbc0d845cf5dbaf58244d93338760609a67ec02" + }, + "get_table_cell": { + "name": "get_table_cell", + "doc": "Returns contents of a table cell.\n\n The table is located using the ``locator`` argument and its cell\n found using ``row`` and ``column``. See the `Locating elements`\n section for details about the locator syntax.\n\n Both row and column indexes start from 1, and header and footer\n rows are included in the count. It is possible to refer to rows\n and columns from the end by using negative indexes so that -1\n is the last row/column, -2 is the second last, and so on.\n\n All ```` and ```` elements anywhere in the table are\n considered to be cells.\n\n See `Page Should Contain` for an explanation about the ``loglevel``\n argument.\n ", + "sha256": "616f2d925fbd431f1cdde9427ff865b4f402806b2f15b99dfd033a96e0d0a42e" + }, + "table_cell_should_contain": { + "name": "table_cell_should_contain", + "doc": "Verifies table cell contains text ``expected``.\n\n See `Get Table Cell` that this keyword uses internally for\n an explanation about accepted arguments.\n ", + "sha256": "628c09aa35b649beda7c500e914fa906cf91f9eb30afad19973809784ee1f8d6" + }, + "table_column_should_contain": { + "name": "table_column_should_contain", + "doc": "Verifies table column contains text ``expected``.\n\n The table is located using the ``locator`` argument and its column\n found using ``column``. See the `Locating elements` section for\n details about the locator syntax.\n\n Column indexes start from 1. It is possible to refer to columns\n from the end by using negative indexes so that -1 is the last column,\n -2 is the second last, and so on.\n\n If a table contains cells that span multiple columns, those merged\n cells count as a single column.\n\n See `Page Should Contain Element` for an explanation about the\n ``loglevel`` argument.\n ", + "sha256": "e0f898ce00b22cd66e2f4c5ab1cdcbea733f294d53bc210ec33667dfcd1963de" + }, + "table_footer_should_contain": { + "name": "table_footer_should_contain", + "doc": "Verifies table footer contains text ``expected``.\n\n Any ```` element inside ```` element is considered to\n be part of the footer.\n\n The table is located using the ``locator`` argument. See the\n `Locating elements` section for details about the locator syntax.\n\n See `Page Should Contain Element` for an explanation about the\n ``loglevel`` argument.\n ", + "sha256": "454fb3be070acb378460038572ed4268de8b18b96b3aaa903d3a1f0093147691" + }, + "table_header_should_contain": { + "name": "table_header_should_contain", + "doc": "Verifies table header contains text ``expected``.\n\n Any ```` element anywhere in the table is considered to be\n part of the header.\n\n The table is located using the ``locator`` argument. See the\n `Locating elements` section for details about the locator syntax.\n\n See `Page Should Contain Element` for an explanation about the\n ``loglevel`` argument.\n ", + "sha256": "66208e9741c9d18d1c09645bfcb9b54b4ffe2c104e5402c86f2cf54feb02de79" + }, + "table_row_should_contain": { + "name": "table_row_should_contain", + "doc": "Verifies that table row contains text ``expected``.\n\n The table is located using the ``locator`` argument and its column\n found using ``column``. See the `Locating elements` section for\n details about the locator syntax.\n\n Row indexes start from 1. It is possible to refer to rows\n from the end by using negative indexes so that -1 is the last row,\n -2 is the second last, and so on.\n\n If a table contains cells that span multiple rows, a match\n only occurs for the uppermost row of those merged cells.\n\n See `Page Should Contain Element` for an explanation about the\n ``loglevel`` argument.\n ", + "sha256": "2ad4f79443748abaa86e768fb0994f32a2d1386c435688727093fb0c1034d23f" + }, + "table_should_contain": { + "name": "table_should_contain", + "doc": "Verifies table contains text ``expected``.\n\n The table is located using the ``locator`` argument. See the\n `Locating elements` section for details about the locator syntax.\n\n See `Page Should Contain Element` for an explanation about the\n ``loglevel`` argument.\n ", + "sha256": "ea4dc362f588ab33332b985ea6ff059499de1e4c25bdbfceb6e6517cd36b24fc" + }, + "wait_for_condition": { + "name": "wait_for_condition", + "doc": "Waits until ``condition`` is true or ``timeout`` expires.\n\n The condition can be arbitrary JavaScript expression but it\n must return a value to be evaluated. See `Execute JavaScript` for\n information about accessing content on pages.\n\n Fails if the timeout expires before the condition becomes true. See\n the `Timeouts` section for more information about using timeouts\n and their default value.\n\n ``error`` can be used to override the default error message.\n\n Examples:\n | `Wait For Condition` | return document.title == \"New Title\" |\n | `Wait For Condition` | return jQuery.active == 0 |\n | `Wait For Condition` | style = document.querySelector('h1').style; return style.background == \"red\" && style.color == \"white\" |\n ", + "sha256": "4998ab3cee46a578df2b064d390401d2ec0268454607ef194db5c0d3d73c81db" + }, + "wait_until_element_contains": { + "name": "wait_until_element_contains", + "doc": "Waits until the element ``locator`` contains ``text``.\n\n Fails if ``timeout`` expires before the text appears. See\n the `Timeouts` section for more information about using timeouts and\n their default value and the `Locating elements` section for details\n about the locator syntax.\n\n ``error`` can be used to override the default error message.\n ", + "sha256": "982c68220bb622a3d985c04b39ea3bc11b20437e73bcf8e38d51ed7e2032852c" + }, + "wait_until_element_does_not_contain": { + "name": "wait_until_element_does_not_contain", + "doc": "Waits until the element ``locator`` does not contain ``text``.\n\n Fails if ``timeout`` expires before the text disappears. See\n the `Timeouts` section for more information about using timeouts and\n their default value and the `Locating elements` section for details\n about the locator syntax.\n\n ``error`` can be used to override the default error message.\n ", + "sha256": "a2b8bc5ee7de21f06e79317935026beddee2105ae645c22b322446dd5a8be0ad" + }, + "wait_until_element_is_enabled": { + "name": "wait_until_element_is_enabled", + "doc": "Waits until the element ``locator`` is enabled.\n\n Element is considered enabled if it is not disabled nor read-only.\n\n Fails if ``timeout`` expires before the element is enabled. See\n the `Timeouts` section for more information about using timeouts and\n their default value and the `Locating elements` section for details\n about the locator syntax.\n\n ``error`` can be used to override the default error message.\n\n Considering read-only elements to be disabled is a new feature\n in SeleniumLibrary 3.0.\n ", + "sha256": "6202e0635b377e2e7d5eaa091eb6a582b64bc49f9d5edf6ddeb7754723015543" + }, + "wait_until_element_is_not_visible": { + "name": "wait_until_element_is_not_visible", + "doc": "Waits until the element ``locator`` is not visible.\n\n Fails if ``timeout`` expires before the element is not visible. See\n the `Timeouts` section for more information about using timeouts and\n their default value and the `Locating elements` section for details\n about the locator syntax.\n\n ``error`` can be used to override the default error message.\n ", + "sha256": "e112e160d739b0cd0f8730703738cc0692e1c0d57e42308b6d50206db23e6d52" + }, + "wait_until_element_is_visible": { + "name": "wait_until_element_is_visible", + "doc": "Waits until the element ``locator`` is visible.\n\n Fails if ``timeout`` expires before the element is visible. See\n the `Timeouts` section for more information about using timeouts and\n their default value and the `Locating elements` section for details\n about the locator syntax.\n\n ``error`` can be used to override the default error message.\n ", + "sha256": "90878c583a727db5da943e7f532efa4e73c59a525a0107233fd59740bb9dd116" + }, + "wait_until_location_contains": { + "name": "wait_until_location_contains", + "doc": "Waits until the current URL contains ``expected``.\n\n The ``expected`` argument contains the expected value in url.\n\n Fails if ``timeout`` expires before the location contains. See\n the `Timeouts` section for more information about using timeouts\n and their default value.\n\n The ``message`` argument can be used to override the default error\n message.\n\n New in SeleniumLibrary 4.0\n ", + "sha256": "33b91c79fe956c37284bccdb56d318e679ec774ca1565db5e2140250b6b46fb5" + }, + "wait_until_location_does_not_contain": { + "name": "wait_until_location_does_not_contain", + "doc": "Waits until the current URL does not contains ``location``.\n\n The ``location`` argument contains value not expected in url.\n\n Fails if ``timeout`` expires before the location not contains. See\n the `Timeouts` section for more information about using timeouts\n and their default value.\n\n The ``message`` argument can be used to override the default error\n message.\n\n New in SeleniumLibrary 4.3\n ", + "sha256": "5ea0b9da22370c90d509d3e4a8aad47b69652b2bd0ce5b29a9264508d4bea432" + }, + "wait_until_location_is": { + "name": "wait_until_location_is", + "doc": "Waits until the current URL is ``expected``.\n\n The ``expected`` argument is the expected value in url.\n\n Fails if ``timeout`` expires before the location is. See\n the `Timeouts` section for more information about using timeouts\n and their default value.\n\n The ``message`` argument can be used to override the default error\n message.\n\n New in SeleniumLibrary 4.0\n ", + "sha256": "2a0604e9e096908cda4caef1486d56310d6f10d0d974804c96a32a0492eb1f82" + }, + "wait_until_location_is_not": { + "name": "wait_until_location_is_not", + "doc": "Waits until the current URL is not ``location``.\n\n The ``location`` argument is the unexpected value in url.\n\n Fails if ``timeout`` expires before the location is not. See\n the `Timeouts` section for more information about using timeouts\n and their default value.\n\n The ``message`` argument can be used to override the default error\n message.\n\n New in SeleniumLibrary 4.3\n ", + "sha256": "96f19cceb6f263cde977b3dfd4b90d06691a1533ebef77c9c5ef1f0e0925e228" + }, + "wait_until_page_contains": { + "name": "wait_until_page_contains", + "doc": "Waits until ``text`` appears on the current page.\n\n Fails if ``timeout`` expires before the text appears. See\n the `Timeouts` section for more information about using timeouts\n and their default value.\n\n ``error`` can be used to override the default error message.\n ", + "sha256": "2e6b9f7e424ed5ba676c82ce9b6ae964050a5fb7b47baa35a3f94125107d9e57" + }, + "wait_until_page_contains_element": { + "name": "wait_until_page_contains_element", + "doc": "Waits until the element ``locator`` appears on the current page.\n\n Fails if ``timeout`` expires before the element appears. See\n the `Timeouts` section for more information about using timeouts and\n their default value and the `Locating elements` section for details\n about the locator syntax.\n\n ``error`` can be used to override the default error message.\n\n The ``limit`` argument can used to define how many elements the\n page should contain. When ``limit`` is `None` (default) page can\n contain one or more elements. When limit is a number, page must\n contain same number of elements.\n\n ``limit`` is new in SeleniumLibrary 4.4\n ", + "sha256": "712da49e8aff630cb2843522331935693ce334aea9ccb2aacb6c015af9c921b5" + }, + "wait_until_page_does_not_contain": { + "name": "wait_until_page_does_not_contain", + "doc": "Waits until ``text`` disappears from the current page.\n\n Fails if ``timeout`` expires before the text disappears. See\n the `Timeouts` section for more information about using timeouts\n and their default value.\n\n ``error`` can be used to override the default error message.\n ", + "sha256": "96c2f8840c677afdb9f207107bf3f7bbdfb9d1b56e3ce887cf34a88e3e273974" + }, + "wait_until_page_does_not_contain_element": { + "name": "wait_until_page_does_not_contain_element", + "doc": "Waits until the element ``locator`` disappears from the current page.\n\n Fails if ``timeout`` expires before the element disappears. See\n the `Timeouts` section for more information about using timeouts and\n their default value and the `Locating elements` section for details\n about the locator syntax.\n\n ``error`` can be used to override the default error message.\n\n The ``limit`` argument can used to define how many elements the\n page should not contain. When ``limit`` is `None` (default) page can`t\n contain any elements. When limit is a number, page must not\n contain same number of elements.\n\n ``limit`` is new in SeleniumLibrary 4.4\n ", + "sha256": "081d0393a8d8f100d9db65f81170222f4a6678fcc2703a3e123c907ef5ade430" + }, + "close_window": { + "name": "close_window", + "doc": "Closes currently opened and selected browser window/tab. ", + "sha256": "8d00f3bcf62126a5fcc61ca14d62631ad918c2993ee9e8f2641cb57595b591bb" + }, + "get_locations": { + "name": "get_locations", + "doc": "Returns and logs URLs of all windows of the selected browser.\n\n *Browser Scope:*\n\n The ``browser`` argument specifies the browser that shall return\n its windows information.\n\n - ``browser`` can be ``index_or_alias`` like in `Switch Browser`.\n\n - If ``browser`` is ``CURRENT`` (default, case-insensitive)\n the currently active browser is selected.\n\n - If ``browser`` is ``ALL`` (case-insensitive)\n the window information of all windows of all opened browsers are returned.", + "sha256": "3e73811fa673371891cffa16aa99f24fa6dbc87ff826d0d84be6d54fc937163c" + }, + "get_window_handles": { + "name": "get_window_handles", + "doc": "Returns all child window handles of the selected browser as a list.\n\n Can be used as a list of windows to exclude with `Select Window`.\n\n How to select the ``browser`` scope of this keyword, see `Get Locations`.\n\n Prior to SeleniumLibrary 3.0, this keyword was named `List Windows`.\n ", + "sha256": "b051b51a36766e2a3c748a2ecbb76ed6516a20cec807a38d29a96f95c5ea7efa" + }, + "get_window_identifiers": { + "name": "get_window_identifiers", + "doc": "Returns and logs id attributes of all windows of the selected browser.\n\n How to select the ``browser`` scope of this keyword, see `Get Locations`.", + "sha256": "9342df3471d9923e299c60511d11006762b1797802153c97ac0451adcdd5e0bf" + }, + "get_window_names": { + "name": "get_window_names", + "doc": "Returns and logs names of all windows of the selected browser.\n\n How to select the ``browser`` scope of this keyword, see `Get Locations`.", + "sha256": "557778bcbb2b4be2e575416f5422c8077397f2e7d7614e3b064fe3f222bf3225" + }, + "get_window_position": { + "name": "get_window_position", + "doc": "Returns current window position.\n\n The position is relative to the top left corner of the screen. Returned\n values are integers. See also `Set Window Position`.\n\n Example:\n | ${x} | ${y}= | `Get Window Position` |\n ", + "sha256": "c9f1ab8ee31517bc91a6ae9f3dd3782c695f0c3c64adf1639fc3e34ea85e7d9c" + }, + "get_window_size": { + "name": "get_window_size", + "doc": "Returns current window width and height as integers.\n\n See also `Set Window Size`.\n\n If ``inner`` parameter is set to True, keyword returns\n HTML DOM window.innerWidth and window.innerHeight properties.\n See `Boolean arguments` for more details on how to set boolean\n arguments. The ``inner`` is new in SeleniumLibrary 4.0.\n\n Example:\n | ${width} | ${height}= | `Get Window Size` | |\n | ${width} | ${height}= | `Get Window Size` | True |\n ", + "sha256": "d9fc8a6bc4dd38749c761722027b783dfd74ff3c69d16ad3e4ceceb162f2ed64" + }, + "get_window_titles": { + "name": "get_window_titles", + "doc": "Returns and logs titles of all windows of the selected browser.\n\n How to select the ``browser`` scope of this keyword, see `Get Locations`.", + "sha256": "7b2a62a9e808f584ec9674faae954855135aec5ac168ec0b929b11ac73f7fcec" + }, + "maximize_browser_window": { + "name": "maximize_browser_window", + "doc": "Maximizes current browser window.", + "sha256": "de016b8b98dc0a25f624060424c8ae449cc680990baf8789da09181b2643d77b" + }, + "minimize_browser_window": { + "name": "minimize_browser_window", + "doc": "Minimizes current browser window.", + "sha256": "6a99ddaa41cde69ae82c33df6d43976d9ad76a358be5d4e35f065895e94e95db" + }, + "set_window_position": { + "name": "set_window_position", + "doc": "Sets window position using ``x`` and ``y`` coordinates.\n\n The position is relative to the top left corner of the screen,\n but some browsers exclude possible task bar set by the operating\n system from the calculation. The actual position may thus be\n different with different browsers.\n\n Values can be given using strings containing numbers or by using\n actual numbers. See also `Get Window Position`.\n\n Example:\n | `Set Window Position` | 100 | 200 |\n ", + "sha256": "d9c3d6dc138cd350941a1660e5601dbc4441ee6c0a7df08902c76dd15953017c" + }, + "set_window_size": { + "name": "set_window_size", + "doc": "Sets current windows size to given ``width`` and ``height``.\n\n Values can be given using strings containing numbers or by using\n actual numbers. See also `Get Window Size`.\n\n Browsers have a limit on their minimum size. Trying to set them\n smaller will cause the actual size to be bigger than the requested\n size.\n\n If ``inner`` parameter is set to True, keyword sets the necessary\n window width and height to have the desired HTML DOM _window.innerWidth_\n and _window.innerHeight_. See `Boolean arguments` for more details on how to set boolean\n arguments.\n\n The ``inner`` argument is new since SeleniumLibrary 4.0.\n\n This ``inner`` argument does not support Frames. If a frame is selected,\n switch to default before running this.\n\n Example:\n | `Set Window Size` | 800 | 600 | |\n | `Set Window Size` | 800 | 600 | True |\n ", + "sha256": "31b5febddcb935b20320728accc28a892b8a0956301646827aa8c7c74e1cdfec" + }, + "switch_window": { + "name": "switch_window", + "doc": "Switches to browser window matching ``locator``.\n\n If the window is found, all subsequent commands use the selected\n window, until this keyword is used again. If the window is not\n found, this keyword fails. The previous windows handle is returned\n and can be used to switch back to it later.\n\n Notice that alerts should be handled with\n `Handle Alert` or other alert related keywords.\n\n The ``locator`` can be specified using different strategies somewhat\n similarly as when `locating elements` on pages.\n\n - By default, the ``locator`` is matched against window handle, name,\n title, and URL. Matching is done in that order and the first\n matching window is selected.\n\n - The ``locator`` can specify an explicit strategy by using the format\n ``strategy:value`` (recommended) or ``strategy=value``. Supported\n strategies are ``name``, ``title``, and ``url``. These matches windows\n using their name, title, or URL, respectively. Additionally, ``default``\n can be used to explicitly use the default strategy explained above.\n\n - If the ``locator`` is ``NEW`` (case-insensitive), the latest\n opened window is selected. It is an error if this is the same\n as the current window.\n\n - If the ``locator`` is ``MAIN`` (default, case-insensitive),\n the main window is selected.\n\n - If the ``locator`` is ``CURRENT`` (case-insensitive), nothing is\n done. This effectively just returns the current window handle.\n\n - If the ``locator`` is not a string, it is expected to be a list\n of window handles _to exclude_. Such a list of excluded windows\n can be got from `Get Window Handles` before doing an action that\n opens a new window.\n\n The ``timeout`` is used to specify how long keyword will poll to select\n the new window. The ``timeout`` is new in SeleniumLibrary 3.2.\n\n Example:\n | `Click Link` | popup1 | | # Open new window |\n | `Switch Window` | example | | # Select window using default strategy |\n | `Title Should Be` | Pop-up 1 | |\n | `Click Button` | popup2 | | # Open another window |\n | ${handle} = | `Switch Window` | NEW | # Select latest opened window |\n | `Title Should Be` | Pop-up 2 | |\n | `Switch Window` | ${handle} | | # Select window using handle |\n | `Title Should Be` | Pop-up 1 | |\n | `Switch Window` | MAIN | | # Select the main window |\n | `Title Should Be` | Main | |\n | ${excludes} = | `Get Window Handles` | | # Get list of current windows |\n | `Click Link` | popup3 | | # Open one more window |\n | `Switch Window` | ${excludes} | | # Select window using excludes |\n | `Title Should Be` | Pop-up 3 | |\n\n The ``browser`` argument allows with ``index_or_alias`` to implicitly switch to\n a specific browser when switching to a window. See `Switch Browser`\n\n - If the ``browser`` is ``CURRENT`` (case-insensitive), no other browser is\n selected.\n\n *NOTE:*\n\n - The ``strategy:value`` syntax is only supported by SeleniumLibrary\n 3.0 and newer.\n - Prior to SeleniumLibrary 3.0 matching windows by name, title\n and URL was case-insensitive.\n - Earlier versions supported aliases ``None``, ``null`` and the\n empty string for selecting the main window, and alias ``self``\n for selecting the current window. Support for these aliases was\n removed in SeleniumLibrary 3.2.\n ", + "sha256": "2ae583a5179810f31a4f7ae665918443d1f068c53e255c552b51bd1f5205c608" + }, + "__init__": { + "name": "__init__", + "doc": "2 SeleniumLibrary is a web testing library for Robot Framework.\n\nThis document explains how to use keywords provided by SeleniumLibrary.\nFor information about installation, support, and more, please visit the\n[https://github.com/robotframework/SeleniumLibrary|project pages].\nFor more information about Robot Framework, see http://robotframework.org.\n\nSeleniumLibrary uses the Selenium WebDriver modules internally to\ncontrol a web browser. See http://seleniumhq.org for more information\nabout Selenium in general and SeleniumLibrary README.rst\n[https://github.com/robotframework/SeleniumLibrary#browser-drivers|Browser drivers chapter]\nfor more details about WebDriver binary installation.\n\n%TOC%\n\n= Locating elements =\n\nAll keywords in SeleniumLibrary that need to interact with an element\non a web page take an argument typically named ``locator`` that specifies\nhow to find the element. Most often the locator is given as a string\nusing the locator syntax described below, but `using WebElements` is\npossible too.\n\n== Locator syntax ==\n\nSeleniumLibrary supports finding elements based on different strategies\nsuch as the element id, XPath expressions, or CSS selectors. The strategy\ncan either be explicitly specified with a prefix or the strategy can be\nimplicit.\n\n=== Default locator strategy ===\n\nBy default, locators are considered to use the keyword specific default\nlocator strategy. All keywords support finding elements based on ``id``\nand ``name`` attributes, but some keywords support additional attributes\nor other values that make sense in their context. For example, `Click\nLink` supports the ``href`` attribute and the link text and addition\nto the normal ``id`` and ``name``.\n\nExamples:\n\n| `Click Element` | example | # Match based on ``id`` or ``name``. |\n| `Click Link` | example | # Match also based on link text and ``href``. |\n| `Click Button` | example | # Match based on ``id``, ``name`` or ``value``. |\n\nIf a locator accidentally starts with a prefix recognized as `explicit\nlocator strategy` or `implicit XPath strategy`, it is possible to use\nthe explicit ``default`` prefix to enable the default strategy.\n\nExamples:\n\n| `Click Element` | name:foo | # Find element with name ``foo``. |\n| `Click Element` | default:name:foo | # Use default strategy with value ``name:foo``. |\n| `Click Element` | //foo | # Find element using XPath ``//foo``. |\n| `Click Element` | default: //foo | # Use default strategy with value ``//foo``. |\n\n=== Explicit locator strategy ===\n\nThe explicit locator strategy is specified with a prefix using either\nsyntax ``strategy:value`` or ``strategy=value``. The former syntax\nis preferred because the latter is identical to Robot Framework's\n[http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#named-argument-syntax|\nnamed argument syntax] and that can cause problems. Spaces around\nthe separator are ignored, so ``id:foo``, ``id: foo`` and ``id : foo``\nare all equivalent.\n\nLocator strategies that are supported by default are listed in the table\nbelow. In addition to them, it is possible to register `custom locators`.\n\n| = Strategy = | = Match based on = | = Example = |\n| id | Element ``id``. | ``id:example`` |\n| name | ``name`` attribute. | ``name:example`` |\n| identifier | Either ``id`` or ``name``. | ``identifier:example`` |\n| class | Element ``class``. | ``class:example`` |\n| tag | Tag name. | ``tag:div`` |\n| xpath | XPath expression. | ``xpath://div[@id=\"example\"]`` |\n| css | CSS selector. | ``css:div#example`` |\n| dom | DOM expression. | ``dom:document.images[5]`` |\n| link | Exact text a link has. | ``link:The example`` |\n| partial link | Partial link text. | ``partial link:he ex`` |\n| sizzle | Sizzle selector deprecated. | ``sizzle:div.example`` |\n| data | Element ``data-*`` attribute | ``data:id:my_id`` |\n| jquery | jQuery expression. | ``jquery:div.example`` |\n| default | Keyword specific default behavior. | ``default:example`` |\n\nSee the `Default locator strategy` section below for more information\nabout how the default strategy works. Using the explicit ``default``\nprefix is only necessary if the locator value itself accidentally\nmatches some of the explicit strategies.\n\nDifferent locator strategies have different pros and cons. Using ids,\neither explicitly like ``id:foo`` or by using the `default locator\nstrategy` simply like ``foo``, is recommended when possible, because\nthe syntax is simple and locating elements by id is fast for browsers.\nIf an element does not have an id or the id is not stable, other\nsolutions need to be used. If an element has a unique tag name or class,\nusing ``tag``, ``class`` or ``css`` strategy like ``tag:h1``,\n``class:example`` or ``css:h1.example`` is often an easy solution. In\nmore complex cases using XPath expressions is typically the best\napproach. They are very powerful but a downside is that they can also\nget complex.\n\nExamples:\n\n| `Click Element` | id:foo | # Element with id 'foo'. |\n| `Click Element` | css:div#foo h1 | # h1 element under div with id 'foo'. |\n| `Click Element` | xpath: //div[@id=\"foo\"]//h1 | # Same as the above using XPath, not CSS. |\n| `Click Element` | xpath: //*[contains(text(), \"example\")] | # Element containing text 'example'. |\n\n*NOTE:*\n\n- The ``strategy:value`` syntax is only supported by SeleniumLibrary 3.0\n and newer.\n- Using the ``sizzle`` strategy or its alias ``jquery`` requires that\n the system under test contains the jQuery library.\n- Prior to SeleniumLibrary 3.0, table related keywords only supported\n ``xpath``, ``css`` and ``sizzle/jquery`` strategies.\n- ``data`` strategy is conveniance locator that will construct xpath from the parameters.\n If you have element like `
`, you locate the element via\n ``data:automation:automation-id-2``. This feature was added in SeleniumLibrary 5.2.0\n\n=== Implicit XPath strategy ===\n\nIf the locator starts with ``//`` or multiple opening parenthesis in front\nof the ``//``, the locator is considered to be an XPath expression. In other\nwords, using ``//div`` is equivalent to using explicit ``xpath://div`` and\n``((//div))`` is equivalent to using explicit ``xpath:((//div))``\n\nExamples:\n\n| `Click Element` | //div[@id=\"foo\"]//h1 |\n| `Click Element` | (//div)[2] |\n\nThe support for the ``(//`` prefix is new in SeleniumLibrary 3.0.\nSupporting multiple opening parenthesis is new in SeleniumLibrary 5.0.\n\n=== Chaining locators ===\n\nIt is possible chain multiple locators together as single locator. Each chained locator must start with locator\nstrategy. Chained locators must be separated with single space, two greater than characters and followed with\nspace. It is also possible mix different locator strategies, example css or xpath. Also a list can also be\nused to specify multiple locators. This is useful, is some part of locator would match as the locator separator\nbut it should not. Or if there is need to existing WebElement as locator.\n\nAlthough all locators support chaining, some locator strategies do not abey the chaining. This is because\nsome locator strategies use JavaScript to find elements and JavaScript is executed for the whole browser context\nand not for the element found be the previous locator. Chaining is supported by locator strategies which\nare based on Selenium API, like `xpath` or `css`, but example chaining is not supported by `sizzle` or `jquery\n\nExamples:\n| `Click Element` | css:.bar >> xpath://a | # To find a link which is present after an element with class \"bar\" |\n\nList examples:\n| ${locator_list} = | `Create List` | css:div#div_id | xpath://*[text(), \" >> \"] |\n| `Page Should Contain Element` | ${locator_list} | | |\n| ${element} = | Get WebElement | xpath://*[text(), \" >> \"] | |\n| ${locator_list} = | `Create List` | css:div#div_id | ${element} |\n| `Page Should Contain Element` | ${locator_list} | | |\n\nChaining locators in new in SeleniumLibrary 5.0\n\n== Using WebElements ==\n\nIn addition to specifying a locator as a string, it is possible to use\nSelenium's WebElement objects. This requires first getting a WebElement,\nfor example, by using the `Get WebElement` keyword.\n\n| ${elem} = | `Get WebElement` | id:example |\n| `Click Element` | ${elem} | |\n\n== Custom locators ==\n\nIf more complex lookups are required than what is provided through the\ndefault locators, custom lookup strategies can be created. Using custom\nlocators is a two part process. First, create a keyword that returns\na WebElement that should be acted on:\n\n| Custom Locator Strategy | [Arguments] | ${browser} | ${locator} | ${tag} | ${constraints} |\n| | ${element}= | Execute Javascript | return window.document.getElementById('${locator}'); |\n| | [Return] | ${element} |\n\nThis keyword is a reimplementation of the basic functionality of the\n``id`` locator where ``${browser}`` is a reference to a WebDriver\ninstance and ``${locator}`` is the name of the locator strategy. To use\nthis locator, it must first be registered by using the\n`Add Location Strategy` keyword:\n\n| `Add Location Strategy` | custom | Custom Locator Strategy |\n\nThe first argument of `Add Location Strategy` specifies the name of\nthe strategy and it must be unique. After registering the strategy,\nthe usage is the same as with other locators:\n\n| `Click Element` | custom:example |\n\nSee the `Add Location Strategy` keyword for more details.\n\n= Browser and Window =\n\nThere is different conceptual meaning when SeleniumLibrary talks\nabout windows or browsers. This chapter explains those differences.\n\n== Browser ==\n\nWhen `Open Browser` or `Create WebDriver` keyword is called, it\nwill create a new Selenium WebDriver instance by using the\n[https://www.seleniumhq.org/docs/03_webdriver.jsp|Selenium WebDriver]\nAPI. In SeleniumLibrary terms, a new browser is created. It is\npossible to start multiple independent browsers (Selenium Webdriver\ninstances) at the same time, by calling `Open Browser` or\n`Create WebDriver` multiple times. These browsers are usually\nindependent of each other and do not share data like cookies,\nsessions or profiles. Typically when the browser starts, it\ncreates a single window which is shown to the user.\n\n== Window ==\n\nWindows are the part of a browser that loads the web site and presents\nit to the user. All content of the site is the content of the window.\nWindows are children of a browser. In SeleniumLibrary browser is a\nsynonym for WebDriver instance. One browser may have multiple\nwindows. Windows can appear as tabs, as separate windows or pop-ups with\ndifferent position and size. Windows belonging to the same browser\ntypically share the sessions detail, like cookies. If there is a\nneed to separate sessions detail, example login with two different\nusers, two browsers (Selenium WebDriver instances) must be created.\nNew windows can be opened example by the application under test or\nby example `Execute Javascript` keyword:\n\n| `Execute Javascript` window.open() # Opens a new window with location about:blank\n\nThe example below opens multiple browsers and windows,\nto demonstrate how the different keywords can be used to interact\nwith browsers, and windows attached to these browsers.\n\nStructure:\n| BrowserA\n| Window 1 (location=https://robotframework.org/)\n| Window 2 (location=https://robocon.io/)\n| Window 3 (location=https://github.com/robotframework/)\n|\n| BrowserB\n| Window 1 (location=https://github.com/)\n\nExample:\n| `Open Browser` | https://robotframework.org | ${BROWSER} | alias=BrowserA | # BrowserA with first window is opened. |\n| `Execute Javascript` | window.open() | | | # In BrowserA second window is opened. |\n| `Switch Window` | locator=NEW | | | # Switched to second window in BrowserA |\n| `Go To` | https://robocon.io | | | # Second window navigates to robocon site. |\n| `Execute Javascript` | window.open() | | | # In BrowserA third window is opened. |\n| ${handle} | `Switch Window` | locator=NEW | | # Switched to third window in BrowserA |\n| `Go To` | https://github.com/robotframework/ | | | # Third windows goes to robot framework github site. |\n| `Open Browser` | https://github.com | ${BROWSER} | alias=BrowserB | # BrowserB with first windows is opened. |\n| ${location} | `Get Location` | | | # ${location} is: https://www.github.com |\n| `Switch Window` | ${handle} | browser=BrowserA | | # BrowserA second windows is selected. |\n| ${location} | `Get Location` | | | # ${location} = https://robocon.io/ |\n| @{locations 1} | `Get Locations` | | | # By default, lists locations under the currectly active browser (BrowserA). |\n| @{locations 2} | `Get Locations` | browser=ALL | | # By using browser=ALL argument keyword list all locations from all browsers. |\n\nThe above example, @{locations 1} contains the following items:\nhttps://robotframework.org/, https://robocon.io/ and\nhttps://github.com/robotframework/'. The @{locations 2}\ncontains the following items: https://robotframework.org/,\nhttps://robocon.io/, https://github.com/robotframework/'\nand 'https://github.com/.\n\n= Timeouts, waits, and delays =\n\nThis section discusses different ways how to wait for elements to\nappear on web pages and to slow down execution speed otherwise.\nIt also explains the `time format` that can be used when setting various\ntimeouts, waits, and delays.\n\n== Timeout ==\n\nSeleniumLibrary contains various keywords that have an optional\n``timeout`` argument that specifies how long these keywords should\nwait for certain events or actions. These keywords include, for example,\n``Wait ...`` keywords and keywords related to alerts. Additionally\n`Execute Async Javascript`. Although it does not have ``timeout``,\nargument, uses a timeout to define how long asynchronous JavaScript\ncan run.\n\nThe default timeout these keywords use can be set globally either by\nusing the `Set Selenium Timeout` keyword or with the ``timeout`` argument\nwhen `importing` the library. If no default timeout is set globally, the\ndefault is 5 seconds. If None is specified for the timeout argument in the\nkeywords, the default is used. See `time format` below for supported\ntimeout syntax.\n\n== Implicit wait ==\n\nImplicit wait specifies the maximum time how long Selenium waits when\nsearching for elements. It can be set by using the `Set Selenium Implicit\nWait` keyword or with the ``implicit_wait`` argument when `importing`\nthe library. See [https://www.seleniumhq.org/docs/04_webdriver_advanced.jsp|\nSelenium documentation] for more information about this functionality.\n\nSee `time format` below for supported syntax.\n\n== Page load ==\nPage load timeout is the amount of time to wait for page load to complete\nuntil a timeout exception is raised.\n\nThe default page load timeout can be set globally\nwhen `importing` the library with the ``page_load_timeout`` argument\nor by using the `Set Selenium Page Load Timeout` keyword.\n\nSee `time format` below for supported timeout syntax.\n\nSupport for page load is new in SeleniumLibrary 6.1\n\n== Selenium speed ==\n\nSelenium execution speed can be slowed down globally by using `Set\nSelenium speed` keyword. This functionality is designed to be used for\ndemonstrating or debugging purposes. Using it to make sure that elements\nappear on a page is not a good idea. The above-explained timeouts\nand waits should be used instead.\n\nSee `time format` below for supported syntax.\n\n== Time format ==\n\nAll timeouts and waits can be given as numbers considered seconds\n(e.g. ``0.5`` or ``42``) or in Robot Framework's time syntax\n(e.g. ``1.5 seconds`` or ``1 min 30 s``). For more information about\nthe time syntax see the\n[http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#time-format|Robot Framework User Guide].\n\n= Run-on-failure functionality =\n\nSeleniumLibrary has a handy feature that it can automatically execute\na keyword if any of its own keywords fails. By default, it uses the\n`Capture Page Screenshot` keyword, but this can be changed either by\nusing the `Register Keyword To Run On Failure` keyword or with the\n``run_on_failure`` argument when `importing` the library. It is\npossible to use any keyword from any imported library or resource file.\n\nThe run-on-failure functionality can be disabled by using a special value\n``NOTHING`` or anything considered false (see `Boolean arguments`)\nsuch as ``NONE``.\n\n= Boolean arguments =\n\nStarting from 5.0 SeleniumLibrary relies on Robot Framework to perform the\nboolean conversion based on keyword arguments [https://docs.python.org/3/library/typing.html|type hint].\nMore details in Robot Framework\n[http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#supported-conversions|user guide]\n\nPlease note SeleniumLibrary 3 and 4 did have own custom methods to covert\narguments to boolean values.\n\n= EventFiringWebDriver =\n\nThe SeleniumLibrary offers support for\n[https://seleniumhq.github.io/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.event_firing_webdriver.html#module-selenium.webdriver.support.event_firing_webdriver|EventFiringWebDriver].\nSee the Selenium and SeleniumLibrary\n[https://github.com/robotframework/SeleniumLibrary/blob/master/docs/extending/extending.rst#EventFiringWebDriver|EventFiringWebDriver support]\ndocumentation for further details.\n\nEventFiringWebDriver is new in SeleniumLibrary 4.0\n\n= Thread support =\n\nSeleniumLibrary is not thread-safe. This is mainly due because the underlying\n[https://github.com/SeleniumHQ/selenium/wiki/Frequently-Asked-Questions#q-is-webdriver-thread-safe|\nSelenium tool is not thread-safe] within one browser/driver instance.\nBecause of the limitation in the Selenium side, the keywords or the\nAPI provided by the SeleniumLibrary is not thread-safe.\n\n= Plugins =\n\nSeleniumLibrary offers plugins as a way to modify and add library keywords and modify some of the internal\nfunctionality without creating a new library or hacking the source code. See\n[https://github.com/robotframework/SeleniumLibrary/blob/master/docs/extending/extending.rst#Plugins|plugin API]\ndocumentation for further details.\n\nPlugin API is new SeleniumLibrary 4.0", + "sha256": "3d660b78fb0d75d9f2f8265fa6f29967ae30b712f545661d64de0f05f2c1b913" + }, + "__intro__": { + "name": "__intro__", + "doc": "2 SeleniumLibrary is a web testing library for Robot Framework.\n\n This document explains how to use keywords provided by SeleniumLibrary.\n For information about installation, support, and more, please visit the\n [https://github.com/robotframework/SeleniumLibrary|project pages].\n For more information about Robot Framework, see http://robotframework.org.\n\n SeleniumLibrary uses the Selenium WebDriver modules internally to\n control a web browser. See http://seleniumhq.org for more information\n about Selenium in general and SeleniumLibrary README.rst\n [https://github.com/robotframework/SeleniumLibrary#browser-drivers|Browser drivers chapter]\n for more details about WebDriver binary installation.\n\n %TOC%\n\n = Locating elements =\n\n All keywords in SeleniumLibrary that need to interact with an element\n on a web page take an argument typically named ``locator`` that specifies\n how to find the element. Most often the locator is given as a string\n using the locator syntax described below, but `using WebElements` is\n possible too.\n\n == Locator syntax ==\n\n SeleniumLibrary supports finding elements based on different strategies\n such as the element id, XPath expressions, or CSS selectors. The strategy\n can either be explicitly specified with a prefix or the strategy can be\n implicit.\n\n === Default locator strategy ===\n\n By default, locators are considered to use the keyword specific default\n locator strategy. All keywords support finding elements based on ``id``\n and ``name`` attributes, but some keywords support additional attributes\n or other values that make sense in their context. For example, `Click\n Link` supports the ``href`` attribute and the link text and addition\n to the normal ``id`` and ``name``.\n\n Examples:\n\n | `Click Element` | example | # Match based on ``id`` or ``name``. |\n | `Click Link` | example | # Match also based on link text and ``href``. |\n | `Click Button` | example | # Match based on ``id``, ``name`` or ``value``. |\n\n If a locator accidentally starts with a prefix recognized as `explicit\n locator strategy` or `implicit XPath strategy`, it is possible to use\n the explicit ``default`` prefix to enable the default strategy.\n\n Examples:\n\n | `Click Element` | name:foo | # Find element with name ``foo``. |\n | `Click Element` | default:name:foo | # Use default strategy with value ``name:foo``. |\n | `Click Element` | //foo | # Find element using XPath ``//foo``. |\n | `Click Element` | default: //foo | # Use default strategy with value ``//foo``. |\n\n === Explicit locator strategy ===\n\n The explicit locator strategy is specified with a prefix using either\n syntax ``strategy:value`` or ``strategy=value``. The former syntax\n is preferred because the latter is identical to Robot Framework's\n [http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#named-argument-syntax|\n named argument syntax] and that can cause problems. Spaces around\n the separator are ignored, so ``id:foo``, ``id: foo`` and ``id : foo``\n are all equivalent.\n\n Locator strategies that are supported by default are listed in the table\n below. In addition to them, it is possible to register `custom locators`.\n\n | = Strategy = | = Match based on = | = Example = |\n | id | Element ``id``. | ``id:example`` |\n | name | ``name`` attribute. | ``name:example`` |\n | identifier | Either ``id`` or ``name``. | ``identifier:example`` |\n | class | Element ``class``. | ``class:example`` |\n | tag | Tag name. | ``tag:div`` |\n | xpath | XPath expression. | ``xpath://div[@id=\"example\"]`` |\n | css | CSS selector. | ``css:div#example`` |\n | dom | DOM expression. | ``dom:document.images[5]`` |\n | link | Exact text a link has. | ``link:The example`` |\n | partial link | Partial link text. | ``partial link:he ex`` |\n | sizzle | Sizzle selector deprecated. | ``sizzle:div.example`` |\n | data | Element ``data-*`` attribute | ``data:id:my_id`` |\n | jquery | jQuery expression. | ``jquery:div.example`` |\n | default | Keyword specific default behavior. | ``default:example`` |\n\n See the `Default locator strategy` section below for more information\n about how the default strategy works. Using the explicit ``default``\n prefix is only necessary if the locator value itself accidentally\n matches some of the explicit strategies.\n\n Different locator strategies have different pros and cons. Using ids,\n either explicitly like ``id:foo`` or by using the `default locator\n strategy` simply like ``foo``, is recommended when possible, because\n the syntax is simple and locating elements by id is fast for browsers.\n If an element does not have an id or the id is not stable, other\n solutions need to be used. If an element has a unique tag name or class,\n using ``tag``, ``class`` or ``css`` strategy like ``tag:h1``,\n ``class:example`` or ``css:h1.example`` is often an easy solution. In\n more complex cases using XPath expressions is typically the best\n approach. They are very powerful but a downside is that they can also\n get complex.\n\n Examples:\n\n | `Click Element` | id:foo | # Element with id 'foo'. |\n | `Click Element` | css:div#foo h1 | # h1 element under div with id 'foo'. |\n | `Click Element` | xpath: //div[@id=\"foo\"]//h1 | # Same as the above using XPath, not CSS. |\n | `Click Element` | xpath: //*[contains(text(), \"example\")] | # Element containing text 'example'. |\n\n *NOTE:*\n\n - The ``strategy:value`` syntax is only supported by SeleniumLibrary 3.0\n and newer.\n - Using the ``sizzle`` strategy or its alias ``jquery`` requires that\n the system under test contains the jQuery library.\n - Prior to SeleniumLibrary 3.0, table related keywords only supported\n ``xpath``, ``css`` and ``sizzle/jquery`` strategies.\n - ``data`` strategy is conveniance locator that will construct xpath from the parameters.\n If you have element like `
`, you locate the element via\n ``data:automation:automation-id-2``. This feature was added in SeleniumLibrary 5.2.0\n\n === Implicit XPath strategy ===\n\n If the locator starts with ``//`` or multiple opening parenthesis in front\n of the ``//``, the locator is considered to be an XPath expression. In other\n words, using ``//div`` is equivalent to using explicit ``xpath://div`` and\n ``((//div))`` is equivalent to using explicit ``xpath:((//div))``\n\n Examples:\n\n | `Click Element` | //div[@id=\"foo\"]//h1 |\n | `Click Element` | (//div)[2] |\n\n The support for the ``(//`` prefix is new in SeleniumLibrary 3.0.\n Supporting multiple opening parenthesis is new in SeleniumLibrary 5.0.\n\n === Chaining locators ===\n\n It is possible chain multiple locators together as single locator. Each chained locator must start with locator\n strategy. Chained locators must be separated with single space, two greater than characters and followed with\n space. It is also possible mix different locator strategies, example css or xpath. Also a list can also be\n used to specify multiple locators. This is useful, is some part of locator would match as the locator separator\n but it should not. Or if there is need to existing WebElement as locator.\n\n Although all locators support chaining, some locator strategies do not abey the chaining. This is because\n some locator strategies use JavaScript to find elements and JavaScript is executed for the whole browser context\n and not for the element found be the previous locator. Chaining is supported by locator strategies which\n are based on Selenium API, like `xpath` or `css`, but example chaining is not supported by `sizzle` or `jquery\n\n Examples:\n | `Click Element` | css:.bar >> xpath://a | # To find a link which is present after an element with class \"bar\" |\n\n List examples:\n | ${locator_list} = | `Create List` | css:div#div_id | xpath://*[text(), \" >> \"] |\n | `Page Should Contain Element` | ${locator_list} | | |\n | ${element} = | Get WebElement | xpath://*[text(), \" >> \"] | |\n | ${locator_list} = | `Create List` | css:div#div_id | ${element} |\n | `Page Should Contain Element` | ${locator_list} | | |\n\n Chaining locators in new in SeleniumLibrary 5.0\n\n == Using WebElements ==\n\n In addition to specifying a locator as a string, it is possible to use\n Selenium's WebElement objects. This requires first getting a WebElement,\n for example, by using the `Get WebElement` keyword.\n\n | ${elem} = | `Get WebElement` | id:example |\n | `Click Element` | ${elem} | |\n\n == Custom locators ==\n\n If more complex lookups are required than what is provided through the\n default locators, custom lookup strategies can be created. Using custom\n locators is a two part process. First, create a keyword that returns\n a WebElement that should be acted on:\n\n | Custom Locator Strategy | [Arguments] | ${browser} | ${locator} | ${tag} | ${constraints} |\n | | ${element}= | Execute Javascript | return window.document.getElementById('${locator}'); |\n | | [Return] | ${element} |\n\n This keyword is a reimplementation of the basic functionality of the\n ``id`` locator where ``${browser}`` is a reference to a WebDriver\n instance and ``${locator}`` is the name of the locator strategy. To use\n this locator, it must first be registered by using the\n `Add Location Strategy` keyword:\n\n | `Add Location Strategy` | custom | Custom Locator Strategy |\n\n The first argument of `Add Location Strategy` specifies the name of\n the strategy and it must be unique. After registering the strategy,\n the usage is the same as with other locators:\n\n | `Click Element` | custom:example |\n\n See the `Add Location Strategy` keyword for more details.\n\n = Browser and Window =\n\n There is different conceptual meaning when SeleniumLibrary talks\n about windows or browsers. This chapter explains those differences.\n\n == Browser ==\n\n When `Open Browser` or `Create WebDriver` keyword is called, it\n will create a new Selenium WebDriver instance by using the\n [https://www.seleniumhq.org/docs/03_webdriver.jsp|Selenium WebDriver]\n API. In SeleniumLibrary terms, a new browser is created. It is\n possible to start multiple independent browsers (Selenium Webdriver\n instances) at the same time, by calling `Open Browser` or\n `Create WebDriver` multiple times. These browsers are usually\n independent of each other and do not share data like cookies,\n sessions or profiles. Typically when the browser starts, it\n creates a single window which is shown to the user.\n\n == Window ==\n\n Windows are the part of a browser that loads the web site and presents\n it to the user. All content of the site is the content of the window.\n Windows are children of a browser. In SeleniumLibrary browser is a\n synonym for WebDriver instance. One browser may have multiple\n windows. Windows can appear as tabs, as separate windows or pop-ups with\n different position and size. Windows belonging to the same browser\n typically share the sessions detail, like cookies. If there is a\n need to separate sessions detail, example login with two different\n users, two browsers (Selenium WebDriver instances) must be created.\n New windows can be opened example by the application under test or\n by example `Execute Javascript` keyword:\n\n | `Execute Javascript` window.open() # Opens a new window with location about:blank\n\n The example below opens multiple browsers and windows,\n to demonstrate how the different keywords can be used to interact\n with browsers, and windows attached to these browsers.\n\n Structure:\n | BrowserA\n | Window 1 (location=https://robotframework.org/)\n | Window 2 (location=https://robocon.io/)\n | Window 3 (location=https://github.com/robotframework/)\n |\n | BrowserB\n | Window 1 (location=https://github.com/)\n\n Example:\n | `Open Browser` | https://robotframework.org | ${BROWSER} | alias=BrowserA | # BrowserA with first window is opened. |\n | `Execute Javascript` | window.open() | | | # In BrowserA second window is opened. |\n | `Switch Window` | locator=NEW | | | # Switched to second window in BrowserA |\n | `Go To` | https://robocon.io | | | # Second window navigates to robocon site. |\n | `Execute Javascript` | window.open() | | | # In BrowserA third window is opened. |\n | ${handle} | `Switch Window` | locator=NEW | | # Switched to third window in BrowserA |\n | `Go To` | https://github.com/robotframework/ | | | # Third windows goes to robot framework github site. |\n | `Open Browser` | https://github.com | ${BROWSER} | alias=BrowserB | # BrowserB with first windows is opened. |\n | ${location} | `Get Location` | | | # ${location} is: https://www.github.com |\n | `Switch Window` | ${handle} | browser=BrowserA | | # BrowserA second windows is selected. |\n | ${location} | `Get Location` | | | # ${location} = https://robocon.io/ |\n | @{locations 1} | `Get Locations` | | | # By default, lists locations under the currectly active browser (BrowserA). |\n | @{locations 2} | `Get Locations` | browser=ALL | | # By using browser=ALL argument keyword list all locations from all browsers. |\n\n The above example, @{locations 1} contains the following items:\n https://robotframework.org/, https://robocon.io/ and\n https://github.com/robotframework/'. The @{locations 2}\n contains the following items: https://robotframework.org/,\n https://robocon.io/, https://github.com/robotframework/'\n and 'https://github.com/.\n\n = Timeouts, waits, and delays =\n\n This section discusses different ways how to wait for elements to\n appear on web pages and to slow down execution speed otherwise.\n It also explains the `time format` that can be used when setting various\n timeouts, waits, and delays.\n\n == Timeout ==\n\n SeleniumLibrary contains various keywords that have an optional\n ``timeout`` argument that specifies how long these keywords should\n wait for certain events or actions. These keywords include, for example,\n ``Wait ...`` keywords and keywords related to alerts. Additionally\n `Execute Async Javascript`. Although it does not have ``timeout``,\n argument, uses a timeout to define how long asynchronous JavaScript\n can run.\n\n The default timeout these keywords use can be set globally either by\n using the `Set Selenium Timeout` keyword or with the ``timeout`` argument\n when `importing` the library. If no default timeout is set globally, the\n default is 5 seconds. If None is specified for the timeout argument in the\n keywords, the default is used. See `time format` below for supported\n timeout syntax.\n\n == Implicit wait ==\n\n Implicit wait specifies the maximum time how long Selenium waits when\n searching for elements. It can be set by using the `Set Selenium Implicit\n Wait` keyword or with the ``implicit_wait`` argument when `importing`\n the library. See [https://www.seleniumhq.org/docs/04_webdriver_advanced.jsp|\n Selenium documentation] for more information about this functionality.\n\n See `time format` below for supported syntax.\n\n == Page load ==\n Page load timeout is the amount of time to wait for page load to complete\n until a timeout exception is raised.\n\n The default page load timeout can be set globally\n when `importing` the library with the ``page_load_timeout`` argument\n or by using the `Set Selenium Page Load Timeout` keyword.\n\n See `time format` below for supported timeout syntax.\n\n Support for page load is new in SeleniumLibrary 6.1\n\n == Selenium speed ==\n\n Selenium execution speed can be slowed down globally by using `Set\n Selenium speed` keyword. This functionality is designed to be used for\n demonstrating or debugging purposes. Using it to make sure that elements\n appear on a page is not a good idea. The above-explained timeouts\n and waits should be used instead.\n\n See `time format` below for supported syntax.\n\n == Time format ==\n\n All timeouts and waits can be given as numbers considered seconds\n (e.g. ``0.5`` or ``42``) or in Robot Framework's time syntax\n (e.g. ``1.5 seconds`` or ``1 min 30 s``). For more information about\n the time syntax see the\n [http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#time-format|Robot Framework User Guide].\n\n = Run-on-failure functionality =\n\n SeleniumLibrary has a handy feature that it can automatically execute\n a keyword if any of its own keywords fails. By default, it uses the\n `Capture Page Screenshot` keyword, but this can be changed either by\n using the `Register Keyword To Run On Failure` keyword or with the\n ``run_on_failure`` argument when `importing` the library. It is\n possible to use any keyword from any imported library or resource file.\n\n The run-on-failure functionality can be disabled by using a special value\n ``NOTHING`` or anything considered false (see `Boolean arguments`)\n such as ``NONE``.\n\n = Boolean arguments =\n\n Starting from 5.0 SeleniumLibrary relies on Robot Framework to perform the\n boolean conversion based on keyword arguments [https://docs.python.org/3/library/typing.html|type hint].\n More details in Robot Framework\n [http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#supported-conversions|user guide]\n\n Please note SeleniumLibrary 3 and 4 did have own custom methods to covert\n arguments to boolean values.\n\n = EventFiringWebDriver =\n\n The SeleniumLibrary offers support for\n [https://seleniumhq.github.io/selenium/docs/api/py/webdriver_support/selenium.webdriver.support.event_firing_webdriver.html#module-selenium.webdriver.support.event_firing_webdriver|EventFiringWebDriver].\n See the Selenium and SeleniumLibrary\n [https://github.com/robotframework/SeleniumLibrary/blob/master/docs/extending/extending.rst#EventFiringWebDriver|EventFiringWebDriver support]\n documentation for further details.\n\n EventFiringWebDriver is new in SeleniumLibrary 4.0\n\n = Thread support =\n\n SeleniumLibrary is not thread-safe. This is mainly due because the underlying\n [https://github.com/SeleniumHQ/selenium/wiki/Frequently-Asked-Questions#q-is-webdriver-thread-safe|\n Selenium tool is not thread-safe] within one browser/driver instance.\n Because of the limitation in the Selenium side, the keywords or the\n API provided by the SeleniumLibrary is not thread-safe.\n\n = Plugins =\n\n SeleniumLibrary offers plugins as a way to modify and add library keywords and modify some of the internal\n functionality without creating a new library or hacking the source code. See\n [https://github.com/robotframework/SeleniumLibrary/blob/master/docs/extending/extending.rst#Plugins|plugin API]\n documentation for further details.\n\n Plugin API is new SeleniumLibrary 4.0\n ", + "sha256": "59c13272c5a498ee00aa6f3e5e2d1f9cec5c355267e1b03f88c604f15dab6c4e" + } +} \ No newline at end of file diff --git a/utest/test/translation/__init__.py b/utest/test/translation/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/utest/test/translation/test_translation.py b/utest/test/translation/test_translation.py index 7d1255241..18df6ea8d 100644 --- a/utest/test/translation/test_translation.py +++ b/utest/test/translation/test_translation.py @@ -1,12 +1,12 @@ -from pathlib import Path import sys +from pathlib import Path import pytest from SeleniumLibrary import SeleniumLibrary -@pytest.fixture() +@pytest.fixture def sl() -> SeleniumLibrary: sys.path.append(str(Path(__file__).parent.parent.absolute())) return SeleniumLibrary(language="FI") @@ -17,9 +17,20 @@ def test_translation(sl: SeleniumLibrary): assert spec.argument_specification doc: str = spec.documentation assert doc.startswith( - "1 SeleniumLibrary is a web testing library for Robot Framework" + "00 SeleniumLibrary is a web testing library for Robot Framework" ) spec = sl.keywords_spec["hallinnoi_hälytys"] doc: str = spec.documentation assert doc == "Hallinnoi hälytyksen uusi dokkari\n\nToinen rivi" + + +def test_provide_translation_as_list(sl: SeleniumLibrary): + lang_plugin = "robotframework_seleniumlibrary_translation_list" + file_path = Path(__file__).parent.parent / lang_plugin / "translate2.json" + received_path = sl._get_translation("swe") + assert received_path == file_path, received_path.relative_to(file_path) + assert sl._get_translation("wrong") is None + received_path = sl._get_translation("Eng") + file_path = Path(__file__).parent.parent / lang_plugin / "translate1.json" + assert received_path == file_path, received_path.relative_to(file_path) diff --git a/utest/test/utils/test_package.py b/utest/test/utils/test_package.py index 2043421f7..8fe174a84 100644 --- a/utest/test/utils/test_package.py +++ b/utest/test/utils/test_package.py @@ -5,13 +5,13 @@ class UtilsPackageTests(unittest.TestCase): def test_escape_xpath_value_with_apos(self): - self.assertEqual(escape_xpath_value("test '1'"), "\"test '1'\"") + assert escape_xpath_value("test '1'") == "\"test '1'\"" def test_escape_xpath_value_with_quote(self): - self.assertEqual(escape_xpath_value('test "1"'), "'test \"1\"'") + assert escape_xpath_value('test "1"') == "'test \"1\"'" def test_escape_xpath_value_with_quote_and_apos(self): - self.assertEqual( - escape_xpath_value("test \"1\" and '2'"), - "concat('test \"1\" and ', \"'\", '2', \"'\", '')", + assert ( + escape_xpath_value("test \"1\" and '2'") + == "concat('test \"1\" and ', \"'\", '2', \"'\", '')" ) diff --git a/utest/test/utils/test_types.py b/utest/test/utils/test_types.py index 5dfca9e00..7a093ca53 100644 --- a/utest/test/utils/test_types.py +++ b/utest/test/utils/test_types.py @@ -6,5 +6,5 @@ def test_is_noney(): for item in [None, "None", "NONE", "none"]: assert is_noney(item) - for item in TRUTHY + [False, 0, "False", "", [], {}, ()]: + for item in [*TRUTHY, False, 0, "False", "", [], {}, ()]: assert is_noney(item) is False diff --git a/utest/test/utils/test_xpath_escape.py b/utest/test/utils/test_xpath_escape.py index 5f1defae7..1eda8f15c 100644 --- a/utest/test/utils/test_xpath_escape.py +++ b/utest/test/utils/test_xpath_escape.py @@ -5,7 +5,6 @@ from approvaltests.reporters.generic_diff_reporter_factory import ( GenericDiffReporterFactory, ) -from robot.utils import WINDOWS from SeleniumLibrary.utils import escape_xpath_value @@ -21,7 +20,6 @@ def reporter(): return factory.get_first_working() -@pytest.mark.skipif(WINDOWS, reason="ApprovalTest do not support different line feeds") def test_string(reporter): results = [] results.append(escape_xpath_value("tidii"))