如何处理使用 WebDriver 进行页面导航时出现的警报?
How can I handle alerts that occur on page navigation with WebDriver?
这里的情况是我正在测试的某些页面将有一个卸载事件 - 即,如果有未保存的更改,提示保存更改是一个常见的例子,我希望能够检测到并处理它。
具体问题如下:
我正在测试一个非常复杂的 Web 应用程序,它允许用户在浏览器中编辑丰富的内容,并且该应用程序将自动保存用户所做的更改。所以这个测试做了类似下面的事情:
- 导航到应用程序
- 做一些编辑
- 离开
但是,由于应用程序会在离开时自动保存更改并且存在未保存的更改 - 将显示此提示:http://i.stack.imgur.com/c9iP2.png
每当 Selenium 中有警报时,下一个操作将悲惨地失败,调用堆栈如下:
org.openqa.selenium.UnhandledAlertException: unexpected alert open
(Session info: chrome=39.0.2171.65)
(Driver info: chromedriver=2.11.298604 (75ea2fdb5c87f133a8e1b8da16f6091fb7d5321e),platform=Windows NT 6.1 SP1 x86_64) (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 87 milliseconds: null
Build info: version: '2.43.1', revision: '5163bceef1bc36d43f3dc0b83c88998168a363a0', time: '2014-09-10 09:43:55'
System info: host: 'ip-10-231-174-40', ip: '10.231.174.40', os.name: 'Linux', os.arch: 'amd64', os.version: '3.11.0-19-generic', java.version: '1.7.0_51'
Session ID: 889cbda1d1a946a38e90e4ec9f32e827
Driver info: org.openqa.selenium.remote.RemoteWebDriver
Capabilities [{platform=XP, acceptSslCerts=true, javascriptEnabled=true, hasMetadata=true, browserName=chrome, chrome={userDataDir=C:\Users\ADMINI~1\AppData\Local\Temp\scoped_dir1584_15883}, rotatable=false, mobileEmulationEnabled=false, locationContextEnabled=true, webdriver.remote.sessionid=889cbda1d1a946a38e90e4ec9f32e827, version=39.0.2171.65, takesHeapSnapshot=true, databaseEnabled=false, cssSelectorsEnabled=true, handlesAlerts=true, browserConnectionEnabled=false, nativeEvents=true, webStorageEnabled=true, applicationCacheEnabled=false, takesScreenshot=true}]
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:204)
at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:162)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:599)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:614)
at org.openqa.selenium.remote.RemoteWebDriver.getCurrentUrl(RemoteWebDriver.java:319)
所以一个解决方案可能是,每当我的测试导航离开此页面时,我都会放置 try/catches,但我想知道是否有更优雅和系统的解决方案(即可以检测警报或页面的东西导航,以便他们得到处理)。
有人有解决这个问题的有效方法吗?
您需要切换到警报并接受它。 Java 中的示例:
Alert alert = driver.switchTo().alert();
alert.accept();
您可能还需要等待它出现再切换:
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.alertIsPresent());
Alert alert = driver.switchTo().alert();
alert.accept();
或者,您可以首先停止显示弹出窗口。这个想法是用 javascript
:
删除所有 beforeunload
事件监听器
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript(
"window.addEventListener(\"load\", foo, false);" +
"function foo() { " +
"var u = \"beforeunload\";" +
"var v = unsafeWindow;" +
"if (v._eventTypes && v._eventTypes[u]) {" +
"var r=v._eventTypes[u];" +
"for(var s=0;s<r.length;s++) { " +
"v.removeEventListener(u,r[s],false);" +
"}" +
"v._eventTypes[u]=[];" +
"}");
这里的情况是我正在测试的某些页面将有一个卸载事件 - 即,如果有未保存的更改,提示保存更改是一个常见的例子,我希望能够检测到并处理它。
具体问题如下:
我正在测试一个非常复杂的 Web 应用程序,它允许用户在浏览器中编辑丰富的内容,并且该应用程序将自动保存用户所做的更改。所以这个测试做了类似下面的事情:
- 导航到应用程序
- 做一些编辑
- 离开
但是,由于应用程序会在离开时自动保存更改并且存在未保存的更改 - 将显示此提示:http://i.stack.imgur.com/c9iP2.png
每当 Selenium 中有警报时,下一个操作将悲惨地失败,调用堆栈如下:
org.openqa.selenium.UnhandledAlertException: unexpected alert open
(Session info: chrome=39.0.2171.65)
(Driver info: chromedriver=2.11.298604 (75ea2fdb5c87f133a8e1b8da16f6091fb7d5321e),platform=Windows NT 6.1 SP1 x86_64) (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 87 milliseconds: null
Build info: version: '2.43.1', revision: '5163bceef1bc36d43f3dc0b83c88998168a363a0', time: '2014-09-10 09:43:55'
System info: host: 'ip-10-231-174-40', ip: '10.231.174.40', os.name: 'Linux', os.arch: 'amd64', os.version: '3.11.0-19-generic', java.version: '1.7.0_51'
Session ID: 889cbda1d1a946a38e90e4ec9f32e827
Driver info: org.openqa.selenium.remote.RemoteWebDriver
Capabilities [{platform=XP, acceptSslCerts=true, javascriptEnabled=true, hasMetadata=true, browserName=chrome, chrome={userDataDir=C:\Users\ADMINI~1\AppData\Local\Temp\scoped_dir1584_15883}, rotatable=false, mobileEmulationEnabled=false, locationContextEnabled=true, webdriver.remote.sessionid=889cbda1d1a946a38e90e4ec9f32e827, version=39.0.2171.65, takesHeapSnapshot=true, databaseEnabled=false, cssSelectorsEnabled=true, handlesAlerts=true, browserConnectionEnabled=false, nativeEvents=true, webStorageEnabled=true, applicationCacheEnabled=false, takesScreenshot=true}]
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:204)
at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:162)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:599)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:614)
at org.openqa.selenium.remote.RemoteWebDriver.getCurrentUrl(RemoteWebDriver.java:319)
所以一个解决方案可能是,每当我的测试导航离开此页面时,我都会放置 try/catches,但我想知道是否有更优雅和系统的解决方案(即可以检测警报或页面的东西导航,以便他们得到处理)。
有人有解决这个问题的有效方法吗?
您需要切换到警报并接受它。 Java 中的示例:
Alert alert = driver.switchTo().alert();
alert.accept();
您可能还需要等待它出现再切换:
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.alertIsPresent());
Alert alert = driver.switchTo().alert();
alert.accept();
或者,您可以首先停止显示弹出窗口。这个想法是用 javascript
:
beforeunload
事件监听器
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript(
"window.addEventListener(\"load\", foo, false);" +
"function foo() { " +
"var u = \"beforeunload\";" +
"var v = unsafeWindow;" +
"if (v._eventTypes && v._eventTypes[u]) {" +
"var r=v._eventTypes[u];" +
"for(var s=0;s<r.length;s++) { " +
"v.removeEventListener(u,r[s],false);" +
"}" +
"v._eventTypes[u]=[];" +
"}");