Does AngularJS have a feature similar to jQuery.active?

As I utilize selenium to conduct tests on my application, I am encountering numerous ajax calls that utilize $resource or $http. It would be convenient if there was a method in angular to monitor active ajax requests so that selenium could wait until they are completed.

I have considered placing an element on the page for selenium to locate and connecting it to a flag that is set upon successful completion, but this approach might become unwieldy.

An effective way to accomplish this using jQuery is detailed here.

Is there a feature within selenium that can achieve this task which I may have overlooked?

After scouring through the documentation without success, I am open to any suggestions. Thank you.

EDIT: Caleb Boyd's solution is spot-on for detecting angular ajax calls while utilizing selenium web driver. Here is a brief overview of how I implemented this. I adapted Caleb's code variation from this link, which also accounts for ajax errors. Essentially, it achieves the same outcome. Many thanks to Caleb.

Add the following script and element to the bottom of your page. Remember to remove them before deployment:

<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 serves as the testing framework in my case.

[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
     }
}

Below is the WaitForAjax Extension

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);
            }
        }
}

To test the WaitForAjax extension, insert a Thread.Sleep(5000) at the end of your controller method. I hope this information proves useful to someone. Once again, thank you Caleb.

Answer №1

Indeed, there is a callback available for Angular that can be utilized. I have personally implemented it in a substantial project focused on Test Automation with Ruby. The snippet provided below showcases the specific call. In this scenario, we are executing a wait of 30 seconds until the pending Requests.length reaches zero. It's worth noting that the return value is always in string format, hence the comparison to "0".

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

Answer №2

To address this issue, one potential solution is to implement interceptors. Here is an example of how you could set it up:

