Jasmine spies falsely report the calling of functions when they have not actually been called

Below is the code snippet I am currently working with:

$scope.deleteJob = function(job) {
    SandboxService.deleteJob(job.id).then(res => {
        if (res.status == 200) {
            ngToast.success();
            $scope.refreshApps();
        }
        else {
            ngToast.danger();
        }
    });
};

Accompanied by the unit test provided here:

it('should display success toast and refresh apps after deletion', () => {
    spyOn(sandboxService, 'deleteJob').and.returnValue(Promise.resolve({status: 500}));
    spyOn(ngToast, 'success');
    spyOn(scope, 'refreshApps');

    let mockJob = {
        'id': 1
    };

    scope.deleteJob(mockJob);

    sandboxService.deleteJob().then(() => {
        expect(ngToast.success).toHaveBeenCalled();
        expect(scope.refreshApps).toHaveBeenCalled();
    });
});

The main functionality involves displaying a success toast and refreshing the page upon successful job deletion. In case of failure, a danger toast is shown.

Although the expected result is for the test to fail due to a status of 500 being returned, surprisingly it passes. This suggests that both ngToast.success() and scope.refreshApps() have been triggered.

Upon inserting some debug logs into the code, it confirms that indeed status: 500 is returned, leading to execution of the else block.

What could possibly be overlooked in this scenario?

Answer №1

A synchronization issue arises due to the asynchronous nature of the deleteJob function. In this case, the test completes before the expect statement is executed. To address this, you can utilize the fakeAsync and tick functions from @angular/core/testing.

it('should show success toast on delete and refresh apps', fakeAsync(() => {
    ...

    sandboxService.deleteJob();
    tick();

    expect(ngToast.success).toHaveBeenCalled();
    expect(scope.refreshApps).toHaveBeenCalled();
}));

An issue arises when you spy on the deleteJob function below, causing ngToast.success and scope.refreshApps not to be called during the test execution, resulting in a failure.

 spyOn(sandboxService, 'deleteJob').and.returnValue(Promise.resolve({status: 500}));

Answer №2

@uminder's response highlighted that the test was completing before the expect functions were executed, illustrating the asynchronous nature of the process. This was confirmed by adding some logs within the test.

The remedy involved introducing a parameter in the test to be invoked upon completion:

it('should display success toast when deleting and refreshing apps', (done) => {
    spyOn(sandboxService, 'deleteJob').and.returnValue(Promise.resolve({status: 200}));
    spyOn(ngToast, 'success');
    spyOn(scope, 'refreshApps');

    let mockJob = {
        'id': 1
    };

    scope.deleteJob(mockJob);

    sandboxService.deleteJob().then(() => {
        expect(ngToast.success).toHaveBeenCalled();
        expect(scope.refreshApps).toHaveBeenCalled();
        done();
    });
});

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

Updating state array within reducer leads to duplicate execution of calculations

