|
|
@@ -0,0 +1,202 @@
|
|
|
+import { describe, test, expect, beforeAll, afterAll, vi } from 'vitest'
|
|
|
+import { createTestClient } from 'hono/testing'
|
|
|
+import app from '../index'
|
|
|
+import { AgoraTokenService } from '@/server/modules/agora/agora-token.service'
|
|
|
+
|
|
|
+// 模拟AgoraTokenService
|
|
|
+vi.mock('@/server/modules/agora/agora-token.service', () => ({
|
|
|
+ AgoraTokenService: vi.fn().mockImplementation(() => ({
|
|
|
+ generateRtcToken: vi.fn().mockReturnValue('mock-rtc-token'),
|
|
|
+ generateRtmToken: vi.fn().mockReturnValue('mock-rtm-token'),
|
|
|
+ validateTokenParams: vi.fn(),
|
|
|
+ getTokenInfo: vi.fn().mockImplementation((token, type) => ({
|
|
|
+ token,
|
|
|
+ type,
|
|
|
+ expiresAt: Math.floor(Date.now() / 1000) + 3600,
|
|
|
+ expiresIn: 3600,
|
|
|
+ generatedAt: Math.floor(Date.now() / 1000)
|
|
|
+ }))
|
|
|
+ }))
|
|
|
+}))
|
|
|
+
|
|
|
+describe('Agora Token API 集成测试', () => {
|
|
|
+ const client = createTestClient(app)
|
|
|
+
|
|
|
+ beforeAll(() => {
|
|
|
+ // 设置测试环境变量
|
|
|
+ process.env.AGORA_APP_ID = 'test-app-id'
|
|
|
+ process.env.AGORA_APP_SECRET = 'test-app-secret'
|
|
|
+ process.env.AGORA_TOKEN_EXPIRY = '3600'
|
|
|
+ })
|
|
|
+
|
|
|
+ afterAll(() => {
|
|
|
+ vi.clearAllMocks()
|
|
|
+ })
|
|
|
+
|
|
|
+ test('未认证用户访问Token API应该返回401', async () => {
|
|
|
+ const response = await client.api.v1.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()
|
|
|
+ })
|
|
|
+
|
|
|
+ // 临时替换认证中间件
|
|
|
+ const originalMiddleware = app.middleware
|
|
|
+ app.middleware = mockAuthMiddleware
|
|
|
+
|
|
|
+ const response = await client.api.v1.agora.token.$get({
|
|
|
+ query: { type: 'rtc', channel: 'test-channel' }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 恢复原始中间件
|
|
|
+ app.middleware = originalMiddleware
|
|
|
+
|
|
|
+ expect(response.status).toBe(200)
|
|
|
+
|
|
|
+ const data = await response.json()
|
|
|
+ expect(data.token).toBe('mock-rtc-token')
|
|
|
+ expect(data.type).toBe('rtc')
|
|
|
+ expect(data.expiresIn).toBe(3600)
|
|
|
+ expect(data.expiresAt).toBeGreaterThan(Math.floor(Date.now() / 1000))
|
|
|
+ })
|
|
|
+
|
|
|
+ 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({
|
|
|
+ query: { type: 'rtm', userId: 'test-user-123' }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 恢复原始中间件
|
|
|
+ app.middleware = originalMiddleware
|
|
|
+
|
|
|
+ expect(response.status).toBe(200)
|
|
|
+
|
|
|
+ const data = await response.json()
|
|
|
+ expect(data.token).toBe('mock-rtm-token')
|
|
|
+ expect(data.type).toBe('rtm')
|
|
|
+ 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参数
|
|
|
+ })
|
|
|
+
|
|
|
+ // 恢复原始中间件
|
|
|
+ app.middleware = originalMiddleware
|
|
|
+
|
|
|
+ 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()
|
|
|
+ })
|
|
|
+
|
|
|
+ // 临时替换认证中间件
|
|
|
+ const originalMiddleware = app.middleware
|
|
|
+ app.middleware = mockAuthMiddleware
|
|
|
+
|
|
|
+ const response = await client.api.v1.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)
|
|
|
+ })
|
|
|
+
|
|
|
+ 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({
|
|
|
+ query: { type: 'rtc', channel: 'test-channel' }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 恢复原始中间件
|
|
|
+ app.middleware = originalMiddleware
|
|
|
+
|
|
|
+ expect(response.status).toBe(200)
|
|
|
+
|
|
|
+ const data = await response.json()
|
|
|
+
|
|
|
+ // 验证Token信息格式
|
|
|
+ expect(data).toHaveProperty('token')
|
|
|
+ expect(data).toHaveProperty('type')
|
|
|
+ expect(data).toHaveProperty('expiresAt')
|
|
|
+ expect(data).toHaveProperty('expiresIn')
|
|
|
+ expect(data).toHaveProperty('generatedAt')
|
|
|
+
|
|
|
+ // 验证时间戳格式
|
|
|
+ expect(data.expiresAt).toBeGreaterThan(data.generatedAt)
|
|
|
+ expect(data.expiresIn).toBe(3600)
|
|
|
+ expect(data.expiresAt - data.generatedAt).toBe(data.expiresIn)
|
|
|
+ })
|
|
|
+})
|