How do you use Jest to test img.onerror

前端 未结 2 2010
迷失自我
迷失自我 2020-12-11 09:36

I\'ve created a React component that loads an image and determines if the image loaded successfully or not.

import React from \'react\';
import PropTypes fro         


        
相关标签:
2条回答
  • 2020-12-11 09:58

    You could mock document.createElement:

     it('should call any passed in onError after an image load error', () => {
        const img = {}
        global.document.createElement = (type) => type === 'img' ? img : null
        const onError = jest.fn();
        mount(<Image {...props} src="crap.junk"} onError={onError} />);
        img.onload()
        expect(onError).toHaveBeenCalled();
      });
    
    0 讨论(0)
  • 2020-12-11 10:20

    Since behind the scenes, document.createElement('img') is equivalent to new Image(), we can mock part of the jsdom (used by Jest) implementation of Image to achieve what you're going for.

    (For simplicity's sake, I've renamed your component to ImageComponent)

    describe('Callbacks', () => {
      const LOAD_FAILURE_SRC = 'LOAD_FAILURE_SRC';
      const LOAD_SUCCESS_SRC = 'LOAD_SUCCESS_SRC';
    
      beforeAll(() => {
        // Mocking Image.prototype.src to call the onload or onerror
        // callbacks depending on the src passed to it
        Object.defineProperty(global.Image.prototype, 'src', {
          // Define the property setter
          set(src) {
            if (src === LOAD_FAILURE_SRC) {
              // Call with setTimeout to simulate async loading
              setTimeout(() => this.onerror(new Error('mocked error')));
            } else if (src === LOAD_SUCCESS_SRC) {
              setTimeout(() => this.onload());
            }
          },
        });
      });
    
      it('Calls onError when passed bad src', done => {
        const onError = ev => {
          expect(ev).toBeInstanceOf(Error);
    
          // Indicate to Jest that the test has finished
          done();
        };
    
        mount(<ImageComponent onError={onError} src={LOAD_FAILURE_SRC} />);
      });
    });
    

    The reason onerror/onload is never called as it would be in a browser is explained in this jsdom issue. An alternate fix that would affect all your tests is offered up in the same issue thread.

    0 讨论(0)
提交回复
热议问题