101 lines
3.1 KiB
JavaScript
101 lines
3.1 KiB
JavaScript
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
const mocks = vi.hoisted(() => ({
|
|
getFileHash: vi.fn(),
|
|
sliceFile: vi.fn(),
|
|
initUploadTask: vi.fn(),
|
|
getProgress: vi.fn(),
|
|
getUploadUrl: vi.fn(),
|
|
getTaskStatus: vi.fn(),
|
|
completeTask: vi.fn(),
|
|
uploadPart: vi.fn(),
|
|
uploadPartToUrl: vi.fn()
|
|
}))
|
|
|
|
vi.mock('@/utils/uploadTools', () => ({
|
|
getFileHash: mocks.getFileHash,
|
|
sliceFile: mocks.sliceFile
|
|
}))
|
|
|
|
vi.mock('@/services/upload/uploadService', () => ({
|
|
uploadService: {
|
|
initUploadTask: mocks.initUploadTask,
|
|
getProgress: mocks.getProgress,
|
|
getUploadUrl: mocks.getUploadUrl,
|
|
getTaskStatus: mocks.getTaskStatus,
|
|
completeTask: mocks.completeTask,
|
|
uploadPart: mocks.uploadPart,
|
|
uploadPartToUrl: mocks.uploadPartToUrl
|
|
}
|
|
}))
|
|
|
|
import { uploadFile } from '@/services/upload/uploader'
|
|
|
|
const file = {
|
|
name: 'demo.bin',
|
|
size: 10,
|
|
type: 'application/octet-stream'
|
|
}
|
|
|
|
describe('uploadFile', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks()
|
|
mocks.getFileHash.mockResolvedValue('0123456789abcdef0123456789abcdef')
|
|
mocks.sliceFile.mockReturnValue([{ size: 5 }, { size: 5 }])
|
|
})
|
|
|
|
it('returns the final file immediately on an instant upload hit', async () => {
|
|
const finalFile = { id: 'file-1', url: 'https://files.test/file-1' }
|
|
mocks.initUploadTask.mockResolvedValue({
|
|
data: { taskId: 'file-1', instant: true, uploadMode: 'Instant', file: finalFile }
|
|
})
|
|
|
|
await expect(uploadFile(file, { chatType: 'PRIVATE', targetId: 'user-2' }))
|
|
.resolves.toEqual(finalFile)
|
|
expect(mocks.uploadPart).not.toHaveBeenCalled()
|
|
expect(mocks.completeTask).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('uploads every local part, completes, and waits for the final file', async () => {
|
|
const finalFile = { id: 'file-2', url: null }
|
|
mocks.initUploadTask.mockResolvedValue({
|
|
data: {
|
|
taskId: 'task-2',
|
|
uploadSessionId: 'session-2',
|
|
uploadMode: 'LocalMultipart',
|
|
totalPartCount: 2,
|
|
partSizeBytes: 5,
|
|
instant: false
|
|
}
|
|
})
|
|
mocks.uploadPart.mockImplementation((_session, partNumber) =>
|
|
Promise.resolve({ data: { eTag: `etag-${partNumber}` } })
|
|
)
|
|
mocks.completeTask.mockResolvedValue({ data: { state: 'Merging' } })
|
|
mocks.getTaskStatus.mockResolvedValue({ data: { state: 'Completed', file: finalFile } })
|
|
|
|
await expect(uploadFile(file, { chatType: 'GROUP', targetId: 'group-1' }))
|
|
.resolves.toEqual(finalFile)
|
|
expect(mocks.uploadPart).toHaveBeenCalledTimes(2)
|
|
expect(mocks.completeTask).toHaveBeenCalledOnce()
|
|
expect(mocks.getTaskStatus).toHaveBeenCalledWith('task-2')
|
|
})
|
|
|
|
it('does not call complete when a part keeps failing', async () => {
|
|
mocks.initUploadTask.mockResolvedValue({
|
|
data: {
|
|
taskId: 'task-3',
|
|
uploadSessionId: 'session-3',
|
|
uploadMode: 'LocalMultipart',
|
|
totalPartCount: 2,
|
|
partSizeBytes: 5,
|
|
instant: false
|
|
}
|
|
})
|
|
mocks.uploadPart.mockRejectedValue(new Error('part failed'))
|
|
|
|
await expect(uploadFile(file)).rejects.toThrow('part failed')
|
|
expect(mocks.completeTask).not.toHaveBeenCalled()
|
|
})
|
|
})
|