【问题标题】:Behat, PhantomJS - wait for page load after clicking link?Behat,PhantomJS - 单击链接后等待页面加载?
【发布时间】:2015-09-21 22:06:29
【问题描述】:

我正在使用 Behat 3 和 PhantomJS 2。目前我有一个这样定义的场景:

@javascript
Scenario: I visit the blog through the Blog & Events menu.
  Given I am an anonymous user
  And I am on the homepage
  And I follow "Link Text"
  Then I should be on "/path-to-page"

当我用 Goutte 运行它时,它很好。当我使用 vanilla Selenium 运行它时,它很好(它启动了一个我可以看到的浏览器)。但是,当我将 Selenium 配置为将 webdriver 主机指向 PhantomJS 时,它会在 Then I should be on "/path-to-page" 上爆炸,声称它仍在 / 上。

如果我添加以下等待步骤:

@javascript
Scenario: I visit the blog through the Blog & Events menu.
  Given I am an anonymous user
  And I am on the homepage
  And I follow "Link Text"
  And I wait 4 seconds
  Then I should be on "/path-to-page"

然后我的场景顺利通过,一切顺利。

有没有办法让 PhantomJS 在检查当前路径之前等待页面加载?我不想依赖任意超时。我需要一个无头解决方案,而且 PhantomJS 似乎得到了很好的支持,但是如果我不能做一些简单的事情,比如单击链接并验证加载的页面而不在任何地方添加随机等待步骤,我可能需要重新评估我的决定。

【问题讨论】:

    标签: selenium-webdriver phantomjs behat ghostdriver


    【解决方案1】:

    尝试在您的功能上下文中使用这种隐式等待。根据我的经验,它有所帮助。

    /**
     * @BeforeStep
     */
    public function implicitlyWait($event)
    {
        // Set up implicit timeouts
        $driver = $this->getSession()->getDriver()->getWebDriverSession();
        $driver->timeouts()->implicit_wait(array("ms" => 10000));
    }
    

    【讨论】:

      【解决方案2】:

      我遇到了同样的问题,并且这样做失败了,因为它使用了当前 url 的状态:

       $this->getSession()->wait(10000, "document.readyState === 'complete'");
      

      所以我的解决方法是在每次完成一个步骤时向页面添加一个variable。当我点击链接时,variable 将不再存在,这将保证正在使用不同的页面。

      /**
       * @AfterStep
       */
      public function setStepStatus()
      {
          $this->getSession()->evaluateScript('window.behatStepHasCompleted = true;');
      }
      
      /**
       * @When /^(?:|I )wait for the page to be loaded$/
       */
      public function waitForThePageToBeLoaded()
      {
          $this->getSession()->wait(10000, "!window.behatStepHasCompleted && document.readyState === 'complete'");
      }
      

      【讨论】:

        【解决方案3】:

        正如docs 中提到的那样,您始终可以使用闭包函数来封装您的步骤。通过它,您可以在准备就绪时运行您的步骤。让我们实现一个 spinner 函数:

        public function spinner($closure, $secs) {
            for ($i = 0; $i <= $secs; $i++) {
                try {
                    $closure();
                    return;
                }
                catch (Exception $e) {
                    if ($i == $secs) {
                        throw $e;
                    }
                }
                sleep(1);
            }
        }
        

        我们在这里所做的是等待几秒钟以使闭包函数成功运行。当时间用完时,抛出一个异常,因为我们想知道什么时候行为不正确。

        现在让我们包装你的函数以断言你在微调器中的正确页面中:

        public function iShouldBeOnPage($wantedUrl) {
            $this->spinner(function() use($wantedUrl) {
                $currentUrl = $this->getSession()->getCurrentUrl();
                if ($currentUrl == $wantedUrl) {
                    return;
                }
                else {
                    throw new Exception("url is $currentUrl, not $wantedUrl");
                }
            }, 30);
        

        我们在这里所做的是等待最多 30 秒,以便在单击按钮后到达我们想要的网址。它不会等待 30 秒,而是等待我们需要的尽可能多的秒数,直到当前 url 是我们需要的 url。在 *Context.php 中的函数中应用它会导致在 Gherkin 文件中调用它的每一步都应用它。

        【讨论】:

          猜你喜欢
          • 2017-07-10
          • 1970-01-01
          • 2012-07-05
          • 1970-01-01
          • 2017-10-19
          • 2016-10-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多