gongxiangp2/lib/__tests__/dingtalk-complete-profile-route.test.ts

124 lines
4.1 KiB
TypeScript

/** @jest-environment node */
import { getServerSession } from 'next-auth'
import { POST } from '@/app/api/dingtalk/complete-profile/route'
import { prisma } from '@/lib/prisma'
import { verifyDingtalkProfileToken } from '@/lib/dingtalk-profile-token'
jest.mock('next-auth', () => ({
getServerSession: jest.fn(),
}))
jest.mock('@/lib/auth', () => ({ authOptions: {} }))
jest.mock('@/lib/dingtalk-profile-token', () => ({
getDingtalkProfileCookieCandidates: jest.fn(() => ['dingtalk-profile-token']),
getDingtalkProfileCookiePath: jest.fn(() => '/api/dingtalk/complete-profile'),
verifyDingtalkProfileToken: jest.fn().mockResolvedValue(null),
}))
jest.mock('@/lib/prisma', () => ({
prisma: {
user: {
findUnique: jest.fn(),
update: jest.fn(),
},
department: {
findUnique: jest.fn(),
},
},
}))
describe('dingtalk complete-profile route', () => {
beforeEach(() => {
jest.clearAllMocks()
;(verifyDingtalkProfileToken as jest.Mock).mockResolvedValue(null)
})
function createRequest(body: Record<string, unknown>, profileToken?: string) {
return {
json: jest.fn().mockResolvedValue(body),
cookies: {
get: jest.fn((name: string) =>
name === 'dingtalk-profile-token' && profileToken
? { value: profileToken }
: undefined,
),
},
} as any
}
test('匿名请求不得完善资料', async () => {
;(getServerSession as jest.Mock).mockResolvedValue(null)
const response = await POST(createRequest({ userId: 'user-1', department: '设计部' }))
expect(response.status).toBe(401)
expect(prisma.user.update).not.toHaveBeenCalled()
})
test('登录用户不得修改其他用户资料', async () => {
;(getServerSession as jest.Mock).mockResolvedValue({ user: { id: 'user-1' } })
const response = await POST(createRequest({ userId: 'user-2', department: '设计部' }))
expect(response.status).toBe(403)
expect(prisma.user.findUnique).not.toHaveBeenCalled()
expect(prisma.user.update).not.toHaveBeenCalled()
})
test('仅更新会话本人并绑定真实部门', async () => {
;(getServerSession as jest.Mock).mockResolvedValue({ user: { id: 'user-1' } })
;(prisma.user.findUnique as jest.Mock).mockResolvedValue({ id: 'user-1' })
;(prisma.department.findUnique as jest.Mock).mockResolvedValue({ id: 'dept-1', name: '设计部' })
;(prisma.user.update as jest.Mock).mockResolvedValue({
id: 'user-1',
username: 'tester',
email: 'tester@example.com',
realName: '测试用户',
avatar: null,
role: 'USER',
department: '设计部',
isActive: false,
status: 'pending',
})
const response = await POST(createRequest({ userId: 'user-1', department: ' 设计部 ' }))
expect(response.status).toBe(200)
expect(prisma.user.update).toHaveBeenCalledWith(expect.objectContaining({
where: { id: 'user-1' },
data: { department: '设计部', departmentId: 'dept-1' },
}))
})
test('首次登录用户可用短时资料凭证完善自己的部门', async () => {
;(getServerSession as jest.Mock).mockResolvedValue(null)
;(verifyDingtalkProfileToken as jest.Mock).mockResolvedValue('user-1')
;(prisma.user.findUnique as jest.Mock).mockResolvedValue({ id: 'user-1' })
;(prisma.department.findUnique as jest.Mock).mockResolvedValue({ id: 'dept-1', name: '设计部' })
;(prisma.user.update as jest.Mock).mockResolvedValue({
id: 'user-1',
username: 'tester',
email: 'tester@example.com',
realName: '测试用户',
avatar: null,
role: 'USER',
department: '设计部',
isActive: false,
status: 'pending',
})
const response = await POST(
createRequest({ userId: 'user-1', department: '设计部' }, 'signed-profile-token'),
)
expect(response.status).toBe(200)
expect(verifyDingtalkProfileToken).toHaveBeenCalledWith('signed-profile-token')
expect(prisma.user.update).toHaveBeenCalledWith(expect.objectContaining({
where: { id: 'user-1' },
}))
expect(response.headers.get('set-cookie')).toContain('Max-Age=0')
})
})