[SalesForce] Jest LWC, How to test the callback function of a registerListener

I have a LWC component which performs multiple operations in connectedCallback(), one of them is a registerListener which calls an apex method which updates a record in the DB. Here is my question: How can I test the function called by the listener?. The listener is being called, but I can not get the callback function to run. Thanks in advance.

Fragment of the code. line 43 registerListener. I can not get coverage of the function inline 52

connectedCallback() {
    //first load call the methods
    if (!sessionStorage.getItem('sessionId')) {
      this.handleFormFactor();
      this.handleOS();
      this.handleBrowser();
      this.handleGeolocation();
    }
    //refresh get data from sessionStorage
    else {
      this.sessionId = sessionStorage.getItem('sessionId');
      this.sessionRecord = JSON.parse(sessionStorage.getItem('session'));
    }
    //register listeners from PreAppContainer and trigger unload functionality
    registerListener('registerLastPage', this.register, this);
    window.addEventListener('unload', this.unloadHandler.bind(this));
  }

  disconnectedCallback() {
    unregisterAllListeners(this);
  }

  //Register event from PreApp Container and get the last page visited
  register(mes) {
    if (mes.lastPage != 'type') {
      this.updateRecord(this.sessionRecord, mes.message);
    }
  }

  //update session record with the last page visited by the user
  updateRecord(session, last) {
    let sessionString = JSON.stringify(session);
    console.log('in update ' + sessionString);
    updateSessionRecord({ payload: sessionString, lastPage: last })
      .then(result => console.log(result.Last_Page__c))
      .catch(error => console.log(error));
  }

Fragment of the Jest Test class

    it('test registerListener Update', () => {
        insertSession.mockResolvedValue(APEX_SESSION_SUCCESS);
        const element = createElement('c-ab-testing', {
            is: AbTesting
        });
        const fetch = (global.fetch = mockFetch(FETCH_DATA));
        document.body.appendChild(element);
        //testing register listeners
        //expect(registerListener.mock.calls.length).toBe(2);
        expect(registerListener.mock.calls[0][0]).toBe('registerLastPage');

        let callback = registerListener.mock.calls[0][1];
        //FAILING HERE//ATTRIBUTE NULL
        callback.call(MESSAGE_DATA);

        return flushPromises().then(() => {
            //testing that fetch is being called
            expect(fetch).toHaveBeenCalledTimes(1);
            expect(fetch.mock.calls[0][0]).toBe(QUERY_URL); 
            //testing that the record is being inserted
            expect(insertSession.mock.calls[0][0]).not.toEqual(null);
        });
    });

Best Answer

One option that you have is to manually call the callback, to simulate that an event has occurred, passing an arbitrary payload. I don't see all your code, but assuming that we have the next implementation (taken from an example in lwc-recipes):

...    
connectedCallback() {
    registerListener('contactSelected', this.handleContactSelected, this);
}
    
handleContactSelected(contactId) {
    this.recordId = contactId;
}
...

You can do:

// Call callback function manually
const contactId = '12345678';
const callback = registerListener.mock.calls[0][1];
callback.call(element, contactId);

// Expect that callback has been called with the expected payload
expect(element.recordId).toBe(contactId);

I tried out myself and it worked, not sure why you're receiving a null callback function but let me know if this works. Also check that you're setting up the mock correctly doing:

jest.mock('c/pubsub', () => {
    return {
        registerListener: jest.fn(),
        unregisterAllListeners: jest.fn()
    };
});
Related Topic