175 lines
4.2 KiB
TypeScript
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: '调整亮度' })
|
|
})
|
|
})
|