Skip to content

Commit

Permalink
fix: added more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelOsborne committed Feb 20, 2024
1 parent dc66fd4 commit 98d067b
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 76 deletions.
22 changes: 12 additions & 10 deletions packages/dotlottie-js/src/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ export const MIME_TYPES: MimeTypes = {
gif: 'image/gif',
bmp: 'image/bmp',
svg: 'image/svg+xml',
svgxml: 'image/svg+xml',
webp: 'image/webp',
mpeg: 'audio/mpeg',
mp3: 'audio/mp3',
};

Expand All @@ -38,10 +38,12 @@ export const MIME_CODES: MimeCodes = {
png: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a],
gif: [0x47, 0x49, 0x46],
bmp: [0x42, 0x4d],
webp: [0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50],
svg: [0x3c, 0x3f, 0x78],
webp: [0x52, 0x49, 0x46, 0x46, 0x3f, 0x3f, 0x3f, 0x3f, 0x57, 0x45, 0x42, 0x50],
// This covers <svg..
svg: [0x3c, 0x73, 0x76, 0x67],
// This covers <?xml..
svgxml: [0x3c, 0x3f, 0x78, 0x6d, 0x6c],
mp3: [0x49, 0x44, 0x33],
mpeg: [0x66, 0x74, 0x79, 0x70, 0x4d, 0x53, 0x4e, 0x56],
};

