Jasmine test confirms that momentJS objects with the same values do not match

In my angular-cli project, I have a set of Jasmine tests that include various assertions. One particular assertion looks like this:

expect(dispatchSpy).toHaveBeenCalledWith({
  type: 'SET_RANGE', payload: { value: 'Weekly', start: moment('2017-04-24'), end: moment() }
});

However, upon running the test, I encounter the following error message:

Expected spy dispatch to have been called with [ Object({ type: 'SET_RANGE', payload: Object({ value: 'Weekly', start: Mon Apr 24 2017 00:00:00 GMT+0100, end: Sat Apr 29 2017 00:00:00 GMT+0100 }) }) ] but actual calls were [ Object({ type: 'SET_RANGE', payload: Object({ value: 'Weekly', start: Mon Apr 24 2017 00:00:00 GMT+0100, end: Sat Apr 29 2017 00:00:00 GMT+0100 }) }) ]

This issue seems to stem from mismatched properties within the momentJS object. In other scenarios, I've resolved similar problems by comparing formatted date values like so:

expect(moment('2017-01-01').format()).toEqual(moment('2017-01-01').format())

Unfortunately, when using ).toHaveBeenCalledWith(, I can't implement the same format() method. Any ideas on how to approach this situation?

Answer №1

To check for partial object equality, you can utilize the jasmine.objectContaining feature. As noted by @Dave Bush, moment objects require manual verification. You can create a custom matcher for this using jasmine custom matcher along with moment().isSame.

Below is an example of a JavaScript test using Jasmine 2:

describe('Moment containing object', function () {   

    beforeEach(function () {
        jasmine.addMatchers({
            toBeEqualMoment: function () {
                return {
                    compare: function (actual, expected) {
                        let result = {};
                        result.pass = actual.isSame(expected);
                        return result;
                    }
                };
            }
        });
    });

    it('is equal to moment containg object', function () {
        let input = {type: 'SET_RANGE', payload: { value: 'Weekly', start: moment('2017-04-24'), end: moment() }};
        let fooSpy = jasmine.createSpy('foo');

        fooSpy(input);

        let joc = jasmine.objectContaining;
        expect(fooSpy).toHaveBeenCalledWith(joc({type: 'SET_RANGE', payload: joc({value: 'Weekly'})}));
        let spyCallParam = fooSpy.calls.mostRecent().args[0];
        expect(spyCallParam.payload.start).toBeEqualMoment(input.payload.start);
        expect(spyCallParam.payload.end).toBeEqualMoment(input.payload.end);
    });

});

View on JSFiddle

For further insights on custom matchers, I recommend reading this article by @boriscoder.

Answer №2

The issue at hand is the comparison of two separate pointers, rather than two distinct values.

My preferred approach in such scenarios involves creating the object before setting expectations...


let date = moment('2017-01-01');
expect(date).toEqual(date);

If you can manipulate the object intended for use with toHaveBeenCalledWith(), adjust the code to compare pointers.

Alternatively, consider accessing the parameter passed using calls.argsFor(index) and comparing it to format() as customary.

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

What is the process for developing an interface adapter using TypeScript?

I need to update the client JSON with my own JSON data Client JSON: interface Cols { displayName: string; } { cols:[ { displayName: 'abc'; } ] } My JSON: interface Cols { label: string; } { cols:[ { label:&a ...

Extracting arrays from JSON in Angular: A step-by-step guide

I am currently working with Angular2 (version 5) and facing an issue. I am able to make an HTTP request and receive JSON data. While I know how to access and use individual values, I am struggling with accessing and extracting the two arrays inside an elem ...

Vue.js is unable to recognize this type when used with TypeScript

In my code snippet, I am trying to set a new value for this.msg but it results in an error saying Type '"asdasd"' is not assignable to type 'Function'. This issue persists both in Visual Studio and during webpack build. It seems like Ty ...

Guide on implementing an enum as a type by attaching it to a class as a static variable

// file1.ts enum Variant { Success = 'success', Error = 'error', } export class Example { static Variant = Variant; } // file2.ts import { Example } from './file1'; type Props = { variant: Example.Variant; // TS2 ...

The server is showing a discrepancy in date comparisons with MomentJS

I am struggling with grouping events by day in my application. While it works correctly in the development environment (Brazil), on the server (USA) the events that occur at the end of the day are being placed at the beginning of the next day. I suspect th ...

Using the Vuex Module Decorator: A guide on accessing the store from a module

Recently, I've been playing around with the vuex module decorator in order to maintain good TypeScript practices in my vuex stores. However, I'm facing issues when trying to access the store without encountering type definition problems. My setu ...

Error: Unable to generate MD5 hash for the file located at 'C:....gradle-bintray-plugin-1.7.3.jar' in Ionic framework

When attempting to use the command ionic cordova run android, an error occurred that prevented the successful execution: The process failed due to inability to create an MD5 hash for a specific file in the specified directory. This issue arose despite suc ...

The error message "HighCharts Sankey + NextJS: TypeError: Unable to access property 'Core/Series/Point.js' of undefined" occurred

I am attempting to display a Sankey chart from HighCharts using the HighCharts React library within a NextJS project. I have followed the steps outlined in HighChart's documentation to integrate the Sankey module, but I encounter an error on the page: ...

Adjust the icon's color after it has been clicked

How can I make the icon change color after it's clicked in Angular 4 with Bootstrap? I have icons displayed in panels using *ngFor loop and currently, when I click on an icon, it changes color in all panels. How do I make it change color only in the s ...

Retrieving text content from a file using React

I've been experiencing difficulties with my fetch function and its usage. Although I can retrieve data from the data state, it is returning a full string instead of an array that I can map. After spending a few hours tinkering with it, I just can&apos ...

Efficient Typescript ambient modules using shorthand notation

Exploring the code snippet from the official module guide, we see: import x, {y} from "hot-new-module"; x(y); This syntax raises a question: why is 'x' not within curly brackets? What does this coding structure signify? ...

Sorting the table in Angular Material is proving to be a challenge

I'm attempting to organize data within an Angular table by utilizing the MatSortModule. Unfortunately, the sorted table is not functioning correctly. Below is the provided code: main.module.ts import { MatTableModule, MatSortModule } from '@ang ...

Creating a specialized Docker image for Angular 9 production deployment

I don't have much experience with frontend development, but I'm currently working on creating a Docker image for an Angular 9 application. Here's what I've tried: ARG NODE_VERSION=12.16.1 # stage - # 1 FROM node:${NODE_VERSION}-buster- ...

Is data binding not functioning properly in Angular 8?

This query has been raised multiple times in the past and I have reviewed all the suggested solutions. However, I am encountering a common issue - how to retrieve data from the parent component to the child component. I'm unsure of where I'm goin ...

Building Components on the Fly with Angular 5

I've been utilizing code similar to this to dynamically generate components within my application. These components need to support dynamic inputs. However, upon attempting to upgrade to Angular 5, I've encountered an issue with ReflectiveInjecto ...

I am developing a JWT authentication and authorization service for my Angular application. However, I am running into issues when trying to implement observables

I have created a user class and required interfaces as outlined below: user.ts import { Role } from '../auth/auth.enum' export interface IUser { _id: string email: string name: IName picture: string role: Role | string userStatus: b ...

Leveraging Array.map within Angular Interpolation

Is it possible to achieve the following in HTML using Angular 2+? {{ object.array.map((o) => o.property ) }} Whenever I try to execute this code, it crashes the Angular application. Do I need to utilize Pipes or any other technique? ...

Effective ways of making mat-toolbar react to Angular modifications

For a while now, I've been struggling to create a simple header for the homepage of my web app using mat-toolbar. However, no matter what I try, I just can't seem to get it to display the way I want. Here's the code I've been working wi ...

Primeng could not locate the material theme

Within my Angular application, I have incorporated the primeng npm package using npm install. Following the instructions provided on the GetStarted page for primeng, it is mentioned that the library includes 32 free themes. However, upon exploring the node ...

I'm having trouble with the @Input() binding in my custom directive and it's not working as intended

Example Link - Creating a Custom Directive import { Directive, ElementRef, Input } from '@angular/core'; @Directive({ selector: '[appCustomDirective]', }) export class CustomDirective { @Input('appCustomDirective') bord ...