0

I'm currently trying to test some Promise heavy functions in the codebase. This snippet also has the added joy of an event listener as well.

How would I go about testing this?

const createImage = url =>
  new Promise((resolve, reject) => {
    const image = new Image();
    image.addEventListener("load", () => resolve(image));
    image.addEventListener("error", error => reject(error));
    image.setAttribute("crossOrigin", "anonymous"); // needed to avoid cross-origin issues on CodeSandbox
    image.src = url;
  });

export default createImage;
skyboyer
  • 22,209
  • 7
  • 57
  • 64
Daniel Cross
  • 51
  • 13
  • Does this answer your question? [Best Way to Test Promises in Jest](https://stackoverflow.com/questions/43037566/best-way-to-test-promises-in-jest) – ggorlen Jan 02 '20 at 19:34

2 Answers2

1

I got a solution to this issue via Reddit, here's the answer for those interested:

It's not about testing Promises, it's about testing Image load operation. Jest uses JSDOm, and we can look into its implementation for HTMLImage. Unfortunately there is no code to trigger events like load or error.

So we cannot mock request(say using Nock to respond with 500 for particular URL) and validate Promise is rejected(which would be the best). Instead we have to rely on implementation details and inject into Image.prototype:

let onLoadFn, onErrorFn;
Image.prototype.addEventListener = jest.fn((type, fn) => { 
  if (type === 'load') onLoadFn = fn;
  if (type === 'error') onErrorFn = fn;
});

and later either

const result = yourFunction('someurl');
onLoadFn();
return expect(result).resolves.toEqual(expect.any(Image));

or

const result = yourFunction('someurl');
onErrorFn("test");
return expect(result).rejects.toEqual("test");
Also it looks like a known thing in JSDOm that events are not dispatched at least for load/error
Daniel Cross
  • 51
  • 13
-1

You can do it with the following. This checks if the resolved Promise was not an Error, if it was successfully Created.

describe('Create Image', () => {
  it('Creates Image.', async () => {
    const result = await createImage('some image url here');
    const isError = result instaceOf Error;
    expect(isError).toEqual(false);
  });
});
Ayushya
  • 1,862
  • 1
  • 10
  • 15
  • Thanks for the reply! So I get a few issues with this. First of all, there's an issue with the `instanceOf`part, it's not recognised. Even if I use `result.toBeInstanceOf(Error)`. The other issue is I get: ```Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.``` Whenever I use async/await. Any ideas? – Daniel Cross Jan 02 '20 at 19:35