wgnet / webium

Webium is a Page Object pattern implementation library for Python (http://martinfowler.com/bliki/PageObject.html). It allows you to extend WebElement class to your custom controls like Link, Button and group them as pages.
Apache License 2.0
161 stars 37 forks source link

Can't execute JavaScript on an element with Firefox #19

Open alekspog opened 7 years ago

alekspog commented 7 years ago

I have a page with elements which are out of the visible browser area and I need to scroll these elements to view. I try to use execute_script("return arguments[0].scrollIntoView(true);", element) method but it fails for Firefox with TypeError: <selenium.webdriver.remote.webelement.WebElement (session="732d3ce1-eaed-494c-b441-b29fdb9e02e3", element="e9db3f8c-9836-4c68-a9c9-364066a3d76e")> is not JSON serializable . However, it works fine in Chrome.

It seems the root of this problem is described in https://github.com/SeleniumHQ/selenium/issues/2666#issuecomment-289146650. "the problem might have been that the reporter was using a custom subclass of WebElement with Firefox." - it means it can happens for the same reason for Webium which use also custom subclass when you use Selenium 3.

How do you handle this problem in your projects? Is there chance that you can implement something for Webium similar to this patch?

This example can reproduce the problem. selenium==3.4.1 webium==1.2.1 geckodriver is 0.16

from selenium.webdriver.common.by import By
from selenium.webdriver.remote.webelement import WebElement
from webium.controls.link import Link
from webium.driver import get_driver
from webium import BasePage, Find, Finds

class GooglePage(BasePage):
    url = 'http://www.google.com'

    text_field = Find(by=By.NAME, value='q')
    button = Find(by=By.NAME, value='btnG')

class ResultItem(WebElement):
    link = Find(Link, By.XPATH, './/h3/a')

class ResultsPage(BasePage):
    stat = Find(by=By.ID, value='resultStats')
    results = Finds(ResultItem, By.XPATH, '//div/li')
    suggest1 = Find(by=By.CSS_SELECTOR, value='.card-section .brs_col:nth-child(1) ._e4b:nth-child(1) a')

if __name__ == '__main__':
    home_page = GooglePage()
    home_page.open()
    home_page.text_field.send_keys('Page Object')
    home_page.button.click()
    results_page = ResultsPage()
    print('Results summary: ' + results_page.stat.text)
    for item in results_page.results:
        print(item.link.text)
    # results_page._driver.execute_script("window.scrollBy(0, -120);")
    element = results_page.suggest1
    # try to scroll to first link with other search suggestion
    get_driver().execute_script("return arguments[0].scrollIntoView(true);", element)
    get_driver().quit()

Results summary: Результатов: примерно 11 200 000 (0,22 сек.) Traceback (most recent call last): File "C:/Source2/PythonProjects/untitled1/page_test.py", line 37, in get_driver().execute_script("return arguments[0].scrollIntoView(true);", element) File "C:\Users\user\webium_test1\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 487, in execute_script 'args': converted_args})['value'] File "C:\Users\user\webium_test1\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 250, in execute response = self.command_executor.execute(driver_command, params) File "C:\Users\user\webium_test1\lib\site-packages\selenium\webdriver\remote\remote_connection.py", line 461, in execute data = utils.dump_json(params) File "C:\Users\user\webium_test1\lib\site-packages\selenium\webdriver\remote\utils.py", line 34, in dump_json return json.dumps(json_struct) File "C:\Python352\lib\json__init__.py", line 230, in dumps return _default_encoder.encode(obj) File "C:\Python352\lib\json\encoder.py", line 198, in encode chunks = self.iterencode(o, _one_shot=True) File "C:\Python352\lib\json\encoder.py", line 256, in iterencode return _iterencode(o, 0) File "C:\Python352\lib\json\encoder.py", line 179, in default raise TypeError(repr(o) + " is not JSON serializable") TypeError: <selenium.webdriver.remote.webelement.WebElement (session="732d3ce1-eaed-494c-b441-b29fdb9e02e3", element="e9db3f8c-9836-4c68-a9c9-364066a3d76e")> is not JSON serializable

SUNx2YCH commented 7 years ago

Thanks for the feedback. As I understand, the problem was introduced in https://github.com/SeleniumHQ/selenium/commit/09dab5afe5280476290f9cc43d51269aac672853 and https://github.com/SeleniumHQ/selenium/commit/18432f5b0fb4fcd477fec1f02914c9ddd8c72793. Webium uses remote WebElement class by default and obviously its instance is not recognized as FirefoxWebElement instance. For now I can suggest a couple of dirty workarounds:

from selenium.webdriver.firefox.webelement import FirefoxWebElement
# ...
suggest1 = Find(FirefoxWebElement, by=By.CSS_SELECTOR, value='.card-section .brs_col:nth-child(1) ._e4b:nth-child(1) a')

or you can patch the expected class after driver initialization:

from selenium.webdriver.remote.webelement import WebElement
from webium.driver import get_driver
# ...
get_driver()._web_element_cls = WebElement

We can do some patch in webium, but I think this probably should be fixed in selenium. Will try to work on this.

alekspog commented 7 years ago

Thanks!

Both workarounds are working, hope selenium team are going to fix this problem in the future.

mdmintz commented 1 year ago

This issue has been resolved. Please upgrade to the latest versions of selenium and geckodriver.