import test from 'node:test' import assert from 'node:assert/strict' import { closeAdminTaskWithDeps } from './admin-write-service.js' test('closeAdminTaskWithDeps revokes claim link, releases reserved inventory, and closes browser session', async () => { const calls = { updateToken: [], releaseReserved: [], closeSession: [], updateTask: [], createEvent: [], } const task = { id: 30, task_status: 'link_generated', delivery_status: 'pending', inventory_status: 'reserved', user_action_status: 'pending_claim', browser_session_id: 'browser-session-30', primary_claim_token_id: 9, claim_expires_at: '2026-04-15T10:00:00.000Z', last_error: '', updated_at: '2026-04-14T10:00:00.000Z', } const now = '2026-04-14T10:16:18.000Z' const result = await closeAdminTaskWithDeps(task.id, { getRequiredTask: async () => task, listTaskInventoryBindingsByTaskId: async () => ([ { inventory_item_id: 17, binding_status: 'reserved' }, { inventory_item_id: 18, binding_status: 'released' }, { inventory_item_id: 17, binding_status: 'reserved' }, ]), releaseReservedInventoryItem: async (inventoryItemId, updatedAt) => { calls.releaseReserved.push({ inventoryItemId, updatedAt }) return { id: inventoryItemId } }, updateClaimToken: async (tokenId, patch) => { calls.updateToken.push({ tokenId, patch }) return { id: tokenId, ...patch } }, closeTencentBrowserSession: async (sessionId) => { calls.closeSession.push(sessionId) return { sessionId, closed: true } }, updateTask: async (taskId, patch) => { calls.updateTask.push({ taskId, patch }) return { ...task, ...patch } }, createTaskEvent: async (taskId, eventType, payload, createdAt) => { calls.createEvent.push({ taskId, eventType, payload, createdAt }) return null }, nowIso: () => now, }) assert.equal(calls.updateToken.length, 1) assert.deepEqual(calls.updateToken[0], { tokenId: 9, patch: { status: 'revoked', expired_at: now, updated_at: now, }, }) assert.deepEqual(calls.releaseReserved, [ { inventoryItemId: 17, updatedAt: now }, ]) assert.deepEqual(calls.closeSession, ['browser-session-30']) assert.equal(calls.updateTask.length, 1) assert.equal(calls.updateTask[0].patch.task_status, 'closed') assert.equal(calls.updateTask[0].patch.delivery_status, 'closed') assert.equal(calls.updateTask[0].patch.inventory_status, 'pending') assert.equal(calls.updateTask[0].patch.user_action_status, 'closed') assert.equal(calls.updateTask[0].patch.browser_session_id, '') assert.equal(calls.updateTask[0].patch.claim_expires_at, now) assert.match(calls.updateTask[0].patch.last_error, /领取链接已失效/) assert.match(calls.updateTask[0].patch.last_error, /预占库存已释放/) assert.equal(calls.createEvent.length, 1) assert.deepEqual(calls.createEvent[0], { taskId: 30, eventType: 'task_closed', payload: { claimTokenRevoked: true, releasedInventoryItemIds: [17], releasedInventoryCount: 1, browserSessionClosed: true, }, createdAt: now, }) assert.equal(result.task.status, 'closed') }) test('closeAdminTaskWithDeps rejects redeemed tasks', async () => { await assert.rejects( () => closeAdminTaskWithDeps(99, { getRequiredTask: async () => ({ id: 99, task_status: 'redeemed', }), }), /已兑换任务不能关闭/, ) })