2017-06-09 28 views
1

イメージをロードし、イメージが正常にロードされたかどうかを判断するReactコンポーネントを作成しました。Jestを使ってimg.onerrorをテストするにはどうすればいいですか?

import React from 'react'; 
import PropTypes from 'prop-types'; 
import { LOADING, SUCCESS, ERROR } from '../helpers'; 

class Image extends React.Component { 
    static propTypes = { 
    onError: PropTypes.func, 
    onLoad: PropTypes.func, 
    src: PropTypes.string.isRequired, 
    } 

    static defaultProps = { 
    onError: null, 
    onLoad: null, 
    } 

    constructor(props) { 
    super(props); 
    this.state = { imageStatus: LOADING }; 
    this.initImage(); 
    } 

    componentDidMount() { 
    this.image.onload = this.handleImageLoad; 
    this.image.onerror = this.handleImageError; 
    this.image.src = this.props.src; 
    } 

    initImage() { 
    this.image = document.createElement('img'); 
    this.handleImageLoad = this.handleImageLoad.bind(this); 
    this.handleImageError = this.handleImageError.bind(this); 
    } 

    handleImageLoad(ev) { 
    this.setState({ imageStatus: SUCCESS }); 
    if (this.props.onLoad) this.props.onLoad(ev); 
    } 

    handleImageError(ev) { 
    this.setState({ imageStatus: ERROR }); 
    if (this.props.onError) this.props.onError(ev); 
    } 

    render() { 
    switch (this.state.imageStatus) { 
     case LOADING: 
     return this.renderLoading(); 
     case SUCCESS: 
     return this.renderSuccess(); 
     case ERROR: 
     return this.renderError(); 
     default: 
     throw new Error('unknown value for this.state.imageStatus'); 
    } 
    } 
} 

export default Image; 

私はJest + Enzymeを使用してテストを作成して、イメージが読み込まれないときをテストしようとしています。

it('should call any passed in onError after an image load error',() => { 
    const onError = jest.fn(); 
    mount(<Image {...props} src="crap.junk"} onError={onError} />); 
    expect(onError).toHaveBeenCalled(); 
    }); 

私が何をしていても、Jestは常にイメージを正常にレンダリングする方法を見つけます。 srcをfalseに設定しても、何らかの形でイメージがレンダリングされます。誰もあなたが画像負荷を失敗するように冗談を強制することができる方法を知っていますか?

答えて

0

あなたは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

私はあなたが何かにいると思っていますが、document.createElementを嘲笑する問題があります。 My Image関数は、引数に応じてspanとdivを作成するので、nullを返すとテストがクラッシュします。今私は、すべての属性を追加できるかどうかをテストしています。動いていない。これは私が得た限りです:https://gist.github.com/mrbinky3000/567b532928f456ee74e55ebe959c66ec – mrbinky3000

+1

私はあきらめました。 wrapper.instance()を使い、instance.image.onerror()を直接呼び出すことにしました。私が過度のテストをしていることが私に起こりました。イメージエラーが発生した場合、HTMLImageElementがonerrorを起動することを信頼する必要があります。そうでない場合は、Webブラウザのソースコードに大きなエラーがあります。その確率:無し。だから私は手動でエラーをシミュレートするためにエラーを発生させた。ケースが閉まった。しかし、ありがとう。 – mrbinky3000

0

舞台裏ので、document.createElement('img')new Image()に相当し、我々はあなたがのために行っているものを達成するために(冗談で使用される)jsdom Imageの実装の一部を模擬することができます。

(簡単にするため、私はImageComponentにあなたのコンポーネントに改名しました)

describe('Callbacks',() => { 
    const LOAD_FAILURE_SRC = 'LOAD_FAILURE_SRC'; 
    const LOAD_SUCCESS_SRC = 'LOAD_SUCCESS_SRC'; 

    let originalImageSrcProto; 
    beforeAll(() => { 
    // Keep a copy of the original Image.prototype.src 
    // in order to restore it after these tests are done 
    originalImageSrcProto = Object.getOwnPropertyDescriptor(
     global.Image.prototype, 
     'src' 
    ); 

    // 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()); 
     } 
     }, 
    }); 
    }); 

    afterAll(() => { 
    // Restore the original Image.prototype.src 
    Object.defineProperty(global.Image.prototype, 'src', originalImageSrcProto); 
    }); 

    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} />); 
    }); 
}); 

それはブラウザでも同じような理由onerror/onloadが呼び出されることはありませんが、このjsdom issueで説明されています。すべてのテストに影響を与える別の修正プログラムが同じissue threadで提供されています。

関連する問題