4

I'm automating tests for our webapp in Selenium WebDriver for C#. One of our test scenarios identified an issue with clicking the save button multiple times resulting in multiple identical records.

The standard IWebElement.Click() causes Selenium to block until the page is fully loaded. That means by the time our second click comes around to executing, the postback has been performed and we're not on the form page anymore.

Does anyone know a means of 'manually' clicking an element that won't cause Selenium to block?

Ajinkya
  • 22,324
  • 33
  • 110
  • 161
Smoke
  • 275
  • 3
  • 11

3 Answers3

1

You could either wait for a predetermined amount of time for the page to load:

driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));

...or to be more dynamic and wait for your button to appear:

var driver = new WebDriver();
var wait = new WebDriverWait(driver, TimeSpan(0, 1, 0));
wait.Until(d => d.FindElement(By.Id("button"));

Source: https://stackoverflow.com/a/7811812/2006048

Selenium also has source code that is similar to the second method: http://selenium.googlecode.com/svn/trunk/dotnet/src/WebDriver.Support/UI/ExpectedConditions.cs

Let me know if it works out for you. I personally use these options with WatiN:

browser.WaitForComplete();

...or:

browser.WaitUntilContainsText("Text");

It's a shame Selenium does not have the first one.

Community
  • 1
  • 1
B.K.
  • 9,982
  • 10
  • 73
  • 105
  • I'm not waiting for the button to load, quite the opposite. I need to be able to click the button while a postback is being performed. Selenium typically blocks execution at that point; I'm trying to overcome that. – Smoke Aug 13 '14 at 09:15
1

If we use JavaScript to send our click events, Selenium will not be blocked and we can click multiple times. However, because our click triggers a page load, we cannot reference the element directly. Instead, we need to specify the location to click and then fire our click events.

Because our WebApp uses JQuery, I was able to use the code specified here: How to simulate a click by using x,y coordinates in JavaScript?

So in the end our C# logic looks something like this:

IWebElement element = driver.findElement(By.id("foobar"));
Point point = element.Location;
IJavascriptExecutor jscript = (IJavascriptExecutor)driver;
jscript.executeScript("$(document.elementFromPoint(arguments[0], arguments[0])).click();", point.X, point.Y);

Although this sends the click event I'm not 100% sure that the element receives it; I'll run some experiments and see.

Community
  • 1
  • 1
Smoke
  • 275
  • 3
  • 11
0

What you need to do is click via javascript. In java this is done like this:

IJavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", driver.findElement(By.id("gbqfd")));
executor.executeScript("arguments[0].click();", driver.findElement(By.id("gbqfd")));

I actually imagine it is very similar, this will not block selenium and you should be able to chain a few on before the page comes back.

if this newer approach is too slow you might be quicker doing it all in js, e.g.

IJavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("document.getElementById(id).click();");
executor.executeScript("document.getElementById(id).click();");
Paul Harris
  • 5,769
  • 1
  • 25
  • 41
  • The approach was correct, but there was a slight problem. Clicking the button resulted in a page refresh, which also meant that sending the click to the WebElement resulted in a stale element reference. I've managed to find a variant that fires click events that I'll post. – Smoke Aug 19 '14 at 05:41
  • If it is just a stale element I would change the code to be the above rather that using points, basically we will just search for the element both times. – Paul Harris Aug 19 '14 at 06:41