单击按钮后如何打开新的浏览器窗口?


Answers:


117

您可以在以下窗口之间切换:

// Store the current window handle
String winHandleBefore = driver.getWindowHandle();

// Perform the click operation that opens new window

// Switch to new window opened
for(String winHandle : driver.getWindowHandles()){
    driver.switchTo().window(winHandle);
}

// Perform the actions on new window

// Close the new window, if that window no more required
driver.close();

// Switch back to original browser (first window)
driver.switchTo().window(winHandleBefore);

// Continue with original browser (first window)

3
我可以确认接受的解决方案在Chrome中始终有效,但在IE中不行。在IE中无法识别新的窗口句柄。@Elmue不正确,因为getWindowHandles()返回Set,并且Set不保证排序。最后一个元素并不总是最后一个窗口。令他惊讶的是,我感到惊讶。
银色

@silver:我不知道你在说什么。在我的代码中,WindowHandles返回一个ReadOnlyCollection <string>,对此我可以保证最后一个条目始终是最新打开的窗口。我测试了 如果这在C#中完美地工作,但在Java中实现不正确,则应将其报告为错误。
Elmue

@Elmue这是一个Java线程。请阅读Luke(Selenium开发人员)关于的回复getWindowHandles()。这是该方法尤其是Java Set <T>的已知行为(不是bug)。因此,switchTo().window(handles[handles.length-1])在Java中不能保证。不能声称AC#解决方案是正确的。

5
@Elmue第三次(也是最后一次),您的答案对于Java是错误的,因为docs和dev可能会误导人们。在您说的是针对C#的地方发布答案,没问题。在GitHub中为Java发行一张发行卡,继续。简而言之,您的答案不适用于该主题中的“ TAGGED”语言,人们可能会另外考虑。如果您无法做出区分,则您的理解力不足。

3
@Elmue顺便说一句,您说driver.close()关闭两个窗口也是错误的。它仅关闭电流。driver.quit()杀死所有实例。我可以看到有人已经向您指出了这一点。您的评论充满了错误。祝你有美好的一天。

12

只是添加到内容...

返回主窗口(默认窗口)。

使用 driver.switchTo().defaultContent();


11

该脚本可帮助您从父窗口切换到子窗口,然后将cntrl切换回父窗口。

String parentWindow = driver.getWindowHandle();
Set<String> handles =  driver.getWindowHandles();
   for(String windowHandle  : handles)
       {
       if(!windowHandle.equals(parentWindow))
          {
          driver.switchTo().window(windowHandle);
         <!--Perform your operation here for new window-->
         driver.close(); //closing child window
         driver.switchTo().window(parentWindow); //cntrl to parent window
          }
       }

1
driver.close()将在新窗口中工作。如果是新标签页,则使用代码关闭新标签页:driver.findElement(By.cssSelector(“ body”))。sendKeys(Keys.CONTROL +“ w”);
Ripon Al Wasim

4

苏里亚,您的方法行不通,原因有两个:

  1. 您不能在评估测试期间关闭驱动程序,因为它将在切换到活动元素之前失去对焦点的关注,并且您会收到NoSuchWindowException。
  2. 如果测试在ChromeDriver上运行,则不会显示一个窗口,而是会在您的应用程序中单击的标签。由于SeleniumDriver不能与选项卡一起使用,只能在窗口之间切换,它会在打开新选项卡的位置单击并挂起,并在超时时崩溃。

1
实际上,您可以使用对driver.close()的调用,因为您要在驱动程序上切换窗口句柄并调用您当前要关闭的窗口。处理多个窗口时,我会在代码中定期使用它。driver.Quit()是将终止测试的调用。在Chromedriver中,您仍然可以调用getWindowHandles()来获取可用窗口列表。我想不出在网络测试中使用选项卡的原因。

@Elmue最初的问题是,单击可打开第二个窗口,从而创建多个窗口句柄。我可以打电话给driver.close(); 并关闭当前具有焦点的窗口。然后,我可以切换到我选择的任何其他活动窗口。driver.close()和driver.quit()不共享相同的功能。调用driver.quit()将杀死活动的驱动程序实例,而close仅杀死当前的窗口句柄。另外,当网站上的javascript创建新窗口时,在单击一次单击后,我还没有看到任何仅打开选项卡的调用。

