Skip to content

Commit

Permalink
[ImageLoader] Simplify getSize implementation, call failure callback …
Browse files Browse the repository at this point in the history
…when decoding fails
  • Loading branch information
lkinasiewicz committed Dec 30, 2024
1 parent a5ba27c commit 04e3092
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import ImageLoader from '../index';

const testImage =
'data:image/webp;base64,UklGRkYAAABXRUJQVlA4IDoAAADwAgCdASoXABMAPi0QhkKhoQ36AAwBYllAHYAAajokAAD+/SFF//G83mta3//9QZ/5Bn/kGfp4AAAA';
const testImageWidth = 23;
const testImageHeight = 19;

const DefaultImage = window.Image;

describe('ImageLoader', () => {
afterEach(() => {
window.Image = DefaultImage;
});

test('Success callback is called when image loads', async () => {
window.Image = MockImage;
const successCallback = jest.fn();
const failureCallback = jest.fn();
ImageLoader.getSize(testImage, successCallback, failureCallback);
await jest.runAllTimers();
expect(failureCallback).toHaveBeenCalledTimes(0);
expect(successCallback).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledWith(
testImageWidth,
testImageHeight
);
});

test('Failure callback is called when image fails to load', async () => {
window.Image = NotLoadingMockImage;
const successCallback = jest.fn();
const failureCallback = jest.fn();
ImageLoader.getSize(testImage, successCallback, failureCallback);
await jest.runAllTimers();
expect(failureCallback).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledTimes(0);
});

test('Failure callback is called when image fails to decode', async () => {
window.Image = NotDecodingMockImage;
const successCallback = jest.fn();
const failureCallback = jest.fn();
ImageLoader.getSize(testImage, successCallback, failureCallback);
await jest.runAllTimers();
expect(failureCallback).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledTimes(0);
});
});

class MockImage {
constructor(width = 0, height = 0) {
this.width = width;
this.height = height;
this.naturalWidth = 0;
this.naturalHeight = 0;
this._src = '';
}
get src() {
return this._src;
}
set src(uri) {
this._src = uri;
window.setTimeout(this.onload, 0);
}
decode() {
this.naturalWidth = testImageWidth;
this.naturalHeight = testImageHeight;
return Promise.resolve();
}
onerror() {}
onload() {}
}

class NotLoadingMockImage extends MockImage {
set src(uri) {
this._src = uri;
window.setTimeout(this.onerror, 0);
}
}

class NotDecodingMockImage extends MockImage {
decode() {
return Promise.reject();
}
}
12 changes: 2 additions & 10 deletions packages/react-native-web/src/modules/ImageLoader/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,31 +88,23 @@ const ImageLoader = {
success: (width: number, height: number) => void,
failure: () => void
) {
let complete = false;
const interval = setInterval(callback, 16);
const requestId = ImageLoader.load(uri, callback, errorCallback);

function callback() {
const image = requests[`${requestId}`];
if (image) {
const { naturalHeight, naturalWidth } = image;
if (naturalHeight && naturalWidth) {
success(naturalWidth, naturalHeight);
complete = true;
} else {
errorCallback();
}
}
if (complete) {
ImageLoader.abort(requestId);
clearInterval(interval);
}
}

function errorCallback() {
if (typeof failure === 'function') {
failure();
}
ImageLoader.abort(requestId);
clearInterval(interval);
}
},
has(uri: string): boolean {
Expand Down

0 comments on commit 04e3092

Please sign in to comment.