flnxi-Wu/app/api/tunnel/__tests__/route.test.ts
2026-05-25 17:12:11 +08:00

139 lines
3.8 KiB
TypeScript

import { NextRequest } from 'next/server'
jest.mock('@/lib/auth', () => ({
authOptions: {},
}))
jest.mock('next-auth', () => ({
getServerSession: jest.fn(),
}))
jest.mock('@/lib/config', () => ({
featureFlags: {
tunnelEnabled: false,
},
}))
jest.mock('@/lib/license', () => ({
canUseIntranetPenetration: jest.fn(),
}))
jest.mock('@/lib/prisma', () => ({
prisma: {
user: {
findUnique: jest.fn(),
},
systemSettings: {
findFirst: jest.fn(),
},
},
}))
jest.mock('@/lib/admin-permissions', () => ({
isCurrentSuperAdmin: jest.fn(),
}))
import { POST as startTunnel } from '../start/route'
import { GET as getTunnelStatus } from '../status/route'
import { POST as stopTunnel } from '../stop/route'
const { getServerSession } = require('next-auth')
const { canUseIntranetPenetration } = require('@/lib/license')
const { prisma } = require('@/lib/prisma')
const { isCurrentSuperAdmin } = require('@/lib/admin-permissions')
function buildRequest(method: string) {
return new NextRequest('http://localhost:3000/api/tunnel', { method })
}
describe('内网穿透 API 许可证边界', () => {
beforeEach(() => {
jest.resetAllMocks()
getServerSession.mockResolvedValue({
user: {
id: 'super-admin-1',
role: 'ADMIN',
isSuperAdmin: true,
},
})
prisma.systemSettings.findFirst.mockResolvedValue({
enableTunnelService: true,
})
isCurrentSuperAdmin.mockResolvedValue(true)
canUseIntranetPenetration.mockResolvedValue(true)
})
test('未登录不能启动内网穿透', async () => {
getServerSession.mockResolvedValue(null)
const response = await startTunnel(buildRequest('POST'))
const data = await response.json()
expect(response.status).toBe(401)
expect(data.error).toBe('未登录')
expect(canUseIntranetPenetration).not.toHaveBeenCalled()
})
test('旧会话带最高权限标记但数据库已撤销时不能启动', async () => {
getServerSession.mockResolvedValue({
user: {
id: 'admin-1',
role: 'ADMIN',
isSuperAdmin: true,
},
})
isCurrentSuperAdmin.mockResolvedValue(false)
const response = await startTunnel(buildRequest('POST'))
const data = await response.json()
expect(response.status).toBe(403)
expect(data.error).toContain('最高权限')
expect(prisma.systemSettings.findFirst).not.toHaveBeenCalled()
expect(canUseIntranetPenetration).not.toHaveBeenCalled()
})
test('许可证不包含内网穿透时不能启动', async () => {
canUseIntranetPenetration.mockResolvedValue(false)
const response = await startTunnel(buildRequest('POST'))
const data = await response.json()
expect(response.status).toBe(403)
expect(data.error).toContain('许可证')
})
test('许可证不包含内网穿透时不能查看状态', async () => {
canUseIntranetPenetration.mockResolvedValue(false)
const response = await getTunnelStatus(buildRequest('GET'))
const data = await response.json()
expect(response.status).toBe(403)
expect(data.status).toBe('license_restricted')
expect(data.error).toContain('许可证')
})
test('许可证不包含内网穿透时不能停止', async () => {
canUseIntranetPenetration.mockResolvedValue(false)
const response = await stopTunnel(buildRequest('POST'))
const data = await response.json()
expect(response.status).toBe(403)
expect(data.error).toContain('许可证')
})
test('最高权限账号且许可证允许时可以启动占位隧道', async () => {
const response = await startTunnel(buildRequest('POST'))
const data = await response.json()
expect(response.status).toBe(200)
expect(data.tunnelUrl).toBe('https://mock-tunnel.example.com')
expect(canUseIntranetPenetration).toHaveBeenCalled()
})
})