How can I simulate a callback function that was not tested?

Currently experimenting with the method below:

  startScriptLoad(): void {
    const documentDefaultView = this.getDocumentDefaultView();
    if (documentDefaultView) {
      const twitterData: ICourseContentElementEmbedTweetWidgetData = this.getTwitterWidgetData() ?? {
        // eslint-disable-next-line @typescript-eslint/no-empty-function
        ready: () => {},
        _e: [],
      };
      if (this.scriptExists()) {
        ((this.document.defaultView as unknown) as ICourseContentElementEmbedTweetDocument)[
          this.TWITTER_OBJECT
        ] = twitterData;
        return;
      }
      this.appendScriptToDOM();
      twitterData._e = [];
      twitterData.ready = (callback: () => void) => {
        twitterData._e.push(callback);
      };
      ((this.document.defaultView as unknown) as ICourseContentElementEmbedTweetDocument)[
        this.TWITTER_OBJECT
      ] = twitterData;
    }
  }

Testing out the above with the following test scenario:

  describe('startScriptLoad()', () => {
    it('should load script', () => {
      jest.spyOn(service, 'getDocumentDefaultView');
      jest.spyOn(service, 'appendScriptToDOM');
      service.startScriptLoad();
      expect(service.getDocumentDefaultView).toHaveBeenCalled();
      expect(service.appendScriptToDOM).toHaveBeenCalled();
    });
  });

I'm encountering issues getting coverage for these specific lines within startScriptLoad():

  twitterData.ready = (callback: () => void) => {
    twitterData._e.push(callback);
  };

Any suggestions on how to potentially mock the callback method call?

Answer №1

Utilize the power of a Proxy object to create a mocked version of an object, allowing us to intercept and redefine key operations for that object. Specifically, we can use handler.set() to establish a trap for setting the private method ready on the mTwitterData object.

The concept is to assign the anonymous method associated with ready to a variable like _ready. This way, we can call it manually during testing procedures.

service.ts:

export class SomeService {
  getTwitterWidgetData() {
    return {} as any;
  }
  startScriptLoad(): void {
    const twitterData = this.getTwitterWidgetData();
    twitterData._e = [];
    twitterData.ready = (callback: () => void) => {
      twitterData._e.push(callback);
    };
  }
}

service.test.ts:

import { SomeService } from './service';

describe('69041800', () => {
  test('should pass', () => {
    const service = new SomeService();
    let _ready;
    const mTwitterData = new Proxy({} as any, {
      set: (obj, prop, value) => {
        if (prop === 'ready') {
          _ready = value;
        }
        obj[prop] = value;
        return true;
      },
    });
    const getTwitterWidgetDataSpy = jest.spyOn(service, 'getTwitterWidgetData').mockReturnValue(mTwitterData);
    service.startScriptLoad();
    expect(getTwitterWidgetDataSpy).toBeCalledTimes(1);
    // test ready private method
    const mCallback = jest.fn();
    _ready(mCallback);
    expect(mTwitterData._e).toEqual([mCallback]);
    getTwitterWidgetDataSpy.mockRestore();
  });
});

test result:

 PASS  examples/69041800/service.test.ts (9.519 s)
  69041800
    ✓ should pass (4 ms)

------------|---------|----------|---------|---------|-------------------
File        | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
------------|---------|----------|---------|---------|-------------------
All files   |   83.33 |      100 |   66.67 |   83.33 |                   
 service.ts |   83.33 |      100 |   66.67 |   83.33 | 3                 
------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        10.148 s

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

Include draggable functionality to a seating chart that is generated dynamically

I developed a function that generates table seats dynamically with equal spacing. The issue arises when I try to drag names from a list and drop them onto the seats as children. Unfortunately, I can't seem to achieve this functionality with the dynami ...

Exploring the functionalities of bootstrapFactory with DartAngular 5

