mirror of
https://github.com/saltbo/zpan.git
synced 2026-08-29 00:01:42 +08:00
fix(downloader): clear eta after transfer completion
This commit is contained in:
@@ -499,6 +499,41 @@ describe('Download tasks API integration', () => {
|
||||
torrent: { infoHash: 'patch-info-hash', name: 'patch-progress' },
|
||||
trackers: [{ url: 'udp://tracker.example/announce', status: 'working', seeds: 2 }],
|
||||
})
|
||||
|
||||
const completedRes = await app.request(`/api/download-tasks/${task.id}`, {
|
||||
method: 'PATCH',
|
||||
headers: downloaderHeaders,
|
||||
body: JSON.stringify({
|
||||
status: 'completed',
|
||||
runtime: { phase: 'completed' },
|
||||
}),
|
||||
})
|
||||
expect(completedRes.status).toBe(200)
|
||||
const completedTask = (await completedRes.json()) as DownloadTask
|
||||
expect(completedTask.status.runtime).toMatchObject({
|
||||
phase: 'completed',
|
||||
etaSeconds: null,
|
||||
})
|
||||
|
||||
const seedingRes = await app.request(`/api/download-tasks/${task.id}`, {
|
||||
method: 'PATCH',
|
||||
headers: downloaderHeaders,
|
||||
body: JSON.stringify({
|
||||
runtime: {
|
||||
phase: 'seeding',
|
||||
seeding: { active: true, uploadedBytes: 1024, uploadBytesPerSecond: 128 },
|
||||
},
|
||||
}),
|
||||
})
|
||||
expect(seedingRes.status).toBe(200)
|
||||
const seedingTask = (await seedingRes.json()) as DownloadTask
|
||||
expect(seedingTask.status.runtime).toMatchObject({
|
||||
engine: 'aria2',
|
||||
phase: 'seeding',
|
||||
etaSeconds: null,
|
||||
torrent: { infoHash: 'patch-info-hash', name: 'patch-progress' },
|
||||
seeding: { active: true, uploadedBytes: 1024, uploadBytesPerSecond: 128 },
|
||||
})
|
||||
})
|
||||
|
||||
it('returns storage failure details when multipart upload session creation fails', async () => {
|
||||
@@ -968,6 +1003,45 @@ describe('Download tasks API integration', () => {
|
||||
runtime: null,
|
||||
},
|
||||
})
|
||||
|
||||
const downloadingAfterRestartRes = await app.request(`/api/download-tasks/${createdTask.id}`, {
|
||||
method: 'PATCH',
|
||||
headers: downloaderHeaders,
|
||||
body: JSON.stringify({
|
||||
...transferProgress({ downloadBytes: 1024, totalBytes, downloadBps: 256 }),
|
||||
runtime: { phase: 'downloading', etaSeconds: 36 },
|
||||
}),
|
||||
})
|
||||
expect(downloadingAfterRestartRes.status).toBe(200)
|
||||
|
||||
const completedAfterRestartRes = await app.request(`/api/download-tasks/${createdTask.id}`, {
|
||||
method: 'PATCH',
|
||||
headers: downloaderHeaders,
|
||||
body: JSON.stringify({
|
||||
status: 'completed',
|
||||
runtime: { phase: 'completed' },
|
||||
}),
|
||||
})
|
||||
expect(completedAfterRestartRes.status).toBe(200)
|
||||
await expect(completedAfterRestartRes.json()).resolves.toMatchObject({
|
||||
status: {
|
||||
runtime: { phase: 'completed', etaSeconds: null },
|
||||
},
|
||||
})
|
||||
|
||||
const seedingAfterRestartRes = await app.request(`/api/download-tasks/${createdTask.id}`, {
|
||||
method: 'PATCH',
|
||||
headers: downloaderHeaders,
|
||||
body: JSON.stringify({
|
||||
runtime: { phase: 'seeding', seeding: { active: true } },
|
||||
}),
|
||||
})
|
||||
expect(seedingAfterRestartRes.status).toBe(200)
|
||||
await expect(seedingAfterRestartRes.json()).resolves.toMatchObject({
|
||||
status: {
|
||||
runtime: { phase: 'seeding', etaSeconds: null, seeding: { active: true } },
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it('uses transitional states for downloading task pause and cancel actions', async () => {
|
||||
|
||||
@@ -579,6 +579,9 @@ function nextTaskRuntime(
|
||||
|
||||
function mergeTaskRuntimePatch(current: DownloadTaskRuntime | null, patch: DownloadTaskRuntime): DownloadTaskRuntime {
|
||||
const merged: DownloadTaskRuntime = { ...(current ?? {}), ...patch }
|
||||
if (patch.phase === 'completed' || patch.phase === 'seeding') {
|
||||
merged.etaSeconds = null
|
||||
}
|
||||
if (current?.progress || patch.progress) {
|
||||
merged.progress = mergeTaskProgress(current?.progress, patch.progress)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user