Tips for simulating a callback function to evaluate a promise using jasmine in an Angular 8 environment

I'm struggling with figuring out how to mock a callback function and the function that calls it. The specific function I'm trying to mock is "listenOnAMessageWithCallBack" from a service I'm injecting, along with the callback function it triggers.

Here is my current implementation:

  async getUsername(): Promise<string> {
    return await new Promise<string>((resolve, reject) => {
      try {
        this.electronController.sendMessage('userName');
        let cb = (event, username) =>{
          this.username = username;
          let user = this.stripDomain(this.username);
          resolve(user);
        };
        this.electronController.listenOnAMessageWithCallBack('catchUser', cb); 
      } catch (err) {
        reject(err);
      }
    })
  }

And here's the test setup:

  it('testing function with callback', async() => {
    const stripDomain = spyOn(service, 'stripDomain').and.callFake(()=>{
      service.username = service.username.split('\\').reverse()[0];
      return service.username;
    });
    let cb = (event, username)=>{Promise.resolve('username')}
    spyOn(electronController, 'listenOnAMessageWithCallBack').withArgs('message').and.callFake(()=>{});
    let username = await service.getUsername();
    expect(username).toBe('username');
    expect(stripDomain).toHaveBeenCalledTimes(1);
  });

When running the test, I encounter the following error message: "Spy 'listenOnAMessageWithCallBack' received a call with arguments [ 'catchUser', Function ] but all configured strategies specify other arguments."

If anyone has insights on how to properly mock the callback function and its caller, your help would be greatly appreciated. Thank you!

Answer №1

The reason for the error message is due to the configuration of the listenOnAMessageWithCallBack spy with .withArgs('message'). This means that the spy will only be used if the method is called with the argument 'message'. However, in the service code, the method is actually called with 'catchUser' and a callback function, not 'message', resulting in the spy not being invoked. If you remove the .withArgs('message') condition, the spy will be triggered regardless of the arguments passed to the method.

Once the spy is properly invoked, within the callFake function of the spy, you can access the callback passed into the method in your service code:

spyOn(electronController, 'listenOnAMessageWithCallBack').and.callFake(
  (msg, cb) => {
    expect(msg).toBe('catchUser');
    expect(typeof cb).toBe('function');

    // Invoke the callback passed into listenOnAMessageWithCallBack
    cb('mockEvent', 'mockUsername');
  }
);

It's important to clarify what you are trying to achieve because the callback sets the service.username to the username provided, but it seems like you are attempting to spy on service.stripDomain to set service.username instead. Therefore, defining the exact purpose of your test is crucial.

For reference, here's a stackblitz demonstrating how callFake works and grants access to the callback function: StackBlitz Link

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

The TypeScript 'object' type

My query regarding the definition of TypeScript's {} type has brought about some confusion. Initially, I believed it represented an "empty object with no properties," but I recently encountered an ESLint rule that prohibits the use of {} type because ...

Differences in React projects utilizing materialize-css compared to those using react-toolbox or material-ui

Is there a difference in technical benefits or code reliability when directly using material-css in JSX versus utilizing JSX specific libraries like material-ui or react-toolbox? Conversely, could using JSX libraries like material-ui or react-toolbox provi ...

Instructions on creating an input field and a slider simultaneously

Currently, I am exploring the world of CSS 3D transforms and I am particularly interested in creating sliders to manage these transforms. I recently stumbled upon the Three.js editor and was impressed by how it handles the positioning, rotation, and scalin ...

Access network path through browser using Angular

