2017-02-10 50 views
0

我已經爲我的項目創建了一個組件來幫助加載一些圖片。試圖單元測試我正在與HTML圖像API的一些困難時,該組件對我來說不過工作的偉大:React unit testing,enzyme/mocha testing(or mocking?)html image api

要開始,我的組件使用new Image();語法一些圖像加載,這裏是組件

import React from 'react'; 

require('./progressive-image.scss'); 

export default class ProgressiveImage extends React.Component { 
    constructor(props) { 
    super(props); 
    } 

    componentDidMount() { 
    const small = this.refs['small-img']; 
    const large = this.refs['large-img']; 

    const img = new Image(); 

    img.src = this.props.smallImg; 
    img.onload = function() { 
     small.classList.add('loaded'); 
    }; 

    const imgLarge = new Image(); 

    imgLarge.src = this.props.largeImg; 
    imgLarge.onload = function() { 
     imgLarge.classList.add('loaded'); 
    }; 

    large.appendChild(imgLarge); 
    } 

    componentDidUpdate() { 
    const small = this.refs['small-img']; 
    const large = this.refs['large-img']; 
    const sameImg = large.childNodes[2].src === this.props.largeImg; 

    // if loading same img, do nothing 
    if (!sameImg) { 
     // remove loaded 
     small.classList.remove('loaded'); 

     const img = new Image(); 

     img.src = this.props.smallImg; 
     img.onload = function() { 
     small.classList.add('loaded'); 
     }; 

     // remove old img 
     large.childNodes[2].remove(); 

     const imgLarge = new Image(); 

     imgLarge.src = this.props.largeImg; 
     imgLarge.onload = function() { 
     imgLarge.classList.add('loaded'); 
     }; 

     large.appendChild(imgLarge); 
    } 
    } 

    render() { 
    const imgStyle = { 'paddingBottom': this.props.heightRatio }; 

    return (
     <div className="progressive-placeholder" ref="large-img"> 
      <img className="img-small" ref="small-img" /> 
      <div style={imgStyle} ></div> 
     </div> 
    ); 
    } 
} 

ProgressiveImage.displayName = 'ProgressiveImage'; 

ProgressiveImage.propTypes = { 
    bgColor: React.PropTypes.string, 
    heightRatio: React.PropTypes.string.isRequired, 
    largeImg: React.PropTypes.string.isRequired, 
    smallImg: React.PropTypes.string.isRequired, 
}; 

使用酶mount完全呈現,我做這樣的事情進行單元測試的componentDidMount(並希望在今後的componentdidupdate)。

it('should load images on mount',() => { 
    const instance = mount(
      <FollainProgressiveImage 
      bgColor={bgColor} 
      heightRatio={heightRatio} 
      largeImg={largeImg} 
      smallImg={smallImg} 
      /> 
    ); 
    }); 

但是測試跑步者對我大喊Image is not defined。所以,我想是這樣

it('should load images on mount',() => { 
    global.Image = spy(); 
    const instance = mount(
      <FollainProgressiveImage 
      bgColor={bgColor} 
      heightRatio={heightRatio} 
      largeImg={largeImg} 
      smallImg={smallImg} 
      /> 
    ); 
    }); 

那間諜是sinon.spy,但是這給了我的First argument to Node.prototype.appendChild must be a Node的錯誤,但我可以在覆蓋報告中指出,componentDidMount正在熱播看。

我不知道如何最好的方法來測試這個,我應該完全嘲笑對象,還是有一些更好的方法來做到這一點?

僅供參考 - 我的測試ENV設置如下:

global.document = jsdom.jsdom('<!doctype html><html><body></body></html>'); 
global.window = document.defaultView; 
global.navigator = {userAgent: 'node.js'}; 

也許這需要改變?

真的卡在這裏,尋找任何關於如何測試此代碼的輸入。謝謝!!

回答

2

Image()構造函數是瀏覽器的一部分,因此不在Node.js中。當您在瀏覽器中呼叫new Image()時,它相當於呼叫new window.Image()。使用jsdom您已設置global.window來模擬瀏覽器的window。這意味着您現在可以訪問window.Image。如果您希望在不使用window前綴的情況下使其可用,則可以將其設爲全局,則不需要手動進行間諜或模擬操作。只需添加到您的測試設置:

global.Image = window.Image; 
+0

謝謝你解釋,這解決了問題,你幫我理解爲什麼它不工作! – ajmajmajma