Specify wait time between Actions when using Selenium Actionchains

15,486

Solution 1

Note: Better answer

RobZ's answer is sufficient. The ActionChains class has a pause method that will do what was asked in the original question without requiring any subclassing or custom code.

Original answer

Here's a Python example based on Kim Homann's tip. It extends the ActionChains Selenium class to add a wait action.

import time
from selenium.webdriver import ActionChains

class Actions(ActionChains):
    def wait(self, time_s: float):
        self._actions.append(lambda: time.sleep(time_s))
        return self

Then your test becomes:

Actions(driver) \
    .move_to_element(menu) \
    .wait(2) \
    .click(hidden_submenu) \
    .perform()

Solution 2

I tried this and seems working

from selenium import webdriver 

action = webdriver.ActionChains(driver)

action.pause(3)

action.perform()

driver.close()

Solution 3

I don't know Python, but I think it's the same as in C#. I hope my code is readable for you.

You can create your own class ActionsEx deriving from Actions. Then you declare a method public Actions Wait(TimeSpan duration). Inside this method, you call AddAction(new SleepAction(duration));. AddAction() is a protected method of Selenium's Actions class, which is accessible only if you derive from this class.

SleepAction is a class implementing the IAction interface, which you have to create. It can look like this example:

public class SleepAction : IAction
{
    public SleepAction(TimeSpan duration)
    {
        _duration = duration;
    }

    private TimeSpan _duration;

    void IAction.Perform()
    {
        ToolBox.Sleep((int) _duration.TotalMilliseconds);
    }
}

ActionsEx class:

public class ActionsEx : Actions
{
    public ActionsEx(IWebDriver driver) : base(driver)
    {
    }

    public Actions Wait(TimeSpan duration)
    {
        AddAction(new SleepAction(duration));

        return this;
    }
}

Then you can call an action chain like this:

var actions = new ActionsEx(driver);
var duration = TimeSpan.FromSeconds(1);

((ActionsEx)actions
    .Wait(duration)
    .MoveToElement(element))
    .Wait(duration)
    .Click()
    .Build()
    .Perform();

Solution 4

Simply import the time modul and use sleep whenever you need it:

from time import sleep

action = webdriver.ActionChains(driver)
action.move_to_element(menu)
sleep(5)
action.click(hidden_submenu).perform()

Hope this helps you a bit.

Solution 5

I believe the issue is that a delay executed outside of the ActionChain will be ignored once perform is called. Think of the chain like a queue of actions in sched: you could wait for hours and hours between adding items to the queue, but once you call run, each task will execute in simple sequence without a delay.

So, to create a delay inside the chain, I would use Selenium's pause method.

Docs here: http://selenium-python.readthedocs.io/api.html

Share:
15,486

Related videos on Youtube

Jonas
Author by

Jonas

Updated on September 15, 2022

Comments

  • Jonas
    Jonas over 1 year

    The ActionChains is a very handy method when using Selenium. It works really well, only thing i am missing is how to insert wait times between the Actions.

    I will take the same example from the official google Selenium Documentation. https://selenium.googlecode.com/git/docs/api/py/webdriver/selenium.webdriver.common.action_chains.html

    menu = driver.find_element_by_css_selector(".nav")
    hidden_submenu = driver.find_element_by_css_selector(".nav #submenu1")
    
    ActionChains(driver).move_to_element(menu).click(hidden_submenu).perform()
    

    What i am looking for is a way to insert wait times between the two actions

    ActionChains(driver).move_to_element(menu)**(..wait some seconds)**.click(hidden_submenu).perform()
    

    Thanks!

  • Jonas
    Jonas about 8 years
    If i execute that, then it won't be a chain anymore. They will be separate Actions. For example if i want to click on a menu item and then wait a bit and then press Down and then press Enter, these three Actions should be executed as a chain.
  • Roman
    Roman about 8 years
    check my edit, should also work like this, but I never tested
  • Jonas
    Jonas about 8 years
    ActionChains hat no attribute sleep :)
  • Jonas
    Jonas about 8 years
    This Problem is only specific to the Website I am testing. The first Suggestion works fine on other Websites i just checked-
  • maQ
    maQ almost 7 years
    @midopa answer below is one that should be accepted
  • Tjorriemorrie
    Tjorriemorrie about 6 years
  • Adrian M
    Adrian M over 4 years
    What library should we import to be able to use ToolBox.Sleep method ?
  • Kim Homann
    Kim Homann over 4 years
    The ToolBox is just something from my personal code. You can call whatever sleep method you like, usually System.Threading.Thread.Sleep()
  • user1111380
    user1111380 over 3 years
    Seems that AddAction was removed in WebDriver 4.0+.
  • Erik Kokalj
    Erik Kokalj over 3 years
    Maybe extension methods would be appropriate in this context: private static Actions Wait(this Actions actions, int delay) { Task.Delay(delay).Wait(); // Not async! return actions; } And incorporating it into the Action chain like this: var actions = new Actions(acc.Wb.Driver); actions.MoveToElement(element) .Wait(5) .Build() .Perform();
  • Yaakov Bressler
    Yaakov Bressler over 3 years
    Updated with pause method, see answer below