gongxiangp2/lib/__tests__/task-material-completion-safety.test.ts
chenpei 7326e273e1 fix: harden media upload and release safety
Protect upload cleanup and atomic completion paths, add durable media worker leases and brand asset validation, and introduce verified migration/bootstrap/deployment gates.
2026-08-12 18:04:08 +08:00

74 lines
2.4 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/** @jest-environment node */
import { prisma } from '@/lib/prisma'
import { inspectTaskMaterialCompletionAfterError } from '@/lib/task-material-completion-safety'
jest.mock('@/lib/prisma', () => ({
prisma: {
material: { findUnique: jest.fn() },
},
}))
describe('task material completion acknowledgement safety', () => {
beforeEach(() => {
jest.clearAllMocks()
})
test.each([
['processing', 'processing'],
['failed', 'other'],
[null, 'other'],
] as const)('数据库状态 %s 映射为 %s', async (taskStatus, expectedState) => {
;(prisma.material.findUnique as jest.Mock).mockResolvedValue({
taskStatus,
previewUrl: '',
zipFilePath: '',
assets: [],
})
await expect(inspectTaskMaterialCompletionAfterError('material-1')).resolves.toMatchObject({
state: expectedState,
})
})
test('只有预览、ZIP 与两类资产证据齐全才映射为 completed', async () => {
;(prisma.material.findUnique as jest.Mock).mockResolvedValue({
taskStatus: 'completed',
previewUrl: 'https://s3.example/preview.webp',
zipFilePath: 'materials/source.zip',
assets: [{ assetType: 'preview' }, { assetType: 'zip' }],
})
await expect(inspectTaskMaterialCompletionAfterError('material-1')).resolves.toMatchObject({
state: 'completed',
})
})
test.each([
['', 'materials/source.zip', [{ assetType: 'preview' }, { assetType: 'zip' }]],
['https://s3.example/preview.webp', '', [{ assetType: 'preview' }, { assetType: 'zip' }]],
['https://s3.example/preview.webp', 'materials/source.zip', [{ assetType: 'preview' }]],
])('已完成但证据不全时映射为 completed_incomplete', async (previewUrl, zipFilePath, assets) => {
;(prisma.material.findUnique as jest.Mock).mockResolvedValue({
taskStatus: 'completed',
previewUrl,
zipFilePath,
assets,
})
await expect(inspectTaskMaterialCompletionAfterError('material-1')).resolves.toMatchObject({
state: 'completed_incomplete',
})
})
test('查询失败时返回 unknown,调用方必须保留文件', async () => {
const error = new Error('database unavailable')
;(prisma.material.findUnique as jest.Mock).mockRejectedValue(error)
await expect(inspectTaskMaterialCompletionAfterError('material-1')).resolves.toEqual({
state: 'unknown',
error,
})
})
})