我错了,并删除了我的评论。您也可以删除答案。
Elmue 2015年

3

修改IE的注册表:

ie_x64_tabprocgrowth.png

  1. HKEY_CURRENT_USER \ Software \ Microsoft \ Internet Explorer \ Main
  2. 右键单击→新建→字符串值→值名称:TabProcGrowth(如果不存在则创建)
  3. TabProcGrowth(右键单击)→修改...→值数据:0

来源: Internet Explorer 8-10中的Selenium WebDriver Windows切换问题

就我而言,IE在注册表编辑后开始检测新的窗口句柄。

摘自MSDN博客:

制表进程的增长:设置IE创建“新制表”进程的速率。

“最大数量”(Max-Number)算法:这指定在特定的强制完整性级别(MIC)下,单个帧会话的单个隔离会话可以执行的选项卡进程的最大数量。相对值是:

  • TabProcGrowth = 0:选项卡和框架在同一进程中运行;跨MIC级别的帧没有统一。
  • TabProcGrowth = 1:给定帧过程的所有选项卡在给定MIC级别的单个选项卡过程中运行。

来源: 打开一个新选项卡可能会使用Internet Explorer 8.0启动一个新过程


互联网选项:

  • 安全→取消选中所有区域(Int​​ernet,本地Intranet,受信任的站点,受限制的站点)的启用保护模式
  • 高级→安全性→取消选中启用增强保护模式

码:

浏览器: IE11 x64(缩放:100%)
操作系统: Windows 7 x64
硒: 3.5.1
WebDriver: IEDriverServer x64 3.5.1

public static String openWindow(WebDriver driver, By by) throws IOException {
String parentHandle = driver.getWindowHandle(); // Save parent window
WebElement clickableElement = driver.findElement(by);
clickableElement.click(); // Open child window
WebDriverWait wait = new WebDriverWait(driver, 10); // Timeout in 10s
boolean isChildWindowOpen = wait.until(ExpectedConditions.numberOfWindowsToBe(2));
if (isChildWindowOpen) {
    Set<String> handles = driver.getWindowHandles();
    // Switch to child window
    for (String handle : handles) {
        driver.switchTo().window(handle);
        if (!parentHandle.equals(handle)) {
            break;
        }
    }
    driver.manage().window().maximize();
}
return parentHandle; // Returns parent window if need to switch back
}



/* How to use method */
String parentHandle = Selenium.openWindow(driver, by);

// Do things in child window
driver.close();

// Return to parent window
driver.switchTo().window(parentHandle);

上面的代码包含一个if-check,以确保您没有切换到父窗口,因为Set<T>Java中没有保证的顺序WebDriverWait如下所述,似乎增加了成功的机会。

引用自Luke Inman-Semerau:(硒开发人员)

浏览器可能需要一些时间来确认新窗口,并且您可能会在弹出窗口出现之前陷入switchTo()循环中。

您会自动假定getWindowHandles()返回的最后一个窗口将是最后打开的窗口。不一定是正确的,因为不能保证以任何顺序返回它们。

来源: 无法处理IE中的弹出窗口,控件未转移到弹出窗口


相关文章:


2

您可以使用:

driver.SwitchTo().Window(WindowName);

其中WindowName是一个字符串,代表您要将焦点切换到的窗口的名称。完成后,使用原始窗口的名称再次调用此函数以返回到该窗口。


1
谢谢你的建议,有什么办法,我该如何设置窗口名称掩码?类似于“ WinName *”,其中*-任何符号。
Volodymyr Prysiazhniuk 2012年

1
我隐式地是10秒,但是在2秒的时间内却给了我NoSuchWindowException异常。
Volodymyr Prysiazhniuk 2012年

2

我使用迭代器和while循环来存储各种窗口句柄,然后来回切换。