Here is a snippet of code showing the main method: Future<Null> main() async { final securityService = new SecurityService(new BrowserClient()); await securityService.getObject(); bootstrapStatic<AppComponent>( AppComponent, ...

Failure to trigger Ajax callback function

I am currently working on a form page that will be submitted using Ajax. The steps I have planned are: 1. Use Ajax to check if the email already exists 2. Verify if the passwords match 3. Switch to another "screen" if they do match 4. Final ...

Exploring and extracting values from nested arrays of objects in JavaScript and React

Hey there, I am having trouble getting the data from the backend server to display on a chart library. Can you please take a look at my code and help me out? const data = [ { id: "americano", data: [{x: "10",y: 10,}, {x: &quo ...

Testing the signin component using jest and react testing library: A step-by-step guide

Struggling with creating an integrated test for a sign-in component. The main goal is to confirm that upon entering email and password credentials, and clicking submit, the user gets redirected to a specific page. Attempting to use waitForComponentToBeRemo ...

Verifying the visibility status of a div and toggling a class based on it

I'm facing a challenge with multiple checkboxes in a row. When a button is clicked, it displays a div (#locale_container), and flips a small arrow by adding a rotated class. However, I only want the arrow to flip when the div is being shown or hidden ...

The request body is not defined within the Express controller

Currently facing an issue with my controller: when I use console.log(req), I can see all the content of the request body. However, when I try console.log(req.body), it returns as undefined. This problem arises while working on my Portfolio project with Nex ...

Having trouble integrating CKEditor into a React Typescript project

Error: 'CKEditor' is declared but its value is never read.ts(6133) A declaration file for module '@ckeditor/ckeditor5-react' could not be found. The path '/ProjectNameUnknown/node_modules/@ckeditor/ckeditor5-react/dist/ckeditor.js& ...

What is the correct way to utilize Array.reduce with Typescript?

My current approach looks something like this: [].reduce<GenericType>( (acc, { value, status, time }) => { if (time) { return { ...acc, bestValue: valu ...

What is the method used by three.js to render video with spherical UV mapping?

I have a streaming video displayed in a 3*3 format. I am able to splice the entire video into individual sections using THREE, // Creating a 3x3 PlaneGeometry var geometry = new THREE.PlaneGeometry(400, 200, 3, 3); const video1 = document.getElem ...

Create distinct projects for WebApi and Angular to keep them separate

Currently, I am working on a project that involves webApi and Angular apps combined in one project by default from Visual Studio. However, I want to separate them into two distinct projects. To achieve this, I removed all the SPA-related code from my StarU ...

JavaScript getting overshadowed by other JavaScript libraries

My current CMS, Liferay, heavily relies on jQuery for various functions. Recently, I introduced a new feature to our website using fancybox. However, I realized that this new addition was causing issues with other jQuery functionalities on the page. Remov ...

Passing $index variable from a bootstrap modal window does not work in AngularJS

I'm running into a wall here. My issue involves using ng-repeat to populate a table with two buttons in each row - one for updating the row content and another for uploading files. The upload button triggers a bootstrap modal window where users can se ...

What is the most effective method in React JS to achieve real-time results with every keystroke by making REST calls to the server?

We are dealing with a huge database and the task at hand is to display results as the user types them in the search box. Preloading queries to attempt matching is out of question due to the enormity of our data. Currently, we make a server request with th ...

Is there a way to transform an Array or Object into a new Object mapping?

When using the map method in JavaScript, it typically returns an Array. However, there are instances where I would like to create an Object instead. Is there a built-in way or a simple and efficient implementation to achieve this? Solutions using jQuery ar ...

What options do I have for personalizing event listeners in d3.js?

I am currently working on a simple program that involves using a slider to move a rectangle across a webpage. I have set up the slider like this: <input type = "range" min = "5" max = "500" value = "5" id = "xvalue" > and I am able to access the sl ...

When I submit a form with an empty date input field, the Datepicker is sending a 0000-00-00 date

[I am experiencing an issue with my date input field. When I submit without entering any value, the date on the view page shows as 0000-00-00 instead of being empty or blank.] <div class="col-sm-3 col-sm-offset-1"> <div class="input-group"& ...

What are the best methods for preserving paint color when changing wheel styles, and vice versa?

I posted this query about a year ago, but I did not have a fiddle prepared at that time and my question was not as well articulated as it could have been. Despite that, many people came forward to offer their help, and I am truly grateful for that. This ti ...

Using CSS and JavaScript to hide a div element

In my one-page website, I have a fixed side navigation bar within a div that is initially hidden using the display:none property. Is there a way to make this side nav appear when the user scrolls to a specific section of the page, like when reaching the # ...

The most effective method for transforming an array into an object in JavaScript using a prefixed value as the key

I am working with an array that contains prefix values ["options_a", "options_b", "options_c", "capable_d", "capable_e_c" ] I am looking for a way to transform this array into an object format with the pre ...