使用Selenium/Protractor Javascript切换到新窗口

10

我需要帮助,想知道在点击“登录”按钮后如何获取一个新的“弹出”窗口。

我可以获取到窗口显示的时机,但是我认为我当前使用的代码无法正确地抓取窗口“句柄”。我的情况有点不同,因为我在页面内使用protractor,但新窗口不基于Angular,所以我必须切换到在该窗口中使用Selenium WebDriver。(是否有人知道这种方法可能会存在问题?)

下面是我正在使用的代码片段,用于创建Selenium驱动程序,并试图“切换/抓取”弹出的新窗口的句柄。 我知道它没有正常工作,因为在接下来的代码中尝试查找页面上的表单时,我一直收到“没有这样的元素”的错误消息。

    // Create selenium webdriver / driver
    var webdriver = require('selenium-webdriver');

    var driver = new webdriver.Builder().
        withCapabilities(webdriver.Capabilities.chrome()).
        build();

  // Now make sure that the new window is popping up and we are navigating   correctly to it
      var handlePromise = browser.driver.getAllWindowHandles();
      handlePromise.then(function (handles) {
        // parentHandle = handles[0];
        var popUpHandle = handles[1];

        // Change to new handle
        browser.driver.switchTo().window(popUpHandle);

        var popUpHandleFinal = browser.driver.getWindowHandle();
        expect(popUpHandleFinal).toEqual(popUpHandle);
    });

关于此事有几点需要注意:

  1. 如果我在这行代码中移除 "browser",变成 "driver.switchTo().window(popUpHandle)",则会收到一个错误信息,其内容为 "UnknownError: unknown error: 'name' must be a nonempty string" 经过一番搜索之后发现,这是因为驱动程序上的 "switchTo()" 方法不能为 null。只需使用上述代码即可清除此错误。

  2. 我不确定应该使用protractor(全局 "browser" 变量),还是使用我在此之前设置的原生 "driver" (Selenium)来获取弹出窗口。

感谢您的帮助。


可能与此相关:https://dev59.com/h14b5IYBdhLWcg3w9FkI。 - alecxe
1
如果您已经在工作的 Protractor 驱动程序上下文中,您不需要在内部启动单独的 webdriver 实例。(这可能会让浏览器混淆两个远程控制器)。Protractor 通过 browser.driver 公开其正在使用的原始 webdriver,因此应该正确使用。 - P.T.
这是我的主要问题。谢谢。一旦我取消了设置其他驱动程序,然后在几次迭代后重新使用browser.driver,我就能够让它正常工作了。 - parchambeau
4个回答

17

截至最新版本的Protractor(v2.2),使用protractor窗口句柄不应该存在问题,它返回一个当前显示的窗口数组。正如P.T指出的那样,没有必要调用单独的驱动程序实例,而是可以使用browser全局变量。调用弹出窗口的窗口在数组索引中为0,弹出窗口将在数组索引中为1。下面是切换到弹出窗口并在其中工作的示例。

browser.getAllWindowHandles().then(function(handles){
    browser.switchTo().window(handles[1]).then(function(){
        //do your stuff on the pop up window
    });
});

希望这能有所帮助。


谢谢,这真的很有帮助。 - lonewarrior556
嗨,我尝试了这段代码,但是出现了相同的错误:UnknownError: unknown error: 'name' must be a nonempty string" 以下是代码: var handlePromise = browser.driver.getAllWindowHandles(); handlePromise.then(function (handles) { // parentHandle = handles[0]; var popUpHandle = handles[1];// 切换到新的句柄 browser.driver.switchTo().window(popUpHandle);}); - anuvrat singh
@anuvratsingh能否调试更多并告诉我你在哪一行遇到了这个错误?还可以检查一下handles数组的长度吗? 我认为你那里没有两个窗口,只有一个,所以你无法切换到handles[1]。谢谢。 - giri-sh
@GirishSortur - 你能建议如何将它变成通用函数吗?我希望这个函数可以被使用并切换到下一个标签,无论它在Chrome窗口中的位置如何。因此,如果我的浏览器正在创建一个新标签,我应该切换到那个新标签,如果我的新标签正在创建另一个标签,那么我的浏览器焦点应该切换到那个新标签。 - NewWorld
@NewWorld 创建一个函数,该函数只调用 switch 到新窗口,您可以在需要切换到新窗口时使用它,这将是最后一个窗口数组元素。要获取最后一个数组元素,请使用 array.length-1 操作。例如 - browser.switchTo().window(handles[handles.length-1]) - 这将切换到最后一个打开的窗口。希望能有所帮助。 - giri-sh
it('一些规范', async () => { await browser.switchTo().window(handles[1]); // 做你的事情 }); - ViES

7
如果您点击任何链接或按钮以打开弹出窗口,请使用 browser.sleep(ms) 在单击后添加一些等待时间。这对我很有用,并且消除了“缺少'handle'参数”的错误。
element(by.className("name")).click();
browser.sleep(10000); //This line is important
var winHandles=browser.getAllWindowHandles();
winHandles.then(function(handles) 
{
    var parentWindow=handles[0];
    var popUpWindow=handles[1];
    browser.switchTo().window(popUpWindow);
    browser.switchTo().window(parentWindow);
})

0
如果您调用了https:// URL并再次重定向到http:// URL,则此弹出窗口是由于安全问题而出现的。
1- 您必须配置https://http://中的两个应用程序。

-1

检查窗口是否可用,因为窗口从0开始计数。所以,尝试减少计数并使用,这可能有效...;) 因为我这样做已经成功了...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接