How can we verify that console.log has been called with a specific subset of expected values using Jest?

I am currently experimenting with a function that adds logging and timing functionality to any function passed to it. However, I am facing a challenge when trying to test the timing aspect of it. Here are my functions:

//utils.js
export const util_sum = (x: number = 0, y: number = 0): number => x + y;
export const util_getTime = () => performance.now();
export const util_addTimeLogger = (fn: Function) => {
  let t_start = util_getTime();
  const beautify = JSON.stringify;
  return (...args: any[]) => {
    console.log(`entering ${fn.name}: ${beautify(args, null, 2)}`);
    try {
      const valueToReturn = fn(...args);
      console.log(`normal exiting ${fn.name}: ${beautify(valueToReturn, null, 2)}`);
      console.log(`--->total execution time:${util_getTime() - t_start}ms`);
      return valueToReturn;
    } catch (thrownError) {
      console.log(`exception thrown ${fn.name}: threw ${thrownError}--->time:${util_getTime() - t_start}ms`);
      throw thrownError;
    }
  }
};

Testing Section:

//util.test.js
describe("util_addTimeLogger", () => {
  it("should add logging functionality with time to any functions", () => {
    console.log = jest.fn();
    const entering_msg = 'entering util_sum: [\n' +
    '  1,\n' +
    '  2\n' +
    ']';
    const normal_msg = 'normal exiting util_sum: 3';
    const total_time ='--->total execution time:0.47500000800937414ms';
    const loggedSum = util_addTimeLogger(util_sum);
    loggedSum(1,2);
    expect(console.log).toHaveBeenCalledWith(entering_msg);
    expect(console.log).toHaveBeenCalledWith(normal_msg);
    expect(console.log).toHaveBeenNthCalledWith(total_time);
  });
});

The issue lies in the third test, which is :

expect(console.log).toHaveBeenNthCalledWith(total_time.slice());

I have not been able to find a matcher like `toHaveBeencalledContainOf` or `subSetOf` as mentioned in the Jest document: https://jestjs.io/docs/en/expect.html

Is there a workaround for handling such situations?

Answer №1

I have discovered a resolution for this particular scenario by utilizing Jest. You can find the documentation here: https://jestjs.io/docs/en/expect#expectstringcontainingstring:

expect.stringContaining(string)

The expect.stringContaining(string) function matches the received value if it is a string that contains the expected string exactly.

expect.stringMatching(string | regexp)

The expect.stringMatching(string | regexp) function matches the received value if it is a string that matches the expected string or regular expression.

expect(console.log).toHaveBeenCalledWith(expect.stringMatching(/--->total execution time:0.*/));

Alternatively, you can use:

const total_time ='--->total execution time:0.';
expect(console.log).toHaveBeenCalledWith(expect.stringContaining(total_time));

Update: In order to provide a comprehensive solution for other developers who may encounter similar issues while testing the error section, it is possible to throw an error. However, make sure to use try-catch block to correctly handle the thrown error:

it("should throw error with fn.name and its calculated time", function () {
    const errorThrown = util_addTimeLogger(() => {
      throw new TypeError();
    });
    const error_msg = "exception thrown : threw TypeError--->time:";
    try {
      errorThrown();
    }
    catch (error) {
      expect(console.log).toHaveBeenCalledWith("entering : []");
      expect(console.log).toHaveBeenCalledWith(expect.stringContaining(error_msg));
    }
});

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

Tips for including an object as a prop using Vue Router

