Investigating Linked Promises in Testing (Jasmine, React, Karma)

There have been multiple instances on my current project where I faced a chain of promises that I am uncertain how to handle.

Below is the relevant code snippet:

    return this.axios.get(path, requestOpts)
        .then((response) => {console.log('did authorize: ', response); return response})
        .then((response) => {
            if (response.data.ok) {
                window.localStorage.setItem(path, JSON.stringify(response.data));
                console.log("Setting localStorage item ", path, response.data);

                return response.data.payloadUrl;
            } else {
                console.error("Non-ok response for ", path, response.data);
                const resp: DisplayTokenResponse = response.data;

                //TODO: reject promise?
                if (resp.status === "AUTHENTICATION_REQUIRED") {
                    this.axiosService.goToLoginPage(window.location + '');
                }

                Promise.reject(response.data.message);
            }
        });

My current test script looks something like this:

describe('.authorize()', () => {
    let axiosSpy: jasmine.Spy;

    beforeEach((done) => {
        spyOn(svc, 'keyPath').and.returnValue(path);
        spyOn(svc, 'storedToken').and.returnValue(stored);

        let response = {
            data: {
                ok: true,
                message: 'test-response',
                payloadUrl: 'http://payload-url.com'
            }
        }



        spyOn(svc.axios, 'get').and.callFake(
            (path:string, reqOpts:AxiosRequestConfig) => {
                return new Promise(() => {
                    response
                });
            }, (e) => {
                console.log(`failed`);
            });
    });

    describe('should authorize user', () => {
        it('when supplied a STRING', () => {
            clientId = clientId_string;
        });
        it('when supplied a NUMBER', () => {
            clientId = clientId_number;
        });

        afterEach((done) => {
            svc.authorize(clientId, locationId, screenId).then((result) => {
                console.log(`result ${result}`);
                done();
            }, (e) => {
                console.log(`failed with error ${e}`);
                done();
            });
        });
    });
});

I can successfully test promises one level down, but how do I set up my tests to handle complex scenarios like this?

Answer №1

At last, I have solved the puzzle. The issue seemed to arise from a mix-up between creating Promise instances and their resolvers.

Here is how the updated beforeEach block appears:

    beforeEach(() => {
        spyOn(svc, 'keyPath').and.returnValue(path);
        spyOn(svc, 'storedToken').and.returnValue(stored);

        let axiosPromise = new Promise((resolve, reject) => {
            var responseData = {
                data: {
                    ok: true,
                    message: 'test-response',
                    payloadUrl: 'http://payload-url.com'
                }
            };

            resolve(responseData);
        });

        spyOn(svc.axios, 'get').and.callFake(
            ()=>{
                return axiosPromise;
            }
        );
    });

Hooray! My tests are now successful.

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

Can data be fetched from a local port using either Javascript or ASP.NET?

I have created the code below to broadcast data in a Windows application using C#. UdpClient server = new UdpClient("127.0.0.1", 9050); string welcome = "Hello, are you there?"; data = Encoding.ASCII.GetBytes(welcome); ...

When an object is not empty, the function Object.getOwnPropertyNames will still return an empty array

In my code, I am filling $scope.master with data from a csv file. When I populate $scope.master within the function, all the data is present. This can be observed in the log output displayed below. However, outside of the function, although $scope.master ...

JQuery UI Autocomplete - Issue with loading data object

I've been attempting to implement autocomplete with JQuery UI, but I'm encountering difficulties when passing in a label & value object. var individuals = []; var test = new Array(); var dataObject = jQuery.parseJSON(data) ...

How can one access a dynamically generated element in Angular without using querySelector?

Currently in the process of developing my custom toastr service, as shown in the GIF below https://i.sstatic.net/Zpbxs.gif My Objective: https://stackblitz.com/edit/angular-ivy-tgm4st?file=src/app/app.component.ts But without using queryselector. It&apos ...

tips for extracting a specific attribute value from an XML document

