如何使用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.跳转到该模态窗口,拿到该窗口内的文字


使用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");       	
        }
}

其中有个延伸方法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("*********");

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


你可能感兴趣的:(selenium,自动化测试,webdriver,Holmos)