//Click your link
driver.findElement(By.xpath("xpath")).click();
//Get all the window handles in a set
Set <String> handles =driver.getWindowHandles();
Iterator<String> it = handles.iterator();
//iterate through your windows
while (it.hasNext()){
String parent = it.next();
String newwin = it.next();
driver.switchTo().window(newwin);
//perform actions on new window
driver.close();
driver.switchTo().window(parent);
            }

它无法切换到新选项卡,但是会在所需的新选项卡上单击。为什么?
paul 2014年

有什么原因可能导致此代码测试变得非常缓慢?似乎在这段代码之后,大约需要10分钟才能在newwin中执行任何操作
Hugo

0
 main you can do :

 String mainTab = page.goToNewTab ();
 //do what you want
 page.backToMainPage(mainTab);  

 What you need to have in order to use the main   

        private static Set<String> windows;

            //get all open windows 
            //return current window
            public String initWindows() {
                windows = new HashSet<String>();
                driver.getWindowHandles().stream().forEach(n ->   windows.add(n));
                return driver.getWindowHandle();
            }

            public String getNewWindow() {
                List<String> newWindow = driver.getWindowHandles().stream().filter(n -> windows.contains(n) == false)
                        .collect(Collectors.toList());
                logger.info(newWindow.get(0));
                return newWindow.get(0);
            }


            public String goToNewTab() {
                String startWindow = driver.initWindows();
                driver.findElement(By.cssSelector("XX")).click();
                String newWindow = driver.getNewWindow();
                driver.switchTo().window(newWindow);
                return startWindow;
            }

            public void backToMainPage(String startWindow) {
                driver.close();
                driver.switchTo().window(startWindow);
            }

0

因此,许多此类解决方案的问题是您假设窗口立即出现(没有立即发生,并且在IE中发生的情况明显少于立即发生)。另外,您假设单击元素之前只有一个窗口,但情况并非总是如此。IE也不会以可预测的顺序返回窗口句柄。因此,我将执行以下操作。

 public String clickAndSwitchWindow(WebElement elementToClick, Duration 
    timeToWaitForWindowToAppear) {
    Set<String> priorHandles = _driver.getWindowHandles();

    elementToClick.click();
    try {
        new WebDriverWait(_driver,
                timeToWaitForWindowToAppear.getSeconds()).until(
                d -> {
                    Set<String> newHandles = d.getWindowHandles();
                    if (newHandles.size() > priorHandles.size()) {
                        for (String newHandle : newHandles) {
                            if (!priorHandles.contains(newHandle)) {
                                d.switchTo().window(newHandle);
                                return true;
                            }
                        }
                        return false;
                    } else {
                        return false;
                    }

                });
    } catch (Exception e) {
        Logging.log_AndFail("Encountered error while switching to new window after clicking element " + elementToClick.toString()
                + " seeing error: \n" + e.getMessage());
    }

    return _driver.getWindowHandle();
}

-1

如果您有一个以上的浏览器(使用Java 8)

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;

public class TestLink {

  private static Set<String> windows;

  public static void main(String[] args) {

    WebDriver driver = new FirefoxDriver();
    driver.get("file:///C:/Users/radler/Desktop/myLink.html");
    setWindows(driver);
    driver.findElement(By.xpath("//body/a")).click();
    // get new window
    String newWindow = getWindow(driver);
    driver.switchTo().window(newWindow);

    // Perform the actions on new window
    String text = driver.findElement(By.cssSelector(".active")).getText();
    System.out.println(text);

    driver.close();
    // Switch back
    driver.switchTo().window(windows.iterator().next());


    driver.findElement(By.xpath("//body/a")).click();

  }

  private static void setWindows(WebDriver driver) {
    windows = new HashSet<String>();
    driver.getWindowHandles().stream().forEach(n -> windows.add(n));
  }

  private static String getWindow(WebDriver driver) {
    List<String> newWindow = driver.getWindowHandles().stream()
        .filter(n -> windows.contains(n) == false).collect(Collectors.toList());
    System.out.println(newWindow.get(0));
    return newWindow.get(0);
  }

}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.