Within my C program, I am working with the following XML data: <apStats><command chart_num="0">750</command><command chart_num="1">400</command></apStats> . $.ajax({ type: "POST", dataType: "xml", url: ge ...

A guide to converting variables into a JSON Object in Javascript

I am looking for a way to insert external variables into a JSON object. An example of what I want: var username = "zvincze"; And then, using that variable to inject it into a JSON object: var json = '{"username":"VARIABLE_GOES_HERE"}' var obj ...

Definitions for images in the following format

I am currently utilizing typescript in conjunction with NextJs and next-images. Here is the code snippet: import css from "./style.sass"; import img from './logo.svg'; import Link from 'next/link'; export default () => <Link hre ...

The AJAX function fires only on the first click and does not work upon subsequent clicks when utilizing buttons within dynamically created tables

Currently, I am facing an issue where I am attempting to trigger an event to delete an element. This particular delete event should apply to the element that is clicked as well as an object above it. The Ajax call below works perfectly fine when utilized w ...

There is a possibility of encountering an endless update loop in the watcher when utilizing the expression "tabs" error in vue

My code includes a watcher on tabs to prevent them from changing based on the values of the edit. If edit is false, then go to the next tab; otherwise, prevent the change. However, when I try to click on the tab heading to change the tab, I encounter an er ...

Pressing the up arrow in Javascript to retrieve the most recent inputs

Is there a way to retrieve the most recent inputs I entered in a specific order? For example: I have an array with 20 elements, and every time I enter something, I remove the first element from the array and add the new input at the end. So, when I press ...

Is there a way to create a textbox input that provides autocomplete/autosuggest but displays only the first match directly within the textbox instead of showing a list?

While I came across several autocomplete/autosuggest samples, none of them quite fit what I'm looking for. Instead of displaying a list below the textbox that requires clicking or selecting, I want to show the closest match inside the textbox itself a ...

What is the reason for AngularJS not invoking the said function?

I need to trigger a function when the app starts in order to display a modal. I have attempted to do this by... The function is invoked using the onDeviceReady event. document.addEventListener("deviceready", onDeviceReady, false); function onDeviceR ...

Encountered a new problem post code refactoring: "Error with prop validation: prop failed type check"

Currently, I am developing an application using Vue.js 2 with Typescript and utilizing the vue-property-decorator attributes. Recently, I made the decision to refactor a majority of my code which has resulted in encountering errors whenever I pass a binded ...

Is there an issue with loading Vue list rendering due to Axios not returning the data?

Utilize the axios request api interface to fetch data and populate a list, but encounter a problem when trying to iterate through the properties of an object using v-for. Take a look at the javascript snippet below: var vm = new Vue({ el: '# ...

Modify background image upon hovering using AngularJS

I cannot seem to make the background images of my divs change. Despite trying various options, none of them have been successful. Here's an example of my code: <div ng-controller="mainController" class="main"> <div ng-repeat="land in lan ...

What steps should I take to resolve a plugin error specifically related to index.js while using Cypress?

I am encountering an error in Cypress A plugin has thrown the following error, causing our tests to stop running due to a plugin crash. Please verify your plugins file (/home/dev2/Desktop/kavitaSeffcon/CypressProject/cypress/plugins/index.js) Error: ENOE ...

Identifying route changes and new view replacements in Angular: A comprehensive guide

I'm currently trying to detect when a route changes and a new view (HTML) is replaced. I attempted the code below but I'm unsure of how to proceed from here. this._routerSub = this.router.events .filter(event => event instanceof Navigation ...

Enable checkbox selection on Vue.js table rows with a simple click

Having trouble making a list item clickable? Need the checkbox within the list item to be enabled or disabled on click, but it's not behaving as expected? Here is an example: var app = new Vue({ el: '#app', data: { showNav: ...

How to change an HTML value to a string using jQuery

Looking for some assistance here: Here is the code snippet I am working with: <td id="myid">something</td> Here is the related JavaScript: var test = $("#myid").html(); console.log(test); if(test == "something"){ alert("Great!"); } I am en ...

A guide to dynamically adding a class based on the content of a variable in Vue.js

I have a situation where I need to pass a variable to a component and use it as a class in a div. However, Vue is adding the variable name instead of its content. So, I am passing the prop color which contains the value red. Desired outcome: <div cla ...