The definitive method for resolving synchronization problems between Protractor and Angular

The Issue at Hand:

We recently encountered a common error while attempting to open a specific page in our application during a Protractor end-to-end test:

Error: We timed out waiting for asynchronous Angular tasks to complete after 50 seconds. This could be due to the current page not being recognized as an Angular application.

This error arises when we make a browser.get("/some/page/"); call in one of our test cases:

describe("Test", function () {
    beforeEach(function () {
        browser.get("/some/page/");
    });

    it("should test something", function () {
        // ...
    });
)};

What baffles us is that this error only occurs on this particular page within our Angular web application - Protractor seamlessly syncs with Angular on all other pages. The placement of ng-app is consistent throughout our site - it is defined on the root html tag:

<html class="ng-scope" lang="en-us" ng-app="myApp" ng-strict-di="">

This behavior remains consistent - each time we navigate to this problematic page using browser.get(), the error surfaces. When navigating to any other page, synchronization works flawlessly.

While we can disable sync for this page and treat it as non-angular, this is merely a temporary fix.

The Queries:

What other factors could lead to Protractor failing to synchronize with Angular? What steps should we take to troubleshoot?

Furthermore, what strategies are recommended for debugging sync issues in Protractor?

We are currently utilizing the latest versions of Protractor 5.5.1 and Angular 1.5.6.

Answer №1

After being intrigued by that question, I delved into finding a programmatic solution to determine what Protractor is waiting for:

var _injector = angular.element(document).injector();
var _$browser = _injector.get('$browser');
var _$http = _injector.get('$http');
var pendingTimeout = true;

//this method resembles what Protractor uses while waiting to sync
//if the callback is called immediately, it indicates no $timeout or $http calls are pending
_$browser.notifyWhenNoOutstandingRequests(function callback () {
  pendingTimeout = false
});

setTimeout(function () {
  //this helps differentiate between $http and timeouts from the "notifyWhenNoOutstandingRequests" method
  if (_$http.pendingRequests.length) {
    console.log('Outstanding $http requests', _$http.pendingRequests.length)
  } else if (pendingTimeout) {
    console.log('Outstanding timeout')
  } else {
    console.log('All good in Angular, must be something else causing delay')
  }
}, 100)

Feel free to experiment with the timeout and $http call in this Plunker link. My delayed endpoint will wait for 10 seconds before resolving the call. Hopefully, this information proves helpful to you.

Answer №2

My thoughts align with @maurycy's perspective that the issue stems from $http/$timeout interactions. One common solution is to substitute $timeout with $interval, which is well-documented here: https://github.com/angular/protractor/blob/master/docs/timeouts.md

Suggestions:


merge these reasonable defaults: 
  allScriptsTimeout: 60000, // 1 minute
  jasmineNodeOpts: {
    defaultTimeoutInterval: 300000 
    // 5 minutes. Allows for 5 commands spanning the full synchronization timeout.
  }

If pinpointing the root cause of the $http/$timeout problem is your goal, consider utilizing angular decorators to implement custom logic around these services. This can also be beneficial for mocking angular services that interact with third-party services. https://docs.angularjs.org/guide/decorators

//DISCLOSURE: Unlinted & Untested.
beforeAll(() => {
  browser.addMockModule('culpritMock', () => {
    angular.module('culpritMock', [])
      .config(['$httpProvider',
        $httpProvider => $httpProvider.interceptors.push('httpCounterInterceptor')
      ])
      .factory('httpCounterInterceptor', ['$q', '$window', ($q, $window) => {
        if ($window.httpCounterInterceptor == null) {
          $window.httpCounterInterceptor = {};
        }
        return {
          request: config => {
            $window.httpCounterInterceptor[config.url] = 'started';
            return config;
          },
          response: response => {
            $window.httpCounterInterceptor[response.config.url] = 'completed';
            return response;
          },
          responseError: rejection => {
            $window.httpCounterInterceptor[rejection.config.url] = 'error';
            return $q.reject(rejection);
          }
        };
      }])
      .decorator('$timeout', ['$delegate', $delegate => {
        const originalTimeout = $delegate;
        function modifiedTimeout() {
          console.log(arguments);
         return originalTimeout.apply(null, arguments);
        }
        modifiedTimeout.cancel = function(promise) {
          return $delegate.cancel(promise);
        }
        return modifiedTimeout;
      }]);
  });
});

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

Error message: Selenium/C# - Element is not visible

After successfully locating the button element using an Xpath, I encountered a element not visible exception when attempting to click on it. <div class="modal-footer"> <button id="btnRegister" type="button" class="btn btn-primary btn-block"> ...

If a different link is selected, remove the class from the ID, and vice versa

I've been working on solving a jQuery issue that involves manipulating classes in a parent container with two divs and links. The goal is to add a class to change the background when a link is clicked in one div, and remove it if the other link is cli ...

