- A user clicks on a button
- A pop-up slides down
- The user clicks close button in the pop-up
- The pop-op is sliding up and closes
That's a simple GUI use case which uses animation (gradual resizing). Normally when automating a pup-up via Selenium you'll click a button, after that check visibility of a DIV and then click the close button. The problem is that the browser won't handle any clicks until animation is over.
Using Thread.Sleep() or any similar execution delay is not a good technique (slow, hard to choose optimal value for both slow and fast environments etc.). Bellow you may find a C# extension method for Selenium IWebDriver interface which utilizes polling mechanism in order trace element style changes and decide whether animation is over:
public static void WaitForCssStyleChange(this IWebDriver webDriver, string xPath,
bool failOnNoCHange = true)
{
var i = 0; // poll counter
var cumulative = 0; // the number of CSS/style checks that didn't find any changes
var element = webDriver.FindElementEx(By.XPath(xPath));
var originalCss = element == null ? String.Empty : element.GetAttribute("class");
var originalStyle = element == null ? String.Empty : element.GetAttribute("style");
var prevCss = originalCss;
var prevStyle = originalStyle;
while (i < SeleniumConfiguration.PollingThreshold) // Do polls until threshold is exceeded
{
element = webDriver.FindElementEx(By.XPath(xPath));
if (element != null)
{
var css = element.GetAttribute("class");
var style = element.GetAttribute("style");
// if the previous CSS/Style is same - increase the counter
if ((css == prevCss || style == prevStyle)) cumulative++;
if (cumulative > 2) return; // most like animation is over
prevCss = css;
prevStyle = style;
}
Thread.Sleep(SeleniumConfiguration.PollingPeriod * 100);
i++;
}
if (element == null) throw new TimeoutException("Element not found "); // fail if no element
if (failOnNoCHange && (originalCss == prevCss) && (originalStyle == prevCss))
throw new TimeoutException("Element was not changed"); //require element style/CSS change
}
The approach is similar to a common AJAX synchronization solution via polling (where a test waits for some element to become present or visible) . The difference is that in our case we are trying not to register a single DOM change, but see when element's style is in progress of changing and when it stops. Style changes stopped - animation completed and the element is ready for use.
Worked for me in IE8, 9 and FF.
if (failOnNoCHange && (originalCss == prevCss) && (originalStyle == prevCss))
ReplyDeletethrow new TimeoutException("Element was not changed"); //require element style/CSS change
there is a typo - (originalStyle == prevCss) should be (originalStyle == prevStyle)
i am not getting this: SeleniumConfiguration.PollingThreshold.
ReplyDeleteMaxim Saplin Blog: Selenium Web Driver Animation Synchronization >>>>> Download Now
ReplyDelete>>>>> Download Full
Maxim Saplin Blog: Selenium Web Driver Animation Synchronization >>>>> Download LINK
>>>>> Download Now
Maxim Saplin Blog: Selenium Web Driver Animation Synchronization >>>>> Download Full
>>>>> Download LINK C4