When working with Vue JS3, I have encountered an issue regarding passing props in my Vue component. Here is how I am currently doing it: <script> export default { data() { return { links: [], }; }, methods: { editLink(el) { this.$ ...

Enhancing Angular with Plotly: Implementing click events on bar chart legends

I'm currently working on implementing color pickers for my plotly-plot charts within an Angular template. I am looking to add a function that triggers when the chart legend is clicked. How can I achieve this and get a click event for the chart legends ...

Error encountered: The module '@mui/x-data-grid' does not export 'GridActionsCellItem'

I'm facing an issue while trying to import 'GridActionsCellItem' from '@mui/x-data-grid'. Here's the code: import { GridActionsCellItem } from '@mui/x-data-grid'; An error message pops up indicating: Attempted impor ...

"Exploring the functionalities of jquery .change() specifically in the

I have a jQuery change function set up to adjust the values of another select drop down whenever the user changes the month (to display the correct number of days). Everything works perfectly in most browsers, but Firefox seems to be giving me trouble :( ...

What is the best way to update a tag element in Vue.js?

Currently, I am working with Vuejs and struggling with a specific task - How can I replace the div tags with button tags? In the DOM, <div class="prev">prev</div> <div class="next">next</div> I would like to ac ...

Tips for updating an object variable dynamically in an Angular application

const person = { "name": "jacob", "age": 22 } I am looking to dynamically update it to: { "name": "jacob", "age": 22, "dob": number } ...

Issue occurs where the system is unable to recognize a defined variable, despite it being clearly defined

I keep encountering an error message stating that my variable is not defined, even though I have clearly defined it just a few lines above where the error occurs. The reason behind this error is baffling to me, as I cannot identify any potential triggers ...

Parsley JS: A Solution for Distinct IDs

I have a form that contains multiple select boxes, and I need to ensure that no two select boxes have the same value selected. In simpler terms, if select box 1 is set to value 2 and select box 4 is also set to value 2, an error should be triggered. While ...

Bug in toFixed causing incorrect results

function calculateTaxAndTotalRent(rent) { var phoneCharges = parseFloat($('#phone_charges').val()); phoneCharges = phoneCharges.toFixed(2); rent = parseFloat(rent); rent = rent.toFixed(2); var tax = parseFloat((rent * 15) / 1 ...

Unraveling the Mystery of the JavaScript forEach() Function

Exploring the use of nodejs in Ubuntu and delving into the MDN documentation for the JavaScript forEach() method. While aware of alternative methods, I find that hands-on learning suits me best; my current goal is to create a unique array named copy, conta ...

Issue with parsing JSON values in a Chrome extension

Struggling to retrieve the value of a JSON key, but it keeps returning empty. Check out the code snippet below: let json_=JSON.parse(JSON.stringify(result)); console.log(json_); console.log(json ...

implement some level of control within the ngFor directive in Angular

For instance, let's say I have an ngfor loop: <ng-container *ngFor="let setting of settings | trackBy: trackById"> <button mat-button [matMenuTriggerFor]="menu">Menu</button> <mat-me ...

What is preventing bots and crawlers from detecting Next.js meta tags?

I'm currently using Next.js with Typescript and MongoDB to retrieve data. I'm encountering difficulties in rendering the page because the crawler is unable to detect the meta tags. For instance, Bing Search Engine claims that Title and Meta desc ...

Utilize HighCharts to seamlessly implement multiple series with the help of AJAX requests

I am facing an issue with plotting the performance results on HighCharts using AJAX. The problem lies with the .addSeries API call not functioning correctly. I need assistance in determining if my approach is correct. $(function () { $('#chart3&a ...

Proper method of retrieving a property as a designated type within a union type

I have a scenario where I need to return a specific property from a function in various parts of an application. This property can fall into one of two categories, each with string literal properties. One category is an extension of the other. How can I ...

Is verifying email and password with jquery possible?

I am currently working on a jQuery form validation project: While the password and username validation are working fine, I am facing issues with email and password confirmation validations. Surprisingly, I have used the same technique for both. If you wa ...

vm.property compared to this.property

Although it may seem like a simple question, I am in need of some clarification. Currently, I have vuejs running on a single page of my website. The vm app is running in the footer script of the page without utilizing an app.js file or templates/components ...

I am eager to design a form input field within the vuetify framework

https://i.sstatic.net/zbCfI.png I'm having trouble creating a text field in Vuetify where the button and height are not behaving as expected. I've attempted to adjust the height multiple times without success. Although I have the necessary CSS, ...

Transform the JSON object into a different JSON format

I am in the process of restructuring the JSON data which is currently organized by categories, with each category containing multiple locations. Each location consists of latitude/longitude coordinates and an area code: { "cat1":[ {"location":{ ...

Which is more efficient: Storing the database as a private member variable in Ionic 3 SQLite or creating a new database for every query

Here's a question for you - in the context of Ionic 3, what would be the preferable approach: keeping the opened database as a private member variable within a database provider class, or calling create every time a query is made to the database? For ...