What methods would you use to test a Vanilla JS Ajax call handled by a Promise using Jasmine?

I recently came across a great solution on How to make an AJAX call without jQuery? that I wanted to implement. However, I found it challenging to mock the Promise, the AJAX call, or both in my testing.

My initial attempt with jasmine-ajax didn't work out as expected due to a reported bug. It also appeared that this tool is designed for the browser environment only.

Additionally, I tried to mock the XMLHttpRequest object, but unfortunately, I couldn't get it to work successfully.

At this point, I'm unsure about the alternatives available to me:

function get(url) {
  return new Promise((resolve, reject) => {
    const req = new XMLHttpRequest();
    req.open('GET', url);
    req.onload = () => req.status === 200 ? resolve(req.response) : reject(Error(req.statusText));
    req.onerror = (e) => reject(Error(`Network Error: ${e}`));
    req.send();
  });
}

Answer №1

Illustration showcasing how XMLHttpRequest can be simulated

function fetch(url) {
  return new Promise((resolve, reject) => {
    const req = new XMLHttpRequest();
    req.open('GET', url);
    req.onload = () => req.status === 200 ? resolve(req.response) : reject(Error(req.statusText));
    req.onerror = (e) => reject(Error(`Network Error: ${e}`));
    req.send();
  });
}

describe('XMLHttpRequest', function() {
  var xhr
  var urls

  beforeEach(() => {
    xhr = {
      open: (_type_, _url_) => {
        xhr.status = urls[_url_].status
        xhr.response = urls[_url_].response
        xhr.statusText = urls[_url_].statusText
      },
      send: () => {
        setTimeout(xhr.onload, 1)
      }
    }

    XMLHttpRequest = jasmine.createSpy(xhr).and.returnValue(xhr)
  })

  it('resolves query with `response`', function(done) {
    urls = {
      'http://foo/bar': {
        response: 'some other value',
        status: 200
      }
    };

    fetch('http://foo/bar')
    .then(r => expect(r).toBe('some other value'), e => expect(e).toBe(undefined))
      .then(done)
  })

  it('rejects query with `statusText`', function(done) {
    urls = {
      'http://baz/quux': {
        response: 'some other value',
        status: 500,
        statusText: 'some error'
      }
    };

    fetch('http://baz/quux')
    .then(r => expect(r).toBe(undefined), e => expect(e.message).toBe('some error'))
      .then(done)
  })
})
<script src="https://safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine-2.0.3-concated.js"></script>
<link href="https://safjanowski.github.io/jasmine-jsfiddle-pack/pack/jasmine.css" rel="stylesheet" />

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

There seems to be an issue with the pastebin api createPasteFromFile method as it is showing an error of 'create

I'm currently working on a logging system using node for a twitch chat. The idea is that when you type "!logs user" in the chat, it should upload the corresponding user.txt file to pastebin and provide a link to it in the chat. For this project, I am ...

Searching for entries using an array of _id along with other possible column values

const query_id = [1,2,3,4,5,6]; const query_type = "A"; let queries = await Query.find({ _id: query_id, query_type: query_type }); The current code functions as intended, but there may be a better and more elegant way to achieve t ...

Converting Javascript Array to PHP Array: A Step-by-Step Guide

For my web application, I am utilizing PHP and MySql. When inserting a string into Mysql, it is formatted as a JavaScript Array ["0","1","2","3","4","5","6"] After retrieving the value from the database, it is saved in a PHP Variable $dow I am now looki ...

Continuously monitor and track the advancements within the update panel

Within an update panel, I have two buttons that need to trigger the update progress and display a .gif image on each button click. When Button1 is clicked, only its associated update progress should be shown while the other one remains invisible. ...

JSON data displaying improper date format

After retrieving date from the database, it is in the following format: {5/13/2002 12:00:00 AM} Once this is passed as JSON and bound to a textbox, it appears like this: /Date(1021228200000)/ Is there a way to display the date in the correct format? E ...

