Files
FileHost/app/utils/upload-progress.test.ts
2026-10-19 15:04:41 +08:00

73 lines
1.6 KiB
TypeScript

import { afterEach, describe, expect, it, vi } from 'vitest'
import { uploadFormDataWithProgress } from './upload-progress'
class FakeXhr {
static current: FakeXhr
upload = {
onprogress: null as ((event: ProgressEvent) => void) | null
}
status = 200
statusText = 'OK'
responseText = '{"ok":true}'
withCredentials = false
onload: (() => void) | null = null
onerror: (() => void) | null = null
constructor() {
FakeXhr.current = this
}
open() {}
send() {}
}
describe('uploadFormDataWithProgress', () => {
afterEach(() => {
vi.unstubAllGlobals()
})
it('reports the uploaded byte percentage', async () => {
vi.stubGlobal('XMLHttpRequest', FakeXhr)
const onProgress = vi.fn()
const result = uploadFormDataWithProgress<{ ok: boolean }>(
'/upload',
new FormData(),
onProgress
)
FakeXhr.current.upload.onprogress!({
lengthComputable: true,
loaded: 40,
total: 100
} as ProgressEvent)
FakeXhr.current.onload!()
await expect(result).resolves.toEqual({ ok: true })
expect(onProgress).toHaveBeenCalledWith(40)
})
it('keeps the HTTP status and server error message', async () => {
vi.stubGlobal('XMLHttpRequest', FakeXhr)
const result = uploadFormDataWithProgress(
'/upload',
new FormData(),
() => {}
)
FakeXhr.current.status = 401
FakeXhr.current.statusText = 'Unauthorized'
FakeXhr.current.responseText = JSON.stringify({
data: { error: { message: '未登录' } }
})
FakeXhr.current.onload!()
await expect(result).rejects.toMatchObject({
statusCode: 401,
message: '未登录'
})
})
})