Is there a way in ScalaTest to set up a feature before initializing a featureSpec suite?

I'm new to using ScalaTest and I'm looking to set up some initialization before running my feature test. Here is an example of my test: class InvoiceTests extends FeatureSpec with GivenWhenThen with ShouldMatchers { feature("Traffic Ligh ...

The AngularJS factory does not hold on to its value

I have developed a basic factory to store a value from my authService: app.factory("subfactory", function() { var subValue = {}; return { set: set, get: get }; functi ...

Using React JS, how to easily upload a CSV file to Amazon S3 with your AWS credentials

Seeking guidance on how to utilize AWS credentials to upload a CSV file using React S3 Uploader. The code snippet I've tried so far is as follows: import React, { PureComponent } from "react"; import ReactS3Uploader from "react-s3-uploader"; sav ...

The Angular directive ng-model is not able to return a value

I'm currently troubleshooting an issue with the filters in an older project. Here's the HTML snippet: <input type="text" class="form-control" ng-model="FilterEventsEdit" ng-change="FilterEvents()" ...

Persistent vertical menu dropdown that remains expanded on sub menu pages

I am struggling to understand how to keep my menu sub items open when on the active page. Although I have tried similar solutions, I have not been successful in implementing them. I apologize if this question has been asked before. My approach involves usi ...

Error: An error occurred due to an unexpected asterisk symbol. The import call only accepts one argument in Posenet

While attempting to utilize posenet on a python http server, I encountered a syntax error in the camera.js file at this specific line. import * as posenet from '@tensorflow-models/posenet'; This piece of code has been cloned from the following G ...

What is the best way to extract a JSON string from the login PHP response?

I am working on creating a basic website along with an Android application that both retrieve data from the same database. While I have no issues in dealing with Android, I am facing difficulty in handling JSON strings in HTML. How can I fetch the JSON res ...

The generator-karma is failing to meet the peerDependencies requirements of its sibling modules

Encountering the familiar and frustrating issue npm update -g yo The usual suggestion to uninstall generator-karma proves ineffective as it reinstalls itself. Looking for a clearer explanation of why this occurs and a viable solution? ...

The sequence of divs in a language that reads from right to left

Is there a way in HTML to designate a set of divs so that they automatically align from left to right for languages that read left to right, and alternatively, flow from right to left for languages that read right to left? This means that the direction of ...

What is the reason for calling Proxy on nested elements?

Trying to organize Cypress methods into a helper object using getters. The idea is to use it like this: todoApp.todoPage.todoApp.main.rows.row .first().should('have.text', 'Pay electric bill'); todoApp.todoPage.todoApp.main.rows.ro ...

What is the best way to allocate a unique color to every item within an array?

I've been working on some JavaScript code that pulls a random color from a selection: const colors = [blue[800], green[500], orange[500], purple[800], red[800]]; const color = colors[Math.floor(Math.random() * colors.length)]; Within my JSX code, I ...

When using keyBy in Laravel, the response may return an object instead of an array

Currently, I am in the process of developing a project where I am setting up a back-end RESTful API using Laravel and a front-end with angularJS. Initially, from my controller@index, I was returning a simple all()->toArray() like this: A. return Respo ...

One efficient way to handle multiple concurrent tasks in NodeJs is by using the forEach method to iterate

Having trouble getting the promises to return any values, as they are coming back empty. Despite following suggestions on Stack Overflow, I am still unable to resolve this issue. Frustration levels are high and I'm feeling lost; Can anyone help me pi ...

Tips for keeping Fancybox from deleting the selected thumbnail

New to using fancybox and running into some issues.. starting to regret adding it. I have a row of thumbnails, all good, but when I click one it opens the THUMBNAIL instead of the actual link and on top of that, it DELETES the thumbnail from the DOM. I tr ...

Effective Angular - ensuring all API calls are completed in a forEach loop before returning the final array

Struggling with the asynchronous nature of Angular, I'm faced with a challenge. My task involves looping through various cards where certain types require API calls while others do not. However, upon completion of the loop, only the cards that do not ...

Tips for using Angular's formatDate function to format dates

I am attempting to achieve a specific format using Angular's formatDate "2019-01-01T00:00:00Z" Here is the code I am using: formatDate( '2019-01-01', 'yyyy-MM-ddT00:00:00Z', 'en-US' ) The output I am getting is ...

Step-by-step guide to creating a pop-up div that appears on hover and remains visible when clicked

I'm trying to figure out how to make a popup appear when the mouse hovers over it and then stay visible when clicked on. The issue I'm facing is that currently, the popup disappears when the mouse moves away from it. How can I modify the code so ...

What steps can I take to resolve this error when utilizing an npm package in client-side JavaScript?

Just when I thought I was getting the hang of socket.io, I hit a roadblock on the client side. Following my instructor's advice, I installed socket.io-client package for my project. But when I tried to use it in my client-side JS code, I encountered a ...