如何让Behat等待AJAX​​通话?

时间:2012-09-25 10:13:14

标签: php ajax bdd behat

场景:修改并保存对广告系列的不完整更改

Given I click on the Campaign section folder
And I press Save in the selected Campaign
Then I should see an error balloon informing the changes cannot be saved

重点是这个错误气球'在最后一步是ajax调用,然后根据操作的成功带来绿色或红色气球。目前我所做的就是追求 '我按保存...'我会睡觉(3)给它时间让这个气球出现。这似乎非常聪明,因为你浪费时间,也因为有时候处理这​​个电话会花费更多或更少的时间。

你们是如何让你的behat测试等待Ajax的呢?而不仅仅是让野兽入睡?

非常感谢您的任何反馈!

3 个答案:

答案 0 :(得分:26)

这是通过等待你的杰出ajax调用达到0来完成的.jQuery.active将为你检查。

在你的FeatureContext.php中,你可以做类似的事情;

public function iShouldSeeAnErrorBalloon($title)
{
    $time = 5000; // time should be in milliseconds
    $this->getSession()->wait($time, '(0 === jQuery.active)');
    // asserts below
}

并确保使用运行javascript和ajax的Mink驱动程序(默认情况下不运行)。

答案 1 :(得分:2)

我是通过等待DOM因Ajax调用而改变来实现的。我创建了DocumentElement的子类,将其称为AsyncDocumentElement并覆盖了findAll方法:

public function findAll($selector, $locator, $waitms=5000)
{
    $xpath = $this->getSession()->getSelectorsHandler()->selectorToXpath($selector, $locator);

    // add parent xpath before element selector
    if (0 === strpos($xpath, '/')) {
        $xpath = $this->getXpath().$xpath;
    } else {
        $xpath = $this->getXpath().'/'.$xpath;
    }

    $page = $this->getSession()->getPage();

    // my code to wait until the xpath expression provides an element
    if ($waitms && !($this->getSession()->getDriver() instanceof \Behat\Symfony2Extension\Driver\KernelDriver)) {
        $templ = 'document.evaluate("%s", document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null ).snapshotLength > 0;';

        $waitJs = sprintf($templ, $xpath);

        $this->getSession()->wait($waitms, $waitJs);
    }

    return $this->getSession()->getDriver()->find($xpath);
}

然后在\ Behat \ Mink \ Session我改变了构造函数以使用该类。

public function __construct(DriverInterface $driver, SelectorsHandler $selectorsHandler = null)
{
    $driver->setSession($this);

    if (null === $selectorsHandler) {
        $selectorsHandler = new SelectorsHandler();
    }

    $this->driver           = $driver;
    $this->page             = new AsyncDocumentElement($this);
    $this->selectorsHandler = $selectorsHandler;
}

一旦我这样做,我发现我的AngularJS测试工作正常。到目前为止,我只在Firefox中测试过。

答案 2 :(得分:1)

如果您使用的是Prototype Js(i.n Magento),则等效代码为:

public function iShouldSeeAnErrorBalloon($title)
{
    $this->getSession()->wait($duration, '(0 === Ajax.activeRequestCount)');
    // asserts below
}