jest.mock('expo-file-system', () => {
const FileSystem = require.requireActual('expo-file-system');
return {
...FileSystem,
bundleDirectory: 'file:///Expo.app/',
cacheDirectory: 'file:///Caches/Expo.app/',
bundledAssets: ['asset_test1.png'],
getInfoAsync: jest.fn(),
downloadAsync: jest.fn(),
};
});
jest.mock('react-native/Libraries/Image/AssetRegistry', () => {
return {
getAssetByID: jest.fn(),
};
});
jest.mock('react-native/Libraries/Image/resolveAssetSource', () => {
return {
default: jest.fn(),
setCustomSourceTransformer: jest.fn(),
};
});
jest.mock('../ImageAssets', () => {
const ImageAssets = require.requireActual('../ImageAssets');
return {
...ImageAssets,
getImageInfoAsync: jest.fn(),
};
});
const mockImageMetadata = {
name: 'test',
type: 'png',
hash: 'cafecafecafecafecafecafecafecafe',
scales: [1],
httpServerLocation: '/assets',
};
afterEach(() => {
jest.resetModules();
});
describe(`source resolution with React Native`, () => {
it(`automatically registers a source resolver`, () => {
require('../index');
const {
setCustomSourceTransformer,
} = require('react-native/Libraries/Image/resolveAssetSource');
expect(setCustomSourceTransformer).toHaveBeenCalledTimes(1);
});
});
it(`creates assets from metadata`, () => {
const { Asset } = require('../index');
let asset = Asset.fromMetadata(mockImageMetadata);
expect(asset.hash).toBe('cafecafecafecafecafecafecafecafe');
});
it(`interns assets by hash`, () => {
const { Asset } = require('../index');
let asset1 = Asset.fromMetadata(mockImageMetadata);
let asset2 = Asset.fromMetadata(mockImageMetadata);
expect(asset1).toBe(asset2);
});
it(`creates assets from URIs`, () => {
const { Asset } = require('../index');
let asset = Asset.fromURI('https://example.com/image.png');
expect(asset.uri).toBe('https://example.com/image.png');
expect(asset.type).toBe('png');
expect(asset.hash).toBeNull();
});
it(`creates assets from data URIs`, () => {
const { Asset } = require('../index');
let asset = Asset.fromURI('data:text/html;base64,dGVzdA%3D%3D');
expect(asset.type).toBe('html');
});
it.skip(`supports non-Base64 data URIs`, () => {
const { Asset } = require('../index');
let asset = Asset.fromURI('data:,test');
expect(asset.type).toBe('txt');
});
it(`interns assets by URI`, () => {
const { Asset } = require('../index');
let uri = 'data:,Hello%2C%20World!';
let asset1 = Asset.fromURI(uri);
let asset2 = Asset.fromURI(uri);
expect(asset1).toBe(asset2);
});
it(`creates assets from virtual modules`, () => {
const { Asset } = require('../index');
const { getAssetByID } = require('react-native/Libraries/Image/AssetRegistry');
getAssetByID.mockReturnValueOnce(mockImageMetadata);
let asset = Asset.fromModule(1);
expect(asset.hash).toBe('cafecafecafecafecafecafecafecafe');
});
it(`throws when creating an asset from a missing module`, () => {
const { Asset } = require('../index');
const { getAssetByID } = require('react-native/Libraries/Image/AssetRegistry');
getAssetByID.mockReturnValueOnce(undefined);
expect(() => Asset.fromModule(2)).toThrowError();
});
it(`downloads uncached assets`, async () => {
const FileSystem = require('expo-file-system');
const { Asset } = require('../index');
let asset = Asset.fromMetadata(mockImageMetadata);
expect(asset.localUri).toBeNull();
FileSystem.getInfoAsync.mockReturnValueOnce({ exists: false });
FileSystem.downloadAsync.mockReturnValueOnce({ md5: mockImageMetadata.hash });
await asset.downloadAsync();
expect(asset.downloading).toBe(false);
expect(asset.downloaded).toBe(true);
expect(asset.localUri).toBe(
'file:///Caches/Expo.app/ExponentAsset-cafecafecafecafecafecafecafecafe.png'
);
});
it(`throws when the file's checksum does not match`, async () => {
const FileSystem = require('expo-file-system');
const { Asset } = require('../index');
let asset = Asset.fromMetadata(mockImageMetadata);
expect(asset.localUri).toBeNull();
FileSystem.getInfoAsync.mockReturnValueOnce({ exists: false });
FileSystem.downloadAsync.mockReturnValueOnce({ md5: 'deadf00ddeadf00ddeadf00ddeadf00d' });
await expect(asset.downloadAsync()).rejects.toThrowError('failed MD5 integrity check');
});
it(`uses the local filesystem's cache directory for downloads`, async () => {
const FileSystem = require('expo-file-system');
const { Asset } = require('../index');
let asset = Asset.fromMetadata(mockImageMetadata);
FileSystem.getInfoAsync.mockReturnValueOnce({
exists: true,
md5: mockImageMetadata.hash,
});
await asset.downloadAsync();
expect(asset.downloaded).toBe(true);
expect(FileSystem.downloadAsync).not.toHaveBeenCalled();
});
it(`coalesces downloads`, async () => {
const FileSystem = require('expo-file-system');
const { Asset } = require('../index');
let asset = Asset.fromMetadata(mockImageMetadata);
FileSystem.getInfoAsync.mockReturnValue({ exists: false });
FileSystem.downloadAsync.mockReturnValue({ md5: mockImageMetadata.hash });
await Promise.all([asset.downloadAsync(), asset.downloadAsync()]);
expect(FileSystem.getInfoAsync).toHaveBeenCalledTimes(1);
expect(FileSystem.downloadAsync).toHaveBeenCalledTimes(1);
});
const { Platform } = require('@unimodules/core');
if (Platform.OS === 'web') {
describe('web', () => {
it(`fetches images to determine the dimensions`, async () => {
const ImageAssets = require('../ImageAssets');
const { Asset } = require('../index');
let asset = Asset.fromMetadata(mockImageMetadata);
ImageAssets.getImageInfoAsync.mockResolvedValueOnce({
width: 120,
height: 180,
name: 'test',
});
await asset.downloadAsync();
expect(asset.width).toBe(120);
expect(asset.height).toBe(180);
expect(asset.downloaded).toBe(true);
expect(asset.localUri).toBe(asset.uri);
});
});
}
describe('embedding', () => {
beforeAll(() => {
jest.doMock('expo-constants', () => {
const Constants = require.requireActual('expo-constants');
return {
...Constants,
appOwnership: 'standalone',
manifest: {},
};
});
// @ts-ignore: the type declaration marks __DEV__ as read-only
__DEV__ = false;
});
afterAll(() => {
jest.dontMock('expo-constants');
// @ts-ignore: the type declaration marks __DEV__ as read-only
__DEV__ = true;
});
it(`considers embedded assets to be downloaded`, () => {
const { Asset } = require('../index');
let asset = Asset.fromMetadata({
...mockImageMetadata,
hash: 'test1',
type: 'png',
});
expect(asset.localUri).toBe('file:///Expo.app/asset_test1.png');
});
});