Encountering an error code of 500 when executing the createIndex function in Pouch

I'm currently working on setting up a basic index, and I have the following code snippet: currentDB.createIndex({ index: { fields: ['name'] } }).then((result) => { }).catch((error) => { }) However, when I try to r ...

Tips for preventing the playback of the sound while recording

When creating a basic JavaScript application that involves opening a stream from the user and analyzing frequencies, I found that while Google Chrome and Opera work well by providing feedback in the headphones, Firefox often remains silent. Additionally, F ...

Turn off the authentication middleware for a particular HTTP method on a specific endpoint

Currently, I am using Express/Node and have developed authentication middleware to validate JWT on each request. My requirement is to disable this middleware for a specific route (POST '/api/user/') while keeping it active for another route (GET ...

Utilizing a numeric array as an associative array in JavaScript

Within a Javascript context, I am tackling an array of objects named users. Accessing users[1].name allows me to retrieve the user's name. I am aiming to utilize the user ID as the index instead of relying on an incrementing counter. For instance, in ...

JSON Schema: ensuring that all elements within an array are distinct and not null

I am currently in the process of developing a JSON schema that needs to meet the following criteria: The schema must declare a top-level object with at least one property Each property's value should be an array, with each array containing exactly N ...

How can I identify when the payment form in Stripe Elements has finished loading?

When implementing a payment form using Stripe elements, I have noticed that there is sometimes a delay of 5-10 seconds for the form to load completely. Is there a way to detect when the form has finished loading so that I can display a loading animation or ...

Massive Memory Drain Due to XMLHttp POST Request

Is there a way to prevent XHR POST Memory leak in my web app? I have searched extensively for solutions but have not found any satisfactory answers. My issue is similar to the one described in this blog post that outlines the problem without offering any f ...

Retrieve the item that is contained within a separate item within the original

Is there a way to access the Photos object in my code? I attempted to use {{ item.image.Photos[0].image }} but it was unsuccessful https://i.stack.imgur.com/IGC2c.png Looking for Assistance with TypeScript listHotelPhotos( hotel_id ){ let loader = t ...

Is there a way to update the parent component when changes occur in the child component?

I have been working on a book tracking application that allows users to keep track of the books they have read or plan to read. The app is built using Vue.js on the front end and Express.js on the server side. It consists of three lists or categories for o ...

How can one properly utilize material-ui CSS?

Just starting out with material-ui and react, I'm currently following this palette customization guide from Material-UI. However, when attempting to replicate the example shown, I encountered the error: Cannot read property 'prepareStyles' ...

Is it possible for Vue to retrieve refs on mounted during nextTick following the dynamic import of the component?

Utilizing Nuxt js and Element UI, I have dynamically imported Element UI plugins in the plugins folder. export default () => { Vue.component("ElForm", () => import("element-ui/lib/form")); Vue.component("ElFormItem", ...

"Exploring the technique of extracting substrings in JavaScript while excluding any symbols

I am working on a JavaScript web network project and I need to use the substring method. However, I want to exclude the colon symbol from the substring because it represents a hexadecimal IP address. I do not want to include colons as part of the result. H ...

Using Django to dynamically fill out a form with data retrieved through ajax

My registration form is pretty straightforward, but I need some help with filtering data. There are three additional fields in the form: University Course Module The goal is to allow the user to select a University, and based on that selection, populate ...

The Keydown event in Three.js should initially move my player a set distance, however, the further the player moves

I've been working on a Threejs project where I have set up keydown controls for my player character in the animate function. Pressing 'a' and 'd' moves the character left and right, while 'w' and 's' move them u ...

Trigger the .focus() method on a neighboring VueJS Component

I am facing an issue with two independent components in my Vue instance. I have a select component and an input component, both of which are siblings. I need to trigger a focus event on the input component when the select component is changed. Since both ...