1

I am writing selenium test scripts using the industry standard of webdriver waits before interacting with elements, but I still frequently find my tests are failing, and it seems to be due to a race condition.

Here's the example I have been running into lately:

  1. Go to the product catalog page
  2. Apply a filter
  3. Wait for the filter to be applied
  4. Click the save button on the product which loads after the filter is applied

Step number 4 only works if I place a Thread.Sleep() in front of the step - using webdriverwait is not enough. I'm guessing this is because the webdriverwait only waits until the element is attached to the DOM, even though the relevant JavaScript click event has not been added to the element.

How do you get around this issue? Is there an industry standard for dealing with this race condition?

EDIT This was resolved by upgrading to the latest version firefox. Thanks everyone!

GKS1
  • 291
  • 2
  • 12
  • What is the error when you remove the thread sleep? Is it a case where the button is disabled while the filter is being applied and it is enabled post filter apply is complete? – shri046 Mar 13 '15 at 15:22
  • @shri046 The save button is loaded after the filter is applied. When I remove the thread.sleep, there is no error. Selenium will click on the save button. The problem is that nothing happens when selenium clicks (I am assuming this happens because there is no javascript click event attached to the button as soon as it loads). Let me know if I am not explaining this well. – GKS1 Mar 13 '15 at 15:28
  • That makes sense but my question was more along the lines of is the button "grayed out" for a short period while the filter is applied. In other words, is the button attached to the DOM before and after applying a filter and the only difference is enabling/disabling the button while the filter is being applied. – shri046 Mar 13 '15 at 15:49

2 Answers2

1

As we discovered in comments, updating Firefox to the latest version did the trick.


The code looks really good to me and makes total sense.

What I would try is to move to the element before making a click:

Actions builder = new Actions(WebDriver);
IWebElement saveButton = wait.Until(ExpectedConditions.ElementIsVisible(By.CssSelector(".button-wishlist")));

Actions hoverClick = builder.MoveToElement(saveButton).Click();
hoverClick.Build().Perform();

As we've discovered in comments, the issue is related to the size of the window (the test passed without a Thread.sleep() if the browser window is maximized). This makes me think that if you scroll to the element before making a click it could be enough to make it work:

IWebElement saveButton = wait.Until(ExpectedConditions.ElementIsVisible(By.CssSelector(".button-wishlist")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].scrollIntoView(true);", saveButton);

Actions hoverClick = builder.MoveToElement(saveButton).Click();
hoverClick.Build().Perform();
alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
  • I just tried that and I'm seeing the same problem. :( Test only passes with the Thread.Sleep() – GKS1 Mar 13 '15 at 15:39
  • @GKS1 thanks for trying it out. I'll play around with the code more and hopefully would come back to you. Do you see this behavior regardless of the browser used? – alecxe Mar 13 '15 at 15:43
  • @GKS1 I could not reproduce the issue. Though I've approached it with python, here is the [gist](https://gist.github.com/alecxe/30723d6a8c86f3778b29). One more thing to try: maximize the window after navigating to the URL. Thanks. – alecxe Mar 13 '15 at 15:50
  • Thanks for looking into this. This test is specifically to ensure that the button works while using the mobile view, so maximizing isn't really an option (*out of curiosity, I did maximize the browser before doing the click, which causes the test to pass without the sleep. Interesting, but not super helpful*) – GKS1 Mar 13 '15 at 15:56
  • @GKS1 this is a kind of a progress. At least we know it is related to the size of the window. To follow this logic, move to element option should have worked, right? I'll update the answer with one more thing to try. Thanks. – alecxe Mar 13 '15 at 15:56
  • @GKS1 please see the update and let me know whether it helps or not. Thanks. – alecxe Mar 13 '15 at 16:02
  • Just throwing it out there - so maximizing the window provides just enough time for the button to be clickable? If it were a case of not visible or even overlap there would have been an exception. One more thing to try is varying duration of thread sleep. What is the least amount of thread sleep required to make the test pass? – shri046 Mar 13 '15 at 16:02
  • @shri046 yeah, I think it is related to that responsive design style of the page - the structure of the page changes when you resize the window - that's why I'm trying to make it scroll/focus/hover the button before a click.. – alecxe Mar 13 '15 at 16:10
  • @alecxe So I tried scrolling to the element explicitly with javascript, and even added a line to highlight the element to make sure I'm trying to click the right thing: IWebElement saveButton = wait.Until(ExpectedConditions.ElementIsVisible(By.CssSelector(".button-wishlist"))); ((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].scrollIntoView(true);", saveButton); ((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].style.backgroundColor = 'red'", saveButton); saveButton.Click(); but this still fails without the thread.sleep. – GKS1 Mar 13 '15 at 16:45
  • @GKS1 okay, then we are probably doing it correctly and the problem is at the next step. You should get a new popup window opened after the click and you don't see it opened, correct? Can you check the browser console and see if there are any errors? Thanks. – alecxe Mar 13 '15 at 16:46
  • @alecxe There are no errors logged in the dev tools. I should note that the line of JavaScript to scroll into view does not actually scroll it into view. So it seems my code hits that line before the object actually has a position? Possible? – GKS1 Mar 13 '15 at 16:49
  • @GKS1 may be. Another shot in the dark: could you upgrade to most recent selenium and firefox versions? Thanks. (I've played around with that python code and it is working for me even if I set the window size to 600, 700).. – alecxe Mar 13 '15 at 16:56
  • @alecxe Wow. Haha now I feel dumb, but that worked. I updated firefox and it now passes every time. Thanks! – GKS1 Mar 13 '15 at 17:02
  • @GKS1 this is awesome :) Make sure this is really the reason and not just an inconsistency in the reproducing the bug :) – alecxe Mar 13 '15 at 17:05
  • @alecxe Yep! Passed ten times in a row after updating firefox. Thanks! – GKS1 Mar 13 '15 at 17:13
0

Take a look at this SO post for custom wait method. Sounds like element presence is not enough of a check in your case because the button may be present at all times in the DOM. What you need is something along the lines of ExpectedConditions.elementToBeClickable().

I am not familiar with the C# API but it looks like there is no built in method to do the same thing as in Java. So you could write a custom wait function that will have checks according to your needs.

Community
  • 1
  • 1
shri046
  • 1,148
  • 11
  • 12
  • Good suggestion, though "element to be clickable" basically checks for the element to be enabled and visible..not sure it would help. Thanks. – alecxe Mar 13 '15 at 15:55
  • @alecxe Correct. Clickable from the base framework should work for most generic cases and one would only have to rely on custom wait if the out of the box does not work. Totally depends on UI implementation that is being tested but I wanted to highlight both options. – shri046 Mar 13 '15 at 15:59