Jest Expected and receive are identical

Viewed 209

Is there a reason why Jest would see this as a not identical when both seem exactly the same?

So here is the code I am using to do the test, it's basically just a function that calls for an event emiter, in the event emiter if the date is invalid, I let it as is :

  const datepickerComponent: Datepicker = new Datepicker();

  const mockEvent = {
    target: {
      classList: {
        remove: jest.fn(),
        add: jest.fn(),
      },
      value: '01-01-197',
    },
  } as unknown as InputEvent;

  datepickerComponent.onInput(mockEvent);

  const emitMock: jest.Mock = jest.fn();
  datepickerComponent.dsdDatepickerInputChange = { emit: emitMock } as unknown as EventEmitter<dsdDatepickerInputChangeEvent>;

  // when
  datepickerComponent.onInput(mockEvent);

  const dateValue = new Date('197-01-01T00:00:00');

  // then
  expect(emitMock).toHaveBeenCalledWith({ value: '197-01-01', valueAsDate: dateValue });

enter image description here

2 Answers

The reason why you are observing this error is because whilst Date { NaN } values look the same, they actually refer to different object instances and cannot be traversed for equality any further, hence the actual error should be the following:

Expected: {"value": "197-01-01", "valueAsDate": Date { NaN }}
Received: serializes to the same string

(To reproduce this error - create two new dates using new Date('197-01-01T00:00:00') and pass them into .equals())

To get past this error, all you need to do is to simply refactor your .toHaveBeenCalledWith test into the following:

const calledWithArg = emitMock.mock.calls[0][0];
expect(JSON.stringify(calledWithArg)).toEqual(JSON.stringify({ value: '197-01-01', valueAsDate: dateValue }));

The reason why .toHaveBeenCalledWith does not work is because it does not allow us to reshape the argument object before a comparison (in our case we need to stringify it), hence we can alternatively extract the argument that the mock was called with via .mock.calls[0][0], stringify it and then compare it to the stringified version of the expected object.

Reference of valueAsDate is different. But Jest doc affirm it uses .toEqual for comparison. That means it try to deeply compare two new Date. This is a bad idea, you don't control the Date class, and there are probably some moving parts inside.

To loose match a value, you can check this issue: https://stackoverflow.com/a/55569458/7696155

Related