export interface MimeToExtension {
Expand Down Expand Up @@ -156,7 +158,7 @@ export const getMimeTypeFromBase64 = (base64: string): string | undefined => {

if (!base64) {
throw new DotLottieError(
'Failed to determine the MIME type from the base64 asset string. Please check the input data. Supported asset types for dotlottie-js are: jpeg, png, gif, bmp, svg, webp, mp3, mpeg',
'Failed to determine the MIME type from the base64 asset string. Please check the input data. Supported asset types for dotlottie-js are: jpeg, png, gif, bmp, svg, webp, mp3',
ErrorCodes.INVALID_DOTLOTTIE,
);
}
Expand All @@ -179,12 +181,12 @@ export const getMimeTypeFromBase64 = (base64: string): string | undefined => {
const dataArr = MIME_CODES[mimeType];

if (mimeType === 'webp' && dataArr && bufData.length > dataArr.length) {
const riff = Array.from(bufData.subarray(0, 4));
const webpCheck = Array.from(bufData.subarray(8, 12));
const riffHeader = Array.from(bufData.subarray(0, 4));
const webpFormatMarker = Array.from(bufData.subarray(8, 12));

if (
riff.every((byte, index) => byte === dataArr[index]) &&
webpCheck.every((byte, index) => byte === dataArr[index + 8])
riffHeader.every((byte, index) => byte === dataArr[index]) &&
webpFormatMarker.every((byte, index) => byte === dataArr[index + 8])
) {
return MIME_TYPES[mimeType];
}
Expand All @@ -198,7 +200,7 @@ export const getMimeTypeFromBase64 = (base64: string): string | undefined => {
}

throw new DotLottieError(
'Failed to determine the MIME type from the base64 asset string. Please check the input data. Supported asset types for dotlottie-js are: jpeg, png, gif, bmp, svg, webp, mp3, mpeg',
'Failed to determine the MIME type from the base64 asset string. Please check the input data. Supported asset types for dotlottie-js are: jpeg, png, gif, bmp, svg, webp, mp3',
ErrorCodes.INVALID_DOTLOTTIE,
);
};
Expand Down
7 changes: 4 additions & 3 deletions packages/dotlottie-js/src/dotlottie.ts
Original file line number Diff line number Diff line change
Expand Up @@ -358,9 +358,10 @@ export class DotLottie extends DotLottieCommon {
}
}
}
} catch (err: any) {
// throw error as it's invalid json
throw new DotLottieError(`Invalid manifest inside buffer! ${err.message}`);
} catch (err) {
if (err instanceof Error) {
throw new DotLottieError(`Invalid manifest inside buffer! ${err.message}`);
}
}
} else {
// throw error as it's invalid buffer
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Binary file not shown.
Binary file not shown.
2 changes: 1 addition & 1 deletion packages/dotlottie-js/src/tests/lottie-audio-node.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import type { Animation as AnimationType } from '@lottiefiles/lottie-types';

import { DotLottie, LottieAudio, isAudioAsset } from '..';
import { DotLottie, LottieAudio, getMimeTypeFromBase64, isAudioAsset } from '..';

// eslint-disable-next-line @lottiefiles/import-filename-format
import AUDIO_ANIMATION_1_DATA from './__fixtures__/audio/instruments_1.json';
Expand Down
72 changes: 41 additions & 31 deletions packages/dotlottie-js/src/tests/lottie-image-browser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import type { Animation as AnimationType } from '@lottiefiles/lottie-types';

import { DotLottie, LottieImage } from '..';
import { DotLottie, LottieImage, getMimeTypeFromBase64 } from '..';

import BULL_DATA from './__fixtures__/image-asset-optimization/bull.json';
import IMAGE_ANIMATION_1_DATA from './__fixtures__/image-asset-optimization/image-animation-layer-1.json';
Expand All @@ -14,9 +14,9 @@ import IMAGE_ANIMATION_3_DATA from './__fixtures__/image-asset-optimization/imag
import IMAGE_ANIMATION_2_DATA from './__fixtures__/image-asset-optimization/image-animation-layer-2.json';
import DUPES_DATA from './__fixtures__/image-asset-optimization/lots-of-dupes.json';
import SIMPLE_IMAGE_ANIMATION from './__fixtures__/image-asset-optimization/simple-image-animation.json';
import SVG_IMAGE_DOTLOTTIE from './__fixtures__/simple/svg-image.lottie';
import AUDIO_TEST from './__fixtures__/mimetype-tests/mp-3-test.txt';
import SVG_XML_TEST from './__fixtures__/mimetype-tests/svg-xml-test.txt';
import VIDEO_DOTLOTTIE from './__fixtures__/simple/video-embedded.lottie';
import OPTIMIZED_DOTLOTTIE from './__fixtures__/simple/webp-optimized.lottie';

describe('LottieImage', () => {
it('gets and sets the zipOptions', () => {
Expand Down Expand Up @@ -224,44 +224,54 @@ describe('LottieImage', () => {
});
});

it('Properly detects mimetype of images.', async () => {
let dotlottie = new DotLottie();
it('getMimeTypeFromBase64 Properly detects mimetype of images.', async () => {
const jpegFormat = getMimeTypeFromBase64(
'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAZABkAAD/2wCEABQQEBkSGScXFycyJh8mMi4mJiYmLj41NTU1NT5EQUFBQUFBREREREREREREREREREREREREREREREREREREREQBFRkZIBwgJhgYJjYmICY2RDYrKzZERERCNUJERERERERERERERERERERERERERERERERERERERERERERERERERP/AABEIAAEAAQMBIgACEQEDEQH/xABMAAEBAAAAAAAAAAAAAAAAAAAABQEBAQAAAAAAAAAAAAAAAAAABQYQAQAAAAAAAAAAAAAAAAAAAAARAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/AJQA9Yv/2Q==',
);

dotlottie = await dotlottie.fromArrayBuffer(OPTIMIZED_DOTLOTTIE);
expect(jpegFormat).toEqual('image/jpeg');

const animations = dotlottie.getAnimations();
const pngFormat = getMimeTypeFromBase64(
// eslint-disable-next-line no-secrets/no-secrets
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR42mP4z8AAAAMBAQD3A0FDAAAAAElFTkSuQmCC',
);

if (animations) {
animations.map(async (animation) => {
const anim = await animation[1].toJSON({
inlineAssets: true,
});
expect(pngFormat).toEqual('image/png');

expect(JSON.stringify(anim).includes('image/webp'));
expect(!JSON.stringify(anim).includes('image/png'));
expect(!JSON.stringify(anim).includes('image/jpeg'));
});
}
const gifFormat = getMimeTypeFromBase64('data:image/gif;base64,R0lGODdhAQABAPAAAP8AAAAAACwAAAAAAQABAAACAkQBADs=');

let bullWithSvg = new DotLottie();
expect(gifFormat).toEqual('image/gif');

bullWithSvg = await bullWithSvg.fromArrayBuffer(SVG_IMAGE_DOTLOTTIE);
const bmpFormat = getMimeTypeFromBase64(
'data:image/bmp;base64,Qk06AAAAAAAAADYAAAAoAAAAAQAAAAEAAAABABgAAAAAAAQAAADEDgAAxA4AAAAAAAAAAAAAAgD+AA==',
);

const bullAnimations = bullWithSvg.getAnimations();
expect(bmpFormat).toEqual('image/bmp');

if (bullAnimations) {
bullAnimations.map(async (animation) => {
const anim = await animation[1].toJSON({
inlineAssets: true,
});
const webpFormat = getMimeTypeFromBase64(
// eslint-disable-next-line no-secrets/no-secrets
'data:image/webp;base64,UklGRkAAAABXRUJQVlA4IDQAAADwAQCdASoBAAEAAQAcJaACdLoB+AAETAAA/vW4f/6aR40jxpHxcP/ugT90CfugT/3NoAAA',
);

expect(JSON.stringify(anim).includes('image/webp'));
expect(JSON.stringify(anim).includes('image/svg'));
expect(!JSON.stringify(anim).includes('image/png'));
expect(!JSON.stringify(anim).includes('image/jpeg'));
});
}
expect(webpFormat).toEqual('image/webp');

const svgFormat = getMimeTypeFromBase64(
// eslint-disable-next-line no-secrets/no-secrets
'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxyZWN0IHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InJlZCIvPjwvc3ZnPg==',
);

expect(svgFormat).toEqual('image/svg+xml');

const svgXmlFormat = getMimeTypeFromBase64(SVG_XML_TEST);

expect(svgXmlFormat).toEqual('image/svg+xml');

const mp3Format = getMimeTypeFromBase64(AUDIO_TEST);

expect(mp3Format).toEqual('audio/mp3');
});

it('Throws an error when an unrecognized file mimetype is detected.', async () => {
try {
let videoDotLottie = new DotLottie();

Expand Down
72 changes: 41 additions & 31 deletions packages/dotlottie-js/src/tests/lottie-image-node.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import type { Animation as AnimationType } from '@lottiefiles/lottie-types';

import { DotLottie, LottieImage } from '../node';
import { DotLottie, LottieImage, getMimeTypeFromBase64 } from '../node';

import BULL_DATA from './__fixtures__/image-asset-optimization/bull.json';
import IMAGE_ANIMATION_1_DATA from './__fixtures__/image-asset-optimization/image-animation-layer-1.json';
Expand All @@ -14,9 +14,9 @@ import IMAGE_ANIMATION_3_DATA from './__fixtures__/image-asset-optimization/imag
import IMAGE_ANIMATION_2_DATA from './__fixtures__/image-asset-optimization/image-animation-layer-2.json';
import DUPES_DATA from './__fixtures__/image-asset-optimization/lots-of-dupes.json';
import SIMPLE_IMAGE_ANIMATION from './__fixtures__/image-asset-optimization/simple-image-animation.json';
import SVG_IMAGE_DOTLOTTIE from './__fixtures__/simple/svg-image.lottie';
import AUDIO_TEST from './__fixtures__/mimetype-tests/mp-3-test.txt';
import SVG_XML_TEST from './__fixtures__/mimetype-tests/svg-xml-test.txt';
import VIDEO_DOTLOTTIE from './__fixtures__/simple/video-embedded.lottie';
import OPTIMIZED_DOTLOTTIE from './__fixtures__/simple/webp-optimized.lottie';

describe('LottieImage', () => {
it('gets and sets the zipOptions', () => {
Expand Down Expand Up @@ -223,44 +223,54 @@ describe('LottieImage', () => {
});
});

it('Properly detects mimetype of images.', async () => {
let dotlottie = new DotLottie();
it('getMimeTypeFromBase64 Properly detects mimetype of images.', async () => {
const jpegFormat = getMimeTypeFromBase64(
'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAZABkAAD/2wCEABQQEBkSGScXFycyJh8mMi4mJiYmLj41NTU1NT5EQUFBQUFBREREREREREREREREREREREREREREREREREREREQBFRkZIBwgJhgYJjYmICY2RDYrKzZERERCNUJERERERERERERERERERERERERERERERERERERERERERERERERERP/AABEIAAEAAQMBIgACEQEDEQH/xABMAAEBAAAAAAAAAAAAAAAAAAAABQEBAQAAAAAAAAAAAAAAAAAABQYQAQAAAAAAAAAAAAAAAAAAAAARAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhEDEQA/AJQA9Yv/2Q==',
);

dotlottie = await dotlottie.fromArrayBuffer(OPTIMIZED_DOTLOTTIE);
expect(jpegFormat).toEqual('image/jpeg');

const animations = dotlottie.getAnimations();
const pngFormat = getMimeTypeFromBase64(
// eslint-disable-next-line no-secrets/no-secrets
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVR42mP4z8AAAAMBAQD3A0FDAAAAAElFTkSuQmCC',
);

if (animations) {
animations.map(async (animation) => {
const anim = await animation[1].toJSON({
inlineAssets: true,
});
expect(pngFormat).toEqual('image/png');

expect(JSON.stringify(anim).includes('image/webp'));
expect(!JSON.stringify(anim).includes('image/png'));
expect(!JSON.stringify(anim).includes('image/jpeg'));
});
}
const gifFormat = getMimeTypeFromBase64('data:image/gif;base64,R0lGODdhAQABAPAAAP8AAAAAACwAAAAAAQABAAACAkQBADs=');

let bullWithSvg = new DotLottie();
expect(gifFormat).toEqual('image/gif');

bullWithSvg = await bullWithSvg.fromArrayBuffer(SVG_IMAGE_DOTLOTTIE);
const bmpFormat = getMimeTypeFromBase64(
'data:image/bmp;base64,Qk06AAAAAAAAADYAAAAoAAAAAQAAAAEAAAABABgAAAAAAAQAAADEDgAAxA4AAAAAAAAAAAAAAgD+AA==',
);

const bullAnimations = bullWithSvg.getAnimations();
expect(bmpFormat).toEqual('image/bmp');

if (bullAnimations) {
bullAnimations.map(async (animation) => {
const anim = await animation[1].toJSON({
inlineAssets: true,
});
const webpFormat = getMimeTypeFromBase64(
// eslint-disable-next-line no-secrets/no-secrets
'data:image/webp;base64,UklGRkAAAABXRUJQVlA4IDQAAADwAQCdASoBAAEAAQAcJaACdLoB+AAETAAA/vW4f/6aR40jxpHxcP/ugT90CfugT/3NoAAA',
);

expect(JSON.stringify(anim).includes('image/webp'));
expect(JSON.stringify(anim).includes('image/svg'));
expect(!JSON.stringify(anim).includes('image/png'));
expect(!JSON.stringify(anim).includes('image/jpeg'));
});
}
expect(webpFormat).toEqual('image/webp');

const svgFormat = getMimeTypeFromBase64(
// eslint-disable-next-line no-secrets/no-secrets
'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxyZWN0IHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InJlZCIvPjwvc3ZnPg==',
);

expect(svgFormat).toEqual('image/svg+xml');

const svgXmlFormat = getMimeTypeFromBase64(SVG_XML_TEST);

expect(svgXmlFormat).toEqual('image/svg+xml');

const mp3Format = getMimeTypeFromBase64(AUDIO_TEST);

expect(mp3Format).toEqual('audio/mp3');
});

it('Throws an error when an unrecognized file mimetype is detected.', async () => {
try {
let videoDotLottie = new DotLottie();

Expand Down

0 comments on commit 98d067b

Please sign in to comment.