The correct method for ensuring a promise is successfully handled (with the inclusion of the finally clause) before making an assertion in Vue.js and Jest

I am facing a situation where I have a component with behavior similar to the one below:

@Component
export default class MyComponent extends Vue {
  public result: number = 0;

  public ready: boolean = false;
  
  // for test purpose only. In the real code, this promise is the result of a call to a dependency service.
  public promise!: Promise<void>;

  private myMethod(): void {
    this.promise
      .then(() => {
        this.result = 1;
      })
      .catch(() => {
        this.result = 2;
      })
      .finally(() => {
        this.ready = true;
        // setTimeout(() => {
        //   this.finallyExecuted = true;
        // }, 50);
      });
  }
}

The execution of a method, triggered from a click on the following button, depends on the resolution of a promise.

<button id="myButton" type="button" @click="myMethod()">My button</button>

I aim to unit test this behavior using Jest.

// variable 'wrapper' contains the result of a shallow mount of the component, using vue-test-utils
// variable 'component' contains 'wrapper.vm', after the component has been shallow mounted

it('should set the result to 1 and be ready', async () => {
  // Given
  component.promise = Promise.resolve();

  // When
  wrapper.find('#myButton').trigger('click');
  await expect(component.promise).resolves.toBeUndefined();

  // Then
  expect(component.result).toBe(1);
  expect(component.ready).toBe(true);
});

it('should set the result to 2 and be ready', async () => {
  // Given
  component.promise = Promise.reject();

  // When
  wrapper.find('#myButton').trigger('click');
  await expect(component.promise).rejects.toBeUndefined();

  // Then
  expect(component.result).toBe(2);
  expect(component.ready).toBe(true);
});

Unfortunately, both of these unit tests fail because Jest does not wait for the finally clause to be executed before performing the last assertion. The assertion on result passes, but ready is incorrectly seen as false in both cases.

I need a solution to make Jest wait for the promise to be fully handled, including the finally clause. Ideally, I would like to achieve this without relying on an additional library.

Answer №1

It seems that the promise call within the function myMethod is not being awaited, causing your test to check for results before they have actually occurred.

A possible solution is to modify myMethod so that it returns the result of the promise call:

public myMethod(promise: Promise<void>) {
  return promise
    .then(() => {
      this.result = 1;
    })
    .catch(() => {
      this.result = 2;
    })
    .finally(() => {
      this.ready = true;
    });
}

After making this adjustment, your tests will be able to await the result:

await component.myMethod(promise);

If you need a demonstration, you can check out this GitHub demo.

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

Transferring information from an online platform onto pre-arranged sheets for hard copy

Has anyone had success printing from a website? I have some papers that are already printed with checkboxes. These checkboxes need to be filled in based on information entered through a web form or retrieved from a MySQL database. All of this information ...

After closing, the position of the qtip2 is being altered