I'm having trouble opening a network path from my browser using the code below. The browser keeps throwing an error saying it's unable to load local resources. Can you please provide some advice on this issue? public openUrl() { window.o ...

What sets apart a space after the ampersand from no space in Material UI?

Could you clarify the difference between using a space after the ampersand compared to not having a space? For example: Why is there a space after the ampersand in & label.Mui-focused but no space in &.Mui-focused fieldset? const WhiteBorderTextF ...

Unusual behavior observed within for loop; code within not running as expected

I will be presenting my code along with some images to illustrate the issue at hand. Something as simple as declaring a variable or using the log function results in the json being undefined. Upon entering text into the input field, the ajax call is trigg ...

Sending DataView to controller using JavaScript

Struggling to establish communication between the view and controller for updating values in the database using JavaScript, MVC, and Asp.Net. Here is a snippet of my view: function updateRejectType() { $("#btnvalider").click(function () { var IdRTD ...

Select only the desired time option from the Datetime-picker in AngularJS

I am working with AngularJS and I need to split a datetime-picker into two separate parts. Normally, when you open the calendar, you first select the day and then the time (hours and minutes). My goal is to have two different datetime-pickers - one for sel ...

Ways to trigger the submit function of a child component through another child component

After struggling for 48 hours, I still can't figure it out. How can I trigger the onSubmit method in the CreateProject component when the onApply function is called in the ModalContent component using TypeScript and react-hook-form? The concept is sim ...

Triggering an event for a div using Javascript, along with a Rails loop

I have a page showcasing a collection of listings that are displayed on the main page. <% @listings.each do |listing| %> # do something <% end %> Each listing now includes a data-toggle, essentially a button. <a id="chat-menu-toggle" h ...

Creating a JSON utility type for an already existing type, such as JSON<SomeExistingType>

Is there any tool or utility available that can accomplish this task? const foo: Foo = { ... } const bar: string = JSON.stringify(foo) const baz: JSON<Foo> = JSON.parse(foo) JSON<Foo> would essentially mirror all the properties of Foo, with th ...

When I close all of my tabs or the browser, I aim to clear the local storage

Could you recommend any strategies for clearing local storage upon closing the last tab or browser? I have attempted to use local storage and session storage to keep track of open and closed sessions in an array stored in local storage. However, this meth ...

Setting up a Node project with sub modules on the CircleCI platform

We are working on a project in Git that consists of multiple modules organized as shown below: project |- module1 |- package.json (...) |- module2 |- package.json (...) Each package.json file contains a test entry to run tests for the respective ...

Launch a nearby hyperlink in a separate tab

I am currently facing an issue where all the URLs in a Text get linked as Hyperlinks. However, when a user types www., the browser interprets it as a local URL and associates the link with the application's URL. Does anyone know how to open a local U ...

Creating a file upon pressing a submit button in an HTML file using NodeJS

When I click the submit button, the value of the id should be retrieved to create a new file. However, an error is being displayed when attempting to make the file. Code for HTML file:- <label for="">Make New File : </label> < ...

Checking for Three.js WebGL compatibility and then switching to traditional canvas if necessary

Is there a way to check for WebGL support in three.js and switch to a standard Canvas render if not available? I'd appreciate any insights from those who have experience with this library. ...

Experiencing a lengthy installation process of TypeScript on Node.js

I attempted to set up TypeScript on my laptop running MS Windows 8.1 (64-bit). After installing Node.js 64-bit, I ran the command npm install -g typescript. However, the installation appeared to stall with a spinning '/' for over 2 hours. When I ...

Tips for excluding specific elements when clicking on a document

JavaScript $(document).click( function () { alert("Hello there"); } Web Development <div id="wrapper"> <div id="inner-1"> <div id="sub-inner1">Sub Inner1 Content</div> <div id="sub-inner2">Sub Inner2 Content&l ...

Is dividing a website into two parts acceptable?

In the process of creating a social network, one major concern is making sure that the content is easily readable by Google while also providing users with a seamless and engaging experience through Ajax support. However, it's well-known that Ajax and ...

The onNodeContextMenuSelect function does not seem to be functioning properly within the p-tree

<p-tree [value]="files" selectionMode="single" (onNodeContextMenuSelect)="showContect($event)" > </p-tree> Whenever I right click, the event doesn't seem to be triggering. Instead, the default browser c ...