Retrieve the callback arguments using sinon.spy within a JavaScript promise

During my test with mocha and sinon, I encountered an issue where I couldn't retrieve a callback value from inside a promise scope of an HTTP-request due to the asynchronous nature of promises. It seems that by the time sinon.spy checks on the callback, it has already vanished or become empty/undefined. Below is the testing code snippet:

 it('should issue GET /messages ', function() {
  server.respondWith('GET', `${apiUrl}/messages?counter=0`, JSON.stringify([]));
  let callback = sinon.spy();
  Babble.getMessages(0, callback);
  server.respond();
  sinon.assert.calledWith(callback, []);
});

Here's the promise in question:

function requestPoll(props) {
    return new Promise(function(resolve, reject) {
            var xhr = new XMLHttpRequest();
            xhr.open(props.method, props.action);
            xhr.timeout = 500; // time in milliseconds
            if (props.method === 'post' ) {
                    xhr.setRequestHeader('Content-Type', 'application/json');
            }
            xhr.addEventListener('load', function(e) {
                    resolve(e.target.responseText);
            });

            xhr.send(JSON.stringify(props.data));


    });
}

and the call which I'm trying to get a callback from using sinon.spy

getMessages: function(counter, callback){

            requestPoll({

                            method: "GET",
                            action: "http://localhost:9090/messages?counter="+counter

            }).then(function(result){

                    callback(result);
            });


        }

The issue lies in sinon.spy not receiving any arguments (due to the async functionality). I attempted to find a way to extract the result outside the scope and assign it to the callback, but it proved impossible. I also tried using resolve and promise return methods but found no success.

How can I ensure this unit test passes?

Edit:
this is my attempt:

getMessages: function(counter, callback){

            var res;
            res = httpRequestAsync("GET",'',"http://localhost:9097/messages?counter=",counter);

            console.log(res);
            if(res!="")
                    callback( JSON.parse(res) );                      
        }

I moved the request to a separate function:

function httpRequestAsync(method,data,theUrl,counter)
    {

            return requestPoll({

                    method: method,
                    action: theUrl+counter,
                    data: data

            }).then(JSON.parse);

    }

It returned res as the promise and within its prototype contains the promised value required.

Is there a way to access that promised value successfully?

Answer №1

It is advisable not to mix promises and callbacks. It is best to stick with a promise-based function if you are already using one.

To ensure getMessages does not disrupt the promise chain, make sure it returns a Promise:

getMessages: function(counter) {
  return requestPoll({
    method: "GET",
    action: "http://localhost:9090/messages?counter=" + counter
  }).then(JSON.parse)
}

Then utilize this promise in your test case:

it('should issue GET /messages ', function() {
  server.respondWith('GET', `${apiUrl}/messages?counter=0`, JSON.stringify([{testdata}]));
  const gettingMessages = Babble.getMessages(0);
  server.respond();

  // Ensure to return a promise so that the testing framework recognizes the test as asynchronous
  return gettingMessages.then(function(messages) {
      // Perform assertion to verify that messages actually match the test data
  })
})

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

Exploring the wonders of ReactJs in the ComponentDidMount

I am encountering some issues with my app. Although I am not a Javascript expert, it seems like an easy fix to me. I need to make the following call: this.props.onNavStyleChange(NAV_STYLE_FIXED); to change the navigation when this page loads. However, I ...

Utilize ModifyDOM to erase text triggered by selecting a radio button

I have created a form that includes four radio buttons along with a reset button to clear the form. When a radio button is selected, information is displayed using "displayText". I am looking to add an onclick handler to trigger a function that will delete ...

Having trouble shutting down Metro Bundler on Windows?

While working on my React Native development, I regularly use npm start to get things going. However, I've run into an issue recently when trying to stop the process using Ctrl + c. It seems like I can no longer use npm start smoothly: ERROR Metro ...

What causes SomeFunction.prototype to appear as "SomeFunction {}" when viewed in the console?

This is the code snippet: function Person(){} console.log(Person.prototype); // Person {} console.log(Person.prototype instanceof Person); // false console.log(Person.prototype instanceof Object); // true The output shows Person {} for Person.prototype, e ...

Ajax request missing Github Basic OAuth token in authentication process

