mirror of
				https://github.com/langgenius/dify.git
				synced 2025-10-31 10:53:02 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			630 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			630 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import mime from 'mime'
 | |
| import { upload } from '@/service/base'
 | |
| import {
 | |
|   downloadFile,
 | |
|   fileIsUploaded,
 | |
|   fileUpload,
 | |
|   getFileAppearanceType,
 | |
|   getFileExtension,
 | |
|   getFileNameFromUrl,
 | |
|   getFilesInLogs,
 | |
|   getProcessedFiles,
 | |
|   getProcessedFilesFromResponse,
 | |
|   getSupportFileExtensionList,
 | |
|   getSupportFileType,
 | |
|   isAllowedFileExtension,
 | |
| } from './utils'
 | |
| import { FileAppearanceTypeEnum } from './types'
 | |
| import { SupportUploadFileTypes } from '@/app/components/workflow/types'
 | |
| import { TransferMethod } from '@/types/app'
 | |
| import { FILE_EXTS } from '../prompt-editor/constants'
 | |
| 
 | |
| jest.mock('mime', () => ({
 | |
|   __esModule: true,
 | |
|   default: {
 | |
|     getAllExtensions: jest.fn(),
 | |
|   },
 | |
| }))
 | |
| 
 | |
| jest.mock('@/service/base', () => ({
 | |
|   upload: jest.fn(),
 | |
| }))
 | |
| 
 | |
| describe('file-uploader utils', () => {
 | |
|   beforeEach(() => {
 | |
|     jest.clearAllMocks()
 | |
|   })
 | |
| 
 | |
|   describe('fileUpload', () => {
 | |
|     it('should handle successful file upload', async () => {
 | |
|       const mockFile = new File(['test'], 'test.txt')
 | |
|       const mockCallbacks = {
 | |
|         onProgressCallback: jest.fn(),
 | |
|         onSuccessCallback: jest.fn(),
 | |
|         onErrorCallback: jest.fn(),
 | |
|       }
 | |
| 
 | |
|       jest.mocked(upload).mockResolvedValue({ id: '123' })
 | |
| 
 | |
|       await fileUpload({
 | |
|         file: mockFile,
 | |
|         ...mockCallbacks,
 | |
|       })
 | |
| 
 | |
|       expect(upload).toHaveBeenCalled()
 | |
|       expect(mockCallbacks.onSuccessCallback).toHaveBeenCalledWith({ id: '123' })
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   describe('getFileExtension', () => {
 | |
|     it('should get extension from mimetype', () => {
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['pdf']))
 | |
|       expect(getFileExtension('file', 'application/pdf')).toBe('pdf')
 | |
|     })
 | |
| 
 | |
|     it('should get extension from mimetype and file name 1', () => {
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['pdf']))
 | |
|       expect(getFileExtension('file.pdf', 'application/pdf')).toBe('pdf')
 | |
|     })
 | |
| 
 | |
|     it('should get extension from mimetype with multiple ext candidates with filename hint', () => {
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['der', 'crt', 'pem']))
 | |
|       expect(getFileExtension('file.pem', 'application/x-x509-ca-cert')).toBe('pem')
 | |
|     })
 | |
| 
 | |
|     it('should get extension from mimetype with multiple ext candidates without filename hint', () => {
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['der', 'crt', 'pem']))
 | |
|       expect(getFileExtension('file', 'application/x-x509-ca-cert')).toBe('der')
 | |
|     })
 | |
| 
 | |
|     it('should get extension from filename if mimetype fails', () => {
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(null)
 | |
|       expect(getFileExtension('file.txt', '')).toBe('txt')
 | |
|       expect(getFileExtension('file.txt.docx', '')).toBe('docx')
 | |
|       expect(getFileExtension('file', '')).toBe('')
 | |
|     })
 | |
| 
 | |
|     it('should return empty string for remote files', () => {
 | |
|       expect(getFileExtension('file.txt', '', true)).toBe('')
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   describe('getFileAppearanceType', () => {
 | |
|     it('should identify gif files', () => {
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['gif']))
 | |
|       expect(getFileAppearanceType('image.gif', 'image/gif'))
 | |
|         .toBe(FileAppearanceTypeEnum.gif)
 | |
|     })
 | |
| 
 | |
|     it('should identify image files', () => {
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['jpg']))
 | |
|       expect(getFileAppearanceType('image.jpg', 'image/jpeg'))
 | |
|         .toBe(FileAppearanceTypeEnum.image)
 | |
| 
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['jpeg']))
 | |
