fix(backups): сохранить идентичность фоновой задачи

This commit is contained in:
Denozordec committed 2026-10-01 15:44:02 +07:00
1 parent 30bd479a6f
commit 4aee2a34f1
13 files changed
+157 -12

No files matched your search

+9 -3
View File
@@ -6,7 +6,7 @@ const base = "https://api.example.test"
const item = { id: "backup-1", serverId: 1, serverName: "router", filename: "config.rsc", sizeBytes: 0, createdAt: "2026-10-01T00:00:00Z", kind: "manual", storage: "local" }
const schedule = { enabled: false, frequency: "daily", hour: 0, minute: 0, weekDay: 0, monthDay: 1, keepCount: 7, format: "rsc", serverIds: [] }
const storage = { provider: "local", s3Endpoint: "", s3Region: "", s3Bucket: "", s3Prefix: "", s3AccessKeyId: "", secretConfigured: false, s3ForcePathStyle: false, keepLocalCopy: false }
const job = { id: "job-1", status: "done", total: 2, completed: 2, requestedAt: "2026-10-01T00:00:00Z", finishedAt: "2026-10-01T00:01:00Z", created: [item], failures: [{ serverId: "2", error: "RouterOS unavailable" }] }
const job = { id: "job-1", serverIds: ["1", "2"], status: "done", total: 2, completed: 2, requestedAt: "2026-10-01T00:00:00Z", finishedAt: "2026-10-01T00:01:00Z", created: [item], failures: [{ serverId: "2", error: "RouterOS unavailable" }] }
function json(payload: unknown, status = 200) { return new Response(JSON.stringify(payload), { status }) }
test("known empty and zero are preserved; malformed catalogue and duplicates rejected", async () => {
@@ -35,7 +35,7 @@ test("settings require a confirmed response and preserve false rather than defau
})
test("invalid mutations fail before HTTP; create receives job acknowledgment", async () => {
const original = globalThis.fetch; let calls = 0, body: unknown
globalThis.fetch = async (_url, init) => { calls++; body = JSON.parse(String(init?.body)); return json({ jobId: "job-1", status: "queued", total: 1, completed: 0 }, 202) }
globalThis.fetch = async (_url, init) => { calls++; body = JSON.parse(String(init?.body)); return json({ jobId: "job-1", serverIds: ["1"], status: "queued", total: 1, completed: 0 }, 202) }
try {
await assert.rejects(() => createBackupsAsync(base, { serverIds: [] }))
await assert.rejects(() => createBackupsAsync(base, { serverIds: ["1", "1"] }))
@@ -44,7 +44,7 @@ test("invalid mutations fail before HTTP; create receives job acknowledgment", a
assert.equal(calls, 0)
assert.equal((await createBackupsAsync(base, { serverIds: ["1"], notes: "manual" })).jobId, "job-1")
assert.deepEqual(body, { serverIds: ["1"], notes: "manual" })
globalThis.fetch = async () => json({ jobId: "job-1", status: "queued", total: 2, completed: 0 }, 202); await assert.rejects(() => createBackupsAsync(base, { serverIds: ["1"] }), /всех выбранных/);
globalThis.fetch = async () => json({ jobId: "job-1", serverIds: ["1", "2"], status: "queued", total: 2, completed: 0 }, 202); await assert.rejects(() => createBackupsAsync(base, { serverIds: ["1"] }), /выбранные серверы/);
globalThis.fetch = async () => json({ created: [item], failures: [] }); await assert.rejects(() => createBackupsAsync(base, { serverIds: ["1"] }))
} finally { globalThis.fetch = original }
})
@@ -90,3 +90,9 @@ test("settings acknowledgment must match submitted fields and confirm a new secr
await assert.rejects(() => putBackupStorageSettings(base, { s3SecretAccessKey: "new-test-secret" }), /ключа/)
} finally { globalThis.fetch = original }
})
test("backup request ID is sent and a different acknowledgment is rejected", async () => {
const original = globalThis.fetch, requestId = "11111111-1111-4111-8111-111111111111"; let body: Record<string, unknown> = {}
globalThis.fetch = async (_url, init) => { body = JSON.parse(String(init?.body)); return json({ jobId: "other", serverIds: ["1"], status: "queued", total: 1, completed: 0 }, 202) }
try { await assert.rejects(() => createBackupsAsync(base, { requestId, serverIds: ["1"] }), /другому запросу/); assert.equal(body.requestId, requestId) } finally { globalThis.fetch = original }
})