Skip to content

Commit

Permalink
feat: improve error message when downloading message
Browse files Browse the repository at this point in the history
  • Loading branch information
EmmanuelDemey committed Jul 12, 2024
1 parent c5fdf13 commit 0872ecd
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 19 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"@testing-library/jest-dom": "^6.4.6",
"@testing-library/react": "^16.0.0",
"@testing-library/user-event": "^14.5.2",
"@types/file-saver": "^2.0.7",
"@types/jest": "^29.5.12",
"@typescript-eslint/parser": "^7.15.0",
"babel-jest": "^29.7.0",
Expand Down
19 changes: 0 additions & 19 deletions src/js/new-architecture/utils/files.js

This file was deleted.

49 changes: 49 additions & 0 deletions src/js/new-architecture/utils/files.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { saveFileFromHttpResponse } from './files';
import FileSaver from 'file-saver';

jest.mock('file-saver', () => ({
saveAs: jest.fn(),
}));

describe('saveFileFromHttpResponse', () => {
beforeEach(() => {
jest.spyOn(console, 'error').mockImplementation(() => {});
});

it('should reject if Content-Disposition header is missing', async () => {
const response = new Response(null, {
headers: new Headers({}),
});

await expect(saveFileFromHttpResponse(response)).rejects.toBeUndefined();
expect(console.error).toHaveBeenCalledWith(
'Unable to download the File due to a missing Content-Disposition header'
);
});

it('should reject if Content-Disposition header is invalid', async () => {
const response = new Response(null, {
headers: new Headers({
'Content-Disposition': 'invalid-header',
}),
});

await expect(saveFileFromHttpResponse(response)).rejects.toBeUndefined();
expect(console.error).toHaveBeenCalledWith(
'Unable to parse the Content-Disposition header'
);
});

it('should save file with correct file name from Content-Disposition header', async () => {
const blob = new Blob(['test content'], { type: 'text/plain' });
const response = new Response(blob, {
headers: new Headers({
'Content-Disposition': 'attachment; filename="testfile.txt"',
}),
});

await saveFileFromHttpResponse(response);

expect(FileSaver.saveAs).toHaveBeenCalledWith(blob, 'testfile.txt');
});
});
26 changes: 26 additions & 0 deletions src/js/new-architecture/utils/files.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import FileSaver from 'file-saver';

const CONTENT_DISPOSITION_FILENAME_REGEXP =
/filename[^;\n=]*="((['"]).*?\2|[^;\n]*)"/;

export const saveFileFromHttpResponse = (response: Response) => {
const contentDisposition = response.headers.get('Content-Disposition');

if (contentDisposition === null) {
console.error(
'Unable to download the File due to a missing Content-Disposition header'
);
return Promise.reject();
}

const matches = contentDisposition.match(CONTENT_DISPOSITION_FILENAME_REGEXP);

if (matches === null) {
console.error('Unable to parse the Content-Disposition header');
return Promise.reject();
}

const fileName = matches[1];

return response.blob().then((blob) => FileSaver.saveAs(blob, fileName));
};
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2363,6 +2363,11 @@
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==

"@types/file-saver@^2.0.7":
version "2.0.7"
resolved "https://registry.yarnpkg.com/@types/file-saver/-/file-saver-2.0.7.tgz#8dbb2f24bdc7486c54aa854eb414940bbd056f7d"
integrity sha512-dNKVfHd/jk0SkR/exKGj2ggkB45MAkzvWCaqLUUgkyjITkGNzH8H+yUwr+BLJUBjZOe9w8X3wgmXhZDRg1ED6A==

"@types/glob@^7.1.1":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb"
Expand Down

0 comments on commit 0872ecd

Please sign in to comment.