diff --git a/examples/components/Image/ImageExample.js b/examples/components/Image/ImageExample.js
index 75a610fb0..9521759a8 100644
--- a/examples/components/Image/ImageExample.js
+++ b/examples/components/Image/ImageExample.js
@@ -218,7 +218,7 @@ const examples = [
render: function() {
return (
);
diff --git a/src/components/Image/__tests__/index-test.js b/src/components/Image/__tests__/index-test.js
index fec17b07e..cde80b6e5 100644
--- a/src/components/Image/__tests__/index-test.js
+++ b/src/components/Image/__tests__/index-test.js
@@ -34,8 +34,8 @@ suite('components/Image', () => {
test('sets background image when value is an object', () => {
const defaultSource = { uri: 'https://google.com/favicon.ico' };
const image = shallow();
- const backgroundImage = StyleSheet.flatten(image.prop('style')).backgroundImage;
- assert(backgroundImage.indexOf(defaultSource.uri) > -1);
+ const style = StyleSheet.flatten(image.prop('style'));
+ assert(style.backgroundImage.indexOf(defaultSource.uri) > -1);
});
test('sets background image when value is a string', () => {
@@ -45,13 +45,30 @@ suite('components/Image', () => {
const backgroundImage = StyleSheet.flatten(image.prop('style')).backgroundImage;
assert(backgroundImage.indexOf(defaultSource) > -1);
});
+
+ test('sets "height" and "width" styles if missing', () => {
+ const defaultSource = { uri: 'https://google.com/favicon.ico', height: 10, width: 20 };
+ const image = mount();
+ const html = image.html();
+ assert(html.indexOf('height: 10px') > -1);
+ assert(html.indexOf('width: 20px') > -1);
+ });
+
+ test('does not override "height" and "width" styles', () => {
+ const defaultSource = { uri: 'https://google.com/favicon.ico', height: 10, width: 20 };
+ const image = mount();
+ const html = image.html();
+ assert(html.indexOf('height: 20px') > -1);
+ assert(html.indexOf('width: 40px') > -1);
+ });
});
test('prop "onError"', function (done) {
this.timeout(5000);
- mount();
+ const image = mount();
function onError(e) {
- assert.equal(e.nativeEvent.type, 'error');
+ assert.ok(e.nativeEvent.error);
+ image.unmount();
done();
}
});
@@ -63,6 +80,7 @@ suite('components/Image', () => {
assert.equal(e.nativeEvent.type, 'load');
const hasBackgroundImage = (image.html()).indexOf('url("https://google.com/favicon.ico")') > -1;
assert.equal(hasBackgroundImage, true);
+ image.unmount();
done();
}
});
@@ -74,6 +92,7 @@ suite('components/Image', () => {
assert.ok(true);
const hasBackgroundImage = (image.html()).indexOf('url("https://google.com/favicon.ico")') > -1;
assert.equal(hasBackgroundImage, true);
+ image.unmount();
done();
}
});
@@ -121,10 +140,11 @@ suite('components/Image', () => {
test('sets background image when value is an object', (done) => {
const source = { uri: 'https://google.com/favicon.ico' };
- mount();
+ const image = mount();
function onLoad(e) {
const src = e.nativeEvent.target.src;
assert.equal(src, source.uri);
+ image.unmount();
done();
}
});
@@ -132,10 +152,11 @@ suite('components/Image', () => {
test('sets background image when value is a string', (done) => {
// emulate require-ed asset
const source = 'https://google.com/favicon.ico';
- mount();
+ const image = mount();
function onLoad(e) {
const src = e.nativeEvent.target.src;
assert.equal(src, source);
+ image.unmount();
done();
}
});
diff --git a/src/components/Image/index.js b/src/components/Image/index.js
index 85cec69db..a9ab17adf 100644
--- a/src/components/Image/index.js
+++ b/src/components/Image/index.js
@@ -17,11 +17,20 @@ const STATUS_IDLE = 'IDLE';
const ImageSourcePropType = PropTypes.oneOfType([
PropTypes.shape({
- uri: PropTypes.string.isRequired
+ height: PropTypes.number,
+ uri: PropTypes.string.isRequired,
+ width: PropTypes.number
}),
PropTypes.string
]);
+const resolveAssetDimensions = (source) => {
+ if (typeof source === 'object') {
+ const { height, width } = source;
+ return { height, width };
+ }
+};
+
const resolveAssetSource = (source) => {
return ((typeof source === 'object') ? source.uri : source) || null;
};
@@ -93,12 +102,15 @@ class Image extends Component {
} = this.props;
const displayImage = resolveAssetSource(!isLoaded ? defaultSource : source);
+ const imageSizeStyle = resolveAssetDimensions(!isLoaded ? defaultSource : source);
const backgroundImage = displayImage ? `url("${displayImage}")` : null;
- const flatStyle = StyleSheet.flatten(this.props.style);
- const resizeMode = this.props.resizeMode || flatStyle.resizeMode || ImageResizeMode.cover;
+ const originalStyle = StyleSheet.flatten(this.props.style);
+ const resizeMode = this.props.resizeMode || originalStyle.resizeMode || ImageResizeMode.cover;
+
const style = StyleSheet.flatten([
styles.initial,
- flatStyle,
+ imageSizeStyle,
+ originalStyle,
backgroundImage && { backgroundImage },
resizeModeStyles[resizeMode]
]);
@@ -147,14 +159,18 @@ class Image extends Component {
}
}
- _onError = (e) => {
- const { onError } = this.props;
- const event = { nativeEvent: e };
-
+ _onError = () => {
+ const { onError, source } = this.props;
this._destroyImageLoader();
- this._updateImageState(STATUS_ERRORED);
this._onLoadEnd();
- if (onError) { onError(event); }
+ this._updateImageState(STATUS_ERRORED);
+ if (onError) {
+ onError({
+ nativeEvent: {
+ error: `Failed to load resource ${resolveAssetSource(source)} (404)`
+ }
+ });
+ }
}
_onLoad = (e) => {
@@ -189,7 +205,6 @@ class Image extends Component {
const styles = StyleSheet.create({
initial: {
- alignSelf: 'flex-start',
backgroundColor: 'transparent',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',