Web Driver处理模态窗口无法获得句柄的问题

今天在用web driver的方法:driver.getWindowHandles()只能得到一个句柄,但是明明打开了一个父窗口和一个子窗口,而子窗口是模态窗口。这是怎么一回事呢?

看到网上的这篇文章http://17test.info/?p=712的回复后,我得到了答案。原来是2.21版本的问题。于是就从seleniumhq.com下载了新的版本2.24.

句柄终于拿到了。

普及一下模态和非模态,也是回顾一下:

对话框一般分为两种类型:模态类型(modal)与非模态类型(modeless)。所谓模态对话框,就是指除非采取有效的关闭手段,用户的鼠标焦点或者输入光标将一直停留在其上的对话框。非模态对话框则不会强制此种特性,用户可以在当前对话框以及其他窗口间进行切换。

同时分享方法,得到已知标题的web page的driver

public boolean SwitchToWindowUsingTitle(WebDriver driver, String windowTitle) {
		String currentWindow = driver.getWindowHandle();
		Set<String> availableWindows = driver.getWindowHandles();
		if(availableWindows.size() != 0) {
			Iterator<String> windowIDIterator = availableWindows.iterator();
			while(windowIDIterator.hasNext()) {
				if(driver.switchTo().window(windowIDIterator.next()).getTitle().equals(windowTitle)) {
					return true;
				}
			}
			driver.switchTo().window(currentWindow);
		}
		return false;
	}


=======================================================美丽的分割线==================================================================

在折腾了一天之后,我终于得到了更完美的解决方案。

这个问题是这样的:完成了上面的方法之后,我做了几次的测试,通过。转天过来再试,就不行了。每当我debug看handles值,没问题。但是当我运行而不是debug。就无法得到所有的句柄。这个问题跟版本无关。我现在运行的版本还是2.21.

工夫不负苦心人。我终于从一篇文章中得到了答案。先贴出代码和网页

Address: https://groups.google.com/forum/?fromgroups#!topic/webdriver/Wi1-1U9snTs 最后的留言

public boolean switchToWindowFromGoogle(WebDriver driver, WebElement elementToTRModal, final String windowTitle) {
		 final Set<String> handles = driver.getWindowHandles();
		 elementToTRModal.click();
		 return (new WebDriverWait(driver, 1000))
					 .until(new ExpectedCondition<Boolean>() {
			
						@Override
						public Boolean apply(WebDriver arg0) {
							// TODO Auto-generated method stub
							Set<String> newHandles = arg0.getWindowHandles();
							newHandles.removeAll(handles);
							if(newHandles.size() > 0) {
								if(arg0.switchTo().window(newHandles.iterator().next())
										.getTitle().contains(windowTitle)) {
									System.out.println("driver switch to pop up window.");
									return true;
								}
							}
							System.out.println("Not find any other handle. Go to current window.");
							return false;
						}
					});
		
	}

这段代码的区别就是加入了WebDriverWait,通过回放我发现"Not find any other handle. Go to current window."这句话执行了两遍。第三次的时候才成功得到所有的句柄。当然我还不明白是为什么。但是我看WebDriverWait是很好的解决方法。

根据我之前商业工具的经验,应该是对象库或者说反射时,句柄不是一下就能得到的,需要等一段时间。而等多长时间呢?之前我们是定一个比较长的值。但是有一回,我们在一个非常慢的机器上进行脚本回放时,出事了。等待时间长度不够。导致程序找不到对象,然后一次次失败。

Web Driver提供的Wait方法,可以手动写条件,条件不满足则继续等待。这样的方式比较好。

===================================================================================================================================

上面的方案在对付一个模态窗口时可以,但是在打开多个模态时fail。因为拿到iterator之后,没有循环。补充

public boolean switchToWindowFromGoogle(final String windowTitle) {
		final String currentHandle = this.driver.getWindowHandle();
		return (new WebDriverWait(this.driver, 1000))
				.until(new ExpectedCondition<Boolean>() {

					@Override
					public Boolean apply(WebDriver arg0) {
						// Get handles to set
						Set<String> newHandles = arg0.getWindowHandles();
						// Remove current window
						newHandles.remove(currentHandle);

						// Iterate with handles
						Iterator<String> handlesIterator = newHandles.iterator();
						while (handlesIterator.hasNext()) {
							// If it is the expect window matching title.
							if (arg0.switchTo()
									.window((String) handlesIterator.next())
									.getTitle().contains(windowTitle)) {
								System.out
										.println("driver switch to pop up window.");
								return true;
							}
						}
						System.out
								.println("Not find any other handle. Go to current window.");
						return false;
					}
				});

	}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在Qt中,可以使用QProcess进行子进程的创建和管理。然而,QProcess本身并不提供获取窗口的功能。要获取子进程的窗口,可以借助一些底层操作系统的API。 首先,在Qt中启动子进程之后,可以使用QProcess的pid()函数获取子进程的进程ID。然后,可以使用操作系统相关的API来获取子进程的窗口。以下以Windows操作系统为例,介绍如何实现: 1. 使用QProcess启动子进程。 ``` QProcess process; process.start("your_executable_file"); ``` 2. 获取子进程的进程ID。 ``` qint64 pid = process.pid(); ``` 3. 使用Windows API函数EnumWindows()遍历所有顶级窗口,并查找与子进程进程ID对应的窗口。 ```cpp #include <windows.h> HWND childWindow = nullptr; BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) { DWORD pid; GetWindowThreadProcessId(hwnd, &pid); if (pid == static_cast<DWORD>(lParam)) { childWindow = hwnd; return FALSE; // 找到目标窗口后,终止遍历 } return TRUE; } EnumWindows(EnumWindowsProc, static_cast<LPARAM>(pid)); ``` 4. 最后,可以使用获取到的窗口进行后续操作,例如设置窗口属性、发送消息等。 ```cpp // 设置窗口标题 QString title = "New Window Title"; SetWindowText(childWindow, title.toStdWString().c_str()); // 发送消息到子进程窗口 std::wstring message = L"Hello from Parent"; SendMessage(childWindow, WM_SETTEXT, 0, reinterpret_cast<LPARAM>(message.c_str())); ``` 需要注意的是,获取窗口是操作系统相关的操作,不同平台可能有不同的实现方式。因此,上述代码只适用于Windows平台。在其他平台上,可能需要使用不同的API函数或方法来获取窗口

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值