import { AdminDeepSeekController } from '../../../src/modules/ai/controller/admin/deepseek'; import { DeepSeekService } from '../../../src/modules/ai/service/deepseek'; import { CoolCommException } from '@cool-midway/core'; describe('AdminDeepSeekController 多租户 BYOK 与 Token 用量控制台 (TDD)', () => { let controller: AdminDeepSeekController; let service: DeepSeekService; beforeEach(() => { service = new DeepSeekService(); controller = new AdminDeepSeekController(); controller.deepSeekService = service; (controller as any).ok = (data: any) => ({ code: 1000, message: 'success', data }); }); describe('1. 租户管理员私有 BYOK 配置隔离', () => { it('租户管理员保存私有 API Key,仅生效于该租户,不污染全局配置', async () => { // 模拟租户 888 的登录上下文 (controller as any).ctx = { admin: { username: 'tenant_admin_888', tenantId: 888 }, }; // 租户保存私有 Key const saveRes: any = await controller.config({ apiKey: 'sk-tenant-888-secret-key-123456', model: 'deepseek-reasoner', }); expect(saveRes.code).toBe(1000); expect(saveRes.data.isConfigured).toBe(true); expect(saveRes.data.model).toBe('deepseek-reasoner'); // 验证脱敏显示 expect(saveRes.data.apiKey).toBe('sk-t****3456'); // 验证底层 service 中该租户已配置独立 Key expect(service.isConfigured(888)).toBe(true); expect(service.getTenantConfig(888).apiKey).toBe('sk-tenant-888-secret-key-123456'); // 验证全局公共池并未被污染 expect(service.isConfigured()).toBe(false); expect(service.getConfig().apiKey).toBeFalsy(); }); it('超管访问 config 操作平台公共资金池配置', async () => { // 模拟平台超管上下文 (controller as any).ctx = { admin: { username: 'admin', isSuper: true }, }; await controller.config({ apiKey: 'sk-platform-master-key-999999', model: 'deepseek-chat', }); // 平台全局已配置 expect(service.isConfigured()).toBe(true); expect(service.getConfig().apiKey).toBe('sk-platform-master-key-999999'); }); it('租户 BYOK 经 setTenantConfig 写穿,无 repository 时内存 Map 兜底仍可被管理端读取', async () => { await service.setTenantConfig(555, { apiKey: 'sk-tenant-555-byok-key-abcdef', model: 'deepseek-reasoner', }); (controller as any).ctx = { admin: { username: 'tenant_admin_555', tenantId: 555 }, }; const res: any = await controller.config({}); expect(res.code).toBe(1000); expect(res.data.isConfigured).toBe(true); expect(res.data.model).toBe('deepseek-reasoner'); expect(res.data.apiKey).toBe('sk-t****cdef'); // 脱敏回显不得包含完整密钥 expect(JSON.stringify(res)).not.toContain('sk-tenant-555-byok-key-abcdef'); }); }); describe('2. 租户 Token 消耗统计与用量查询 (POST /usage)', () => { it('租户可准确查询自身的 Token 消耗与配额进度', async () => { // 模拟记录租户 666 的 Token 消耗 service.recordTokenUsage(666, { promptTokens: 120, completionTokens: 80, totalTokens: 200, }); service.setTenantTokenQuota(666, 10000); (controller as any).ctx = { admin: { username: 'tenant_user_666', tenantId: 666 }, }; const usageRes = await (controller as any).usage(); expect(usageRes.code).toBe(1000); expect(usageRes.data.totalTokens).toBe(200); expect(usageRes.data.promptTokens).toBe(120); expect(usageRes.data.completionTokens).toBe(80); expect(usageRes.data.callCount).toBe(1); expect(usageRes.data.quota).toBe(10000); expect(usageRes.data.percent).toBe(2); // 200 / 10000 = 2% }); }); describe('3. 超管设置租户配额 (POST /quota)', () => { it('超级管理员可成功为指定租户设置额度上限', async () => { (controller as any).ctx = { admin: { username: 'admin', isSuper: true }, }; const quotaRes = await (controller as any).quota({ tenantId: 777, maxTokens: 50000, }); expect(quotaRes.code).toBe(1000); // 验证生效 expect(() => service.assertTenantTokenQuota(777, 40000)).not.toThrow(); expect(() => service.assertTenantTokenQuota(777, 60000)).toThrow(CoolCommException); }); it('非超级管理员调用 quota 必须抛出 403 阻断越权', async () => { (controller as any).ctx = { admin: { username: 'tenant_rep', tenantId: 10 }, }; await expect( (controller as any).quota({ tenantId: 10, maxTokens: 999999 }) ).rejects.toThrow(CoolCommException); }); }); });