angular.module('myApp',[])
.value('httpStatus',{count:0})
.factory('activeHttpInterceptors',function(httpStatus,$q,$rootScope){
    //connect $rootScope with httpStatus
    $rootScope.httpStatus = httpStatus;
    return {
        'request': function(config){
            httpStatus.count++; 
            return config || $q.when(config);
        },
        'response': function(config){
            httpStatus.count--; 
            return config || $q.when(config);
        }
    }

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

In your HTML file, you can include something like this:

<span class="hideMe">{{httpStatus.count}}</span>

If you are using web-driver for 'polling', the update in the DOM should be automatic due to the digest that is triggered by $http.

Answer №3

Below is my method using Capybara and Capybara-Webkit in a Ruby application to handle asynchronous requests:

def wait_for_ajax_response
  Timeout.timeout(Capybara.default_max_wait_time) do
    loop until all_ajax_requests_completed?
  end
end

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

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using jQuery to Iterate Through an AJAX Response

I'm working on a tagger application. When a user submits a tag, ajax sends the following response: {"returnmessage":"The Ajax operation was successful.","tagsinserted":"BLAH, BLOOOW","returncode":"0"} My goal is to extract the tags inserted and dyna ...

The existence of useRef.current is conditional upon its scope, and it may be null in certain

I'm currently working on drawing an image on a canvas using React and Fabric.js. Check out the demo here. In the provided demo, when you click the "Draw image" button, you may notice that the image is not immediately drawn on the canvas as expected. ...

Recreating elements in ng-repeat using ng-click conditionally

I am attempting to swap an anchor tag with an image when clicked by the user. The code snippet I'm using looks like this: <div ng-repeat="postpart in currentPost.parts "> <div ng-if = "!postpart.isclicked"> <img ng-src= ...

Exporting Data and Utilizing a Steady Data Table

I have incorporated the Fixed Data Grid into my latest project. https://facebook.github.io/fixed-data-table/example-sort.html My goal is to generate csv and pdf reports from the data displayed on the grid. Could you please advise me on how to export gri ...

URLRouterProvider's otherwise state reloads due to empty state parameters of the parent

My state configurations are set up as follows: $stateProvider .state('parentState', { abstract: true, url: '/:tenantId/', param: { tenantId: { array: false } }, ...

Understanding how to open a PNG file in the client-side browser and transform it using PNGJS in React

Utilizing React JS for my application development is a current focus of mine. I have a solid understanding of how to import images within the client/browser folder structure. For example: import maze_text from '../../mazes/images/maze_text.png&apos ...

Using Flask and jQuery, learn how to toggle the visibility of a reply text box

After a break from using HTML/JavaScript, I find myself a bit puzzled about how to handle this. I'm working on creating a reddit-like clone with Flask. I've reached a point where I can add child comments to any comment and have them display nic ...

Apply a jQuery class to the element if the current date matches today's date

I've been struggling to find the correct solution online for adding a class if today's date matches an event in my list. For example, I have a list of events and I want to highlight the event date if it is today. Here is the current output: 12 ...

Converting a floating point number to a 4-byte hex string in JavaScript and reversing the process

I have received a hexadecimal data from the server side that is supposed to be in float format. I am trying to convert these hexadecimals into floats using JavaScript, but so far I have been unable to find a suitable method. Can anyone provide assistance ...

Using Rxjs to dynamically map values from an array with forkJoin

Greetings! I have a collection of Boolean observables and would like to apply a logical AND operation. Currently, I am passing static values 'a' and 'b', but I am unsure of the number of elements in the totalKeys array. import { forkJoi ...

Altering the state ahead of rendering

I am experiencing an issue where the Parent component is passing empty props to the Child component. This may be due to my attempt to set the state of my data within a function instead of in a constructor (for the Parent component). I only want the state o ...

What are some tips for incorporating Google Maps v3 with Twitter Bootstrap?

I'm looking to incorporate Twitter Bootstrap's Tabbed Menus into a Google Maps project that is currently coded entirely in javascript. The issue I'm facing is that since Twitter relies on jQuery, I'm unsure of how to effectively utilize ...

Use javascript to modify a specific section of a link

I have a set of datatable rows with links that contain data, and I need to modify part of the link text. For instance, if the link is 200.0.0.10, I want to change it to 160.11.10.12. Despite attempting the following code, the link does not change: var ...

Any suggestions for a quicker method to manage state changes between OnMouseDown and OnMouseUp events in React?

I am attempting to create a window that can only be dragged from the top bar, similar to a GUI window. Currently, I have set up state updates based on OnMouseDown and OnMouseUp events on the top bar. However, I am experiencing slow updates as it seems to ...

Setting up JavaScript imports in Next.js may seem tricky at first, but with

Whenever I run the command npx create-next-app, a prompt appears asking me to specify an import alias. This question includes options such as ( * / ** ) that I find confusing. My preference is to use standard ES6 import statements, like this: import Nav f ...

Having trouble showing an image with jQuery after it has been uploaded

Currently, I have a URL that shows an image upon loading. However, I want to provide the option for users to replace this image using a form input. My goal is to display the uploaded image as soon as it's selected so users can evaluate it. I'm a ...

VueJS component fails to properly sanitize the readme file, as discovered by Marked

Could someone explain why the output from the compiledMarkdown function is not sanitized, resulting in unstyled content from the markdown file? <template> <div style="padding:35px;"> <div v-html="compiledMarkdown" ...

Traversing an array of objects using D3.js

I'm attempting to create a row of bars that are all the same height and width based on their titles. I have an array of 100 objects, each with a key called results containing another array of 20 objects. This means I should end up with a row of 2000 b ...

Tips for Implementing {{ }} within Angular Filters in Nested ng-repeat statements

I am looking to incorporate {{ }} within the Angular "filter" filter, specifically while nested inside an ng-repeat. Let's consider the relationship below: var categories = [ {"title":"land"}, {"title":"sea"}, {"title":"air"} ]; var vehi ...

The sendKeys() method is malfunctioning in Selenium WebDriver

When attempting to enter phone numbers into the designated field, an error is being encountered. Exception in thread "main" org.openqa.selenium.NoSuchElementException: no such element The following code snippet is involved: driver.get("https://m ...