Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test img.onload using Jest?

I'm stuck with img.onload event testing. I know that this is an async operation and it should be maybe mocked, but I still couldn't figure out how to solve the problem. I've also seen a couple of similar cases, but they are different from this one.

Previously visited:

  • How do you use Jest to test img.onerror
  • How to test asnyc code with Jest ( or test "image.onload" with jsdom )
  • How do I test `image.onload` using jest in the context of redux actions (or other callbacks assigned in the action)

Code to test:

  function funcToTest(img, callback) {
    const img = new Image()
    img.src = img

    img.onload = () => {
      callback(true) // should return callback with true on finish
    }

    img.onerror = (e) => {
      callback(false) // should return callback with false on error
      console.log(e) 
    }
  }

  funcToTest()

Testing environment:

describe('tet it', () => {
  it('test', done => {
    const callback = status => {
      expect(status).toEqual(true) // but nothing happen
      done()
    }

    funcToTest('some_image', callback)
  })
})

Also I get an error on the finish:

    Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.
        > 2 |   it('test', done => {...

Thanks in advance!

like image 854
Max Travis Avatar asked Jul 18 '19 10:07

Max Travis


Video Answer


1 Answers

While this was answered, I disagree with the purpose of the solution.

We shouldn't write tests to pass coverage, we should write tests that prove a point, and ensure pieces of code behave as expected.

The way to test it is to mock the Image constructor and replace it with something that will invoke the onload function.

describe('tet it', () => {

  it('test', done => {
    global.Image = class {
      constructor() {
        setTimeout(() => {
          this.onload(); // simulate success
        }, 100);
      }
    }

    const callback = status => {
      done()
    }

    funcToTest('some_image', callback)
  })
})

The method just assumes that the 'browser' will download the image within 100 ms, you can tweak the code for failure, or move parts of it to beforeEach if you need to share this behavior between tests.

like image 103
Patrick Avatar answered Sep 30 '22 08:09

Patrick