|       expect(getFileAppearanceType('image.jpeg', 'image/jpeg'))
 | |
|         .toBe(FileAppearanceTypeEnum.image)
 | |
| 
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['png']))
 | |
|       expect(getFileAppearanceType('image.png', 'image/png'))
 | |
|         .toBe(FileAppearanceTypeEnum.image)
 | |
| 
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['webp']))
 | |
|       expect(getFileAppearanceType('image.webp', 'image/webp'))
 | |
|         .toBe(FileAppearanceTypeEnum.image)
 | |
| 
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['svg']))
 | |
|       expect(getFileAppearanceType('image.svg', 'image/svgxml'))
 | |
|         .toBe(FileAppearanceTypeEnum.image)
 | |
|     })
 | |
| 
 | |
|     it('should identify video files', () => {
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['mp4']))
 | |
|       expect(getFileAppearanceType('video.mp4', 'video/mp4'))
 | |
|         .toBe(FileAppearanceTypeEnum.video)
 | |
| 
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['mov']))
 | |
|       expect(getFileAppearanceType('video.mov', 'video/quicktime'))
 | |
|         .toBe(FileAppearanceTypeEnum.video)
 | |
| 
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['mpeg']))
 | |
|       expect(getFileAppearanceType('video.mpeg', 'video/mpeg'))
 | |
|         .toBe(FileAppearanceTypeEnum.video)
 | |
| 
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['webm']))
 | |
|       expect(getFileAppearanceType('video.web', 'video/webm'))
 | |
|         .toBe(FileAppearanceTypeEnum.video)
 | |
|     })
 | |
| 
 | |
|     it('should identify audio files', () => {
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['mp3']))
 | |
|       expect(getFileAppearanceType('audio.mp3', 'audio/mpeg'))
 | |
|         .toBe(FileAppearanceTypeEnum.audio)
 | |
| 
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['m4a']))
 | |
|       expect(getFileAppearanceType('audio.m4a', 'audio/mp4'))
 | |
|         .toBe(FileAppearanceTypeEnum.audio)
 | |
| 
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['wav']))
 | |
|       expect(getFileAppearanceType('audio.wav', 'audio/vnd.wav'))
 | |
|         .toBe(FileAppearanceTypeEnum.audio)
 | |
| 
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['amr']))
 | |
|       expect(getFileAppearanceType('audio.amr', 'audio/AMR'))
 | |
|         .toBe(FileAppearanceTypeEnum.audio)
 | |
| 
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['mpga']))
 | |
|       expect(getFileAppearanceType('audio.mpga', 'audio/mpeg'))
 | |
|         .toBe(FileAppearanceTypeEnum.audio)
 | |
|     })
 | |
| 
 | |
|     it('should identify code files', () => {
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['html']))
 | |
|       expect(getFileAppearanceType('index.html', 'text/html'))
 | |
|         .toBe(FileAppearanceTypeEnum.code)
 | |
|     })
 | |
| 
 | |
|     it('should identify PDF files', () => {
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['pdf']))
 | |
|       expect(getFileAppearanceType('doc.pdf', 'application/pdf'))
 | |
|         .toBe(FileAppearanceTypeEnum.pdf)
 | |
|     })
 | |
| 
 | |
|     it('should identify markdown files', () => {
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['md']))
 | |
|       expect(getFileAppearanceType('file.md', 'text/markdown'))
 | |
|         .toBe(FileAppearanceTypeEnum.markdown)
 | |
| 
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['markdown']))
 | |
|       expect(getFileAppearanceType('file.markdown', 'text/markdown'))
 | |
|         .toBe(FileAppearanceTypeEnum.markdown)
 | |
| 
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['mdx']))
 | |
|       expect(getFileAppearanceType('file.mdx', 'text/mdx'))
 | |
|         .toBe(FileAppearanceTypeEnum.markdown)
 | |
|     })
 | |
| 
 | |
|     it('should identify excel files', () => {
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['xlsx']))
 | |
|       expect(getFileAppearanceType('doc.xlsx', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'))
 | |
|         .toBe(FileAppearanceTypeEnum.excel)
 | |
| 
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['xls']))
 | |
|       expect(getFileAppearanceType('doc.xls', 'application/vnd.ms-excel'))
 | |
