0

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)

2 Answers2

1

This is happening because you don't return axios.get().then(), so downloadPDFFile() returns undefined and await has no effect, leading to expect(urlCreateObjectSpy).toHaveBeenCalledWith("blob"); being called before anchor.href = URL.createObjectURL(response.data);

Just update this line to add return

  return axios.get(formattedUrl, config).then((response) => {

Alternatively, you can make the function asynchronous

const downloadPDFFile = async (urlTemplate, name, readToken, isWatermarked) => {

and then use the await syntax

  const response = await axios.get(formattedUrl, config);
  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);
  }
Samathingamajig
  • 11,839
  • 3
  • 12
  • 34
0

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.

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 02 '22 at 06:28