Search code examples
pythonseleniumselenium-webdriveraction

AttributeError: move_to requires a WebElement error calling move_to_element(by_locator) using Selenium and Python


I'm using ActionChains in pytest to scroll till an element but getting error "move_to requires a WebElement". I have used same code in unittest and it worked fine but it doesn't in pytest. Here is my code:

import time
from selenium.webdriver.common.by import By
from Pages.BasePage import BasePage


class CreateGroup(BasePage):

     # ..........................Open created group Locators..............................
    GROUPS = (By.XPATH, "//span[text()='Groups']")
    SEARCH_GROUP = (By.XPATH, "//input[@ng-reflect-placeholder='Filter groups by name...']")
    GO_TO_GROUP = (By.XPATH, "//span[text()=' Go to Group ']")

    def __init__(self, driver):
        super().__init__(driver)

    def go_to_group(self, group):
        self.do_click(self.GROUPS)
        time.sleep(3)
        self.do_send_keys(self.SEARCH_GROUP, group)
        time.sleep(5)
        self.do_scroll(self.GO_TO_GROUP)

And here is another class code:

from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class BasePage:
    def __init__(self, driver):
        self.driver = driver

    def do_scroll(self, by_locator):
        ac = ActionChains(self.driver)
        ac.move_to_element(by_locator)
        ac.perform()

Error logs:

    def move_to(self, element, x=None, y=None):
        if not isinstance(element, WebElement):
>           raise AttributeError("move_to requires a WebElement")
E           AttributeError: move_to requires a WebElement

Solution

  • move_to_element(to_element)

    move_to_element(to_element) moves the mouse to the middle of an element. It is defined as:

    def move_to_element(self, to_element):
        """
        Moving the mouse to the middle of an element.
    
        :Args:
         - to_element: The WebElement to move to.
        """
    
        self.w3c_actions.pointer_action.move_to(to_element)
        self.w3c_actions.key_action.pause()
    
        return self
        
    

    So, you need to pass an element as an argument to move_to_element() where as you are passing a by_locator as:

    ac.move_to_element(by_locator)
    

    Hence you see the error:

    AttributeError: move_to requires a WebElement
    

    Solution

    So your effective solution would be:

    def do_scroll(self, by_locator):
        element = WebDriverWait(self.driver, 20).until(EC.visibility_of_element_located(by_locator))
        ActionChains(self.driver).move_to_element(element).perform()