Poplen在selenium webdrivers中

时间:2014-12-22 19:07:19

标签: c# selenium selenium-webdriver

所以我在c#winform中使用selenium firefox webdrivers,我在下面有这个代码来获取当你点击“webtraffic_popup_start_button”时显示的弹出窗口的句柄,它应该得到弹出窗口的句柄但弹出窗口句柄与当前句柄相同。

string current = driver.CurrentWindowHandle;
driver.FindElement(By.XPath("//*[@id='webtraffic_popup_start_button']")).Click();
Thread.Sleep(Sleep_Seconds);
popup = driver.CurrentWindowHandle;
Thread.Sleep(3000);
driver.SwitchTo().Window(current);
Thread.Sleep(1000);

非常感谢您对此的任何帮助

弹出窗口就是这样。

Popup_Image

3 个答案:

答案 0 :(得分:27)

WebDriver绝对不会跟踪检测哪个窗口实际位于操作系统的前台,并且在打开新的浏览器窗口时不会自动切换。这意味着获取新打开的弹出窗口句柄的正确方法是一个多步骤的过程。为此,你会:

  1. 将当前关注的窗口句柄保存到变量中以便您 可以稍后再切换回来。
  2. 获取当前打开的窗口句柄列表。
  3. 执行可能导致新窗口显示的操作。
  4. 等待窗口句柄数增加1。
  5. 获取新的窗口句柄列表。
  6. 在句柄列表中找到新句柄。
  7. 切换到新窗口。
  8. 在使用.NET语言绑定的代码中,看起来像这样:

    string currentHandle = driver.CurrentWindowHandle;
    ReadOnlyCollection<string> originalHandles = driver.WindowHandles;
    
    // Cause the popup to appear
    driver.FindElement(By.XPath("//*[@id='webtraffic_popup_start_button']")).Click();
    
    // WebDriverWait.Until<T> waits until the delegate returns
    // a non-null value for object types. We can leverage this
    // behavior to return the popup window handle.
    WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(5));
    string popupWindowHandle = wait.Until<string>((d) =>
    {
        string foundHandle = null;
    
        // Subtract out the list of known handles. In the case of a single
        // popup, the newHandles list will only have one value.
        List<string> newHandles = driver.WindowHandles.Except(originalHandles).ToList();
        if (newHandles.Count > 0)
        {
            foundHandle = newHandles[0];
        }
    
        return foundHandle;
    });
    
    driver.SwitchTo().Window(popupWindowHandle);
    
    // Do whatever you need to on the popup browser, then...
    driver.Close();
    driver.SwitchToWindow(currentHandle);
    

    或者,如果您正在使用.NET绑定,则WebDriver.Support程序集中有一个PopupWindowFinder类,专门用于为您执行这些操作。使用该类更简单。

    // Get the current window handle so you can switch back later.
    string currentHandle = driver.CurrentWindowHandle;
    
    // Find the element that triggers the popup when clicked on.
    IWebElement element = driver.FindElement(By.XPath("//*[@id='webtraffic_popup_start_button']"));
    
    // The Click method of the PopupWindowFinder class will click
    // the desired element, wait for the popup to appear, and return
    // the window handle to the popped-up browser window. Note that
    // you still need to switch to the window to manipulate the page
    // displayed by the popup window.
    PopupWindowFinder finder = new PopupWindowFinder(driver);
    string popupWindowHandle = finder.Click(element);
    
    driver.SwitchTo().Window(popupWindowHandle);
    
    // Do whatever you need to on the popup browser, then...
    driver.Close();
    driver.SwitchToWindow(currentHandle);
    

答案 1 :(得分:4)

如果最后打开的窗口是您的目标,则只需在单击

后执行以下操作
driver.SwitchTo().Window(driver.WindowHandles.ToList().Last());

修改

//You may need to go back to parent window to perform additional actions;

// to the new window
driver.SwitchTo().Window(driver.WindowHandles.ToList().Last());

 // to the new window
driver.SwitchTo().Window(driver.WindowHandles.ToList().First());
//or
driver.SwitchTo().DefaultContent();

答案 2 :(得分:0)

我有一些你可能喜欢的代码。最快的解决方案是使用Popup Finder,但我也制作了自己的方法。我永远不会依赖Window Handles所在的顺序来选择合适的窗口。弹出窗口查找器:

PopupWindowFinder finder = new PopupWindowFinder(driver);
driver.SwitchTo().Window(newWin); 

我的自定义方法。基本上你传递了你想要点击的元素,你的webdriver,以及你点击元素后搜索之前等待的时间。

它会获取所有当前句柄并生成一个列表。它使用该列表来消除以前存在的窗口意外切换到。然后单击启动新窗口的元素。点击后应始终存在某种延迟,因为没有立即发生。然后它创建一个新列表并将其与旧列表进行比较,直到找到新窗口或循环到期为止。如果找不到新窗口,则返回null,因此如果你有一个并不总是有用的iffy webelement,你可以进行空检查,看看交换机是否有效。

public static string ClickAndSwitchWindow(IWebElement elementToBeClicked,
IWebDriver driver, int timer = 2000)
        {
            System.Collections.Generic.List<string> previousHandles = new 
System.Collections.Generic.List<string>();
            System.Collections.Generic.List<string> currentHandles = new 
System.Collections.Generic.List<string>();
        previousHandles.AddRange(driver.WindowHandles);
        elementToBeClicked.Click();

        Thread.Sleep(timer);
        for (int i = 0; i < 20; i++)
        {
            currentHandles.Clear();
            currentHandles.AddRange(driver.WindowHandles);
            foreach (string s in previousHandles)
            {
                currentHandles.RemoveAll(p => p == s);
            }
            if (currentHandles.Count == 1)
             {
                driver.SwitchTo().Window(currentHandles[0]);
                Thread.Sleep(100);
                return currentHandles[0];
            }
            else
            {
                Thread.Sleep(500);
            }
        }
        return null;
    }