Refactor File Download Logic and Streamline Test Suite (#9281)
Closes #9277 ## Summary of Changes - Updated the file-download functionality to use the `saveAs` method from the `file-saver` library, ensuring a more reliable and consistent implementation. - Removed redundant tests to streamline the test suite and reduce maintenance overhead. ## Testing Performed - [x] Verified that exporting the view to a CSV file works as expected.
This commit is contained in:
@ -1,3 +1,4 @@
|
|||||||
|
import { saveAs } from 'file-saver';
|
||||||
import { getFileAbsoluteURI } from '~/utils/file/getFileAbsoluteURI';
|
import { getFileAbsoluteURI } from '~/utils/file/getFileAbsoluteURI';
|
||||||
|
|
||||||
export const downloadFile = (fullPath: string, fileName: string) => {
|
export const downloadFile = (fullPath: string, fileName: string) => {
|
||||||
@ -8,13 +9,6 @@ export const downloadFile = (fullPath: string, fileName: string) => {
|
|||||||
: Promise.reject('Failed downloading file'),
|
: Promise.reject('Failed downloading file'),
|
||||||
)
|
)
|
||||||
.then((blob) => {
|
.then((blob) => {
|
||||||
const url = window.URL.createObjectURL(blob);
|
saveAs(blob, fileName);
|
||||||
const a = document.createElement('a');
|
|
||||||
a.style.display = 'none';
|
|
||||||
a.href = url;
|
|
||||||
a.download = fileName;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
window.URL.revokeObjectURL(url);
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,32 +2,10 @@ import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'
|
|||||||
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
|
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
|
||||||
|
|
||||||
import { RelationDefinitionType } from '~/generated-metadata/graphql';
|
import { RelationDefinitionType } from '~/generated-metadata/graphql';
|
||||||
import {
|
import { displayedExportProgress, generateCsv } from '../useExportRecords';
|
||||||
csvDownloader,
|
|
||||||
displayedExportProgress,
|
|
||||||
download,
|
|
||||||
generateCsv,
|
|
||||||
} from '../useExportRecords';
|
|
||||||
|
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
|
|
||||||
describe('download', () => {
|
|
||||||
it('creates a download link and clicks it', () => {
|
|
||||||
const link = document.createElement('a');
|
|
||||||
document.createElement = jest.fn().mockReturnValue(link);
|
|
||||||
const appendChild = jest.spyOn(document.body, 'appendChild');
|
|
||||||
const click = jest.spyOn(link, 'click');
|
|
||||||
|
|
||||||
URL.createObjectURL = jest.fn().mockReturnValue('fake-url');
|
|
||||||
download(new Blob(['test'], { type: 'text/plain' }), 'test.txt');
|
|
||||||
|
|
||||||
expect(appendChild).toHaveBeenCalledWith(link);
|
|
||||||
expect(link.href).toEqual('http://localhost/fake-url');
|
|
||||||
expect(link.getAttribute('download')).toEqual('test.txt');
|
|
||||||
expect(click).toHaveBeenCalledTimes(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('generateCsv', () => {
|
describe('generateCsv', () => {
|
||||||
it('generates a csv with formatted headers', async () => {
|
it('generates a csv with formatted headers', async () => {
|
||||||
const columns = [
|
const columns = [
|
||||||
@ -58,32 +36,6 @@ describe('generateCsv', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('csvDownloader', () => {
|
|
||||||
it('downloads a csv', () => {
|
|
||||||
const filename = 'test.csv';
|
|
||||||
const data = {
|
|
||||||
rows: [
|
|
||||||
{ id: 1, name: 'John' },
|
|
||||||
{ id: 2, name: 'Alice' },
|
|
||||||
],
|
|
||||||
columns: [],
|
|
||||||
objectNameSingular: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
const link = document.createElement('a');
|
|
||||||
document.createElement = jest.fn().mockReturnValue(link);
|
|
||||||
const createObjectURL = jest.spyOn(URL, 'createObjectURL');
|
|
||||||
|
|
||||||
csvDownloader(filename, data);
|
|
||||||
|
|
||||||
expect(link.getAttribute('download')).toEqual('test.csv');
|
|
||||||
expect(createObjectURL).toHaveBeenCalledWith(expect.any(Blob));
|
|
||||||
expect(createObjectURL).toHaveBeenCalledWith(
|
|
||||||
expect.objectContaining({ type: 'text/csv' }),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('displayedExportProgress', () => {
|
describe('displayedExportProgress', () => {
|
||||||
it.each([
|
it.each([
|
||||||
[undefined, undefined, 'percentage', 'Export'],
|
[undefined, undefined, 'percentage', 'Export'],
|
||||||
|
|||||||
@ -10,21 +10,12 @@ import {
|
|||||||
} from '@/object-record/record-index/export/hooks/useExportFetchRecords';
|
} from '@/object-record/record-index/export/hooks/useExportFetchRecords';
|
||||||
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
|
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
|
||||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||||
|
import { saveAs } from 'file-saver';
|
||||||
import { RelationDefinitionType } from '~/generated-metadata/graphql';
|
import { RelationDefinitionType } from '~/generated-metadata/graphql';
|
||||||
import { FieldMetadataType } from '~/generated/graphql';
|
import { FieldMetadataType } from '~/generated/graphql';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isDefined } from '~/utils/isDefined';
|
||||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||||
|
|
||||||
export const download = (blob: Blob, filename: string) => {
|
|
||||||
const url = URL.createObjectURL(blob);
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.href = url;
|
|
||||||
link.setAttribute('download', filename);
|
|
||||||
document.body.appendChild(link);
|
|
||||||
link.click();
|
|
||||||
link.parentNode?.removeChild(link);
|
|
||||||
};
|
|
||||||
|
|
||||||
type GenerateExportOptions = {
|
type GenerateExportOptions = {
|
||||||
columns: ColumnDefinition<FieldMetadata>[];
|
columns: ColumnDefinition<FieldMetadata>[];
|
||||||
rows: object[];
|
rows: object[];
|
||||||
@ -128,7 +119,7 @@ export const displayedExportProgress = (progress?: ExportProgress): string => {
|
|||||||
const downloader = (mimeType: string, generator: GenerateExport) => {
|
const downloader = (mimeType: string, generator: GenerateExport) => {
|
||||||
return (filename: string, data: GenerateExportOptions) => {
|
return (filename: string, data: GenerateExportOptions) => {
|
||||||
const blob = new Blob([generator(data)], { type: mimeType });
|
const blob = new Blob([generator(data)], { type: mimeType });
|
||||||
download(blob, filename);
|
saveAs(blob, filename);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user