flnxi-Wu/app/api/ai/edit/__tests__/route.test.ts
2026-05-28 16:08:49 +08:00

175 lines
4.2 KiB
TypeScript

import { NextRequest } from 'next/server'
jest.mock('@/lib/auth', () => ({
authOptions: {},
}))
jest.mock('next-auth', () => ({
getServerSession: jest.fn(),
}))
jest.mock('@/lib/config', () => ({
featureFlags: {
aiEditEnabled: false,
},
}))
jest.mock('@/lib/prisma', () => ({
prisma: {
systemSettings: {
findFirst: jest.fn(),
},
material: {
findFirst: jest.fn(),
},
user: {
findUnique: jest.fn(),
},
department: {
findMany: jest.fn(),
},
},
}))
import { POST } from '../route'
const { getServerSession } = require('next-auth')
const { prisma } = require('@/lib/prisma')
function buildRequest(body: Record<string, unknown> = {}) {
return new NextRequest('http://localhost:3000/api/ai/edit', {
method: 'POST',
body: JSON.stringify({
materialId: 'material-1',
operation: 'remove-background',
...body,
}),
})
}
function createMaterial(overrides: Record<string, unknown> = {}) {
return {
id: 'material-1',
userId: 'owner-1',
ownerType: 'TEAM',
ownerId: null,
deletedAt: null,
user: {
id: 'owner-1',
department: '设计部',
},
...overrides,
}
}
describe('AI 改图接口权限边界', () => {
beforeEach(() => {
jest.resetAllMocks()
getServerSession.mockResolvedValue({
user: {
id: 'owner-1',
role: 'USER',
},
})
prisma.systemSettings.findFirst.mockResolvedValue({
enableAiImageEdit: true,
})
prisma.material.findFirst.mockResolvedValue(createMaterial())
prisma.user.findUnique.mockImplementation(async ({ where }: any) => {
if (where.id === 'owner-1') {
return {
id: 'owner-1',
role: 'USER',
isSuperAdmin: false,
department: '设计部',
managedDepartment: null,
}
}
if (where.id === 'other-user') {
return {
id: 'other-user',
role: 'USER',
isSuperAdmin: false,
department: '运营部',
managedDepartment: null,
}
}
return null
})
prisma.department.findMany.mockResolvedValue([])
})
test('未登录不能创建 AI 改图任务', async () => {
getServerSession.mockResolvedValue(null)
const response = await POST(buildRequest())
const data = await response.json()
expect(response.status).toBe(401)
expect(data.error).toBe('未登录')
expect(prisma.material.findFirst).not.toHaveBeenCalled()
})
test('系统未启用 AI 改图时不能创建任务', async () => {
prisma.systemSettings.findFirst.mockResolvedValue({
enableAiImageEdit: false,
})
const response = await POST(buildRequest())
const data = await response.json()
expect(response.status).toBe(501)
expect(data.error).toBe('AI改图功能未启用')
expect(prisma.material.findFirst).not.toHaveBeenCalled()
})
test('素材不存在或已删除时不能创建任务', async () => {
prisma.material.findFirst.mockResolvedValue(null)
const response = await POST(buildRequest())
const data = await response.json()
expect(response.status).toBe(404)
expect(data.error).toBe('素材不存在')
expect(prisma.material.findFirst).toHaveBeenCalledWith(
expect.objectContaining({
where: {
id: 'material-1',
deletedAt: null,
},
})
)
})
test('无权管理该素材的普通用户不能创建任务', async () => {
getServerSession.mockResolvedValue({
user: {
id: 'other-user',
role: 'USER',
},
})
const response = await POST(buildRequest())
const data = await response.json()
expect(response.status).toBe(403)
expect(data.error).toBe('您没有权限操作此素材')
})
test('素材本人可以创建占位任务', async () => {
const response = await POST(buildRequest({ params: { prompt: '调整亮度' } }))
const data = await response.json()
expect(response.status).toBe(200)
expect(data.status).toBe('queued')
expect(data.materialId).toBe('material-1')
expect(data.operation).toBe('remove-background')
expect(data.params).toEqual({ prompt: '调整亮度' })
})
})