Can someone tell me how to implement the spy function within an object in Angular using Jasmine?

Below is a method written in the service called CapacitorManager:

backButtonHandler() {
        return () => {
            const activeModalInstance = this.dataService.getItem(Constants.activeModalInstanceKey);
            const doesActiveModalExist = activeModalInstance !== -1;
            if (doesActiveModalExist) {
                activeModalInstance.close();
            }
            else {
                this.location.back();
            }
        }
    }

This method should invoke the close method within the object activeModalInstance (where activeModalInstance is an instance of NgbModal) if there is an activeModalInstance inside the instance referred to by dataService.getItem(). The getItem method has already been mocked to return an object including the close method.

fdescribe('CapacitorManager', () => {
    let service: CapacitorManager;
    let dataService: DataService;
    let location: Location;
    let dataServiceStub: Partial<DataService>;
    beforeEach(async(() => {
        dataServiceStub = {
            getItem: () => {
                return {
                    close: () => {

                    }
                }
            }
        }
        TestBed.configureTestingModule({
            providers: [
                { provide: Location, useClass: SpyLocation },
                { provide: DataService, useValue: dataServiceStub },
                CapacitorManager
            ],
            imports: [
                RouterTestingModule
            ]
        }).compileComponents().then(() => {
            service = TestBed.inject(CapacitorManager);
            dataService = TestBed.inject(DataService);
            location = TestBed.inject(Location);
        });
    }));

    afterEach(() => {
        service = null;
    });

    it('should create the component', () => {
        expect(service).toBeTruthy();
    });

    it('should backButtonHandler call activeModal in case activeModalInstance exists', () => {
        const activeModalInstance = dataService.getItem("activeModal");
        spyOn(activeModalInstance, "close");            
        service.backButtonHandler();
        expect(activeModalInstance.close).toHaveBeenCalled();
        expect(location.back).not.toHaveBeenCalled();
    });

});

The last test case is where I am facing the issue of Expected a spy, but got Function. How can I pass this test case successfully?

Answer №1

After some troubleshooting, I believe the modified code provided below will resolve the issue you are facing. I have included comments to highlight the changes made in order to pass the test successfully.

One last thing to consider is verifying that

expect(location.back).not.toHaveBeenCalled();
is not causing the problem due to line numbers.

fit('should backButtonHandler call activeModal in case activeModalInstance exists', () => {
  const modal = {
    close: () => {

    }
  };
  // Revision made here to ensure consistent object spying
  dataService.getItem = () => modal;
  const activeModalInstance = dataService.getItem("activeModal");
  spyOn(activeModalInstance, "close");
  const func = service.backButtonHandler();
  // In this scenario, your capacitor manager returns a function which requires calling
  func();
  expect(activeModalInstance.close).toHaveBeenCalled();
  expect(location.back).not.toHaveBeenCalled();
});

An adjustment was made to an if statement where TypeScript flagged an issue due to comparing an object to -1

backButtonHandler() {
  return () => {
    const activeModalInstance = 
    this.dataService.getItem(Constants.activeModalInstanceKey);
    // The purpose of this comparison is unclear (perhaps mistranslated)            
    const doesActiveModalExist = activeModalInstance !== -1;
    if (doesActiveModalExist) {
      activeModalInstance.close();
    }
    else {
      this.location.back();
    }
  }
}

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

Retrieve every item in a JSON file based on a specific key and combine them into a fresh array

I have a JSON file containing contact information which I am retrieving using a service and the following function. My goal is to create a new array called 'contactList' that combines first names and last names from the contacts, adding an &apos ...

The crosshair functionality in Zing Chart is causing a CPU leak

After enabling the crosshair feature on my chart, I noticed a significant issue when using Chrome 57 (and even with versions 58 and ZingChart 2.6.0). The CPU usage spikes above 25% when hovering over the chart to activate the crosshair. With two charts, th ...

The value is undefined until a new Resource object is pushed with the item

I've encountered an issue while testing a factory and I can't seem to find anyone else with the same problem. Can someone help me figure out what's causing this strange error? TypeError: 'undefined' is not a function (evaluating & ...

What is the best way to attach an attribute to a element created dynamically in Angular2+?

After reviewing resources like this and this, I've run into issues trying to set attributes on dynamically generated elements within a custom component (<c-tabs>). Relevant Elements https://i.stack.imgur.com/9HoC2.png HTML <c-tabs #mainCom ...

