Guide to mocking the 'git-simple' branchLocal function using jest.mock

Utilizing the simple-git package, I have implemented the following function:

import simpleGit from 'simple-git';

/**
 * The function returns the ticket Id if present in the branch name
 * @returns ticket Id
 */
export const getTicketIdFromBranchName = async (ticketRegex: RegExp) => {
    const git = simpleGit();

    try {
        const localBranches = await git.branchLocal();
        const currentBranch = localBranches.current;
        const currentBranchTicketMatches = currentBranch.match(ticketRegex);

        if (currentBranchTicketMatches) {
            return currentBranchTicketMatches[0];
        }

        return null;
    } catch {
        return null;
    }
};

I am attempting to write a unit test for this function:

import { getTicketIdFromBranchName } from '@/utils/git-info';

const TICKET_ID_REGEX = /((?<!([A-Z]{1,10})-?)[A-Z]+-\d+)/.source;

describe('[utils/git-info]', () => {
    it('getTicketIdFromBranchName | Function should correctly identify ticket Id when one is present', async () => {
        const ticketId = 'CLO-1234';

        jest.mock('simple-git', () => {
            const mGit = {
                branchLocal: jest.fn(() => Promise.resolve({ current: `${ticketId} DUMMY TEST` })),
            };

            return jest.fn(() => mGit);
        });

        const result = await getTicketIdFromBranchName(new RegExp(TICKET_ID_REGEX));

        expect(result === ticketId).toEqual(true);
    });
});

Unfortunately, the unit test fails, indicating that it expected to receive true but instead received false on the final line.

I suspect that my usage of jest.mock may be incorrect.

Answer №1

The official guide provides vital information on the usage of jest.mock.

Important: To ensure proper mocking, it is necessary for jest.mock('moduleName') to be within the same scope as the require/import statement.

While you are calling jest.mock('moduleName') inside the test case function scope, you are importing the git-info module in the module scope. This mismatch is why the mock doesn't function correctly.

To resolve this issue, utilize require('moduleName') or await import('moduleName') within the test case function. The order of the require/import and jest.mock() statements is irrelevant.

git-info.js:

import simpleGit from 'simple-git';

/**
 * This function retrieves the ticket ID, if present, from the branch name
 * @returns ticket ID
 */
export const getTicketIdFromBranchName = async (ticketRegex) => {
  const git = simpleGit();

  try {
    const localBranches = await git.branchLocal();
    const currentBranch = localBranches.current;
    const currentBranchTicketMatches = currentBranch.match(ticketRegex);

    if (currentBranchTicketMatches) {
      return currentBranchTicketMatches[0];
    }

    return null;
  } catch {
    return null;
  }
};

git-info.test.js:

const TICKET_ID_REGEX = /((?<!([A-Z]{1,10})-?)[A-Z]+-\d+)/.source;

describe('[utils/git-info]', () => {
  it('getTicketIdFromBranchName | Function should return correct ticket Id when available', async () => {
    const { getTicketIdFromBranchName } = await import('./git-info');
    const ticketId = 'CLO-1234';

    jest.mock(
      'simple-git',
      () => {
        const mGit = {
          branchLocal: jest.fn(() => Promise.resolve({ current: `${ticketId} DUMMY TEST` })),
        };

        return jest.fn(() => mGit);
      },
      { virtual: true }
    );

    const result = await getTicketIdFromBranchName(new RegExp(TICKET_ID_REGEX));

    expect(result === ticketId).toEqual(true);
  });
});

Test outcome:

 PASS  stackoverflow/71808909/git-info.test.js (7.439 s)
  [utils/git-info]
    ✓ getTicketIdFromBranchName | Function should return correct ticket Id when available (6892 ms)

-------------|---------|----------|---------|---------|-------------------
File         | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------|---------|----------|---------|---------|-------------------
All files    |   84.62 |       50 |     100 |   81.82 |                   
 git-info.js |   84.62 |       50 |     100 |   81.82 | 19-21             
-------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        8.215 s, estimated 9 s

package version: "jest": "^26.6.3"

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

How to smoothly transition a div from one location to another using animations in an Ionic3-Angular4 application

I'm attempting to incorporate some animation into my Ionic 3 mobile app. Specifically, I want to shift a div from one location to another. In the code snippet provided below, I am looking to move the div with the "upper" class after the timeline-item ...

The function of jQuery's .prop('defaultSelected') appears to be unreliable when used in Internet Explorer 9

Below is the code I am currently using: $selects = $('select'); $selects.val( $selects.prop('defaultSelected')); The purpose of this code is to reset the values of all select elements on my webpage. However, I am facing an issue in IE ...

Using methods from one component in another with NgModules

