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

Delete items from several arrays on a click event in React

I'm working with an array of objects that contain multiple arrays. My goal is to remove the item when a button is clicked, but I keep getting undefined as a result. JSON Data [ { "services": [ { "id": "1b9 ...

Obtain the thread number of the current wdio instance

My automated UI tests run in parallel using the wdio maxInstances, generating a unique mobile number at the start of each test. 07 - All numbers start with this number. Next is a 9-digit number based on time & date - `new Date().getTime().toString(). ...

Steps for automating the process of opening a link in a new tab using Selenium UI test automation in C

Currently, I am in the process of creating selenium UI tests. My goal is to open a link in a new tab after clicking on it. Although I attempted to achieve this using the code below, I wasn't successful. Actions action = new Actions(WebDriver); action ...

How can I remove unnecessary components from an API result in discord.js before sending it?

The particular API being discussed is a pun-themed one, specifically this one. Here is the code snippet I am currently utilizing: const superagent = require("superagent") module.exports = { run: async(client, message, args) => { const pun = a ...

Using AngularJS promises within a loop

I have been working on a code snippet that iterates through the list of reports, modifies each one's name, and performs an update operation. Everything seemed to be in order when there was only one report in the list. However, things went haywire when ...

Protecting client-side game logic operations with web application security

I've been developing a web-based game that utilizes the Canvas feature of HTML5. However, I've come to realize that there is a significant vulnerability in my system. The scoring and gameplay statistics are currently being calculated on the clien ...

Retrieve data from the database by selecting an option from the dropdown menu

I am currently facing a minor issue with the filtering system I am developing. The problem arises when selecting the "All" category from a dropdown menu, which is not part of the database but a separate HTML option. Here is a visual representation of the ...

Select a random character from a string using JavaScript

This question sets itself apart from Removing random letters from a string as it focuses on selecting a random letter from a string in JavaScript without removing any characters. The goal is to implement a code that picks random letters from a string in J ...

In Next.js, the elements inside the div created by glider-js are not properly loaded

I'm currently working on setting up a carousel in nextjs using the data retrieved from an API and utilizing glider-js for this purpose. However, I'm facing an issue where the div created by glinder-js does not include the elements that are render ...

Sending JSON data two times to the ASP.NET MVC controller via POST request

function onTestComplete(content) { var url = '<%= Url.Action("JsonTest","Organization") %>'; $.post(url, null, function(data) { alert(data["name"]); alert(data["ee"]); }); } <% using (Ajax.BeginForm("JsonTe ...

Embed Text inside an HTML Canvas

As someone who is relatively new to working with html canvas, I am having a bit of trouble when it comes to containing text within the canvas area. Specifically, I am pulling text from a textarea and displaying it on the canvas, but it seems to stay as one ...

Encountering issues with installing packages while creating a new Angular 9 project

Recently I updated to node version 12.16.1 (LTS) and Angular CLI version 9.0.3. After creating a new project with the CLI, all files in the root folder are generated but it gets stuck during the installation of node packages. Has anyone else encountered t ...

Having trouble with the Angular Material datepicker component?

I have recently started learning angularjs and decided to utilize the angularjs material datepicker component to manage dates in my project. However, I seem to be encountering some issues as the control is not displaying properly on my DatePicker.html page ...

How to modify this to return a function and eliminate the need for declaring a function

Greetings! I understand that this may seem simple to some of you, but I am feeling quite lost. I've been tasked with removing the function declaration and converting it into a return function. Any assistance would be greatly appreciated. const canView ...

Click Action on CanJS Table

I am currently developing a canJS application and have been able to successfully handle the click event for an HTML table using the code below. 'table td click':function(el,event){ console.log('clicked ',el.text()); } ...

Utilizing the Filter Function to Eliminate an Element from an Array

I am a beginner in the world of React and I'm currently working on developing a simple timesheet tool where users can add tasks and save them. My tech stack includes React and Typescript. Currently, my main component has an empty array for tasks and ...

Experiencing a 404 error after attempting to access an endpoint following a successful MSAL Azure AD

Incorporating the UserAgentApplication.loginPopup function to authenticate users on our Azure AD has been a challenge as we transition from an ASP.NET MVC application to a Vue.js front end and ASP.NET 'API' backend. The goal is to pass the access ...

Learning how to dynamically update a value in Angular based on user input

My goal is to dynamically change the output value based on user input using Angular. I have successfully implemented the functionality to increment the value, but unfortunately, when the input changes, the outputed value remains static. Below is my curren ...

Prepending a string to the key of a JSON object using JavaScript

Is there a way to add 'd:' before the key of a JSON object? Here is the JSON data: "data": { "aa": "value", "ab": "value" } The expected result should look like this: "d:data": ...

Extracting text from HTML response and implementing a condition in Node.js

Hello, I am a beginner when it comes to node js and haven't had much experience with it before. I could really use some assistance in resolving an issue that I am facing. Below is the code snippet that I am working with: async function reserved_slot(p ...