/** * 许可证限制检查工具测试 * 测试 lib/license/check-limits.ts 中的限制检查函数 */ import { canCreateUser, canUploadMaterial, canUseCustomTemplates, canUseDepartmentIsolation, canUseIntranetPenetration, canUseSystemSettings, canUseApiAccess, } from '../license/check-limits'; // Mock license-service 模块 jest.mock('../license/license-service', () => ({ isFeatureEnabled: jest.fn(), getLicenseType: jest.fn(), })); jest.mock('../license/premium-module-service', () => ({ getAuthorizedUsageLimits: jest.fn(), hasPremiumModule: jest.fn(), PREMIUM_MODULE_IDS: { LICENSE_LIMITS_CORE: 'license-limits-core', CUSTOM_TEMPLATES_CORE: 'custom-templates-core', INTRANET_PENETRATION_CORE: 'intranet-penetration-core', }, })); jest.mock('@/lib/prisma', () => ({ prisma: { user: { count: jest.fn() }, material: { count: jest.fn() }, }, })); import { prisma } from '@/lib/prisma'; import { isFeatureEnabled, getLicenseType } from '../license/license-service'; import { getAuthorizedUsageLimits, hasPremiumModule } from '../license/premium-module-service'; const mockIsFeatureEnabled = isFeatureEnabled as jest.MockedFunction; const mockGetLicenseType = getLicenseType as jest.MockedFunction; const mockGetAuthorizedUsageLimits = getAuthorizedUsageLimits as jest.MockedFunction; const mockHasPremiumModule = hasPremiumModule as jest.MockedFunction; const mockUserCount = prisma.user.count as jest.MockedFunction; const mockMaterialCount = prisma.material.count as jest.MockedFunction; describe('canCreateUser', () => { beforeEach(() => { jest.clearAllMocks(); }); it('当未达到限制时应该返回 allowed: true', async () => { mockGetAuthorizedUsageLimits.mockResolvedValue({ maxUsers: 10, maxMaterials: 100 }); mockUserCount.mockResolvedValue(5); const result = await canCreateUser(); expect(result.allowed).toBe(true); expect(result.current).toBe(5); expect(result.max).toBe(10); expect(result.message).toBeUndefined(); expect(mockGetAuthorizedUsageLimits).toHaveBeenCalled(); expect(mockUserCount).toHaveBeenCalled(); }); it('当达到限制时(FREE 版本)应该返回授权处理提示', async () => { mockGetAuthorizedUsageLimits.mockResolvedValue({ maxUsers: 10, maxMaterials: 100 }); mockUserCount.mockResolvedValue(10); mockGetLicenseType.mockResolvedValue('FREE'); const result = await canCreateUser(); expect(result.allowed).toBe(false); expect(result.message).toContain('当前许可证'); expect(result.message).toContain('10'); expect(result.message).toContain('联系管理员'); }); it('当达到限制时(非 FREE 版本)应该返回联系管理员提示', async () => { mockGetAuthorizedUsageLimits.mockResolvedValue({ maxUsers: 100, maxMaterials: 1000 }); mockUserCount.mockResolvedValue(100); mockGetLicenseType.mockResolvedValue('STANDARD'); const result = await canCreateUser(); expect(result.allowed).toBe(false); expect(result.message).toContain('联系管理员'); expect(result.message).toContain('100'); }); it('缺少限额授权模块时应该拒绝创建用户', async () => { mockGetAuthorizedUsageLimits.mockResolvedValue(null); const result = await canCreateUser(); expect(result).toEqual({ allowed: false, current: 0, max: 0, message: '授权限额模块不可用,请重新验证许可证或联系管理员。', }); expect(mockUserCount).not.toHaveBeenCalled(); }); }); describe('canUploadMaterial', () => { beforeEach(() => { jest.clearAllMocks(); }); it('当未达到限制时应该返回 allowed: true', async () => { mockGetAuthorizedUsageLimits.mockResolvedValue({ maxUsers: 10, maxMaterials: 100 }); mockMaterialCount.mockResolvedValue(50); const result = await canUploadMaterial(); expect(result.allowed).toBe(true); expect(result.current).toBe(50); expect(result.max).toBe(100); expect(mockGetAuthorizedUsageLimits).toHaveBeenCalled(); expect(mockMaterialCount).toHaveBeenCalled(); }); it('当达到限制时(FREE 版本)应该返回授权处理提示', async () => { mockGetAuthorizedUsageLimits.mockResolvedValue({ maxUsers: 10, maxMaterials: 100 }); mockMaterialCount.mockResolvedValue(100); mockGetLicenseType.mockResolvedValue('FREE'); const result = await canUploadMaterial(); expect(result.allowed).toBe(false); expect(result.message).toContain('当前许可证'); expect(result.message).toContain('素材'); expect(result.message).toContain('联系管理员'); }); it('当达到限制时(非 FREE 版本)应该返回联系管理员提示', async () => { mockGetAuthorizedUsageLimits.mockResolvedValue({ maxUsers: -1, maxMaterials: 1000 }); mockMaterialCount.mockResolvedValue(1000); mockGetLicenseType.mockResolvedValue('PRO'); const result = await canUploadMaterial(); expect(result.allowed).toBe(false); expect(result.message).toContain('联系管理员'); }); it('缺少限额授权模块时应该拒绝上传素材', async () => { mockGetAuthorizedUsageLimits.mockResolvedValue(null); const result = await canUploadMaterial(); expect(result).toEqual({ allowed: false, current: 0, max: 0, message: '授权限额模块不可用,请重新验证许可证或联系管理员。', }); expect(mockMaterialCount).not.toHaveBeenCalled(); }); }); describe('功能开关检查', () => { beforeEach(() => { jest.clearAllMocks(); }); describe('canUseCustomTemplates', () => { it('当功能启用时应该返回 true', async () => { mockIsFeatureEnabled.mockResolvedValue(true); mockHasPremiumModule.mockResolvedValue(true); expect(await canUseCustomTemplates()).toBe(true); expect(mockIsFeatureEnabled).toHaveBeenCalledWith('customTemplates'); expect(mockHasPremiumModule).toHaveBeenCalledWith('custom-templates-core'); }); it('当功能禁用时应该返回 false', async () => { mockIsFeatureEnabled.mockResolvedValue(false); expect(await canUseCustomTemplates()).toBe(false); expect(mockHasPremiumModule).not.toHaveBeenCalled(); }); it('当缺少付费能力模块凭证时应该返回 false', async () => { mockIsFeatureEnabled.mockResolvedValue(true); mockHasPremiumModule.mockResolvedValue(false); expect(await canUseCustomTemplates()).toBe(false); }); }); describe('canUseDepartmentIsolation', () => { it('当功能启用时应该返回 true', async () => { mockIsFeatureEnabled.mockResolvedValue(true); expect(await canUseDepartmentIsolation()).toBe(true); expect(mockIsFeatureEnabled).toHaveBeenCalledWith('departmentIsolation'); }); it('当功能禁用时应该返回 false', async () => { mockIsFeatureEnabled.mockResolvedValue(false); expect(await canUseDepartmentIsolation()).toBe(false); }); }); describe('canUseIntranetPenetration', () => { it('当功能启用时应该返回 true', async () => { mockIsFeatureEnabled.mockResolvedValue(true); mockHasPremiumModule.mockResolvedValue(true); expect(await canUseIntranetPenetration()).toBe(true); expect(mockIsFeatureEnabled).toHaveBeenCalledWith('intranetPenetration'); expect(mockHasPremiumModule).toHaveBeenCalledWith('intranet-penetration-core'); }); it('当功能禁用时应该返回 false', async () => { mockIsFeatureEnabled.mockResolvedValue(false); expect(await canUseIntranetPenetration()).toBe(false); expect(mockHasPremiumModule).not.toHaveBeenCalled(); }); it('当缺少付费能力模块凭证时应该返回 false', async () => { mockIsFeatureEnabled.mockResolvedValue(true); mockHasPremiumModule.mockResolvedValue(false); expect(await canUseIntranetPenetration()).toBe(false); }); }); describe('canUseSystemSettings', () => { it('当功能启用时应该返回 true', async () => { mockIsFeatureEnabled.mockResolvedValue(true); expect(await canUseSystemSettings()).toBe(true); expect(mockIsFeatureEnabled).toHaveBeenCalledWith('systemSettings'); }); it('当功能禁用时应该返回 false', async () => { mockIsFeatureEnabled.mockResolvedValue(false); expect(await canUseSystemSettings()).toBe(false); }); }); describe('canUseApiAccess', () => { it('当功能启用时应该返回 true', async () => { mockIsFeatureEnabled.mockResolvedValue(true); expect(await canUseApiAccess()).toBe(true); expect(mockIsFeatureEnabled).toHaveBeenCalledWith('apiAccess'); }); it('当功能禁用时应该返回 false', async () => { mockIsFeatureEnabled.mockResolvedValue(false); expect(await canUseApiAccess()).toBe(false); }); }); }); describe('LimitCheckResult 接口', () => { it('应该正确处理无限制情况 (max = -1)', async () => { mockGetAuthorizedUsageLimits.mockResolvedValue({ maxUsers: -1, maxMaterials: -1 }); const result = await canCreateUser(); expect(result.allowed).toBe(true); expect(result.max).toBe(-1); expect(mockUserCount).not.toHaveBeenCalled(); }); });