在angularjs中有类似jQuery.active的东西吗?

时间:2014-02-22 00:27:53

标签: javascript angularjs selenium-webdriver

我正在使用selenium来测试我的应用程序。我有很多使用$ resource或$ http的ajax调用。如果有一种方法可以以角度方式轮询任何活动的ajax请求,以便selenium可以等到这些请求完成后,那就太好了。

我想我可以在页面上放置一个元素(用于查找selenium)并将其连接到一些成功设置的标志,但这可能会非常混乱。

使用jQuery(如here.

所述)时,有一种非常有效的方法

或者硒有没有办法做到这一点我还没找到?

在文档中找不到任何内容?有什么建议?感谢。

修改 Caleb Boyd的答案是正确的,是使用硒网络驱动程序检测角度ajax调用问题的一个很好的解决方案。这是我如何使用它的快速实现。我实际上使用了来自此link的caleb代码的变体,其中包含ajax错误。然而,它基本上是一回事。谢谢Caleb。

将此脚本和元素添加到页面底部。只需在部署之前删除:

<html>
<head><!--My Angular Scripts--></head>
<body ng-app="MyApp">
<!--Your Html -->
<script>
            MyApp.config(function($httpProvider) {
                $httpProvider.interceptors.push('requestInterceptor');
            })
            .factory('requestInterceptor', function($q, $rootScope) {
                $rootScope.pendingRequests = 0;
                return {
                    'request': function(config) {
                        $rootScope.pendingRequests++;
                        return config || $q.when(config);
                    },
                    'requestError': function(rejection) {
                        $rootScope.pendingRequests--;
                        return $q.reject(rejection);
                    },
                    'response': function(response) {
                        $rootScope.pendingRequests--;
                        return response || $q.when(response);
                    },
                    'responseError': function(rejection) {
                        $rootScope.pendingRequests--;
                        return $q.reject(rejection);
                    }
                };
            });
    </script>
    <span id="http-status">{{pendingRequests}}</span>
</body>
</html>

我使用NUnit作为我的测试框架。

[TestFixture]
public class MyTestClass
{
  [Setup}
  public void Setup()
  {
    _webDriver = new ChromeDriver(@"...path to chromedriver.exe")
    //any other properties you need
   }

   [TearDown]
   public void TearDown()
   {
     if(_webDriver == null)
        return;
     _webDriver.Quit();
     _webDriver.Dispose();
    }

    [Test]
    public void Test_my_page_functionality()
    {
      var pageBtn = _webDriver.FindElement(By.Id("my-btn-id"));
      pageBtn.Click();
      _webDriver.WaitForAjax();//see extension below
      //test whatever result you want after ajax request has come back
     }
}

这是WaitForAjax扩展

public static class WebDriverExtensions
{
  public static void WaitForAjax(this IWebDriver webDriver)
        {
            while (true)
            {
                //Note: FindElement is another extension that uses a timer to look for an element
                //It is NOT the one that selenium uses - the selenium extension throws exceptions on a null element
                var ajaxIsComplete = webDriver.FindElement(By.Id("http-status"), 5);
                if (ajaxIsComplete != null && ajaxIsComplete.Text.Equals("0"))
                {
                    //optional wait for angularjs digest or compile if data is returned in ajax call
                    Thread.Sleep(1000);
                    break;
                }
                Thread.Sleep(100);
            }
        }
}

尝试通过在控制器方法的底部放置一个Thread.Sleep(5000)来测试WaitForAjax扩展。 希望这有助于某人。再次感谢Caleb。

3 个答案:

答案 0 :(得分:10)

是的我相信你可以在角度上使用回调。我在使用Ruby的Test Automation的大型项目中使用过它。以下是电话。我们等待30秒,直到挂起的Requests.length变为0.字符串“0”,因为返回值始终是字符串。

Watir::Wait.until(30) {
@browser.execute_script("return angular.element(document.body).injector().get(\'$http\').pendingRequests.length;") == "0"
}

答案 1 :(得分:5)

对此的一个解决方案是利用拦截器。也许是这样的:

angular.module('myApp',[])
.value('httpStatus',{arc:0})
.factory('activeHttpIntercepotrs',function(httpStatus,$q,$rootScope){
    //link up $rootScope and httpStatus
    $rootScope.httpStatus = httpStatus;
    return {
        'request': function(config){
            httpStatus.arc++; return config || $q.when(config);
        },
        'response': function(config){
            httpStatus.arc--; return config || $q.when(config);
        }
    }

})
.config(function($httpProvider){
    $httpProvider.interceptors.push('activeHttpIntercepotrs');
});

在你的DOM中某处...类似于:

<span class="dontDisplayMe">{{httpStatus.arc}}</span>

我没有使用网络驱动程序,以便你做什么'民意调查',我不确定。但是,由于$http

的摘要,你几乎可以保证DOM能保持最新状态。

答案 2 :(得分:1)

以下是我在Ruby应用程序中使用Capybara和Capybara-Webkit完成此操作的方法:

def wait_for_ajax
  Timeout.timeout(Capybara.default_max_wait_time) do
    loop until finished_all_ajax_requests?
  end
end

def finished_all_ajax_requests?
  pending_requests = page.evaluate_script('angular.element(document.body).injector().get("$http").pendingRequests.length')
  pending_requests && pending_requests.zero?
end