Unit testing promises in Angular using Jasmine

My goal is to create a unit test that demonstrates the process of combining two promises using $q.all in Angular, and then confirming that both promises are resolved simultaneously.

  describe("Application controller", function() {
    var scope;
    var controller;

    beforeEach(module('my.namespace'));
//this suite can be removed.
    describe("Application ", function() {
        beforeEach(
            inject(function ($rootScope, $controller,$q) {
                scope = $rootScope.$new();
                controller = $controller('Application', {
                    '$scope': scope
                });
            }));


        it("should merge two promises into one", function (done) {
            inject(function ($rootScope) {
                setTimeout(function () {
                    $rootScope.$apply(function () {
                        var promiseOne = $q.defer(),
                            //promiseOneData;
                            promiseTwo = $q.defer();
                            //promiseTwoData
                        promiseOne.then(function(data){
                            promiseOne.resolve('promiseOne');
                            expect(1).toBe(1);
                        });
                        promiseTwo.then(function(data){
                            promiseTwoData.resolve('promiseTwo');
                        })
                        var allPromises = $q.all([promiseOne,promiseTwo]);
                        allPromises.then(function(data){
                            //data should contain an array of two empty elements for each promise
                            expect(data.length).toBe(2);
                        });
                        done();
                    });
                }, 1000);


    })
});

However, I encounter an error message:

Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
My intention is not to execute any actual HTTP requests here; rather, I simply want to ensure that two promises are resolved before merging them into a single promise. How can this be achieved with Angular and jasmine?

Answer №1

It appears that your intention is to utilize a spy to determine if it has been invoked or not.

describe('test $q', function() {
  var
    $scope;
    $controller;
    $httpBackend;

  beforeEach(function() {
    module('myModule');
    inject(function(_$rootScope_, _$controller_) {
        $scope = _$rootScope_.$new();
        $controller = _$controller_;
        $controller ('MyCtrl', {
          $scope: $scope
        });
    });

  it('should verify that $q.all triggers the callback once dependent promises are fulfilled', function() {
    var deferOne = $q.defer(),
        deferTwo = $q.defer();
        combinedSpy = jasmine.createSpy('combined');    

    $q.all([deferOne.promise, deferTwo.promise]).then(combinedSpy);

    expect(combinedSpy).not.toHaveBeenCalled();
    deferOne.resolve();
    deferTwo.resolve();
    $scope.apply();
    expect(combinedSpy).toHaveBeenCalled();
  });

The title of this test might be misleading as you are not emulating a promise, but instead testing one. Additionally, there is no need for you to write tests for $q since Angular itself already includes such tests.

consolidating them using $q.all

This action creates a third promise which only resolves when both initial promises, A and B, have resolved.

confirming that the promises are simultaneously resolved

Due to JavaScript being single-threaded, the promises cannot resolve simultaneously. The third promise generated by $q.all() will only resolve after both A and B are individually resolved. There may be a delay between these resolutions.

For example, if A is resolved first followed by B an hour later, then C ($q.all) will only resolve in the subsequent digest cycle (triggered by $scope.apply()).

Answer №2

Here is the response given by the original poster and inserted into the question:

it("Testing promise simulation",inject(function($q, $rootScope){
            var deferred = $q.defer();
            var promise = deferred.promise;
            var resolvedData;
            promise.then(function(data){
                resolvedData  = data;
            });
            
            expect(resolvedData).toBeUndefined();
            
            var testObject = {
                id: '123',
                name: 'suebalu',
                database: '234',
                folder: 'c:',
                version: '1.2',
                file: 'previewPubFile',
                date: '2009-01-01'
            };

            deferred.resolve({
                id: '123',
                name: 'suebalu',
                database: '234',
                folder: 'c:',
                version: '1.2',
                file: 'previewPubFile',
                date: '2009-01-01'
            });
            $rootScope.$apply();
            expect(resolvedData).toEqual(testObject);
        }));

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

JavaScript's ASYNC forEach function not following the expected sequence

I'm really struggling to understand the workings of async and await in this scenario. I want the forEach function to run before the console.log and res.json, but no matter what I do with async and await, it always ends up being the last thing executed ...

Create a navigation link using ui.sref that targets a sub-state within another sub-state

What I am trying to accomplish: Within the template of the main state (/model), I have links leading to a child state phase (/phase). But, my goal is to also have the ability to directly link from the main state to a specific child state within a particul ...

Unable to activate the 'Click' function in Angular/Typescript after selecting element with 'document.querySelector'

In my Angular 8 Project, there is an element on a page with a unique string attached to the attribute 'data-convo-id'. This element has a click function that loads data based on the data attribute specified above. However, without direct access ...

When does the ng-disable function become activated?

Here's an example: <button ng-disabled="!isSomethingValid() || loading || disabled" ... class="btn btn-primary"> What determines the condition for the ng-disable attribute to evaluate its expression? ...

The outcomes of JSON.stringify and JSON.parse can vary

I am facing an issue with using JSON.stringify to create a JSON string from an Object. After saving the string into a file, I attempt to read the file and use JSON.parse to retrieve the object again. However, it seems that the process is not working as exp ...

implementing a collapsible sidebar menu with CSS tables

I am working on a layout with three columns created using css tables to perfectly fit the browser window. The first column serves as a menu and I want it to hide or move to the left when clicked, allowing the middle column to expand into its space. However ...

Using AngularJS $routeProvider can be challenging when integrating both AngularJS and jQuery

I am encountering an issue with my application that utilizes both Angular JS and jQuery JS for mobile and web functionalities. The problem arises when the route-provider fails to navigate to the intended page if both jQuery and Angular JS are integrated to ...

What are some common applications of JSON?

Can you explain the purpose of JSON in Javascript and PHP and when it is necessary to use a JSON method? I checked out the link below but couldn't find any information on how JSON is implemented in actual projects. http://www.json.org/js.html ...

Having Trouble with Your React.js Rendering?

I'm starting to learn React.js but I'm having trouble rendering it into the HTML. I can't figure out what's wrong. Any help would be greatly appreciated. Below are the HTML and JSX code: (Note: Full links to the react library are incl ...

Access various results from a jQuery function

Is there a way to efficiently extract the values of petKeys and employeeKey using the jQuery functions provided below? var whenSelectDateFromCalendar = function () { initKeyValues(); petKeys = ? employeeKey = ? }; var initKeyValues = function ...

Sending PHP output data to jQuery

Trying to implement this code snippet /* Popup for notifications */ $(document).ready(function() { var $dialog = $('<div></div>') .html('message to be displayed') .dialog({ ...

Accessing a JavaScript URL beyond the Facebook frame application

I have developed a Facebook application with a navigation menu, and I am seeking a way to open links outside of the iframe app. Is it possible to achieve this? Currently, I am using the code below which loads inside the iframe but I am unable to get it t ...

What causes the HTML element's X position value to double when its X position is updated after the drag release event in Angular's CDK drag-drop feature?

I am facing a challenge with an HTML element that has dual roles: Automatically moving to the positive x-level whenever an Obsarbalve emits a new value. Moving manually to both positive and negative x-levels by dragging and dropping it. The manual drag a ...

Trouble accessing Silverlight site due to incomplete loading

There is a site known as that consists of a Silverlight application. Strangely, this site loads on all other computers except mine. I keep encountering the following error: An Error occurred in the Silverlight Application: String was not recognized as a ...

What is the best way to have various texts display after a certain number of clicks?

I am looking for a way to display different text based on the number of clicks within a certain class. For example, if the user clicks twice, the text displayed should be "You clicked two times", and this pattern continues until the fifth click, after whic ...

Respond to the initial message within the "if" statement

client.on('message', message => { if (message.channel.type === 'text' && message.channel.name.toLowerCase() == "channel-2" && message.content === "test") { message.react("✅") } ...

JavaScript Object Instantiation within the Object Prototype

If we consider a scenario where there are 3 chapters of a novel each with its own unique URL structure: Chapter 1 = /1.html Chapter 2 = /2.html Chapter 3 = /3.html Now, to implement object-oriented principles using jQuery, the idea is to create two JS ...

Colorful radial spinner bar

I am interested in replicating the effect seen in this video: My goal is to create a spinner with text in the center that changes color, and when the color bar reaches 100%, trigger a specific event. I believe using a plugin would make this task simpler, ...

Include a query parameter each time a page is added to bookmarks

Is there a way to automatically add a query parameter to a page URL when bookmarked using Chrome? For example, if I bookmark https://www.example.com, can it be saved as https://www.example.com/?bookmarked? I'm thinking I might need to use JavaScript ...

Transmitting HTML5 application settings via URL

I am interested in creating an HTML5 app that utilizes the WebAudio API. This app will allow users to customize certain parameters. Users should be able to 'share' these settings by sending a share URL, which can be clicked by others to view the ...