From 9a8bf056f907ad8badc39ec7ce44937101331e65 Mon Sep 17 00:00:00 2001 From: CPatchane Date: Mon, 1 Jul 2019 15:34:33 +0200 Subject: [PATCH] fix: :nail_care: Handle fallback icon in AppIcon --- react/AppIcon/Readme.md | 20 +++++++++++ react/AppIcon/index.jsx | 14 ++++++-- react/AppIcon/test/AppIcon.spec.js | 35 +++++++++++++++++++ .../test/__snapshots__/AppIcon.spec.js.snap | 25 +++++++++++++ 4 files changed, 92 insertions(+), 2 deletions(-) diff --git a/react/AppIcon/Readme.md b/react/AppIcon/Readme.md index 2271809831..e61c9ca3e4 100644 --- a/react/AppIcon/Readme.md +++ b/react/AppIcon/Readme.md @@ -54,3 +54,23 @@ initialState = { fetchIcon: fetchIcon1 }; ## `domain` and `secure` props If the `fetchIcon` is missing, the `` component needs the `domain` prop (litteraly the cozy domain) and the secure prop, to know which protocol use between `http` or `https`. + +### Provide `fallbackIcon` + +You can provide an `` `icon` props to fallback when the AppIcon fetched is broken or the `fetchIcon` function errored. + +```jsx +const fetchIcon = () => 'https://placeholder.pics/svg/100/7DC4FF/Test%20Icon' +const fetchIconBroken = () => 'blahblahblah' + +const brokeFetchIcon = () => setState({ fetchIcon: fetchIconBroken }) + +initialState = { fetchIcon }; + +
+ +
+ +
+
+``` diff --git a/react/AppIcon/index.jsx b/react/AppIcon/index.jsx index ea7f754fcb..5a45194d38 100644 --- a/react/AppIcon/index.jsx +++ b/react/AppIcon/index.jsx @@ -5,6 +5,7 @@ import styles from './styles.styl' import Icon from '../Icon' import palette from '../palette' +import { iconPropType } from '../Icon' import { getPreloaded, preload } from './Preloader' import { AppDoctype } from '../proptypes' @@ -24,6 +25,7 @@ export class AppIcon extends Component { status: preloaded ? DONE : FETCHING } this.isUnmounting = false + this.handleError = this.handleError.bind(this) } componentWillUnmount() { @@ -62,8 +64,13 @@ export class AppIcon extends Component { } } + handleError() { + this.setState({ status: ERRORED }) + } + render() { - const { alt, className } = this.props + const { alt, className, fallbackIcon } = this.props + const { icon, status } = this.state switch (status) { case FETCHING: @@ -82,6 +89,7 @@ export class AppIcon extends Component { alt={alt} className={cx(styles['c-app-icon'], className)} src={icon} + onError={this.handleError} /> ) case ERRORED: @@ -94,7 +102,7 @@ export class AppIcon extends Component { className )} height="100%" - icon="cube" + icon={fallbackIcon || 'cube'} width="100%" color={palette['coolGrey']} /> @@ -107,6 +115,8 @@ AppIcon.propTypes = { alt: PropTypes.string, /** Required if fetchIcon is not provided */ app: PropTypes.oneOfType([AppDoctype, PropTypes.string]), + /** Icon to fallback on error (optional), default cube icon */ + fallbackIcon: iconPropType, /** Custom implementation of how to fetch icon */ fetchIcon: PropTypes.func, className: PropTypes.string, diff --git a/react/AppIcon/test/AppIcon.spec.js b/react/AppIcon/test/AppIcon.spec.js index 99ee04c82c..b0b4b2eadb 100644 --- a/react/AppIcon/test/AppIcon.spec.js +++ b/react/AppIcon/test/AppIcon.spec.js @@ -76,6 +76,41 @@ describe('AppIcon component', () => { ) }) + it(`renders provided fallbackIcon when fetch error occurs`, async done => { + const wrapper = shallow( + { + wrapper.update() + const component = wrapper.getElement() + expect(component).toMatchSnapshot() + expect(failureFetchIcon).toHaveBeenCalledWith(app, undefined, secure) + expect(console.error).toHaveBeenCalledTimes(0) + done() + }} + secure={secure} + fallbackIcon="warning" + /> + ) + }) + + it(`renders provided fallbackIcon on img error`, async done => { + const wrapper = shallow( + 'notagoodurl'} + onReady={() => { + wrapper.simulate('error') + wrapper.update() + const component = wrapper.getElement() + expect(component).toMatchSnapshot() + done() + }} + fallbackIcon="warning" + /> + ) + }) + it(`uses Preloader.preload when no fetchIcon method is provided`, async done => { jest.mock('../Preloader') const AppIcon = require('../').default diff --git a/react/AppIcon/test/__snapshots__/AppIcon.spec.js.snap b/react/AppIcon/test/__snapshots__/AppIcon.spec.js.snap index 2e5f962341..2226a4af63 100644 --- a/react/AppIcon/test/__snapshots__/AppIcon.spec.js.snap +++ b/react/AppIcon/test/__snapshots__/AppIcon.spec.js.snap @@ -9,6 +9,7 @@ exports[`AppIcon component renders as loading 1`] = ` exports[`AppIcon component renders correctly 1`] = ` `; @@ -27,13 +28,37 @@ exports[`AppIcon component renders default when fetch error occurs 1`] = ` exports[`AppIcon component renders immediately when icon is alredy preloaded 1`] = ` `; +exports[`AppIcon component renders provided fallbackIcon on img error 1`] = ` + +`; + +exports[`AppIcon component renders provided fallbackIcon when fetch error occurs 1`] = ` + +`; + exports[`AppIcon component uses Preloader.preload when no fetchIcon method is provided 1`] = ` `;