gongxiangp2/lib/__tests__/task-detail-asset-edit-route.test.ts

119 lines
4.1 KiB
TypeScript
Raw 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 { getServerSession } from 'next-auth'
import {
DELETE,
PATCH,
POST,
} from '@/app/api/materials/[id]/assets/[assetId]/route'
import {
deleteTaskDetailImage,
renameTaskDetailImage,
replaceTaskDetailImage,
} from '@/lib/task-detail-asset-edit'
jest.mock('next-auth', () => ({ getServerSession: jest.fn() }))
jest.mock('@/lib/auth', () => ({ authOptions: {} }))
jest.mock('@/lib/task-detail-asset-edit', () => ({
TaskDetailAssetEditError: class TaskDetailAssetEditError extends Error {
statusCode: number
constructor(message: string, statusCode = 400) {
super(message)
this.statusCode = statusCode
}
},
deleteTaskDetailImage: jest.fn(),
renameTaskDetailImage: jest.fn(),
replaceTaskDetailImage: jest.fn(),
}))
const mockedDelete = deleteTaskDetailImage as jest.Mock
const mockedRename = renameTaskDetailImage as jest.Mock
const mockedReplace = replaceTaskDetailImage as jest.Mock
describe('任务-详情单图编辑路由', () => {
beforeEach(() => {
jest.clearAllMocks()
})
test('未登录返回 401,不触发编辑逻辑', async () => {
;(getServerSession as jest.Mock).mockResolvedValue(null)
for (const response of [
await PATCH({ json: async () => ({ newFileName: 'x' }) } as any, { params: { id: 'm1', assetId: 'a1' } }),
await POST({ json: async () => ({ uploadId: 'u1' }) } as any, { params: { id: 'm1', assetId: 'a1' } }),
await DELETE({} as any, { params: { id: 'm1', assetId: 'a1' } }),
]) {
expect(response.status).toBe(401)
}
expect(mockedRename).not.toHaveBeenCalled()
expect(mockedReplace).not.toHaveBeenCalled()
expect(mockedDelete).not.toHaveBeenCalled()
})
test('PATCH 缺少新文件名返回 400', async () => {
;(getServerSession as jest.Mock).mockResolvedValue({ user: { id: 'u1' } })
const response = await PATCH({ json: async () => ({}) } as any, { params: { id: 'm1', assetId: 'a1' } })
expect(response.status).toBe(400)
expect(mockedRename).not.toHaveBeenCalled()
})
test('POST 缺少 uploadId 返回 400', async () => {
;(getServerSession as jest.Mock).mockResolvedValue({ user: { id: 'u1' } })
const response = await POST({ json: async () => ({}) } as any, { params: { id: 'm1', assetId: 'a1' } })
expect(response.status).toBe(400)
expect(mockedReplace).not.toHaveBeenCalled()
})
test('登录用户正常调用并透传参数', async () => {
;(getServerSession as jest.Mock).mockResolvedValue({ user: { id: 'u1', role: 'USER' } })
mockedRename.mockResolvedValue({ success: true })
mockedReplace.mockResolvedValue({ success: true })
mockedDelete.mockResolvedValue({ success: true })
await PATCH(
{ json: async () => ({ newFileName: '新名字' }) } as any,
{ params: { id: 'm1', assetId: 'a1' } },
)
expect(mockedRename).toHaveBeenCalledWith({
materialId: 'm1',
assetId: 'a1',
operatorUserId: 'u1',
operatorRole: 'USER',
newFileName: '新名字',
})
await POST(
{ json: async () => ({ uploadId: 'upload-1' }) } as any,
{ params: { id: 'm1', assetId: 'a2' } },
)
expect(mockedReplace).toHaveBeenCalledWith({
materialId: 'm1',
assetId: 'a2',
operatorUserId: 'u1',
operatorRole: 'USER',
uploadId: 'upload-1',
})
await DELETE({} as any, { params: { id: 'm1', assetId: 'a3' } })
expect(mockedDelete).toHaveBeenCalledWith({
materialId: 'm1',
assetId: 'a3',
operatorUserId: 'u1',
operatorRole: 'USER',
})
})
test('权限类业务错误透传状态码与文案', async () => {
;(getServerSession as jest.Mock).mockResolvedValue({ user: { id: 'intruder' } })
const { TaskDetailAssetEditError: MockedError } = await import('@/lib/task-detail-asset-edit')
mockedDelete.mockRejectedValue(new (MockedError as any)('您没有权限编辑此素材', 403))
const response = await DELETE({} as any, { params: { id: 'm1', assetId: 'a1' } })
expect(response.status).toBe(403)
const body = await response.json()
expect(body.error).toBe('您没有权限编辑此素材')
})
})