I've successfully integrated the qtip2 with fullcalendar jQuery plugin, which are both amazing tools. However, I'm encountering an issue with the positioning of the qtip. Here's the code snippet I'm using: $(window).load(function() { ...

transferring data from config file (conf.js) to a grunt task or sharing information between different grunt

Is there a way to transfer data between different grunt tasks? I need to send a value from one grunt task to another grunt task. In my case, I want to pass a value to a new grunt task after running a protractor test. I attempted to store the value in proc ...

Tips for directing attention to a specific row with an input field in JavaScript

I duplicated a table and added an input field for users to search or focus on a specific row. However, there are two issues: When a user enters a row number, the table displays the wrong row - for example, if the user enters 15, the table shows row number ...

The success function is failing to display the Ajax response

Is there a way to correctly display the ajax response of my code? I noticed that when using async=true, only the last value of yy is shown. However, I want to display it for all values from 0 to a. Interestingly, everything works fine when using async=fa ...

Display a complex JSON string in an ng-grid

My web service is designed to generate a JSON string using the following code: JavaScriptSerializer j = new JavaScriptSerializer(); return "[" + string.Join(",", v.getProbingJobs().Select(a => j.Serialize(a)).ToArray()) + "]"; (The getProbingJobs func ...

JavaScript for Audio: How to Play Sound

I've been struggling to make this play a sound in Firefox, IE, or Chrome. No matter what I do, it just won't work. <html> <head> <script type="text/javascript"> function playSound() { var audio = document.createElem ...

The result of JWT.decode may be null

I am facing an issue with decoding a JSON web token as it is returning null. I have even tried setting complete set to true, but unfortunately it still fails. The function used for generating the token is: import jwt from 'jsonwebtoken'; jwt.s ...

New jQuery div elements do not have animations when using $(document).on

After creating an animation function that worked well with hovering over squares and leaving a trail, I later needed to add or remove squares based on the page size. Seeking help from here, I discovered my bind animation function wouldn't work on new ...

Guide to Implementing i18n-iso-countries Library in React

I am currently developing a React application and attempting to utilize the i18n-iso-countries package to retrieve a countries object in English where keys represent iso codes and values represent country names. This process is straightforward in Node.js, ...

Using Angular to open a modal by invoking the href function

Current Project Context I am currently following a tutorial on CRUD operations with DataTables, but I am using Asp.Net WebApi with Angular for this project. At step 9 of the tutorial, it introduces partial views for pop-up windows. However, instead of us ...

Transfer the filteredWorkers property from the data section to the computed section in Vue.js

Can you please assist me with this task? I need to move the property filteredWorkers and fields to computed properties. As you can see below, I am using b-table from Bootstrap and multiselect from vue.material. I'm not sure of the best approach to ac ...

The UseEffect Async Function fails to execute the await function when the page is refreshed

Having trouble calling the await function on page refresh? Can't seem to find a solution anywhere. Here's the useEffect Code - useEffect(() => { fetchWalletAddress() .then((data) => { setWalletAddress(data); setLoa ...

Unable to retrieve the data-id from the ajax response for extraction and transfer to the modal

I am encountering an issue when trying to retrieve the data-id from an AJAX response within a href tag. The response always returns as undefined. $("#loader_ekpresi").show(); $.ajax({ url:"<?php echo site_url() ?>Home/get_ekspresi", type:& ...

Trouble encountered while setting up Firebase Auth for React Native by utilizing AsyncStorage

Trying to implement SMS authentication via Firebase has presented some challenges for me. Despite poring over the documentation and scouring Google for solutions, I've hit a dead end. My setup is pretty basic - just a single input field and a "Send" b ...

Allowing several text fields to be paired with multiple checkboxes through a unified jQuery function

I have 4 different checkboxes, each one corresponding to a specific text box. I want to enable the disabled textbox when its corresponding checkbox is checked. Currently, I have written a function for each checkbox in the HTML tag itself using onclick="doc ...

JQuery user interface dialog button

When using a jQuery UI dialog, I want to add tooltips to buttons. In my current code: buttons: { 'My Button' : function(e) { $(e.target).mouseover(function() { alert('test'); }); } This code triggers an action only a ...

Steps for installing a package using npm without the need for configuring a package.json file

According to this source, it is feasible to install npm packages before creating the package.json file. After installing nodeJS on my computer, I attempted to run the following command in an empty directory: npm install jQuery This resulted in the follow ...

Jasmine Destiny - Error Encountered: macroTask 'setTimeout': unable to switch to 'active' state, expecting 'planned' state, but it was 'notScheduled'

I am currently using Angular 7 with the Zone.js version of approximately ~0.8.26. Inside my test.ts file, I have included the import statement for 'zone.js/dist/zone-testing'. Below is a snippet from my spec file: import { HttpClientTestingModul ...

Eliminate vertical divider in table with static column using element ui

#inquiry I am currently utilizing the element-ui library for my project. If you would like to learn more, please click here. One challenge I am facing is working with fixed columns in table data. https://i.sstatic.net/u2RRT.png After scrolling horizont ...