在自动化测试过程中发现点击某个按钮后弹出了一个特别的窗口。
特点一,该窗口不关闭就无法切换到其他窗口。
特点二,该窗口无法使用开发人员工具进行探测。
这个特别的窗口就是模态窗口:
对话框一般分为两种类型:模态类型(modal)与非模态类型(modeless)。
所谓模态对话框,就是指除非采取有效的关闭手段,用户的鼠标焦点或者输入光标将一直停留在其上的对话框。
非模态对话框则不会强制此种特性,用户可以在当前对话框以及其他窗口间进行切换。(引用)
Holmos自带的跳转窗口的方法都需要一个参数url地址或者窗口title作为跳转依据,但是模态窗口无法使用开发人员工具进行探测,意味着拿不到url或者title就无法跳转到该窗口上。
这种情况下应该怎么办?如何跳转到一个没有跳转依据的窗口上?
已知Holmos提供可根据浏览器窗口handle属性确定窗口的唯一性。
而窗口的弹出一般都是由单击事件触发的,点击事件触发后,浏览器窗口的数量肯定会多一个。
抓取点击事件后handle的集合减去点击事件之前handle的集合,即得到新的窗口handle。
方法代码如下:
public void clickAndSelectModalDialog() throws BusinessException{ String popupWindowHandle = getPopupWindowHandle(); BrowserWindow currentWindow=Allocator.getInstance().currentWindow; WebDriverBrowserWindow webDriverBrowserWindow=new WebDriverBrowserWindow(currentWindow.getDriver()); webDriverBrowserWindow.setWidowHandle(popupWindowHandle); List<BrowserWindow> windows = new ArrayList<BrowserWindow>(); windows.add(webDriverBrowserWindow); for(BrowserWindow window:windows){ if(window.getHandle().equalsIgnoreCase(popupWindowHandle)){ System.out.println("逮住窗口了"); window.focus(); break; } } }
public String getPopupWindowHandle() throws BusinessException { String popupHandle = null; int maxTimeToWait = 15000; int timeInterval = 1000; int timeElasped = 0; int attempt; // 先拿到点击事件之前的窗口集合 BrowserWindow currentWindow=Allocator.getInstance().currentWindow; Set<String> beforePopup = ((WebDriver)currentWindow.getDriver().getEngine()).getWindowHandles(); // 点击 if(isExist()&&isDisplay()){ click(); } attempt = 1; while (timeElasped < maxTimeToWait) { // 拿到点击事件之后的窗口集合 Set<String> afterPopup = ((WebDriver)currentWindow.getDriver().getEngine()).getWindowHandles(); // 之后的集合-之前的集合=新窗口 afterPopup.removeAll(beforePopup); // 确认一下拿到新窗口了 if(afterPopup.size() == 1) { popupHandle = (String)afterPopup.toArray()[0]; break; } try { Thread.sleep(timeInterval); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } timeElasped = timeInterval * attempt; attempt++; } if ( popupHandle.isEmpty() || popupHandle == null ) { System.out.println("窗口根本没弹出来"); } return popupHandle; }
以下提供两个测试页面来验证一下
页面Noname1.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <TITLE>模态窗口和非模态窗口</TITLE> <script language="javascript"> var sColor="yyyy"; var sName="xmddl369"; function showModalWindow(){ window.showModalDialog('Noname2.html',window,'dialogWidth:400px;dialogHeight:400px'); } function showModellessWindow(){ window.showModelessDialog('Noname2.html',window,'dialogWidth:400px;dialogHeight:400px;edge:sunken'); } function update() { oColor.innerText = sColor; } document.write("sColor="+sColor+"<br>"); document.write("sName="+sName+"<br>"); </script> </HEAD> <BODY> <form> <input type="button" name="button1" value="打开一个模态窗口" onclick="showModalWindow()"> <input type="button" name="button2" value="打开一个非模态窗口" onclick="showModellessWindow()"> <BR> <P>输入你最喜欢的颜色: <SPAN ID="oColor" STYLE="color:red;font-size:24">Yellow</SPAN></P> </form> </BODY> </HTML>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <script language="javascript"> function getInfoAndUpdate() { var callerWindowObj = dialogArguments; //得到文档的引用 callerWindowObj.sColor = document.all("oEnterColor").value; callerWindowObj.update(); } function cancel() { var callerWindowObj = dialogArguments; callerWindowObj.sColor = "Yellow"; callerWindowObj.update(); } </script> </HEAD> <BODY> <form> 输入你最喜欢:<INPUT type="text" name="oEnterColor" ID="oEnterColor"><BR><BR> <INPUT VALUE="Apply" TYPE=button onclick="getInfoAndUpdate();"> <INPUT VALUE="Ok" TYPE=button onclick="getInfoAndUpdate();window.close();"> <INPUT VALUE="Cancel" TYPE=button onclick="cancel();window.close();"> </form> </BODY> </HTML>
测试用例:
1.打开Noname1页面,点击打开一个模态窗口
2.跳转到该模态窗口,拿到该窗口内的文字
使用Holmos实现代码:
public class ModalDialogBoxTest2 { public ModalDialogBoxPage modal=new ModalDialogBoxPage(); @Test public void modalTest() throws BusinessException{ HolmosWindow. openNewWindow(EngineType.WebDriverIE, "C:/Users/yuanwei3-iri/Desktop/testhtml/Noname1.html" ); HolmosWindow.sleep(5000); modal.modalButton1.clickAndSelectModalDialog(); HolmosWindow.getModalDialogText(); //HolmosWindow.getModalDialogHtml(); HolmosWindow.closeAllWindows(); } }
Page类文件:
public class ModalDialogBoxPage extends Page { public ModalDialogBoxPage() { super(); this.init(); } public Button modalButton1 = new Button( "" ); { modalButton1.addNameLocator("button1"); } public Button modalButton2 = new Button( "" ); { modalButton2.addNameLocator("button2"); } }
// 获取模态框窗口的文字内容 public static String getModalDialogText() throws BusinessException{ String Mtext=null; StringBuilder message=new StringBuilder(); BrowserWindow currentWindow=Allocator.getInstance().currentWindow; if(currentWindow instanceof WebDriverBrowserWindow){ String js="var a= window.document.body.innerText;return a;"; WebDriver driver=(WebDriver) currentWindow.getDriver().getEngine(); Mtext= (String) ((JavascriptExecutor)driver).executeScript(js); } message.append(Mtext+"获取模态框窗口的文字内容成功!"); logger.info(message); return Mtext; }
// 获取模态框窗口的HTML public static String getModalDialogHtml() throws BusinessException{ String Mhtml=null; StringBuilder message=new StringBuilder(); BrowserWindow currentWindow=Allocator.getInstance().currentWindow; if(currentWindow instanceof WebDriverBrowserWindow){ String js="var a= window.document.body.innerHTML;return a;"; WebDriver driver=(WebDriver) currentWindow.getDriver().getEngine(); Mhtml= (String) ((JavascriptExecutor)driver).executeScript(js); } message.append(Mhtml+"获取模态框窗口的html内容成功!"); logger.info(message); return Mhtml; } }
延伸方法closeModalDialog()
//关闭模态窗口 public static void closeModalDialog() throws BusinessException{ BrowserWindow currentWindow=Allocator.getInstance().currentWindow; if(currentWindow instanceof WebDriverBrowserWindow){ String js="window.close();"; WebDriver driver=(WebDriver) currentWindow.getDriver().getEngine(); ((JavascriptExecutor)driver).executeScript(js); } Neo4TestLogger.info("模态窗口关闭成功!"); }
从而达到降低使用门槛,节省编写用例时间的目的。