javascriptjestjscreateobjecturl

Why is my jest test failing for URL.createObjectURL?


I have two unit tests like so:

test('should call downloadPDFFile with msSaveOrOpenBlob when the navigator is present', async () => {
  axios.get.mockResolvedValueOnce({ data: 'blob' });
  window.navigator.msSaveOrOpenBlob = () => true;
  const msSaveOrOpenBlobSpy = jest.spyOn(window.navigator, 'msSaveOrOpenBlob');
  await downloadPDFFile('www.pokebook/{+asset_path}', 'squirtle', '123', false);
  expect(msSaveOrOpenBlobSpy).toHaveBeenCalledWith('blob', 'squirtle.pdf');
});

test('should call downloadPDFFile with createObjectURL when the navigator is not present', async () => {
  axios.get.mockResolvedValueOnce({ data: 'blob' });
  window.URL.createObjectURL = () => 'www.pokeball.com';
  console.log(window.navigator);
  const urlCreateObjectSpy = jest.spyOn(window.URL, 'createObjectURL');
  await downloadPDFFile('www.pokebook/{+asset_path}', 'charmander', '123', false);
  expect(urlCreateObjectSpy).toHaveBeenCalledWith('blob');
});

And after reading many posts, it seems like window.URL.createObjectURL = () => {}; should work, however, I keep running into this test failure message on the second one:

expect(jest.fn()).toHaveBeenCalledWith(...expected)

    Expected: "blob"

    Number of calls: 0

      557 |             const urlCreateObjectSpy = jest.spyOn(window.URL, 'createObjectURL');
      558 |             await downloadPDFFile('www.pokebook/{+asset_path}', 'charmander', '123', false);
    > 559 |             expect(urlCreateObjectSpy).toHaveBeenCalledWith('blob');
          |                                        ^
      560 |         });
      561 |     });
      562 | });

Here is the function being tested:

const downloadPDFFile = (urlTemplate, name, readToken, isWatermarked) => {
  const config = { responseType: "blob" };
  const pdfFileName = `${name.split(".")[0]}.pdf`;
  let formattedUrl;

  if (isWatermarked) {
    formattedUrl = urlTemplate.replace("{+temp}?", `?token=${readToken}&`);
  } else {
    formattedUrl = urlTemplate.replace("{+temp}", `?token=${readToken}`);
  }

  axios.get(formattedUrl, config).then((response) => {
    if (window.navigator && window.navigator.msSaveOrOpenBlob) {
      window.navigator.msSaveOrOpenBlob(response.data, pdfFileName);
    } else {
      const anchor = document.createElement("a");
      anchor.download = pdfFileName;
      anchor.href = URL.createObjectURL(response.data);
      document.body.appendChild(anchor);
      anchor.click();
      document.body.removeChild(anchor);
    }
  });
};

Am I missing some kind of a cleanup step in between tests? (the console.log in the second test shows that the window.navigator object is actually defined, which I suspect is why I'm getting strange behavior)


Solution

  • It turned out that I was forgetting to do a cleanup step after my previous test; in my first test I set window.navigator.msSaveOrOpenBlob which is what I wanted/expected. But this carried over into the second test which caused unexpected results.