【问题标题】:How to switch to the new browser window, which opens after click on the button?如何切换到单击按钮后打开的新浏览器窗口?
【发布时间】:2012-03-24 05:37:06
【问题描述】:

我有这样的情况,当点击按钮打开带有搜索结果的新浏览器窗口时。

有什么方法可以连接并关注新打开的浏览器窗口吗?

并使用它,然后返回原始(第一个)窗口。

【问题讨论】:

标签: java selenium selenium-webdriver webdriver new-window


【解决方案1】:

你可以使用:

driver.SwitchTo().Window(WindowName);

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

【讨论】:

  • 谢谢你的建议,有什么办法可以设置窗口名称掩码吗?像“WinName*”,其中 * - 任何符号。
  • 我的隐含时间是 10 秒,但在 2 秒内它给了我异常 NoSuchWindowException。
【解决方案2】:

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

// 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)

【讨论】:

  • 我可以确认接受的解决方案在 Chrome 中始终有效,但在 IE 中无效。 IE 无法识别新的窗口句柄。 @Elmue 不正确,因为 getWindowHandles() 返回一个 Set 和 a Set does not guarantee ordering。最后一个元素并不总是最后一个窗口。我很惊讶他的评论得到了很多支持。
  • @silver:我不知道你在说什么。在我的代码中,WindowHandles 返回一个 ReadOnlyCollection,我可以保证最后一个条目始终是最新打开的窗口。我对此进行了测试。如果这在 C# 中完美运行,但在 Java 中错误实现,则应将其报告为错误。
  • @Elmue 这是一个 Java 线程。请阅读 Luke 的(Selenium 开发人员)response 关于getWindowHandles()。这是该方法的已知行为(不是错误),尤其是 Java Set。因此,switchTo().window(handles[handles.length-1]) 在 Java 中无法保证。不能声称 C# 解决方案是正确的。
  • @Elmue 第三次(也是最后一次),你的答案是 false 对于 Java 的支持,因为文档和开发人员可能会误导人们。在您说它适用于 C# 的地方发布答案,没问题。在 GitHub 中为 Java 提出问题卡,继续。只是您的答案不适用于线程中标记的语言,人们可能会不这么认为。如果你不能区分,你的理解力就不足。
  • @Elmue 顺便说一句,你说 driver.close() 关闭两个窗口也是错误的。它只关闭电流。 driver.quit() 杀死所有实例。我可以看到有人已经向你指出了这一点。你的评论充满了错误。祝你有美好的一天。
【解决方案3】:

我使用迭代器和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);
            }

【讨论】:

  • 它无法切换到新标签,但是它会在所需的新标签上执行点击。为什么?
  • 这段代码是否有任何原因可能导致测试变得很慢?看来在这段代码之后,在newwin中执行任何操作大约需要10分钟
【解决方案4】:

Surya,你的方式行不通,原因有二:

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

【讨论】:

  • 您实际上可以使用对 driver.close() 的调用,因为您正在切换驱动程序上的窗口句柄并调用您当前正在关闭的窗口。在处理多个窗口时,我经常在我的代码中使用它。 driver.Quit() 是会终止测试的调用。在 Chromedriver 中,您仍然可以调用 getWindowHandles() 来获取可用窗口的列表。我想不出在网络测试中使用标签的理由。
  • @Elmue 最初的问题指出,单击会打开第二个窗口,创建多个窗口句柄。我可以打电话 driver.close();并关闭当前焦点所在的窗口。然后我可以切换到我选择的任何其他活动窗口。 driver.close() 和 driver.quit() 不共享相同的功能。调用 driver.quit() 将终止活动的驱动程序实例,而 close 仅​​终止当前窗口句柄。此外,当网站上的 javascript 创建新窗口时,我还没有看到任何仅在单击后打开选项卡的调用。
  • 我错了,删除了我的评论。你也可以删除你的答案。
【解决方案5】:

只是为了添加内容...

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

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

【讨论】:

    【解决方案6】:

    此脚本可帮助您从 父窗口 切换到 子窗口 并返回 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
              }
           }
    

    【讨论】:

    • driver.close() 将适用于新窗口。如果是新标签,则使用代码关闭新标签:driver.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL + "w");
    【解决方案7】:

    如果您有多个浏览器(使用 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);
      }
    
    }
    

    【讨论】:

      【解决方案8】:

      修改 IE 的注册表:

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

      来源: Selenium WebDriver windows switching issue in Internet Explorer 8-10

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

      取自 MSDN 博客:

      标签进程增长:设置 IE 创建新标签进程的速率。

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

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

      来源: Opening a New Tab may launch a New Process with Internet Explorer 8.0


      互联网选项:

      • 安全 → 为所有区域(互联网、 本地 Intranet、可信站点、受限站点)
      • 高级 → 安全 → 取消勾选启用增强保护模式

      代码:

      浏览器: IE11 x64(缩放:100%)
      操作系统: Windows 7 x64
      Selenium: 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 检查,以确保您没有切换到 Set&lt;T&gt; has no guaranteed ordering in Java 的父窗口。 WebDriverWait 似乎增加了成功的机会,如下所述。

      引自Luke Inman-Semerau:(Selenium 开发者)

      浏览器可能需要一些时间来确认新窗口,您可以 在弹出窗口出现之前进入你的 switchTo() 循环。

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

      来源:Unable to handle a popup in IE,control is not transferring to popup window


      相关帖子:

      【讨论】:

        【解决方案9】:
         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);
                    }
        

        【讨论】:

          【解决方案10】:

          因此,很多这些解决方案的问题是您假设窗口立即出现(没有立即发生,而在 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();
          }
          

          【讨论】:

            【解决方案11】:

            此功能适用于 Selenium 4 及更高版本。

            // Opens a new tab and switches to new tab
            driver.switchTo().newWindow(WindowType.TAB);
            
            // Opens a new window and switches to new window
            driver.switchTo().newWindow(WindowType.WINDOW);
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2015-03-30
              • 1970-01-01
              • 2015-10-20
              • 1970-01-01
              • 1970-01-01
              • 2015-09-09
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多