Could a tslint rule be implemented in Typescript classes to ensure method return types are enforced?

After diving into the tslint rules here, it seems that although the typedef rule's call-signature option might be close to what I need, it doesn't address the absence of a return type. Is there a specific rule (if one exists) that can enforce re ...

Troubleshooting the issue with integrating a user-defined Cordova plugin in Ionic 2 using TypeScript

I have developed a custom Cordova plugin and I am trying to integrate it with an Ionic 2 project that is using TypeScript and Angular 2. While I have successfully added the plugin to the Ionic 2 project, I am facing issues when trying to call methods defin ...

The Angular6 application is experiencing an issue where the JWT token is not being transmitted through

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { let request = req.clone({ setHeaders: this.getRequestHeaders() }); return next.handle(request).map((event: HttpEvent< ...

Update the form field with today's date in a JHipster application

In our current project in JHipster, we are facing a challenge with setting the default value of a form field as the current date. JHipster offers a moment format for dates, which is essentially an ngbdatepicker. However, when attempting to change the inpu ...

How can I adjust the column width in OfficeGen?

Currently, I am utilizing officeGen for the purpose of generating word documents. <sup> let table = [ [ { val: "TT", fontFamily: "Times New Roman", }, { val: "Ten hang", ...

Ways to specify the data type of a function's input parameter

I'm new to TypeScript and have a function that accepts another function as a parameter, which in turn takes a number as input. loadResources(updateProgress: Function) { let progress = 100; updateProgress(progress); } When calling this function: l ...

Is there a way to automatically scroll to the bottom of a div when it first

Looking to enhance my application with a chat feature that automatically scrolls to the bottom of the chat page to display the latest messages. Utilizing VueJs: <template> <div id="app"> <div class="comments" ...

Guide on transforming an array containing indexed objects into a simple object

Can anyone help me with converting an array of this specific type? place: [ { "_id": "xxxxx", "loc": [ 0: "xxx", 1: "xxx" ] } ] Into something ...

Encountering a TypeError while attempting to construct and launch an IOS simulator through Cordova

Currently, I am in the process of developing an Ionic app that is designed for cross-platform functionality. Encountering an Error when attempting to build and run an IOS simulator using Cordova TypeError [ERR_INVALID_ARG_TYPE]: The "code" argum ...

ValidationPipes do not support specific body types

Just a quick question: I'm working on applying a ValidationPipe to a POST endpoint responsible for adding an invoice. Before adding the invoice, I need to validate the body. Here is what I have done: invoice.dto.ts import { ContractorDto } from &apo ...

What is the best way to guarantee that an object contains certain fields using Partial<>?

I am dealing with a function that accepts a parameter as shown below: const handleAccount = ( account: Partial<IAccountDocument>, ... ) => { ... } It is crucial that the interface for IAccountDocument cannot be modified to avoid requiring cer ...

Why does the page not work when I enter a certain URL with an ID parameter, and instead displays the error message "Uncaught ReferenceError: System is not defined"?

This is my "app.routing.ts": import {provideRouter, RouterConfig} from "@angular/router"; import {DashboardComponent} from "./dashboard.component"; import {HeroesComponent} from "./heroes.component"; import {HeroDetailsComponent} from "./hero-details.com ...

Having troubles with Angular 2 subscription functionality?

I am attempting to launch a modal window that has its template and logic in a separate component. My goal is to accomplish this by subscribing to an observable, but I am encountering issues. Below is my code: Method within the component where I want to tr ...

Changing the value within an object by using a dynamic variable as the property name in Typescript

Here is a method that I have: updateDate(row: TaskItem, column: keyof TaskItem, date: string) { row[column] = date; } The TaskItem interface is defined as follows: export interface TaskItem { id: number, myDate: string } I would like to call the up ...

Having trouble building the React Native app after adding react-native-vector icons?

A recent project I've been working on involved adding react-native-vector-icons using react-native 0.63.4. However, during the build process, I encountered an error when running the command npx react-native run-ios in the terminal. The warnings/errors ...

Setting up Identity Server 4 integration with Ionic 2

Currently, I am in the process of setting up Identity Server to function with Ionic 2. I am a little confused about how to set up the Redirect URLs specifically for testing purposes in the browser. Furthermore, I am updating and integrating an OIDC Cordov ...