【问题标题】:Switching to a window with no name切换到没有名称的窗口
【发布时间】:2018-07-27 07:41:43
【问题描述】:

使用 Codeception 测试框架和 Selenium 2 模块来测试一个网站,我最终找到了一个超链接,该超链接打开了一个没有名称的新窗口。因此,switchToWindow() 函数将无法工作,因为它正在尝试切换到父窗口(我目前正在打开)。由于无法切换到新窗口,我无法对其进行任何测试。

<a class="external" target="_blank" href="http://mylocalurl/the/page/im/opening">
  View Live 
</a>

同时使用 Chrome 和 Firefox 调试工具,我可以确认新窗口没有名称,我不能给它一个名称,因为我无法编辑我正在处理的 HTML 页面。理想情况下,我会更改 HTML 以使用 javascript onclick="window.open('http://mylocalurl/the/page/im/opening', 'myPopupWindow') 但在我的情况下这是不可能的。

我在 Selenium 论坛上环顾四周,没有任何明确的方法来解决这个问题,而且 Codeception 似乎没有太多的功能。

【问题讨论】:

  • Codeception 中有getWindowNames() 类型命令吗?抱歉,我似乎找不到文档。
  • 不,没有,文档几乎不存在(尽管随着时间的推移而改进),但是大多数功能都是 Selenium 2 方法的扩展。我相信我可以执行 some Selenium 2 方法,但我不知道哪些方法和多少。文档:codeception.com/docs/modules/Selenium2
  • 哇,这是真正的泡菜。我认为executeInSelenium 将是您最好的选择。查看链接到 PHP webdriver 绑定,它确实可以访问 getWindowHandle()getWindowHandles() 方法。因此,我只能冒险在您打开新窗口之前getWindowHandle(),之后getWindowHandles()。这意味着您知道这两个名称,因此您应该能够从getWindowHandles() 返回的数组中提取“新窗口”名称。希望它能给您一些关于下一步的想法,因为不幸的是我无法理解如何编写 Codeception 示例。
  • 我已经收到提醒并且正要尝试的事情:-&gt;executeInSelenium(function (\Webdriver\Session $webdriver) { $handles=$webdriver-&gt;window_handles(); $last_window = end($handles); $webdriver-&gt;focusWindow($last_window); }); 我猜这就是您的建议。
  • 据我所见,这非常符合我的期望。祝你好运,希望它有效。

标签: codeception


【解决方案1】:

在 Selenium 论坛上搜索并从 @Mark Rowlands 获得一些有用的建议后,我使用原始 Selenium 让它工作。

// before codeception v2.1.1, just typehint on \Webdriver
$I->executeInSelenium(function (\Facebook\WebDriver\Remote\RemoteWebDriver $webdriver) {
    $handles=$webdriver->window_handles();
    $last_window = end($handles);
    $webdriver->focusWindow($last_window);
});

返回父窗口很容易,因为我可以使用 Codeception 的 switchToWindow 方法:

$I->switchToWindow();

【讨论】:

  • 请注意,当 codeception v2.1.1 从 facebook/webdriver 0.6.0 跳转到 1.0+ 时,此闭包所需的签名发生了变化。您现在必须输入提示 \Facebook\WebDriver\Remote\RemoteWebDriver,而不是此处显示的 \Webdriver\Session。 (见github.com/Codeception/Codeception/pull/2684
【解决方案2】:

在接受的答案的基础上,在 Codeception 2.2.9 中,我能够将此代码添加到 Acceptance Helper,它似乎可以工作。

/**
 * @throws \Codeception\Exception\ModuleException
 */
 public function switchToNewWindow()
 {
    $webdriver = $this->getModule('WebDriver')->webDriver;
    $handles = $webdriver->getWindowHandles();
    $lastWindow = end($handles);
    $webdriver->switchTo()->window($lastWindow);
 }

然后在测试类中我可以这样做:

$I->click('#somelink');
$I->switchToNewWindow();

// Some assertions...

$I->switchToWindow(); // this switches back to the previous window

我花了很长时间试图通过搜索谷歌来弄清楚如何做到这一点,所以我希望它可以帮助其他人。

【讨论】:

  • 优秀。谢谢你。我还必须添加 - \Helper\Acceptance under enabled: in webdriver.suite.yml
【解决方案3】:

试试这个,

String parentWindowHandle = browser.getWindowHandle(); // save the current window handle.
  WebDriver popup = null;
  Iterator<String> windowIterator = browser.getWindowHandles();
  while(windowIterator.hasNext()) { 
    String windowHandle = windowIterator.next(); 
    popup = browser.switchTo().window(windowHandle);
  }

确保使用返回父窗口,

browser.close(); // close the popup.
browser.switchTo().window(parentWindowHandle); // Switch back to parent window.

希望对你有帮助。

【讨论】:

    【解决方案4】:

    使用 Codeception 2.2+ 它看起来像这样:

    $I->executeInSelenium(function (\Facebook\WebDriver\Remote\RemoteWebDriver $webdriver) {
        $handles = $webdriver->getWindowHandles();
        $lastWindow = end($handles);
        $webdriver->switchTo()->window($lastWindow);
    });
    

    【讨论】:

      最近更新 更多