Selenium: Actions broken when used after each other

Created on 20 Sep 2017  路  7Comments  路  Source: SeleniumHQ/selenium

Meta -

OS: Windows 10
Selenium Version: 3.5.2
Browser: Firefox

Browser Version: 56.0b12 (64-Bit)

Expected Behavior -

Upon calling an action using the Actions API and calling another action after properly executing the first one, the second action gets executed. In this case, either moving up after clicking on a leaflet map, or moving down after having moved up.

Actual Behavior -

The same action happens twice.

Steps to reproduce -

Driver.Navigate().GoToUrl("https://leafletjs.com");
Actions action = new Actions(Browser.Driver);
action.Click(Browser.Driver.FindElement(By.Id("map"))).Build().Perform(); // get rid of the popup
var mapLocationBefore = Browser.Driver.FindElement(By.CssSelector("div.leaflet-map-pane")).GetAttribute("style"); // get translate-3d value
action.SendKeys(Keys.ArrowUp).Build().Perform(); // should scroll up, but clicks popup again
var mapLocationAfter = Browser.Driver.FindElement(By.CssSelector("div.leaflet-map-pane")).GetAttribute("style"); 
Assert.AreNotEqual(mapLocationAfter, mapLocationBefore);
action.SendKeys(Keys.ArrowDown).Build().Perform(); // this moves up instead of down
mapLocationAfter = Browser.Driver.FindElement(By.CssSelector("div.leaflet-map-pane")).GetAttribute("style");    // same location as the inital one, so before and after should match
Assert.AreEqual(mapLocationAfter, mapLocationBefore);

Most helpful comment

The API is designed to allow you to repeat the same action sequence without needing to re-code the same sequence.

Subjectively, it appears to be very inconvenient due to the following points:
1) If I would want to re-use the same sequence of actions I would explicitly extract a method out of it.
2) This action sequence is executed for the same instance of the web element even if you use PageFactory, which means that you will get a StaleElementReferenceException if you will perform it second time for an element found by exactly the same locator (although it would be a different instance of an element). Sounds not quite "re-usable".
3) What about consistency (as far as possible/reasonable) with other bindings? Why should I pile up in memory all these (unnecessary) nuances in case I use different bindings from project to project?
...I might be wrong though.

All 7 comments

This is by design. The API is designed to allow you to repeat the same action sequence without needing to re-code the same sequence. The Actions object is cheap to create in the .NET bindings, both in memory and time, so creating a new one is the right approach.

Thanks for the explanation. I guess I can live with that (given that I've also used your suggestion as a workaround to begin with), although it can make code pretty unreadable in case of huge independent actions.

Would it be a good idea to have this in the documentation somewhere or is it already there and I didn't look hard enough?

@jimevans What do you think about marking Actions object as "used" after Perform invocation, and throwing an exception on the second attempt to invoke it?

The API is designed to allow you to repeat the same action sequence without needing to re-code the same sequence.

Wouldn't that negate this functionality?

Also it is seems now inconsistent with Java as in Java Api it still behaves in old way where Actions is being reset after each Perform.
Why would it changed only in C# API?

Oops, sorry, ignore my comment, I misunderstood the case.

The API is designed to allow you to repeat the same action sequence without needing to re-code the same sequence.

Subjectively, it appears to be very inconvenient due to the following points:
1) If I would want to re-use the same sequence of actions I would explicitly extract a method out of it.
2) This action sequence is executed for the same instance of the web element even if you use PageFactory, which means that you will get a StaleElementReferenceException if you will perform it second time for an element found by exactly the same locator (although it would be a different instance of an element). Sounds not quite "re-usable".
3) What about consistency (as far as possible/reasonable) with other bindings? Why should I pile up in memory all these (unnecessary) nuances in case I use different bindings from project to project?
...I might be wrong though.

Was this page helpful?
0 / 5 - 0 ratings