flnxi-Wu/lib/__tests__/check-limits.test.ts
2026-06-03 11:37:55 +08:00

308 lines
10 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 许可证限制检查工具测试
* 测试 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', () => ({
authorizePremiumModuleAction: jest.fn(),
getAuthorizedUsageLimits: 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 {
authorizePremiumModuleAction,
getAuthorizedUsageLimits,
} from '../license/premium-module-service';
const mockIsFeatureEnabled = isFeatureEnabled as jest.MockedFunction<typeof isFeatureEnabled>;
const mockGetLicenseType = getLicenseType as jest.MockedFunction<typeof getLicenseType>;
const mockGetAuthorizedUsageLimits = getAuthorizedUsageLimits as jest.MockedFunction<typeof getAuthorizedUsageLimits>;
const mockAuthorizePremiumModuleAction =
authorizePremiumModuleAction as jest.MockedFunction<typeof authorizePremiumModuleAction>;
const mockUserCount = prisma.user.count as jest.MockedFunction<typeof prisma.user.count>;
const mockMaterialCount = prisma.material.count as jest.MockedFunction<typeof prisma.material.count>;
describe('canCreateUser', () => {
beforeEach(() => {
jest.clearAllMocks();
mockAuthorizePremiumModuleAction.mockResolvedValue({
available: true,
moduleId: 'license-limits-core',
action: 'licenseLimits:enforce',
status: 'running',
});
});
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();
mockAuthorizePremiumModuleAction.mockResolvedValue({
available: true,
moduleId: 'license-limits-core',
action: 'licenseLimits:enforce',
status: 'running',
});
});
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);
mockAuthorizePremiumModuleAction.mockResolvedValue({
available: true,
moduleId: 'custom-templates-core',
action: 'customTemplates:use',
status: 'running',
});
expect(await canUseCustomTemplates()).toBe(true);
expect(mockIsFeatureEnabled).toHaveBeenCalledWith('customTemplates');
expect(mockAuthorizePremiumModuleAction).toHaveBeenCalledWith(
'custom-templates-core',
'customTemplates:use'
);
});
it('当功能禁用时应该返回 false', async () => {
mockIsFeatureEnabled.mockResolvedValue(false);
expect(await canUseCustomTemplates()).toBe(false);
expect(mockAuthorizePremiumModuleAction).not.toHaveBeenCalled();
});
it('当付费能力模块未运行或拒绝授权时应该返回 false', async () => {
mockIsFeatureEnabled.mockResolvedValue(true);
mockAuthorizePremiumModuleAction.mockResolvedValue({
available: false,
moduleId: 'custom-templates-core',
action: 'customTemplates:use',
status: 'missing',
});
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);
mockAuthorizePremiumModuleAction.mockResolvedValue({
available: true,
moduleId: 'intranet-penetration-core',
action: 'intranetPenetration:use',
status: 'running',
});
expect(await canUseIntranetPenetration()).toBe(true);
expect(mockIsFeatureEnabled).toHaveBeenCalledWith('intranetPenetration');
expect(mockAuthorizePremiumModuleAction).toHaveBeenCalledWith(
'intranet-penetration-core',
'intranetPenetration:use'
);
});
it('当功能禁用时应该返回 false', async () => {
mockIsFeatureEnabled.mockResolvedValue(false);
expect(await canUseIntranetPenetration()).toBe(false);
expect(mockAuthorizePremiumModuleAction).not.toHaveBeenCalled();
});
it('当付费能力模块未运行或拒绝授权时应该返回 false', async () => {
mockIsFeatureEnabled.mockResolvedValue(true);
mockAuthorizePremiumModuleAction.mockResolvedValue({
available: false,
moduleId: 'intranet-penetration-core',
action: 'intranetPenetration:use',
status: 'unhealthy',
});
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();
});
});