2026-06-03 18:41:52 +08:00

178 lines
5.3 KiB
TypeScript

import { NextRequest } from 'next/server'
jest.mock('@/lib/auth', () => ({
authOptions: {},
}))
jest.mock('next-auth', () => ({
getServerSession: jest.fn(),
}))
jest.mock('@/lib/prisma', () => ({
prisma: {
department: {
findUnique: jest.fn(),
findMany: jest.fn(),
create: jest.fn(),
deleteMany: jest.fn(),
},
user: {
findUnique: jest.fn(),
findMany: jest.fn(),
updateMany: jest.fn(),
update: jest.fn(),
},
$transaction: jest.fn(),
},
}))
jest.mock('@/lib/license', () => ({
canUseDepartmentIsolation: jest.fn(),
planDepartmentStructureChangeWithPaidCore: jest.fn(),
}))
const { getServerSession } = require('next-auth')
const { prisma } = require('@/lib/prisma')
const { canUseDepartmentIsolation, planDepartmentStructureChangeWithPaidCore } = require('@/lib/license')
import { POST, PATCH, DELETE } from '../route'
describe('departments route license guard', () => {
beforeEach(() => {
jest.clearAllMocks()
getServerSession.mockResolvedValue({
user: { id: 'admin-id', role: 'ADMIN' },
})
prisma.user.findUnique.mockResolvedValue({ isSuperAdmin: true })
prisma.department.findMany.mockResolvedValue([])
planDepartmentStructureChangeWithPaidCore.mockImplementation(async ({ action, target }: any) => {
if (action === 'create') {
return {
valid: true,
allowed: true,
action,
departmentOps: [{ type: 'create', data: { name: String(target.name).trim() } }],
userOps: [],
}
}
return {
valid: false,
allowed: false,
error: '未设置测试计划',
errorCode: 'TEST_PLAN_MISSING',
statusCode: 500,
}
})
canUseDepartmentIsolation.mockResolvedValue(true)
})
test('POST 普通管理员不能创建部门', async () => {
prisma.user.findUnique.mockResolvedValue({ isSuperAdmin: false })
const request = new NextRequest('http://localhost/api/departments', {
method: 'POST',
body: JSON.stringify({ name: '设计部' }),
})
const response = await POST(request)
const data = await response.json()
expect(response.status).toBe(403)
expect(data.error).toContain('最高权限')
expect(canUseDepartmentIsolation).not.toHaveBeenCalled()
expect(prisma.department.create).not.toHaveBeenCalled()
})
test('POST 最高权限账号可以创建部门', async () => {
prisma.department.create.mockResolvedValue({ id: 'dept-1', name: '设计部' })
const request = new NextRequest('http://localhost/api/departments', {
method: 'POST',
body: JSON.stringify({ name: '设计部' }),
})
const response = await POST(request)
const data = await response.json()
expect(response.status).toBe(201)
expect(data.name).toBe('设计部')
expect(planDepartmentStructureChangeWithPaidCore).toHaveBeenCalledWith({
action: 'create',
target: { name: '设计部' },
departments: [],
})
expect(prisma.department.create).toHaveBeenCalledWith({ data: { name: '设计部' } })
})
test('PATCH 应在许可证不支持时返回 403', async () => {
canUseDepartmentIsolation.mockResolvedValue(false)
const request = new NextRequest('http://localhost/api/departments', {
method: 'PATCH',
body: JSON.stringify({
id: 'dept-1',
name: '新部门',
}),
})
const response = await PATCH(request)
const data = await response.json()
expect(response.status).toBe(403)
expect(data.error).toContain('当前许可证未包含部门隔离功能')
expect(prisma.department.findUnique).not.toHaveBeenCalled()
})
test('PATCH 普通管理员不能重命名部门', async () => {
prisma.user.findUnique.mockResolvedValue({ isSuperAdmin: false })
const request = new NextRequest('http://localhost/api/departments', {
method: 'PATCH',
body: JSON.stringify({
id: 'dept-1',
name: '新部门',
}),
})
const response = await PATCH(request)
const data = await response.json()
expect(response.status).toBe(403)
expect(data.error).toContain('最高权限')
expect(canUseDepartmentIsolation).not.toHaveBeenCalled()
expect(prisma.department.findUnique).not.toHaveBeenCalled()
})
test('DELETE 应在许可证不支持时返回 403', async () => {
canUseDepartmentIsolation.mockResolvedValue(false)
const request = new NextRequest('http://localhost/api/departments?id=dept-1', {
method: 'DELETE',
})
const response = await DELETE(request)
const data = await response.json()
expect(response.status).toBe(403)
expect(data.error).toContain('当前许可证未包含部门隔离功能')
expect(prisma.department.findUnique).not.toHaveBeenCalled()
})
test('DELETE 普通管理员不能删除部门', async () => {
prisma.user.findUnique.mockResolvedValue({ isSuperAdmin: false })
const request = new NextRequest('http://localhost/api/departments?id=dept-1', {
method: 'DELETE',
})
const response = await DELETE(request)
const data = await response.json()
expect(response.status).toBe(403)
expect(data.error).toContain('最高权限')
expect(canUseDepartmentIsolation).not.toHaveBeenCalled()
expect(prisma.department.findUnique).not.toHaveBeenCalled()
})
})