|
|
@@ -2,6 +2,7 @@ import { describe, test, expect, beforeAll, afterAll, vi } from 'vitest'
|
|
|
import { testClient } from 'hono/testing'
|
|
|
import { agoraApiRoutes } from '@/server/api'
|
|
|
import { AgoraTokenService } from '@/server/modules/agora/agora-token.service'
|
|
|
+import { authMiddleware } from '@/server/middleware/auth.middleware'
|
|
|
|
|
|
// 模拟AgoraTokenService
|
|
|
vi.mock('@/server/modules/agora/agora-token.service', () => ({
|
|
|
@@ -19,6 +20,24 @@ vi.mock('@/server/modules/agora/agora-token.service', () => ({
|
|
|
}))
|
|
|
}))
|
|
|
|
|
|
+// Mock用户数据
|
|
|
+const mockUser = {
|
|
|
+ id: 1,
|
|
|
+ username: 'testuser',
|
|
|
+ password: 'password123',
|
|
|
+ phone: null,
|
|
|
+ email: 'test@example.com',
|
|
|
+ nickname: null,
|
|
|
+ name: null,
|
|
|
+ avatarFileId: null,
|
|
|
+ avatarFile: null,
|
|
|
+ isDisabled: 0,
|
|
|
+ isDeleted: 0,
|
|
|
+ roles: [],
|
|
|
+ createdAt: new Date(),
|
|
|
+ updatedAt: new Date()
|
|
|
+}
|
|
|
+
|
|
|
describe('Agora Token API 集成测试', () => {
|
|
|
let client: ReturnType<typeof testClient<typeof agoraApiRoutes>>['api']['v1']
|
|
|
|
|
|
@@ -28,6 +47,16 @@ describe('Agora Token API 集成测试', () => {
|
|
|
process.env.AGORA_APP_SECRET = 'test-app-secret'
|
|
|
process.env.AGORA_TOKEN_EXPIRY = '3600'
|
|
|
|
|
|
+ // Mock auth middleware
|
|
|
+ vi.mocked(authMiddleware).mockImplementation(async (c, next) => {
|
|
|
+ const authHeader = c.req.header('Authorization')
|
|
|
+ if (!authHeader) {
|
|
|
+ return c.json({ message: 'Authorization header missing' }, 401)
|
|
|
+ }
|
|
|
+ c.set('user', mockUser)
|
|
|
+ await next()
|
|
|
+ })
|
|
|
+
|
|
|
// 创建测试客户端
|
|
|
client = testClient(agoraApiRoutes).api.v1
|
|
|
})
|
|
|
@@ -36,32 +65,90 @@ describe('Agora Token API 集成测试', () => {
|
|
|
vi.clearAllMocks()
|
|
|
})
|
|
|
|
|
|
+ test('AgoraTokenService参数验证功能', () => {
|
|
|
+ const agoraTokenService = new AgoraTokenService()
|
|
|
+
|
|
|
+ // 测试RTC Token参数验证
|
|
|
+ expect(() => {
|
|
|
+ agoraTokenService.validateTokenParams('rtc', 'test-channel')
|
|
|
+ }).not.toThrow()
|
|
|
+
|
|
|
+ // 测试RTC Token缺少channel参数
|
|
|
+ expect(() => {
|
|
|
+ agoraTokenService.validateTokenParams('rtc')
|
|
|
+ }).toThrow('RTC Token需要提供channel参数')
|
|
|
+
|
|
|
+ // 测试RTM Token参数验证
|
|
|
+ expect(() => {
|
|
|
+ agoraTokenService.validateTokenParams('rtm', undefined, 'test-user')
|
|
|
+ }).not.toThrow()
|
|
|
+
|
|
|
+ // 测试RTM Token缺少userId参数
|
|
|
+ expect(() => {
|
|
|
+ agoraTokenService.validateTokenParams('rtm')
|
|
|
+ }).toThrow('RTM Token需要提供userId参数')
|
|
|
+
|
|
|
+ // 测试频道名称长度限制
|
|
|
+ expect(() => {
|
|
|
+ agoraTokenService.validateTokenParams('rtc', 'a'.repeat(65))
|
|
|
+ }).toThrow('频道名称长度不能超过64个字符')
|
|
|
+
|
|
|
+ // 测试用户ID长度限制
|
|
|
+ expect(() => {
|
|
|
+ agoraTokenService.validateTokenParams('rtm', undefined, 'a'.repeat(65))
|
|
|
+ }).toThrow('用户ID长度不能超过64个字符')
|
|
|
+ })
|
|
|
+
|
|
|
+ test('AgoraTokenService Token生成功能', () => {
|
|
|
+ const agoraTokenService = new AgoraTokenService()
|
|
|
+
|
|
|
+ // 测试RTC Token生成
|
|
|
+ const rtcToken = agoraTokenService.generateRtcToken('test-channel', '123')
|
|
|
+ expect(rtcToken).toBe('mock-rtc-token')
|
|
|
+
|
|
|
+ // 测试RTM Token生成
|
|
|
+ const rtmToken = agoraTokenService.generateRtmToken('test-user')
|
|
|
+ expect(rtmToken).toBe('mock-rtm-token')
|
|
|
+
|
|
|
+ // 测试Token信息获取
|
|
|
+ const tokenInfo = agoraTokenService.getTokenInfo('test-token', 'rtc')
|
|
|
+ expect(tokenInfo).toEqual({
|
|
|
+ token: 'test-token',
|
|
|
+ type: 'rtc',
|
|
|
+ expiresAt: expect.any(Number),
|
|
|
+ expiresIn: 3600,
|
|
|
+ generatedAt: expect.any(Number)
|
|
|
+ })
|
|
|
+ })
|
|
|
+
|
|
|
test('未认证用户访问Token API应该返回401', async () => {
|
|
|
- const response = await client.api.v1.agora.token.$get({
|
|
|
+ // 临时修改mock以模拟未认证
|
|
|
+ vi.mocked(authMiddleware).mockImplementation(async (c) => {
|
|
|
+ return c.json({ message: 'Authorization header missing' }, 401)
|
|
|
+ })
|
|
|
+
|
|
|
+ const response = await client.agora.token.$get({
|
|
|
query: { type: 'rtc', channel: 'test-channel' }
|
|
|
})
|
|
|
|
|
|
expect(response.status).toBe(401)
|
|
|
- })
|
|
|
|
|
|
- test('认证用户生成RTC Token成功', async () => {
|
|
|
- // 模拟认证中间件
|
|
|
- const mockAuthMiddleware = vi.fn((c, next) => {
|
|
|
- c.set('user', { id: 1, username: 'testuser', role: 'admin' })
|
|
|
- return next()
|
|
|
+ // 恢复mock
|
|
|
+ vi.mocked(authMiddleware).mockImplementation(async (c, next) => {
|
|
|
+ const authHeader = c.req.header('Authorization')
|
|
|
+ if (!authHeader) {
|
|
|
+ return c.json({ message: 'Authorization header missing' }, 401)
|
|
|
+ }
|
|
|
+ c.set('user', mockUser)
|
|
|
+ await next()
|
|
|
})
|
|
|
+ })
|
|
|
|
|
|
- // 临时替换认证中间件
|
|
|
- const originalMiddleware = app.middleware
|
|
|
- app.middleware = mockAuthMiddleware
|
|
|
-
|
|
|
- const response = await client.api.v1.agora.token.$get({
|
|
|
+ test('认证用户生成RTC Token成功', async () => {
|
|
|
+ const response = await client.agora.token.$get({
|
|
|
query: { type: 'rtc', channel: 'test-channel' }
|
|
|
})
|
|
|
|
|
|
- // 恢复原始中间件
|
|
|
- app.middleware = originalMiddleware
|
|
|
-
|
|
|
expect(response.status).toBe(200)
|
|
|
|
|
|
const data = await response.json()
|
|
|
@@ -72,23 +159,10 @@ describe('Agora Token API 集成测试', () => {
|
|
|
})
|
|
|
|
|
|
test('认证用户生成RTM Token成功', async () => {
|
|
|
- // 模拟认证中间件
|
|
|
- const mockAuthMiddleware = vi.fn((c, next) => {
|
|
|
- c.set('user', { id: 1, username: 'testuser', role: 'admin' })
|
|
|
- return next()
|
|
|
- })
|
|
|
-
|
|
|
- // 临时替换认证中间件
|
|
|
- const originalMiddleware = app.middleware
|
|
|
- app.middleware = mockAuthMiddleware
|
|
|
-
|
|
|
- const response = await client.api.v1.agora.token.$get({
|
|
|
+ const response = await client.agora.token.$get({
|
|
|
query: { type: 'rtm', userId: 'test-user-123' }
|
|
|
})
|
|
|
|
|
|
- // 恢复原始中间件
|
|
|
- app.middleware = originalMiddleware
|
|
|
-
|
|
|
expect(response.status).toBe(200)
|
|
|
|
|
|
const data = await response.json()
|
|
|
@@ -97,95 +171,39 @@ describe('Agora Token API 集成测试', () => {
|
|
|
expect(data.expiresIn).toBe(3600)
|
|
|
})
|
|
|
|
|
|
- test('RTC Token缺少channel参数应该返回400', async () => {
|
|
|
- // 模拟认证中间件
|
|
|
- const mockAuthMiddleware = vi.fn((c, next) => {
|
|
|
- c.set('user', { id: 1, username: 'testuser', role: 'admin' })
|
|
|
- return next()
|
|
|
- })
|
|
|
-
|
|
|
- // 临时替换认证中间件
|
|
|
- const originalMiddleware = app.middleware
|
|
|
- app.middleware = mockAuthMiddleware
|
|
|
-
|
|
|
- const response = await client.api.v1.agora.token.$get({
|
|
|
- query: { type: 'rtc' } // 缺少channel参数
|
|
|
+ test('路由参数验证 - 无效Token类型', async () => {
|
|
|
+ // 使用无效的type参数
|
|
|
+ const response = await client.agora.token.$get({
|
|
|
+ query: { type: 'invalid-type', channel: 'test-channel' }
|
|
|
})
|
|
|
|
|
|
- // 恢复原始中间件
|
|
|
- app.middleware = originalMiddleware
|
|
|
-
|
|
|
+ // 由于Zod验证,应该返回400错误
|
|
|
expect(response.status).toBe(400)
|
|
|
-
|
|
|
- const data = await response.json()
|
|
|
- expect(data.message).toContain('RTC Token需要提供channel参数')
|
|
|
})
|
|
|
|
|
|
- test('RTM Token缺少userId参数应该返回400', async () => {
|
|
|
- // 模拟认证中间件
|
|
|
- const mockAuthMiddleware = vi.fn((c, next) => {
|
|
|
- c.set('user', { id: 1, username: 'testuser', role: 'admin' })
|
|
|
- return next()
|
|
|
+ test('路由参数验证 - 缺少必需参数', async () => {
|
|
|
+ // 测试缺少channel参数
|
|
|
+ const response1 = await client.agora.token.$get({
|
|
|
+ query: { type: 'rtc' } // 缺少channel参数
|
|
|
})
|
|
|
|
|
|
- // 临时替换认证中间件
|
|
|
- const originalMiddleware = app.middleware
|
|
|
- app.middleware = mockAuthMiddleware
|
|
|
+ // 由于Zod验证,应该返回400错误
|
|
|
+ expect(response1.status).toBe(400)
|
|
|
|
|
|
- const response = await client.api.v1.agora.token.$get({
|
|
|
+ // 测试缺少userId参数
|
|
|
+ const response2 = await client.agora.token.$get({
|
|
|
query: { type: 'rtm' } // 缺少userId参数
|
|
|
})
|
|
|
|
|
|
- // 恢复原始中间件
|
|
|
- app.middleware = originalMiddleware
|
|
|
-
|
|
|
- expect(response.status).toBe(400)
|
|
|
-
|
|
|
- const data = await response.json()
|
|
|
- expect(data.message).toContain('RTM Token需要提供userId参数')
|
|
|
- })
|
|
|
-
|
|
|
- test('无效的Token类型应该返回400', async () => {
|
|
|
- // 模拟认证中间件
|
|
|
- const mockAuthMiddleware = vi.fn((c, next) => {
|
|
|
- c.set('user', { id: 1, username: 'testuser', role: 'admin' })
|
|
|
- return next()
|
|
|
- })
|
|
|
-
|
|
|
- // 临时替换认证中间件
|
|
|
- const originalMiddleware = app.middleware
|
|
|
- app.middleware = mockAuthMiddleware
|
|
|
-
|
|
|
- // 使用无效的type参数
|
|
|
- const response = await client.api.v1.agora.token.$get({
|
|
|
- query: { type: 'invalid-type', channel: 'test-channel' }
|
|
|
- })
|
|
|
-
|
|
|
- // 恢复原始中间件
|
|
|
- app.middleware = originalMiddleware
|
|
|
-
|
|
|
// 由于Zod验证,应该返回400错误
|
|
|
- expect(response.status).toBe(400)
|
|
|
+ expect(response2.status).toBe(400)
|
|
|
})
|
|
|
|
|
|
test('Token有效期和格式验证', async () => {
|
|
|
- // 模拟认证中间件
|
|
|
- const mockAuthMiddleware = vi.fn((c, next) => {
|
|
|
- c.set('user', { id: 1, username: 'testuser', role: 'admin' })
|
|
|
- return next()
|
|
|
- })
|
|
|
-
|
|
|
- // 临时替换认证中间件
|
|
|
- const originalMiddleware = app.middleware
|
|
|
- app.middleware = mockAuthMiddleware
|
|
|
-
|
|
|
- const response = await client.api.v1.agora.token.$get({
|
|
|
+ const response = await client.agora.token.$get({
|
|
|
query: { type: 'rtc', channel: 'test-channel' }
|
|
|
})
|
|
|
|
|
|
- // 恢复原始中间件
|
|
|
- app.middleware = originalMiddleware
|
|
|
-
|
|
|
expect(response.status).toBe(200)
|
|
|
|
|
|
const data = await response.json()
|