There are two modules in my project, a root module and a shared module. Below is the code for the shared module: import { NgModule } from '@angular/core'; import { SomeComponent } from "./somecomponent"; @NgModule({ declarations: [SomeCompon ...

Adding the location of the onClick event to the hook - a step-by-step guide

Here is the code I am working with: import { MapContainer, TileLayer } from "react-leaflet"; import React, { useState } from 'react'; export default function App() { const [positionLat, setPositionLat] = useState(null); ...

Node.js server only supports cross-origin requests for protocol schemes when working with an Angular front end

Struggling to configure CORS on a local site hosting a Node.js server and an Angular client. Encountering the following error: Access to XMLHttpRequest at 'localhost:3000/api/v1/users' from origin 'http://localhost:4200' has been bl ...

Determining the time gap in milliseconds between two specified times using the "DD/MM/YYYY HH:mm:ss:ms" format in JavaScript

I have a situation where I need to calculate the time difference between two timestamps. Starting time: "2014/10/28 11:50:28:318" Ending time: "2014/10/28 11:50:35:249" To achieve this, I utilized moment.js for the calculation. Here is my code: var msE ...

Reposition div when clicked

I have encountered a challenge where I am unable to perform a small task. My goal is to have the position of "div1" change upon clicking on "div2", taking into account that "div2" is nested inside "div1". Additionally, when clicking on "div2" again, "div1" ...

Place the script tags within the window.load function inside the head section

<head> <script type="text/javascript"> $(window).load(function() { // <script src="js/external.js"></script> // }); </script> </head> Is it possible to insert a script tag(< script src="js/exte ...

Angular utilizes ZoneAwarePromise rather than a plain String output

I expected the giver code to return a string, but it is returning ZoneAwarePromise. Within the service: getCoveredPeriod() { let loanDetails = this.getLoanDetails().toPromise(); loanDetails.then((res: any) => { const coveredPeriodStart ...

Refreshing a Thymeleaf table dynamically without having to reload the entire page

I am currently using the Thymeleaf attribute to render data, but I am now looking to add a "Search" button without reloading the page. Within the attribute departments, I am rendering a List<Department> from the database. While I understand how to a ...

What is the best way to utilize window.find for adjusting CSS styles?

Incorporating both AJAX and PHP technologies, I have placed specific text data within a span element located at the bottom of my webpage. Now, my objective is to search this text for a given string. The page consists of multiple checkboxes, with each check ...

Analyzing a problem with a table directive

Here is the custom directive code I have written: currentApp.directive('testList', ['$compile', function ($compile) { return{ restrict: 'E', template: '<table></table>', ...

Tips for stopping ajax requests from automatically following redirects in jQuery

When utilizing the jQuery ajax functions to connect with a web service, I encounter an issue where the server redirects the response to a page with a 200 status code instead of providing a proper status code indicating an error. Unfortunately, I am unable ...

Effortless Tree Grid Demonstration for Hilla

As someone who is just starting out with TypeScript and has minimal experience with Hilla, I kindly ask for a simple example of a Tree Grid. Please bear with me as I navigate through this learning process. I had hoped to create something as straightforwar ...

Combining tuples with their corresponding data types

Trying to define a new type: type Union = [1, "one"] | [1, "first"] | [2, "two"] type GetTuple<T, U> = Extract<T, [U, ...unknown[]]>; type ObjectFromUnion<T extends Union[0] = Union[0]> = { number: T, word: ?? } Looking to utiliz ...

How can I retrieve the elements that have been removed using $pull in mongoose?

Currently, I am utilizing $pull to eliminate a subdocument from an array within a document. It may be pertinent to note that the subdocuments in my case contain _id and are therefore indexed. Here is the JSON schema description: user: { _id: Strin ...

The back button fails to refresh the page on a website utilizing Ajax technology

Recently, I implemented AJAX on a client's website to introduce some smooth animations for page transitions. When navigating from the homepage of firedogcreative.com to the edit page, and then to one of the work pages, we see a history like this: fir ...

What is the best way to overlay text onto a background image using Material UI's Card and CardMedia components?

Using the card component, I have successfully added a background image. However, I am facing difficulty in figuring out how to overlay text on top of this image. If anyone has suggestions or alternative methods, please feel free to share! <Card> ...

Exploring the capabilities of automation testing with charts.js and the latest version of Angular

While working on my testing automation for charts.js, I utilized the ngContext object to retrieve data with this code snippet: document.getElementsByTagName('chart-dataset')[0].__ngContext__. However, since upgrading to angular 14, it seems that ...

Timepicker.js - Incorrect Placement of Time Picker in Certain Scenarios

Utilizing the timepicker.js library to select a time, I am encountering an issue. When clicking on the input field, the timepicker should appear next to it. This function works as expected when the input is within the main view of the document. However, if ...