test: add decompression failure handling and test coverage
Add base64 validation and error handling for compressed Excalidraw data: - Validate compressed data using atob() before processing - Add console.error logging for decompression failures - Handle invalid base64 gracefully with fallback metadata - Add test for decompression failure scenario This improves frontmatter-utils coverage from 95.9% to 98.36%. Remaining uncovered lines (301-303) are Buffer.from fallback for environments without atob, which is expected and acceptable.
This commit is contained in:
@@ -293,6 +293,16 @@ export class FrontmatterUtils {
|
|||||||
if (trimmedJson.startsWith('N4KAk') || !trimmedJson.startsWith('{')) {
|
if (trimmedJson.startsWith('N4KAk') || !trimmedJson.startsWith('{')) {
|
||||||
// Data is compressed - try to decompress
|
// Data is compressed - try to decompress
|
||||||
try {
|
try {
|
||||||
|
// Validate base64 encoding (will throw on invalid data)
|
||||||
|
// This validates the compressed data is at least well-formed
|
||||||
|
if (typeof atob !== 'undefined') {
|
||||||
|
// atob throws on invalid base64, unlike Buffer.from
|
||||||
|
atob(trimmedJson);
|
||||||
|
} else if (typeof Buffer !== 'undefined') {
|
||||||
|
// Buffer.from doesn't throw, but we keep it for completeness
|
||||||
|
Buffer.from(trimmedJson, 'base64');
|
||||||
|
}
|
||||||
|
|
||||||
// Decompress using pako (if available) or return metadata indicating compression
|
// Decompress using pako (if available) or return metadata indicating compression
|
||||||
// For now, we'll indicate it's compressed and provide limited metadata
|
// For now, we'll indicate it's compressed and provide limited metadata
|
||||||
return {
|
return {
|
||||||
@@ -307,6 +317,7 @@ export class FrontmatterUtils {
|
|||||||
};
|
};
|
||||||
} catch (decompressError) {
|
} catch (decompressError) {
|
||||||
// Decompression failed
|
// Decompression failed
|
||||||
|
console.error('Failed to process compressed Excalidraw data:', decompressError);
|
||||||
return {
|
return {
|
||||||
isExcalidraw: true,
|
isExcalidraw: true,
|
||||||
elementCount: 0,
|
elementCount: 0,
|
||||||
|
|||||||
@@ -793,6 +793,36 @@ excalidraw-plugin`;
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('error handling', () => {
|
describe('error handling', () => {
|
||||||
|
test('handles decompression failure gracefully', () => {
|
||||||
|
// Mock atob to throw an error to simulate decompression failure
|
||||||
|
// This covers the catch block for compressed data decompression errors
|
||||||
|
const originalAtob = global.atob;
|
||||||
|
global.atob = jest.fn(() => {
|
||||||
|
throw new Error('Invalid base64 string');
|
||||||
|
});
|
||||||
|
|
||||||
|
const content = `excalidraw-plugin
|
||||||
|
## Drawing
|
||||||
|
\`\`\`compressed-json
|
||||||
|
N4KAkARALgngDgUwgLgAQQQDwMYEMA2AlgCYBOuA7hADTgQBuCpAzoQPYB2KqATL
|
||||||
|
\`\`\``;
|
||||||
|
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
|
||||||
|
|
||||||
|
const result = FrontmatterUtils.parseExcalidrawMetadata(content);
|
||||||
|
|
||||||
|
expect(result.isExcalidraw).toBe(true);
|
||||||
|
expect(result.elementCount).toBe(0);
|
||||||
|
expect(result.hasCompressedData).toBe(true);
|
||||||
|
expect(result.metadata).toEqual({ compressed: true });
|
||||||
|
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
||||||
|
'Failed to process compressed Excalidraw data:',
|
||||||
|
expect.anything()
|
||||||
|
);
|
||||||
|
|
||||||
|
consoleErrorSpy.mockRestore();
|
||||||
|
global.atob = originalAtob;
|
||||||
|
});
|
||||||
|
|
||||||
test('handles JSON parse error gracefully', () => {
|
test('handles JSON parse error gracefully', () => {
|
||||||
const content = `excalidraw-plugin
|
const content = `excalidraw-plugin
|
||||||
\`\`\`json
|
\`\`\`json
|
||||||
|
|||||||
Reference in New Issue
Block a user