|
|
@@ -0,0 +1,234 @@
|
|
|
+import { describe, test, expect, beforeAll, afterAll, vi } from 'vitest'
|
|
|
+import { testClient } from 'hono/testing'
|
|
|
+import { agoraApiRoutes } from '@/server/api'
|
|
|
+import { authMiddleware } from '@/server/middleware/auth.middleware'
|
|
|
+
|
|
|
+// 只在有真实Agora配置时运行这些测试
|
|
|
+const hasRealAgoraConfig = process.env.AGORA_APP_ID && process.env.AGORA_APP_SECRET
|
|
|
+
|
|
|
+// 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()
|
|
|
+}
|
|
|
+
|
|
|
+// Mock auth middleware
|
|
|
+vi.mock('@/server/middleware/auth.middleware', () => ({
|
|
|
+ authMiddleware: vi.fn()
|
|
|
+}));
|
|
|
+
|
|
|
+describe('Agora Token API 真实API集成测试', () => {
|
|
|
+ let client: ReturnType<typeof testClient<typeof agoraApiRoutes>>['api']['v1']
|
|
|
+
|
|
|
+ beforeAll(() => {
|
|
|
+ // 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
|
|
|
+ })
|
|
|
+
|
|
|
+ afterAll(() => {
|
|
|
+ vi.clearAllMocks()
|
|
|
+ })
|
|
|
+
|
|
|
+ // 跳过测试如果没有真实配置
|
|
|
+ const runIfRealConfig = hasRealAgoraConfig ? test : test.skip
|
|
|
+
|
|
|
+ runIfRealConfig('真实RTC Token生成测试', async () => {
|
|
|
+ const response = await client.agora.token.$get({
|
|
|
+ query: { type: 'rtc', channel: 'test-real-channel' }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ headers: {
|
|
|
+ 'Authorization': 'Bearer test-token'
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ expect(response.status).toBe(200)
|
|
|
+
|
|
|
+ const data = await response.json()
|
|
|
+
|
|
|
+ // 类型断言
|
|
|
+ if ('token' in data) {
|
|
|
+ // 验证真实Token格式
|
|
|
+ expect(data).toHaveProperty('token')
|
|
|
+ expect(data).toHaveProperty('type')
|
|
|
+ expect(data).toHaveProperty('expiresAt')
|
|
|
+ expect(data).toHaveProperty('expiresIn')
|
|
|
+ expect(data).toHaveProperty('generatedAt')
|
|
|
+
|
|
|
+ // 验证Token类型
|
|
|
+ expect(data.type).toBe('rtc')
|
|
|
+
|
|
|
+ // 验证Token格式(Agora Token通常以特定格式开头)
|
|
|
+ expect(data.token).toMatch(/^[A-Za-z0-9+/=]+$/)
|
|
|
+ expect(data.token.length).toBeGreaterThan(50)
|
|
|
+
|
|
|
+ // 验证时间戳格式
|
|
|
+ expect(data.expiresAt).toBeGreaterThan(data.generatedAt)
|
|
|
+ expect(data.expiresIn).toBeGreaterThan(0)
|
|
|
+ expect(data.expiresAt - data.generatedAt).toBe(data.expiresIn)
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ runIfRealConfig('真实RTM Token生成测试', async () => {
|
|
|
+ const response = await client.agora.token.$get({
|
|
|
+ query: { type: 'rtm', userId: 'test-real-user-123' }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ headers: {
|
|
|
+ 'Authorization': 'Bearer test-token'
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ expect(response.status).toBe(200)
|
|
|
+
|
|
|
+ const data = await response.json()
|
|
|
+
|
|
|
+ // 类型断言
|
|
|
+ if ('token' in data) {
|
|
|
+ // 验证真实Token格式
|
|
|
+ expect(data).toHaveProperty('token')
|
|
|
+ expect(data).toHaveProperty('type')
|
|
|
+ expect(data).toHaveProperty('expiresAt')
|
|
|
+ expect(data).toHaveProperty('expiresIn')
|
|
|
+ expect(data).toHaveProperty('generatedAt')
|
|
|
+
|
|
|
+ // 验证Token类型
|
|
|
+ expect(data.type).toBe('rtm')
|
|
|
+
|
|
|
+ // 验证Token格式
|
|
|
+ expect(data.token).toMatch(/^[A-Za-z0-9+/=]+$/)
|
|
|
+ expect(data.token.length).toBeGreaterThan(50)
|
|
|
+
|
|
|
+ // 验证时间戳格式
|
|
|
+ expect(data.expiresAt).toBeGreaterThan(data.generatedAt)
|
|
|
+ expect(data.expiresIn).toBeGreaterThan(0)
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ runIfRealConfig('真实Token有效期验证', async () => {
|
|
|
+ const response = await client.agora.token.$get({
|
|
|
+ query: { type: 'rtc', channel: 'test-channel-validity' }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ headers: {
|
|
|
+ 'Authorization': 'Bearer test-token'
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ expect(response.status).toBe(200)
|
|
|
+
|
|
|
+ const data = await response.json()
|
|
|
+
|
|
|
+ // 类型断言
|
|
|
+ if ('token' in data) {
|
|
|
+ // 验证Token在有效期内
|
|
|
+ const currentTime = Math.floor(Date.now() / 1000)
|
|
|
+ expect(data.expiresAt).toBeGreaterThan(currentTime)
|
|
|
+ expect(data.expiresAt).toBeLessThanOrEqual(currentTime + 3600) // 默认1小时有效期
|
|
|
+
|
|
|
+ // 验证生成时间在当前时间之前或等于
|
|
|
+ expect(data.generatedAt).toBeLessThanOrEqual(currentTime)
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ runIfRealConfig('不同参数组合的真实Token生成', async () => {
|
|
|
+ // 测试不同的用户ID格式
|
|
|
+ const testCases = [
|
|
|
+ { type: 'rtc' as const, channel: 'channel-1', userId: '123' },
|
|
|
+ { type: 'rtc' as const, channel: 'channel-2', userId: 'user-456' },
|
|
|
+ { type: 'rtm' as const, userId: 'test-user-789' }
|
|
|
+ ]
|
|
|
+
|
|
|
+ for (const testCase of testCases) {
|
|
|
+ const response = await client.agora.token.$get({
|
|
|
+ query: testCase
|
|
|
+ },
|
|
|
+ {
|
|
|
+ headers: {
|
|
|
+ 'Authorization': 'Bearer test-token'
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ expect(response.status).toBe(200)
|
|
|
+
|
|
|
+ const data = await response.json()
|
|
|
+
|
|
|
+ // 类型断言
|
|
|
+ if ('token' in data) {
|
|
|
+ expect(data.type).toBe(testCase.type)
|
|
|
+ expect(data.token).toBeTruthy()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 错误场景测试 - 这些应该总是运行,即使没有真实配置
|
|
|
+ test('真实配置下的参数验证错误', async () => {
|
|
|
+ // 测试缺少必需参数
|
|
|
+ const response = await client.agora.token.$get({
|
|
|
+ query: { type: 'rtc' } // 缺少channel参数
|
|
|
+ },
|
|
|
+ {
|
|
|
+ headers: {
|
|
|
+ 'Authorization': 'Bearer test-token'
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ expect(response.status).toBe(400)
|
|
|
+
|
|
|
+ const errorData = await response.json()
|
|
|
+
|
|
|
+ // 类型断言
|
|
|
+ if ('message' in errorData) {
|
|
|
+ expect(errorData.message).toContain('RTC Token需要提供channel参数')
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ test('真实配置下的无效Token类型', async () => {
|
|
|
+ const response = await client.agora.token.$get({
|
|
|
+ query: { type: 'invalid-type' as any, channel: 'test-channel' }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ headers: {
|
|
|
+ 'Authorization': 'Bearer test-token'
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 由于Zod验证,应该返回400错误
|
|
|
+ expect(response.status).toBe(400)
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+// 如果没有真实配置,提供信息性测试
|
|
|
+describe('Agora Token API 配置状态检查', () => {
|
|
|
+ test('检查Agora配置状态', () => {
|
|
|
+ if (!hasRealAgoraConfig) {
|
|
|
+ console.warn('⚠️ 没有真实的Agora配置,真实API测试将被跳过')
|
|
|
+ console.warn(' 请设置AGORA_APP_ID和AGORA_APP_SECRET环境变量来启用真实API测试')
|
|
|
+ }
|
|
|
+
|
|
|
+ // 这个测试总是通过,用于提供信息
|
|
|
+ expect(true).toBe(true)
|
|
|
+ })
|
|
|
+})
|