|         .toBe(FileAppearanceTypeEnum.excel)
 | |
|     })
 | |
| 
 | |
|     it('should identify word files', () => {
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['doc']))
 | |
|       expect(getFileAppearanceType('doc.doc', 'application/msword'))
 | |
|         .toBe(FileAppearanceTypeEnum.word)
 | |
| 
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['docx']))
 | |
|       expect(getFileAppearanceType('doc.docx', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'))
 | |
|         .toBe(FileAppearanceTypeEnum.word)
 | |
|     })
 | |
| 
 | |
|     it('should identify word files', () => {
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['ppt']))
 | |
|       expect(getFileAppearanceType('doc.ppt', 'application/vnd.ms-powerpoint'))
 | |
|         .toBe(FileAppearanceTypeEnum.ppt)
 | |
| 
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['pptx']))
 | |
|       expect(getFileAppearanceType('doc.pptx', 'application/vnd.openxmlformats-officedocument.presentationml.presentation'))
 | |
|         .toBe(FileAppearanceTypeEnum.ppt)
 | |
|     })
 | |
| 
 | |
|     it('should identify document files', () => {
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['txt']))
 | |
|       expect(getFileAppearanceType('file.txt', 'text/plain'))
 | |
|         .toBe(FileAppearanceTypeEnum.document)
 | |
| 
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['csv']))
 | |
|       expect(getFileAppearanceType('file.csv', 'text/csv'))
 | |
|         .toBe(FileAppearanceTypeEnum.document)
 | |
| 
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['msg']))
 | |
|       expect(getFileAppearanceType('file.msg', 'application/vnd.ms-outlook'))
 | |
|         .toBe(FileAppearanceTypeEnum.document)
 | |
| 
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['eml']))
 | |
|       expect(getFileAppearanceType('file.eml', 'message/rfc822'))
 | |
|         .toBe(FileAppearanceTypeEnum.document)
 | |
| 
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['xml']))
 | |
|       expect(getFileAppearanceType('file.xml', 'application/rssxml'))
 | |
|         .toBe(FileAppearanceTypeEnum.document)
 | |
| 
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['epub']))
 | |
|       expect(getFileAppearanceType('file.epub', 'application/epubzip'))
 | |
|         .toBe(FileAppearanceTypeEnum.document)
 | |
|     })
 | |
| 
 | |
