How to check multiple arguments on multiple calls for jest spies?

I have the following function in a React component:

onUploadStart(file, xhr, formData) {
  formData.append('filename', file.name);
  formData.append('mimeType', file.type);
}

This is my test that at least gets the spy to be called:

const formData = { append: jest.fn() };
const file = { name: 'someFileName', type: 'someMimeType' };
eventHandlers.onUploadStart(file, null, formData);

expect(formData.append).toHaveBeenCalledWith(
  ['mimeType', 'someMimeType'],
  ['fileName', 'someFileName']
);

However, the assertion is not working:

Expected mock function to have been called with:
 [["mimeType", "someMimeType"], ["fileName", "someFileName"]]
But it was called with:
  ["mimeType", "someMimeType"], ["filename", "someFileName"]

What is the right way to use toHaveBeenCalledWith?


Solution 1:

I was able mock multiple calls and check the arguments this way:

expect(mockFn.mock.calls).toEqual([
  [arg1, arg2, ...], // First call
  [arg1, arg2, ...]  // Second call
]);

where mockFn is your mocked function name.

Solution 2:

Since jest 23.0 there is .toHaveBeenNthCalledWith(nthCall, arg1, arg2, ....) https://jestjs.io/docs/expect#tohavebeennthcalledwithnthcall-arg1-arg2-

Also under the alias: .nthCalledWith(nthCall, arg1, arg2, ...)

If you have a mock function, you can use .toHaveBeenNthCalledWith to test what arguments it was nth called with. For example, let's say you have a drinkEach(drink, Array<flavor>) function that applies f to a bunch of flavors, and you want to ensure that when you call it, the first flavor it operates on is 'lemon' and the second one is 'octopus'. You can write:

test('drinkEach drinks each drink', () => {
  const drink = jest.fn();
  drinkEach(drink, ['lemon', 'octopus']);
  expect(drink).toHaveBeenNthCalledWith(1, 'lemon');
  expect(drink).toHaveBeenNthCalledWith(2, 'octopus');
});

Note: the nth argument must be positive integer starting from 1.