【问题标题】:Is there something like jQuery.active in angularjs?angularjs 中有类似 jQuery.active 的东西吗?
【发布时间】:2014-02-22 00:27:53
【问题描述】:

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

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

here. 所述,使用 jQuery 时有一种非常有效的方法

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

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

编辑: Caleb Boyd 的回答是正确的,并且是在使用 selenium web 驱动程序时检测角度 ajax 调用问题的一个很好的解决方案。这是我如何使用它的快速实现。我实际上使用了来自 link 的 caleb 代码的变体,其中包括 ajax 错误。然而,本质上是一样的。谢谢迦勒。

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

<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。

【问题讨论】:

    标签: javascript angularjs selenium-webdriver


    【解决方案1】:

    是的,我相信您可以在 Angular 上使用回调。我已经在一个使用 Ruby 进行自动化测试的大型项目中使用了它。下面是通话。我们等待 30 秒,直到待处理的 Requests.length 变为 0。字符串“0”,因为返回值始终是字符串。

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

    【讨论】:

      【解决方案2】:

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

      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>
      

      我没有使用过网络驱动程序,所以你对“投票”做了什么,我不确定。但是你几乎可以保证 DOM 将保持最新,因为 $http 出现的摘要

      【讨论】:

      • 谢谢迦勒。我在上面添加了更多代码来演示使用您的方法的“端到端”类型场景。
      【解决方案3】:

      这是我在 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
      

      【讨论】:

        猜你喜欢
        • 2020-04-10
        • 1970-01-01
        • 2021-08-04
        • 2012-05-31
        • 2012-11-27
        • 2017-11-21
        • 2012-08-03
        • 2015-08-25
        • 1970-01-01
        相关资源
        最近更新 更多