|     it('should handle null mime extension', () => {
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(null)
 | |
|       expect(getFileAppearanceType('file.txt', 'text/plain'))
 | |
|         .toBe(FileAppearanceTypeEnum.document)
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   describe('getSupportFileType', () => {
 | |
|     it('should return custom type when isCustom is true', () => {
 | |
|       expect(getSupportFileType('file.txt', '', true))
 | |
|         .toBe(SupportUploadFileTypes.custom)
 | |
|     })
 | |
| 
 | |
|     it('should return file type when isCustom is false', () => {
 | |
|       expect(getSupportFileType('file.txt', 'text/plain'))
 | |
|         .toBe(SupportUploadFileTypes.document)
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   describe('getProcessedFiles', () => {
 | |
|     it('should process files correctly', () => {
 | |
|       const files = [{
 | |
|         id: '123',
 | |
|         name: 'test.txt',
 | |
|         size: 1024,
 | |
|         type: 'text/plain',
 | |
|         progress: 100,
 | |
|         supportFileType: 'document',
 | |
|         transferMethod: TransferMethod.remote_url,
 | |
|         url: 'http://example.com',
 | |
|         uploadedId: '123',
 | |
|       }]
 | |
| 
 | |
|       const result = getProcessedFiles(files)
 | |
|       expect(result[0]).toEqual({
 | |
|         type: 'document',
 | |
|         transfer_method: TransferMethod.remote_url,
 | |
|         url: 'http://example.com',
 | |
|         upload_file_id: '123',
 | |
|       })
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   describe('getProcessedFilesFromResponse', () => {
 | |
|     it('should process files correctly', () => {
 | |
|       const files = [{
 | |
|         related_id: '2a38e2ca-1295-415d-a51d-65d4ff9912d9',
 | |
|         extension: '.jpeg',
 | |
|         filename: 'test.jpeg',
 | |
|         size: 2881761,
 | |
|         mime_type: 'image/jpeg',
 | |
|         transfer_method: TransferMethod.local_file,
 | |
|         type: 'image',
 | |
|         url: 'https://upload.dify.dev/files/xxx/file-preview',
 | |
|       }]
 | |
| 
 | |
|       const result = getProcessedFilesFromResponse(files)
 | |
|       expect(result[0]).toEqual({
 | |
|         id: '2a38e2ca-1295-415d-a51d-65d4ff9912d9',
 | |
|         name: 'test.jpeg',
 | |
|         size: 2881761,
 | |
|         type: 'image/jpeg',
 | |
|         progress: 100,
 | |
|         transferMethod: TransferMethod.local_file,
 | |
|         supportFileType: 'image',
 | |
|         uploadedId: '2a38e2ca-1295-415d-a51d-65d4ff9912d9',
 | |
|         url: 'https://upload.dify.dev/files/xxx/file-preview',
 | |
|       })
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   describe('getFileNameFromUrl', () => {
 | |
|     it('should extract filename from URL', () => {
 | |
|       expect(getFileNameFromUrl('http://example.com/path/file.txt'))
 | |
|         .toBe('file.txt')
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   describe('getSupportFileExtensionList', () => {
 | |
|     it('should handle custom file types', () => {
 | |
|       const result = getSupportFileExtensionList(
 | |
|         [SupportUploadFileTypes.custom],
 | |
|         ['.pdf', '.txt', '.doc'],
 | |
|       )
 | |
|       expect(result).toEqual(['PDF', 'TXT', 'DOC'])
 | |
|     })
 | |
| 
 | |
|     it('should handle standard file types', () => {
 | |
|       const mockFileExts = {
 | |
|         image: ['JPG', 'PNG'],
 | |
|         document: ['PDF', 'TXT'],
 | |
|         video: ['MP4', 'MOV'],
 | |
|       }
 | |
| 
 | |
|       // Temporarily mock FILE_EXTS
 | |
|       const originalFileExts = { ...FILE_EXTS }
 | |
|       Object.assign(FILE_EXTS, mockFileExts)
 | |
| 
 | |
|       const result = getSupportFileExtensionList(
 | |
|         ['image', 'document'],
 | |
|         [],
 | |
|       )
 | |
|       expect(result).toEqual(['JPG', 'PNG', 'PDF', 'TXT'])
 | |
| 
 | |
|       // Restore original FILE_EXTS
 | |
|       Object.assign(FILE_EXTS, originalFileExts)
 | |
|     })
 | |
| 
 | |
|     it('should return empty array for empty inputs', () => {
 | |
|       const result = getSupportFileExtensionList([], [])
 | |
|       expect(result).toEqual([])
 | |
|     })
 | |
| 
 | |
|     it('should prioritize custom types over standard types', () => {
 | |
|       const mockFileExts = {
 | |
|         image: ['JPG', 'PNG'],
 | |
|       }
 | |
| 
 | |
|       // Temporarily mock FILE_EXTS
 | |
|       const originalFileExts = { ...FILE_EXTS }
 | |
|       Object.assign(FILE_EXTS, mockFileExts)
 | |
| 
 | |
|       const result = getSupportFileExtensionList(
 | |
|         [SupportUploadFileTypes.custom, 'image'],
 | |
|         ['.csv', '.xml'],
 | |
|       )
 | |
|       expect(result).toEqual(['CSV', 'XML'])
 | |
| 
 | |
|       // Restore original FILE_EXTS
 | |
|       Object.assign(FILE_EXTS, originalFileExts)
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   describe('isAllowedFileExtension', () => {
 | |
|     it('should validate allowed file extensions', () => {
 | |
|       jest.mocked(mime.getAllExtensions).mockReturnValue(new Set(['pdf']))
 | |
|       expect(isAllowedFileExtension(
 | |
|         'test.pdf',
 | |
|         'application/pdf',
 | |
|         ['document'],
 | |
|         ['.pdf'],
 | |
|       )).toBe(true)
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   describe('getFilesInLogs', () => {
 | |
|     const mockFileData = {
 | |
|       dify_model_identity: '__dify__file__',
 | |
|       related_id: '123',
 | |
|       filename: 'test.pdf',
 | |
|       size: 1024,
 | |
|       mime_type: 'application/pdf',
 | |
|       transfer_method: 'local_file',
 | |
|       type: 'document',
 | |
|       url: 'http://example.com/test.pdf',
 | |
|     }
 | |
| 
 | |
|     it('should handle empty or null input', () => {
 | |
|       expect(getFilesInLogs(null)).toEqual([])
 | |
|       expect(getFilesInLogs({})).toEqual([])
 | |
|       expect(getFilesInLogs(undefined)).toEqual([])
 | |
|     })
 | |
| 
 | |
|     it('should process single file object', () => {
 | |
|       const input = {
 | |
|         file1: mockFileData,
 | |
|       }
 | |
| 
 | |
|       const expected = [{
 | |
|         varName: 'file1',
 | |
|         list: [{
 | |
|           id: '123',
 | |
|           name: 'test.pdf',
 | |
|           size: 1024,
 | |
|           type: 'application/pdf',
 | |
|           progress: 100,
 | |
|           transferMethod: 'local_file',
 | |
|           supportFileType: 'document',
 | |
|           uploadedId: '123',
 | |
|           url: 'http://example.com/test.pdf',
 | |
|         }],
 | |
|       }]
 | |
| 
 | |
|       expect(getFilesInLogs(input)).toEqual(expected)
 | |
|     })
 | |
| 
 | |
|     it('should process array of files', () => {
 | |
|       const input = {
 | |
|         files: [mockFileData, mockFileData],
 | |
|       }
 | |
| 
 | |
|       const expected = [{
 | |
|         varName: 'files',
 | |
|         list: [
 | |
|           {
 | |
|             id: '123',
 | |
|             name: 'test.pdf',
 | |
|             size: 1024,
 | |
|             type: 'application/pdf',
 | |
|             progress: 100,
 | |
|             transferMethod: 'local_file',
 | |
|             supportFileType: 'document',
 | |
|             uploadedId: '123',
 | |
|             url: 'http://example.com/test.pdf',
 | |
|           },
 | |
|           {
 | |
|             id: '123',
 | |
|             name: 'test.pdf',
 | |
|             size: 1024,
 | |
|             type: 'application/pdf',
 | |
|             progress: 100,
 | |
|             transferMethod: 'local_file',
 | |
|             supportFileType: 'document',
 | |
|             uploadedId: '123',
 | |
|             url: 'http://example.com/test.pdf',
 | |
|           },
 | |
|         ],
 | |
|       }]
 | |
| 
 | |
|       expect(getFilesInLogs(input)).toEqual(expected)
 | |
|     })
 | |
| 
 | |
|     it('should ignore non-file objects and arrays', () => {
 | |
|       const input = {
 | |
|         regularString: 'not a file',
 | |
|         regularNumber: 123,
 | |
|         regularArray: [1, 2, 3],
 | |
|         regularObject: { key: 'value' },
 | |
|         file: mockFileData,
 | |
|       }
 | |
| 
 | |
|       const expected = [{
 | |
|         varName: 'file',
 | |
|         list: [{
 | |
|           id: '123',
 | |
|           name: 'test.pdf',
 | |
|           size: 1024,
 | |
|           type: 'application/pdf',
 | |
|           progress: 100,
 | |
|           transferMethod: 'local_file',
 | |
|           supportFileType: 'document',
 | |
|           uploadedId: '123',
 | |
|           url: 'http://example.com/test.pdf',
 | |
|         }],
 | |
|       }]
 | |
| 
 | |
|       expect(getFilesInLogs(input)).toEqual(expected)
 | |
|     })
 | |
| 
 | |
|     it('should handle mixed file types in array', () => {
 | |
|       const input = {
 | |
|         mixedFiles: [
 | |
|           mockFileData,
 | |
|           { notAFile: true },
 | |
|           mockFileData,
 | |
|         ],
 | |
|       }
 | |
| 
 | |
|       const expected = [{
 | |
|         varName: 'mixedFiles',
 | |
|         list: [
 | |
|           {
 | |
|             id: '123',
 | |
|             name: 'test.pdf',
 | |
|             size: 1024,
 | |
|             type: 'application/pdf',
 | |
|             progress: 100,
 | |
|             transferMethod: 'local_file',
 | |
|             supportFileType: 'document',
 | |
|             uploadedId: '123',
 | |
|             url: 'http://example.com/test.pdf',
 | |
|           },
 | |
|           {
 | |
|             id: undefined,
 | |
|             name: undefined,
 | |
|             progress: 100,
 | |
|             size: 0,
 | |
|             supportFileType: undefined,
 | |
|             transferMethod: undefined,
 | |
|             type: undefined,
 | |
|             uploadedId: undefined,
 | |
|             url: undefined,
 | |
|           },
 | |
|           {
 | |
|             id: '123',
 | |
|             name: 'test.pdf',
 | |
|             size: 1024,
 | |
|             type: 'application/pdf',
 | |
|             progress: 100,
 | |
|             transferMethod: 'local_file',
 | |
|             supportFileType: 'document',
 | |
|             uploadedId: '123',
 | |
|             url: 'http://example.com/test.pdf',
 | |
|           },
 | |
|         ],
 | |
|       }]
 | |
| 
 | |
|       expect(getFilesInLogs(input)).toEqual(expected)
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   describe('fileIsUploaded', () => {
 | |
|     it('should identify uploaded files', () => {
 | |
|       expect(fileIsUploaded({
 | |
|         uploadedId: '123',
 | |
|         progress: 100,
 | |
|       } as any)).toBe(true)
 | |
|     })
 | |
| 
 | |
|     it('should identify remote files as uploaded', () => {
 | |
|       expect(fileIsUploaded({
 | |
|         transferMethod: TransferMethod.remote_url,
 | |
|         progress: 100,
 | |
|       } as any)).toBe(true)
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   describe('downloadFile', () => {
 | |
|     let mockAnchor: HTMLAnchorElement
 | |
|     let createElementMock: jest.SpyInstance
 | |
|     let appendChildMock: jest.SpyInstance
 | |
|     let removeChildMock: jest.SpyInstance
 | |
| 
 | |
|     beforeEach(() => {
 | |
|       // Mock createElement and appendChild
 | |
|       mockAnchor = {
 | |
|         href: '',
 | |
|         download: '',
 | |
|         style: { display: '' },
 | |
|         target: '',
 | |
|         title: '',
 | |
|         click: jest.fn(),
 | |
|       } as unknown as HTMLAnchorElement
 | |
| 
 | |
|       createElementMock = jest.spyOn(document, 'createElement').mockReturnValue(mockAnchor as any)
 | |
|       appendChildMock = jest.spyOn(document.body, 'appendChild').mockImplementation((node: Node) => {
 | |
|         return node
 | |
|       })
 | |
|       removeChildMock = jest.spyOn(document.body, 'removeChild').mockImplementation((node: Node) => {
 | |
|         return node
 | |
|       })
 | |
|     })
 | |
| 
 | |
|     afterEach(() => {
 | |
|       jest.resetAllMocks()
 | |
|     })
 | |
| 
 | |
|     it('should create and trigger download with correct attributes', () => {
 | |
|       const url = 'https://example.com/test.pdf'
 | |
|       const filename = 'test.pdf'
 | |
| 
 | |
|       downloadFile(url, filename)
 | |
| 
 | |
|       // Verify anchor element was created with correct properties
 | |
|       expect(createElementMock).toHaveBeenCalledWith('a')
 | |
|       expect(mockAnchor.href).toBe(url)
 | |
|       expect(mockAnchor.download).toBe(filename)
 | |
|       expect(mockAnchor.style.display).toBe('none')
 | |
|       expect(mockAnchor.target).toBe('_blank')
 | |
|       expect(mockAnchor.title).toBe(filename)
 | |
| 
 | |
|       // Verify DOM operations
 | |
|       expect(appendChildMock).toHaveBeenCalledWith(mockAnchor)
 | |
|       expect(mockAnchor.click).toHaveBeenCalled()
 | |
|       expect(removeChildMock).toHaveBeenCalledWith(mockAnchor)
 | |
|     })
 | |
| 
 | |
|     it('should handle empty filename', () => {
 | |
|       const url = 'https://example.com/test.pdf'
 | |
|       const filename = ''
 | |
| 
 | |
|       downloadFile(url, filename)
 | |
| 
 | |
|       expect(mockAnchor.download).toBe('')
 | |
|       expect(mockAnchor.title).toBe('')
 | |
|     })
 | |
| 
 | |
|     it('should handle empty url', () => {
 | |
|       const url = ''
 | |
|       const filename = 'test.pdf'
 | |
| 
 | |
|       downloadFile(url, filename)
 | |
| 
 | |
|       expect(mockAnchor.href).toBe('')
 | |
|     })
 | |
|   })
 | |
| })
 | 
