07月24, 2014

如何使用Holmos处理模态窗口(ModalDialog)

在自动化测试过程中发现点击某个按钮后弹出了一个特别的窗口。

特点一,该窗口不关闭就无法切换到其他窗口。

特点二,该窗口无法使用开发人员工具进行探测。

这个特别的窗口就是模态窗口:

对话框一般分为两种类型:模态类型(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>

页面Noname2.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.跳转到该模态窗口,拿到该窗口内的文字

3.关闭该窗口

使用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.runJavaScript("window.close();");
        HolmosWindow.closeModalDialog();
        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");           
        }
}

其中有个延伸方法getModalDialogText()用来获取页面文字内容:

//    获取模态框窗口的文字内容
    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;    
    }

延伸方法getModalDialogHtml()

//    获取模态框窗口的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("模态窗口关闭成功!");
    }

以上三个延伸方法从本质上来说是一样的,通过执行脚本来达到特定的目的。

在经过方法封装后,就不必每次使用时手写HolmosWindow.runJavaScript(“*”);

从而达到降低使用门槛,节省编写用例时间的目的。

本文链接:http://blogs.360.cn/post/如何使用holmos处理模态窗口(modaldialog).html

-- EOF --

Comments