diff --git a/src/ImageWithZoom/ImageWithZoom.jsx b/src/ImageWithZoom/ImageWithZoom.jsx index 8f8ac7a4..97840820 100644 --- a/src/ImageWithZoom/ImageWithZoom.jsx +++ b/src/ImageWithZoom/ImageWithZoom.jsx @@ -19,6 +19,8 @@ const ImageWithZoom = class ImageWithZoom extends React.Component { imageClassName: PropTypes.string, overlayClassName: PropTypes.string, spinner: PropTypes.func, + onLoad: PropTypes.func, + onError: PropTypes.func, src: PropTypes.string.isRequired, srcZoomed: PropTypes.string, tag: PropTypes.string, @@ -34,6 +36,8 @@ const ImageWithZoom = class ImageWithZoom extends React.Component { overlayClassName: null, isPinchZoomEnabled: true, spinner: null, + onLoad: null, + onError: null, srcZoomed: null, tag: 'div', } @@ -76,9 +80,12 @@ const ImageWithZoom = class ImageWithZoom extends React.Component { // state changes that require a re-render this.state = { - // tracks the status via image element's onload, onerror events. + // tracks the status via image element's onload events. isImageLoading: true, + // tracks the status via image element's onerror events. + isImageLoadingError: true, + // the mouse is currently hovering over the image. isHovering: false, @@ -100,6 +107,7 @@ const ImageWithZoom = class ImageWithZoom extends React.Component { // event handlers this.handleImageComplete = this.handleImageComplete.bind(this); + this.handleImageLoadError = this.handleImageLoadError.bind(this); this.handleOnMouseMove = this.handleOnMouseMove.bind(this); this.handleOnMouseOut = this.handleOnMouseOut.bind(this); this.handleOnMouseOver = this.handleOnMouseOver.bind(this); @@ -121,10 +129,19 @@ const ImageWithZoom = class ImageWithZoom extends React.Component { } } - handleImageComplete() { + handleImageComplete(ev) { + this.setState({ + isImageLoading: false, + }); + if (this.props && this.props.onLoad) this.props.onLoad(ev); + } + + handleImageLoadError(ev) { this.setState({ + isImageLoadingError: true, isImageLoading: false, }); + if (this.props && this.props.onError) this.props.onError(ev); } handleOnMouseOver() { @@ -324,7 +341,7 @@ const ImageWithZoom = class ImageWithZoom extends React.Component { tag={bgImageTag} src={src} onLoad={this.handleImageComplete} - onError={this.handleImageComplete} + onError={this.handleImageLoadError} {...bgImageProps} /> ', () => { expect(instance.renderLoading()).toBe(null); }); }); - describe('handleImageComplete', () => { - it('should set state isImageLoading', () => { + describe('handleImage callback', () => { + it('should set state isImageLoading when function handleImageComplete is called', () => { const instance = new ImageWithZoom(); instance.setState = jest.fn(); instance.handleImageComplete(); @@ -84,6 +84,29 @@ describe('', () => { isImageLoading: false, }); }); + it('should set state isImageLoading, isImageLoadingError when function handleImageLoadError is called', () => { + const instance = new ImageWithZoom(); + instance.setState = jest.fn(); + instance.handleImageLoadError(); + expect(instance.setState).toHaveBeenCalledWith({ + isImageLoading: false, + isImageLoadingError: true, + }); + }); + it('should call onError prop function when function handleImageLoadError is called', () => { + const onError = jest.fn(); + const instance = new ImageWithZoom({ onError }); + instance.setState = jest.fn(); + instance.handleImageLoadError(); + expect(onError).toHaveBeenCalled(); + }); + it('should call onLoad prop function when function handleImageComplete is called', () => { + const onLoad = jest.fn(); + const instance = new ImageWithZoom({ onLoad }); + instance.setState = jest.fn(); + instance.handleImageComplete(); + expect(onLoad).toHaveBeenCalled(); + }); }); }); describe('integration tests', () => { diff --git a/typings/carouselElements.d.ts b/typings/carouselElements.d.ts index 25636084..7a45e83f 100644 --- a/typings/carouselElements.d.ts +++ b/typings/carouselElements.d.ts @@ -57,6 +57,8 @@ interface ImageWithZoomProps { readonly className?: string readonly imageClassName?: string readonly overlayClassName?: string + readonly onError?: () => void + readonly onLoad?: () => void readonly src: string readonly srcZoomed?: string readonly tag?: string