10

场景:修改并保存对营销活动的不完整更改

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调用,然后会根据操作的成功与否带来一个绿色或红色气球。目前我所做的是在“并且我按下保存...”之后我会做一个 sleep(3) 让它有时间让这个气球出现。这似乎不太聪明,因为您在浪费时间,而且有时可能需要或多或少的时间来处理此呼叫。

你们如何让你的行为测试等待 Ajax 完成,而不是让野兽入睡?

非常感谢您的任何反馈!

4

3 回答 3

27

This is done by waiting for your outstanding ajax calls to hit 0. jQuery.active will check just that for you.

In your FeatureContext.php, you can do something like;

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

And do make sure you use a Mink Driver that runs javascript and ajax (the default does not).

于 2012-09-25T10:40:54.067 回答
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 中进行了测试。

于 2014-10-28T04:36:14.983 回答
1

如果您使用 Prototypejs(例如 Magento),等效代码为:

public function iShouldSeeAnErrorBalloon($title)
{
    $this->getSession()->wait($duration, '(0 === Ajax.activeRequestCount)');
    // asserts below
}
于 2013-11-12T12:18:00.647 回答