mherrmann / helium

Lighter web automation with Python
MIT License
4.79k stars 364 forks source link

Support selenium 4.9.x python 3.11 #114

Closed tbp105 closed 10 months ago

tbp105 commented 10 months ago

This is basically the same as the MR from @petrisorionel but rebased and updated to selenium 4.9

It also does all of the translations for selenium's redefinition of the origin in the _move_to_element function so consumers of helium don't need to worry about it

The questionable test change you had from the previous MR was actually a bug in selenium that was fixed sometime between then and selenium 4.9 so the (1,1) offset change to the tests was reverted

mherrmann commented 10 months ago

This is looking really great. I don't know which geckodriver version you are adding here and don't want to run untrusted binaries. So I tried your code with geckodriver 0.33. When I execute python -m unittest tests.api.test_iframe.IframeTest on Linux, I am getting:

======================================================================
ERROR: test_access_attributes_across_iframes (tests.api.test_iframe.IframeTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/michael/dev/helium/tests/api/test_iframe.py", line 20, in test_access_attributes_across_iframes
    self.assertEqual("This text is inside an iframe.", text.value)
  File "/home/michael/dev/helium/helium/__init__.py", line 700, in value
    return self._impl.value
  File "/home/michael/dev/helium/helium/_impl/__init__.py", line 855, in value
    return self.first_occurrence.text
  File "/home/michael/dev/helium/helium/_impl/selenium_wrappers.py", line 85, in f_decorated
    return f(self, *args, **kwargs)
  File "/home/michael/dev/helium/helium/_impl/selenium_wrappers.py", line 127, in text
    return self.target.text
  File "/home/michael/dev/helium/venv/lib/python3.9/site-packages/selenium/webdriver/remote/webelement.py", line 90, in text
    return self._execute(Command.GET_ELEMENT_TEXT)["value"]
  File "/home/michael/dev/helium/venv/lib/python3.9/site-packages/selenium/webdriver/remote/webelement.py", line 403, in _execute
    return self._parent.execute(command, params)
  File "/home/michael/dev/helium/venv/lib/python3.9/site-packages/selenium/webdriver/remote/webdriver.py", line 440, in execute
    self.error_handler.check_response(response)
  File "/home/michael/dev/helium/venv/lib/python3.9/site-packages/selenium/webdriver/remote/errorhandler.py", line 245, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.NoSuchElementException: Message: The element with the reference 7a8ee120-f242-4050-a3db-411fb1bac05d is not known in the current browsing context
Stacktrace:
RemoteError@chrome://remote/content/shared/RemoteError.sys.mjs:8:8
WebDriverError@chrome://remote/content/shared/webdriver/Errors.sys.mjs:187:5
NoSuchElementError@chrome://remote/content/shared/webdriver/Errors.sys.mjs:505:5
element.getKnownElement@chrome://remote/content/marionette/element.sys.mjs:492:11
deserializeJSON@chrome://remote/content/marionette/json.sys.mjs:233:33
cloneObject@chrome://remote/content/marionette/json.sys.mjs:56:24
deserializeJSON@chrome://remote/content/marionette/json.sys.mjs:244:16
json.deserialize@chrome://remote/content/marionette/json.sys.mjs:248:10
receiveMessage@chrome://remote/content/marionette/actors/MarionetteCommandsChild.sys.mjs:85:30

There are also several new deprecation warnings:

/home/michael/dev/helium/helium/_impl/__init__.py:89: DeprecationWarning: firefox_profile has been deprecated, please use an Options object
  firefox_profile = FirefoxProfile() if profile is None else profile
/home/michael/dev/helium/helium/_impl/__init__.py:91: DeprecationWarning: headless property is deprecated, instead use add_argument('-headless')
  firefox_options.headless = True
/home/michael/dev/helium/helium/_impl/__init__.py:98: DeprecationWarning: firefox_profile has been deprecated, please pass in an Options object
  result = Firefox(service=ServiceFirefox(log_path=service_log_path), **kwargs)
/home/michael/dev/helium/venv/lib/python3.9/site-packages/selenium/webdriver/firefox/webdriver.py:188: DeprecationWarning: Setting a profile has been deprecated. Please use the set_preference and install_addons methods
  options.profile = firefox_profile
mherrmann commented 10 months ago

I would also re-order the imports alphabetically. I'm attaching a patch here.

Patch file ``` diff --git a/helium/_impl/__init__.py b/helium/_impl/__init__.py index e4ca04e..cf54495 100644 --- a/helium/_impl/__init__.py +++ b/helium/_impl/__init__.py @@ -1,9 +1,4 @@ from copy import copy - -from selenium.webdriver.chrome.service import Service as ServiceChrome -from selenium.webdriver.common.by import By -from selenium.webdriver.firefox.service import Service as ServiceFirefox - from helium._impl.chromedriver import install_matching_chromedriver from helium._impl.match_type import PREFIX_IGNORE_CASE from helium._impl.selenium_wrappers import WebElementWrapper, \ @@ -19,6 +14,9 @@ from selenium.common.exceptions import UnexpectedAlertPresentException, \ ElementNotVisibleException, MoveTargetOutOfBoundsException, \ WebDriverException, StaleElementReferenceException, \ NoAlertPresentException, NoSuchWindowException +from selenium.webdriver.chrome.service import Service as ServiceChrome +from selenium.webdriver.common.by import By +from selenium.webdriver.firefox.service import Service as ServiceFirefox from selenium.webdriver.remote.webelement import WebElement from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support.ui import Select diff --git a/helium/_impl/selenium_wrappers.py b/helium/_impl/selenium_wrappers.py index d2c7980..457726b 100644 --- a/helium/_impl/selenium_wrappers.py +++ b/helium/_impl/selenium_wrappers.py @@ -1,9 +1,8 @@ -from selenium.webdriver.common.by import By - from helium._impl.util.geom import Rectangle from selenium.common.exceptions import StaleElementReferenceException, \ NoSuchFrameException, WebDriverException from selenium.webdriver.common.action_chains import ActionChains +from selenium.webdriver.common.by import By from urllib.error import URLError import sys diff --git a/helium/_impl/webdrivers/linux/geckodriver b/helium/_impl/webdrivers/linux/geckodriver index 1ae6fea..8f84330 100755 Binary files a/helium/_impl/webdrivers/linux/geckodriver and b/helium/_impl/webdrivers/linux/geckodriver differ diff --git a/helium/_impl/webdrivers/mac/geckodriver b/helium/_impl/webdrivers/mac/geckodriver index 632a21b..4ba1432 100755 Binary files a/helium/_impl/webdrivers/mac/geckodriver and b/helium/_impl/webdrivers/mac/geckodriver differ diff --git a/helium/_impl/webdrivers/windows/geckodriver.exe b/helium/_impl/webdrivers/windows/geckodriver.exe old mode 100755 new mode 100644 index c59764a..1b5fc2f Binary files a/helium/_impl/webdrivers/windows/geckodriver.exe and b/helium/_impl/webdrivers/windows/geckodriver.exe differ diff --git a/tests/api/__init__.py b/tests/api/__init__.py index 056690b..12c183a 100644 --- a/tests/api/__init__.py +++ b/tests/api/__init__.py @@ -1,10 +1,9 @@ -from selenium.webdriver.common.by import By - from helium import start_chrome, start_firefox, go_to, set_driver, \ kill_browser -from unittest import TestCase +from selenium.webdriver.common.by import By from tests.api.util import get_data_file_url from time import time, sleep +from unittest import TestCase import os diff --git a/tests/api/test_drag.py b/tests/api/test_drag.py index 0031992..751a083 100644 --- a/tests/api/test_drag.py +++ b/tests/api/test_drag.py @@ -1,6 +1,5 @@ -from selenium.webdriver.common.by import By - from helium import * +from selenium.webdriver.common.by import By from tests.api import BrowserAT class DragTest(BrowserAT): diff --git a/tests/api/test_text_impl.py b/tests/api/test_text_impl.py index f5f1d56..2a4db89 100644 --- a/tests/api/test_text_impl.py +++ b/tests/api/test_text_impl.py @@ -1,7 +1,6 @@ -from selenium.webdriver.common.by import By - from helium._impl import TextImpl from helium._impl.selenium_wrappers import WebDriverWrapper +from selenium.webdriver.common.by import By from tests.api import BrowserAT class TextImplTest(BrowserAT): diff --git a/tests/api/test_window_handling.py b/tests/api/test_window_handling.py index 17400ca..1a8ac5a 100644 --- a/tests/api/test_window_handling.py +++ b/tests/api/test_window_handling.py @@ -1,7 +1,6 @@ -from selenium.webdriver.common.by import By - from helium import write, click, switch_to, TextField, Text, get_driver, \ Link, wait_until +from selenium.webdriver.common.by import By from tests.api import BrowserAT, test_browser_name from unittest import skipIf ```
petrisorionel commented 10 months ago

@tbp105 I'm glad that you find out the issue.

tbp105 commented 10 months ago

Ok, applied the patch, deleted the unused binary (main had already added code to fetch on demand), fixed the test, and cleaned up the warnings. So hopefully it is good now.

@petrisorionel It was much easier to find the bug after upgrading selenium and seeing the fix (which, as a side effect, broke the workaround)