I'm writing tests for a web app that typically executes
window.location.href=someUrl after some set of instructions (which can
take an arbitrary amount of time and usually involve a remote ajax
call). I notice that Webdriver doesn't seem to wait for the
instructions to complete before executing the window.location.href
statement. Is there something I might be missing or a different
approach I should take?
Here's how I can reproduce the behavior, which should be: load
location.html, click go, wait 1 second, load ajax.html, verify. Note
that the setTimeout simply mimics the time taken for one of the app's
ajax calls. If I simply open a browser and run it by hand, it works as
expected.
<!-- page 1 : location.html -->
<a href="javascript:void(0);" onclick="go();" id="go_link">go</a>
<script>
function go(){
window.setTimeout( function(){location.href = 'http://dev/sandbox/
ajax.html'; } , 1000);
}
</script>
<!-- page 2 : ajax.html -->
<p id="find_me">found</p>
//-------------------------------------------//
@Test
public void testLocationHref() {
InternetExplorerDriver driver = new InternetExplorerDriver();
driver.get("http://dev/sandbox/location.html");
driver.findElement(By.id("go_link")).click();
String actual = driver.findElement(By.id("find_me")).getText();
Assert.assertEquals("found", actual);
}
//------ stack-----//
org.openqa.selenium.NoSuchElementException: Unable to find element by
id using "find_me" (7)
System info: os.name: 'Windows XP', os.arch: 'x86', os.version: '5.1',
java.version: '1.6.0_03'
Driver info: driver.version: ie
at
org.openqa.selenium.ie.ErrorHandler.verifyErrorCode(ErrorHandler.java:
36)
at org.openqa.selenium.ie.Finder.handleErrorCode(Finder.java:219)
at org.openqa.selenium.ie.Finder.findElementById(Finder.java:93)
at org.openqa.selenium.By$1.findElement(By.java:66)
at org.openqa.selenium.ie.Finder.findElement(Finder.java:207)
at
org.openqa.selenium.ie.InternetExplorerDriver.findElement(InternetExplorerDriver.java:
322)
at tests.WindowLocationTest.testLocationHref(WindowLocationTest.java:
16)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod
$1.runReflectiveCall(FrameworkMethod.java:44)
at
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:
15)
at
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:
41)
at
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:
20)
at
org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:
28)
at
org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:
31)
at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:
73)
at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:
46)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41)
at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173)
at
org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:
28)
at
org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:
31)
at org.junit.runners.ParentRunner.run(ParentRunner.java:220)
at
org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:
46)
at
org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:
38)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:
467)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:
683)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:
390)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:
197)
//------------------------//
The behavior is the same with FirefoxDriver. That is, Webdriver
appears to continue to the next statement following
driver.findElement(By.id("go_link")).click(); without waiting.
Env: Java 6, TestNG, WinXP, IE7. (Note, same behavior for JUnit)
best regards,
bill shelton
This is why we recommend using the WebDriverWait[1] class when
searching for an element after an expected load[2]. I've modified
your test below with an example usage[3]:
public void testLocationHref() {
driver.get("http://dev/sandbox/location.html");
driver.findElement(By.id("go_link")).click();
WebElement findMe = new WebDriverWait(driver, 2000)
.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.id("find_me"));
}
});
Assert.assertEquals("found", findMe.getText());
}
Of course, that's pretty verbose, but you can extract some helper
functions to clean it up.
-- Jason
[1] http://selenium.googlecode.com/svn/trunk/docs/api/java/org/openqa/selenium/support/ui/WebDriverWait.html
[2] We plan to implement implicit waiting on findElement(s) commands;
look for it in a future release (April/May *crosses fingers*).
[3] Test not tested/compiled; there may be some typos.
> --
> You received this message because you are subscribed to the Google Groups "webdriver" group.
> To post to this group, send email to webd...@googlegroups.com.
> To unsubscribe from this group, send email to webdriver+...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/webdriver?hl=en.
>
>
best,
bill
> [1]http://selenium.googlecode.com/svn/trunk/docs/api/java/org/openqa/sel...