70 lines
1.9 KiB
TypeScript
70 lines
1.9 KiB
TypeScript
jest.mock('@/lib/prisma', () => ({
|
|
prisma: {
|
|
systemSettings: {
|
|
findFirst: jest.fn(),
|
|
},
|
|
user: {
|
|
findUnique: jest.fn(),
|
|
},
|
|
},
|
|
}))
|
|
|
|
jest.mock('@/lib/dingtalk-login-token', () => ({
|
|
consumeDingtalkLoginToken: jest.fn(),
|
|
}))
|
|
|
|
jest.mock('bcryptjs', () => ({
|
|
compare: jest.fn(),
|
|
}))
|
|
|
|
import { authOptions } from '../auth'
|
|
import { consumeDingtalkLoginToken } from '../dingtalk-login-token'
|
|
import { prisma } from '../prisma'
|
|
|
|
const mockConsumeDingtalkLoginToken = consumeDingtalkLoginToken as jest.MockedFunction<typeof consumeDingtalkLoginToken>
|
|
|
|
function getDingtalkProvider() {
|
|
const provider = authOptions.providers.find((item: any) => item.id === 'credentials') as any
|
|
if (!provider) {
|
|
throw new Error('credentials provider missing')
|
|
}
|
|
return provider
|
|
}
|
|
|
|
describe('auth dingtalk-token provider', () => {
|
|
beforeEach(() => {
|
|
jest.clearAllMocks()
|
|
;(prisma.systemSettings.findFirst as jest.Mock).mockResolvedValue(null)
|
|
})
|
|
|
|
it('使用一次性钉钉票据登录并返回会话用户', async () => {
|
|
mockConsumeDingtalkLoginToken.mockResolvedValue({
|
|
id: 'user-1',
|
|
email: 'user@example.com',
|
|
username: '张三',
|
|
role: 'USER',
|
|
isSuperAdmin: false,
|
|
avatar: null,
|
|
isActive: true,
|
|
})
|
|
|
|
const user = await getDingtalkProvider().options.authorize({ dingtalkToken: 'one-time-token' })
|
|
|
|
expect(mockConsumeDingtalkLoginToken).toHaveBeenCalledWith('one-time-token', 'login')
|
|
expect(user).toEqual(expect.objectContaining({
|
|
id: 'user-1',
|
|
email: 'user@example.com',
|
|
name: '张三',
|
|
role: 'USER',
|
|
}))
|
|
})
|
|
|
|
it('拒绝无效或已消费的钉钉票据', async () => {
|
|
mockConsumeDingtalkLoginToken.mockResolvedValue(null)
|
|
|
|
await expect(getDingtalkProvider().options.authorize({ dingtalkToken: 'bad-token' }))
|
|
.rejects
|
|
.toThrow('钉钉登录凭证已失效')
|
|
})
|
|
})
|