const updateCartReducer = (state, action)=>{ console.log('running the updater function') const existingItemIndex = state.items.findIndex( (item) => item.restaurant === action.item.restaurant && ...

Different ways to utilize ng-repeat with option tags

Hello, I am currently utilizing a dropdown feature that fetches options from a database. To do this, I have created an array as shown below: const myArray = new Array(); myArray = [{className:5,avg:40},{className:6,avg:50},{className:7,avg:40}}]; Within ...

Each time the Angular children component is reloaded, the user is redirected to localhost:4200

In my Angular project, I encounter an issue with route parameters in children components. While navigating to these child components from the parent is seamless, reloading the child component causes the application to redirect to localhost:4200 and display ...

Secure User Verification in Laravel 5 and AngularJs sans the need for JWT Tokens

I am currently working on a project that involves utilizing a Laravel-based back-end and a front-end built with both Laravel and AngularJS. After completing 40% of the back-end development, I am now faced with the task of implementing the front-end. Howev ...

`AngularFire services/factories that utilize nested models`

I am currently exploring how to nest models using factory-model/classes in combination with Firebase for data storage. For instance, imagine I am developing a task management app where Lists contain multiple Tasks, and each Task has various Details associa ...

Error: The `queries` property is undefined and cannot be read (react.js)

Here is the code snippet I am currently working with: import { useState } from 'react' import { QueryClientProvider, QueryClient } from 'react-query' import { ReactQueryDevtools } from 'react-query-devtools' import Navba ...

Tips for effectively managing the timeout of server-side AJAX calls1. Maxim

I'm currently developing server code in ASP.NET with the MVC framework. The client-side code is written in javascript. When sending an AJAX request from the browser to the server, whether using JQuery or not, timeouts can be set. Additionally, the br ...

The class name is not defined for a certain child element in the icon creation function

Currently, I am developing a Vue2 web application using Leaflet and marker-cluster. I am encountering an issue with the iconCreateFunction option in my template: <v-marker-cluster :options="{ iconCreateFunction: iconCreateClsPrg}"> ...

Is it possible to update table cell content depending on selected option?

Displayed here is the select block: <form> <select id="select"> <option disabled selected value="choose"> CHOOSE </option> <option value="i2g" id="i ...

Refreshing web pages using AJAX

I currently have an application that includes a search feature where users can look up items in the database. The search functionality is working well with AJAX, but I'm now looking to incorporate this AJAX functionality into my pagination system. Spe ...

What is the best way to implement a Fibonacci sequence using a for...of loop?

**Can someone show me how to generate Fibonacci numbers using the for...of loop in JavaScript?** I've tested out the following code and it's giving me the desired output: function createFibonacci(number) { var i; var fib = []; // Initi ...

Using jQuery to smoothly animate a sliding box horizontally

Is there a way to smoothly slide a div left and right using jQuery animation? I have been trying to achieve this by implementing the code below, which can be found in this fiddle. The issue I am facing is that every time I click on the left or right butto ...

Trouble arises when implementing AJAX in conjunction with PHP!

I am facing an issue with my PHP page which collects mp3 links from downloads.nl. The results are converted to XML and display correctly. However, the problem arises when trying to access this XML data using ajax. Both the files are on the same domain, b ...

Utilize node.js to run a local .php file within a polling loop

Here is the purpose of my application in brief. I am using a PHP file to read data via an ODBC connection and then write that data to a local database. This PHP file needs to be executed LOCALLY ON THE SERVER every time a loop is processed in my node.js, ...

Displaying a collection of items using Rails, implementing form_for and integrating Ajax functionality

Looking to display a list of "Interests" for users to "follow" by clicking on a button linked to the Interest's image. Once the follow button is clicked, the Interest and its image should be removed from the list. Attempting to use a hide function in ...

p5.js experiencing issue: Uncaught TypeError - Unable to access property 'transpose3x3' due to null value

I have a simple website built with Flask where I am running several p5.js sketch animations, and everything is working smoothly. However, when I try to add a new sketch that utilizes WEBGL, I encounter the following error: Uncaught TypeError: Cannot read p ...

Changing the variable in the parent scope from the directive scope using two-way binding is not possible

I am currently working on developing a customized directive that takes a username as input. The objective is to validate and verify if the username is available or not. In case the username is unavailable, I aim to send certain data values back to the main ...

The URL in a request is altered prior to execution

I am encountering an issue with my NodeJS application where it automatically appends my domain to the URL set in my http request. How can I prevent this from happening? I have tried to search for similar problems but have not found any relevant solutions. ...

Show the React component once the typewriter effect animation is complete

Hello there, I am looking to showcase my social links once the Typewriter effect finishes typing out a sentence in TypeScript. As someone new to React, I'm not quite sure how to make it happen though. Take a look at the code snippet below: ` import ...

Show a condensed version of a lengthy string in a div using React TS

I've been tackling a React component that takes in a lengthy string and a number as props. The goal of the component is to show a truncated version of the string based on the specified number, while also featuring "show more" and "show less" buttons. ...