My personal access token is not being passed to the request when I make an ajax call. I keep receiving an error message saying API rate limit exceeded for 94.143.188.0. (But here's the good news: Authenticated requests get a higher rate limit.. I atte ...

When running `aws-cdk yarn synth -o /tmp/artifacts`, an error is thrown stating "ENOENT: no such file or directory, open '/tmp/artifacts/manifest.json'"

Starting a new aws-cdk project with the structure outlined below src └── cdk ├── config ├── index.ts ├── pipeline.ts └── stacks node_modules cdk.json package.json The package.json file looks like this: " ...

What is the best way to save a jQuery or JavaScript variable into a JSON file?

Is there a way to save a jquery variable in a json file? I have the following: var image='/test/test.png'; I am obtaining this path through file upload: <input type="file" name="imageurl" value="imagefile"></input> Therefore, I ne ...

Can I use npm's jQuery in an old-school HTML format?

I am looking to incorporate jQuery into a project without having to rely on the website or CDN for downloading the library. As someone new to npm, I am curious to know if following these steps would be advisable or potentially problematic down the line. Wh ...

Determine if the specific subroute has a child using vue-router

After checking similar questions on stackoverflow without success, I am seeking a solution. I am attempting to determine if a subroute is a child of a specific route in order to display a container. Unfortunately, the following code snippet does not work: ...

Size of Output from RSA 2048 Encryption Using JSEncrypt

I've been under the impression that the output size of RSA 2048 bit encryption is 256 bytes. However, I keep getting 344 characters as output when using jsencrypt for testing. Can anyone shed some light on why this discrepancy exists? Tool used for o ...

Creating a nested function and utilizing the return statement in JavaScript

I am facing an issue with my custom function that contains an ajax call. I need to retrieve a variable from the ajax function within my custom function, but I'm unable to do so. Why is this happening? Possible solution 1: <script> function ...

Transforming data from a JSON format into a JavaScript array

I'm trying to convert a JSON string into an array containing the values from the JSON. When I use json.stringify(jsonmybe) and alert it, I see [{"role":"noi_user"},{"role":"bert_user"}] (which is in JSON format). My goal is to extract `noi_user` and ` ...

Using a modal within a map function: Tips and tricks

I've been working on a Gallery application using React.JS and Reactstrap. The application uses the map() function to display each piece of art in a Card. Each card has a button that triggers a modal to show more data from the map function. However, I& ...

Using a javascript variable in php within the Laravel framework

I am trying to retrieve an id from a button for use in my ajax request. Below is the code snippet for the button: <form> <div class="form-group"> <button class="btn btn-primary" name="deletecar" id="{{$car->id}}">Delet ...

What are some ways to avoid the use of underline and slash symbols in material-ui/pickers?

Is there a way to remove the underline and slash characters that separate day, month, and year in the material ui pickers for version mui version 4? <KeyboardDatePicker margin="normal" id="date-picker-dialog" label="Dat ...

"Eliminate the headers of columns within the collapsible rows on the ui-grid interface

I am working with an expandable table and trying to figure out how to hide the column headers for only the expandable rows within the table. I experimented with including showHeader : false in the subGridOptions, but without success as the headers are stil ...

showing a pop-up message when a specific javascript function is triggered

Here is a unique code snippet showcasing a customized dialog box created with HTML, CSS, and JavaScript. The dialog box is displayed when a button is clicked. <!DOCTYPE html> <html> <head> <style> /* Custom Modal Styles */ .modal { ...

Can we pass a search term parameter to getServerSideProps in Next.js?

I've been working on a project to organize all my notes and summaries in one place. The notes are stored as markdown files, converted to HTML dynamically in the backend (it's functioning well). Now, I want to add a search feature on the notes p ...

VueJS component fails to remain anchored at the bottom of the page while scrolling

I am currently using a <md-progress-bar> component in my VueJS application, and I am trying to make it stay fixed at the bottom of the screen when I scroll. I have attempted to use the styles position: fixed;, absolute, and relative, but none of them ...

What's the easiest method for moving div content from side to side?

Working on a plugin for WordPress, I am faced with the task of moving content in a slider from left to right and right to left. My current attempt is as follows: var effect = 'slide'; // Set the options for the chosen effect type var opti ...