第二次调用browser.getAllWindowHandles导致错误

时间:2018-07-03 18:01:58

标签: protractor socketexception

我的量角器脚本中有以下情形:(由于机密性,部分内容被删节)

  it('user story, screen captures', function() {

// Make sure page loads before screenshot happens
browser.waitForAngular();

// Mouseover the status element to get mouse away from toastr popup so the logout link will appear
browser.actions().mouseMove(createPage.menuDocview).perform();

// Sleep the browser to get rid of toastr popup
browser.sleep(5000);

// Take screenshot of page
browser.takeScreenshot().then(function (jpg) {
  writeScreenShot(jpg, 'XXX.jpg');
});

// Click on the  menu item
createPage.menuDocview.click();

// Fill in a last name
createPage.lastName_input.sendKeys('smith');

// Click the Submit button
createPage.submitButton.click();

// Make sure page loads before screenshot happens
browser.waitForAngular();

// Mouseover the selected dataRow element
browser.actions().mouseMove(createPage.dataRow.get(3)).perform();

// Take screenshot of page
browser.takeScreenshot().then(function (jpg) {
  writeScreenShot(jpg, 'XXX.jpg');
});

// Find the element we want (XXX) and click it
createPage.dataRow.get(3).click();

// Make sure page loads before screenshot happens
browser.waitForAngular();

// Take screenshot of page
browser.takeScreenshot().then(function (jpg) {
  writeScreenShot(jpg, 'XXX.jpg');
});

// Mouseover the selected dataRow element
browser.actions().mouseMove(createPage.statusDiv.get(0)).perform();

// Sleep the browser to give popup a chance to show
browser.sleep(2000);

// Take screenshot of page
browser.takeScreenshot().then(function (jpg) {
  writeScreenShot(jpg, 'XXX.jpg');
});

// Mouseover the button element
browser.actions().mouseMove(createPage.printPrescriber).perform();

// Take screenshot of page
browser.takeScreenshot().then(function (jpg) {
  writeScreenShot(jpg, 'XXX.jpg');
});

// Click the button to get the report
createPage.printPrescriber.click();

// Switch to report window and screenshot it
// Sleep the browser for a few seconds to give it time to openup new window/tab
browser.sleep(5000);
// We'll need to switch to new window, so first grab the window handles...
browser.getAllWindowHandles().then(function (handles) { 
  // then grab our new window's handle...
  var mainWindowHandle = handles[0]; // this is your main window
  var newWindowHandle = handles[1]; // this is your new window
  // then switch to it.
  browser.switchTo().window(newWindowHandle).then(function () {
    // this next line is necessary since the generated page isn't Angular, and, as such, Protractor will timeout waiting for it to validate as an Angular page
    browser.ignoreSynchronization = true;
    // Take screenshot of page
    browser.takeScreenshot().then(function (jpg) {
      writeScreenShot(jpg, 'XXX.jpg');
    });

//        browser.close(); //close the current browser

    browser.switchTo().window(mainWindowHandle) //Switch to main window
      .then(function(){
        // Mouseover the Print History button element
        browser.actions().mouseMove(createPage.printHistory).perform();

        // Take screenshot of page
        browser.takeScreenshot().then(function (jpg) {
          writeScreenShot(jpg, 'XXX.jpg');
        });

        // Click the button to get the report
        createPage.printHistory.click();
        // Switch to report window and screenshot it
        // Sleep the browser for a few seconds to give it time to openup new window/tab
        browser.sleep(12000);
        // We'll need to switch to new window, so first grab the window handles...
        browser.getAllWindowHandles().then(function (handles) {//THIS IS THE PROBLEM LINE WHERE IT DIES 
          // then grab our new window's handle...
          var newWindowHandle2 = handles[2]; // this is your new window
          // then switch to it.
          browser.switchTo().window(newWindowHandle2).then(function () {
            // this next line is necessary since the generated page isn't Angular, and, as such, Protractor will timeout waiting for it to validate as an Angular page
            browser.ignoreSynchronization = true;
            // Take screenshot of page
            browser.takeScreenshot().then(function (jpg) {
              writeScreenShot(jpg, 'XXX.jpg');
            });
            // Just send true back since there's nothing we really want to commit to checking on the pdf. If there's a problem, we'll have it before this point.
            expect(true);
          });
        });
      });
  });
});

});

我一点一点地构建了它,基本上是在每个屏幕截图之前添加了每个片段,并确保在继续下一个片段之前可以正常工作。从第二次调用browser.getAllWindowHandles()开始的最后一部分使脚本崩溃,并产生以下错误:

Failed: java.net.SocketException: Software caused connection abort: recv failed

我大大增加了超时时间(如您所见)。我将browser.close()注释掉,以防万一。仍然得到它。

当我观看测试运行时,它一切正常,甚至单击最后一个按钮,生成最后一个报告。当我第二次要求它获取窗口句柄时,它发出嘶哑的声音。我什至可以在屏幕截图之前得到它。

我已经在Google上进行了广泛的搜索,甚至在SO上查找了该错误,但仍然不清楚为什么要这样做。

谢谢!

编辑:因此,我只是尝试单击了第二个报告。同样的错误。可能第二份报告太长了吗?显然,第二个报告(从动态数据生成的PDF)出了点问题。什么样的情况会在生成的PDF中导致此错误?

编辑2:我将browser.wait增加到20秒,但仍然可以得到它。我认为这不是时间问题。

编辑3(7/5):因此,似乎它实际上与计时有关。新的报告窗口需要一点时间。如果我睡了5秒钟,我会收到一个错误消息,因为它不存在,所以无法找到它。我最多移动了6秒,并且得到了socketException。是否愿意改用browser.wait()?在这种情况下我将如何实施?

2 个答案:

答案 0 :(得分:1)

处理浏览器句柄有时会非常棘手,尤其是对于Mozilla和IE11。

这是一种用于检索所有浏览器句柄标题为字符串的方法。您可以轻松地调整代码,并使其在任何情况下均适用。

/**
   * this method helps to get all window titles
   * @param windowTitle
   */
  async getAllRedirectedBrowserWindowTitles() {
    const title: string[] = [];
    await browser.wait(
      async () => {
        return (await browser.getAllWindowHandles()).length >= 2;
      },
      5000,
      `Only one browser handle found. There is no other browser handle to iterate`
    );
    const _windowHandles: string[] = await browser.getAllWindowHandles();
    const _parentHandle: string = _windowHandles[0];
    for (const guid of _windowHandles) {
      if (guid !== _parentHandle) {
        await browser.switchTo().window(guid);
        await browser.wait(
          async () => {
            return (await browser.getTitle()) ? true : false;
          },
          5000,
          `Child browser title not loaded`
        );
        title.push(await browser.getTitle());
        await browser.close();
      }
    }
    await browser.switchTo().window(_parentHandle);
    return title;
  }

现在,您只需要在代码中的任何位置调用此方法:

await getAllRedirectedBrowserWindowTitles(); //this will return the list of window title

编码愉快!

答案 1 :(得分:0)

知道了!!!

我在SO上的其他地方找到了这片摘要的宝石,就成功了。

 browser.driver.wait(function () {
            return browser.getAllWindowHandles().then(function (handles) {

                if (handles.length > 1) {
                    return true;
                }
            });
        }, 10000, 'Waited for window count to be greater than 1');

我在5秒钟的睡眠之前插入了此文件,它的工作就像一种魅力。 另外,需要注意的是,当我没有关闭第一个报告窗口时,第二个报告窗口也不位于handles数组的位置3。它将自己插入位置2,将第一个报告推到位置3。