flnxi-Wu/lib/__tests__/license-service.test.ts
2026-05-28 15:11:36 +08:00

794 lines
27 KiB
TypeScript

/**
* 许可证服务模块测试
* 测试 lib/license/license-service.ts 中的核心功能
*/
// Mock 依赖模块
jest.mock('@/lib/prisma', () => ({
prisma: {
systemConfig: {
findUnique: jest.fn(),
upsert: jest.fn(),
update: jest.fn(),
delete: jest.fn(),
},
user: {
count: jest.fn(),
findFirst: jest.fn(),
create: jest.fn(),
update: jest.fn(),
},
material: {
count: jest.fn(),
},
department: {
findFirst: jest.fn(),
create: jest.fn(),
},
category: {
findFirst: jest.fn(),
create: jest.fn(),
},
scene: {
findFirst: jest.fn(),
create: jest.fn(),
},
$transaction: jest.fn((fn) => fn({
user: {
findFirst: jest.fn(),
create: jest.fn(),
update: jest.fn(),
},
department: {
findFirst: jest.fn(),
create: jest.fn(),
},
category: {
findFirst: jest.fn(),
create: jest.fn(),
},
scene: {
findFirst: jest.fn(),
create: jest.fn(),
},
})),
},
}));
jest.mock('../license/fingerprint-service', () => ({
generateFingerprint: jest.fn(),
getInstanceId: jest.fn(),
}));
jest.mock('../license/crypto-service', () => ({
verifyLicenseSignature: jest.fn(),
encryptLocal: jest.fn((data) => `encrypted:${data}`),
decryptLocal: jest.fn((data) => data.replace('encrypted:', '')),
signLocalIntegrity: jest.fn((data) => `integrity:${data}`),
verifyLocalIntegrity: jest.fn((data, signature) => signature === `integrity:${data}`),
}));
jest.mock('@/lib/system-integrity', () => ({
ensureBuiltinTemplates: jest.fn(),
}));
// Mock global fetch
const mockFetch = jest.fn();
global.fetch = mockFetch;
import { prisma } from '@/lib/prisma';
import { verifyLicenseSignature } from '../license/crypto-service';
import { generateFingerprint, getInstanceId } from '../license/fingerprint-service';
import { LICENSE_CONFIGS } from '../license/types';
import type { SignedLicense } from '../license/types';
const mockVerifyLicenseSignature = verifyLicenseSignature as jest.MockedFunction<typeof verifyLicenseSignature>;
const mockGenerateFingerprint = generateFingerprint as jest.MockedFunction<typeof generateFingerprint>;
const mockGetInstanceId = getInstanceId as jest.MockedFunction<typeof getInstanceId>;
function createSignedLicense(overrides: Record<string, any> = {}): SignedLicense {
const issuedAt = new Date().toISOString();
return {
data: {
type: 'FREE' as const,
limits: { maxUsers: 10, maxMaterials: 100 },
features: {
customTemplates: false,
systemSettings: false,
departmentIsolation: false,
apiAccess: false,
intranetPenetration: false,
},
expiresAt: null,
leaseExpiresAt: new Date(Date.now() + 3 * 24 * 60 * 60 * 1000).toISOString(),
issuedAt,
...overrides,
},
signature: 'valid-signature',
issuedAt,
};
}
function createStoredLocalLicense(overrides: Record<string, any> = {}) {
const signedLicense = overrides.signedLicense || createSignedLicense(overrides.signedLicenseData || {});
return {
instanceId: 'test-instance-id',
licenseKey: 'FLNXI-FREE-TEST-1234-5678-ABCD',
licenseData: `encrypted:${JSON.stringify(signedLicense)}`,
lastVerified: new Date().toISOString(),
cachedConfig: {
type: 'FREE',
limits: { maxUsers: 10, maxMaterials: 100 },
features: {
customTemplates: false,
systemSettings: false,
departmentIsolation: false,
apiAccess: false,
intranetPenetration: false,
},
expiresAt: null,
leaseExpiresAt: new Date(Date.now() + 3 * 24 * 60 * 60 * 1000).toISOString(),
},
signedLicense: undefined,
signedLicenseData: undefined,
...overrides,
};
}
function addClockIntegrity(localData: Record<string, any>) {
const payload = JSON.stringify({
instanceId: localData.instanceId,
licenseKey: localData.licenseKey,
licenseData: localData.licenseData,
lastVerified: localData.lastVerified,
lastSeenAt: localData.lastSeenAt ?? null,
clockRollbackDetectedAt: localData.clockRollbackDetectedAt ?? null,
});
return {
...localData,
clockRollbackDetectedAt: localData.clockRollbackDetectedAt ?? null,
clockIntegrity: `integrity:${payload}`,
};
}
describe('license-service', () => {
beforeEach(() => {
jest.clearAllMocks();
mockFetch.mockReset();
mockVerifyLicenseSignature.mockReturnValue(true);
process.env.LICENSE_PROJECT_CODE = 'flnxi-sucai';
process.env.LICENSE_REQUEST_SIGNING_SECRET = 'a'.repeat(32);
mockGenerateFingerprint.mockResolvedValue({
machineId: 'machine-1',
hostname: 'nas-1',
macAddress: 'AA:BB:CC:DD:EE:FF',
instanceId: 'instance-1',
});
mockGetInstanceId.mockResolvedValue('test-instance-id');
});
afterEach(() => {
jest.useRealTimers();
jest.restoreAllMocks();
delete process.env.LICENSE_PROJECT_CODE;
delete process.env.LICENSE_REQUEST_SIGNING_SECRET;
});
describe('activateFreeTrial', () => {
beforeEach(() => {
(prisma.systemConfig.findUnique as jest.Mock).mockResolvedValue(null);
});
it('应该成功激活免费试用版', async () => {
mockFetch.mockResolvedValueOnce({
json: () => Promise.resolve({
success: true,
}),
});
const { activateFreeTrial } = await import('../license/license-service');
const result = await activateFreeTrial('测试公司');
expect(result.success).toBe(true);
expect(mockFetch).toHaveBeenCalledWith(
'/api/license/activate-free',
expect.objectContaining({
method: 'POST',
headers: { 'Content-Type': 'application/json' },
})
);
});
it('服务器注册失败时应该返回失败(必须联网)', async () => {
// Mock 服务器注册失败
mockFetch.mockRejectedValueOnce(new Error('Network error'));
const { activateFreeTrial } = await import('../license/license-service');
const result = await activateFreeTrial('测试公司');
// 现在必须联网,网络错误应该返回失败
expect(result.success).toBe(false);
expect(result.error).toBe('网络错误,请检查网络连接后重试');
});
it('服务器返回失败时应该返回错误信息', async () => {
// Mock 服务器返回失败
mockFetch.mockResolvedValueOnce({
json: () => Promise.resolve({
success: false,
error: '服务器繁忙,请稍后重试'
}),
});
const { activateFreeTrial } = await import('../license/license-service');
const result = await activateFreeTrial('测试公司');
expect(result.success).toBe(false);
expect(result.error).toBe('服务器繁忙,请稍后重试');
});
it('应该向本地激活接口发送客户信息', async () => {
mockFetch.mockResolvedValueOnce({
json: () => Promise.resolve({
success: true,
}),
});
const { activateFreeTrial } = await import('../license/license-service');
await activateFreeTrial('测试公司', '13800000000');
const fetchCall = mockFetch.mock.calls[0];
if (fetchCall) {
const body = JSON.parse(fetchCall[1].body);
expect(body.customerName).toBe('测试公司');
expect(body.contactInfo).toBe('13800000000');
}
});
});
describe('getLicenseType', () => {
it('未激活时应该返回 FREE', async () => {
(prisma.systemConfig.findUnique as jest.Mock).mockResolvedValue(null);
const { getLicenseType } = await import('../license/license-service');
const type = await getLicenseType();
expect(type).toBe('FREE');
});
});
describe('isFeatureEnabled', () => {
it('未激活时应该返回 false', async () => {
(prisma.systemConfig.findUnique as jest.Mock).mockResolvedValue(null);
const { isFeatureEnabled } = await import('../license/license-service');
const enabled = await isFeatureEnabled('customTemplates');
expect(enabled).toBe(false);
});
it('本地许可证过期后应拒绝功能使用', async () => {
const expiredAt = new Date(Date.now() - 60_000).toISOString();
(prisma.systemConfig.findUnique as jest.Mock).mockResolvedValue({
key: 'license',
value: JSON.stringify(createStoredLocalLicense({
signedLicenseData: {
type: 'PRO',
limits: { maxUsers: -1, maxMaterials: -1 },
features: {
customTemplates: true,
systemSettings: true,
departmentIsolation: true,
apiAccess: true,
intranetPenetration: true,
},
expiresAt: expiredAt,
},
})),
});
const { isFeatureEnabled, getLicenseType, checkLimit } = await import('../license/license-service');
await expect(isFeatureEnabled('customTemplates')).resolves.toBe(false);
await expect(getLicenseType()).resolves.toBe('FREE');
await expect(checkLimit('materials')).resolves.toEqual({ allowed: false, current: 0, max: 0 });
});
it('在线租约过期后应拒绝功能和额度使用', async () => {
const expiredLeaseAt = new Date(Date.now() - 60_000).toISOString();
(prisma.systemConfig.findUnique as jest.Mock).mockResolvedValue({
key: 'license',
value: JSON.stringify(createStoredLocalLicense({
signedLicenseData: {
type: 'PRO',
limits: { maxUsers: -1, maxMaterials: -1 },
features: {
customTemplates: true,
systemSettings: true,
departmentIsolation: true,
apiAccess: true,
intranetPenetration: true,
},
expiresAt: null,
leaseExpiresAt: expiredLeaseAt,
},
})),
});
const { isFeatureEnabled, getLicenseType, checkLimit } = await import('../license/license-service');
await expect(isFeatureEnabled('customTemplates')).resolves.toBe(false);
await expect(getLicenseType()).resolves.toBe('FREE');
await expect(checkLimit('users')).resolves.toEqual({ allowed: false, current: 0, max: 0 });
});
it('付费许可证租约未过期时应继续允许付费功能', async () => {
const futureLeaseAt = new Date(Date.now() + 60_000).toISOString();
(prisma.systemConfig.findUnique as jest.Mock).mockResolvedValue({
key: 'license',
value: JSON.stringify(createStoredLocalLicense({
signedLicenseData: {
type: 'PRO',
limits: { maxUsers: -1, maxMaterials: -1 },
features: {
customTemplates: true,
systemSettings: true,
departmentIsolation: true,
apiAccess: true,
intranetPenetration: true,
},
expiresAt: null,
leaseExpiresAt: futureLeaseAt,
},
})),
});
const { isFeatureEnabled, checkLimit } = await import('../license/license-service');
await expect(isFeatureEnabled('customTemplates')).resolves.toBe(true);
await expect(checkLimit('materials')).resolves.toEqual({ allowed: true, current: 0, max: -1 });
});
it('旧许可证没有在线租约字段时暂按兼容证处理', async () => {
const legacyLicense = createSignedLicense({
type: 'PRO',
limits: { maxUsers: -1, maxMaterials: -1 },
features: {
customTemplates: true,
systemSettings: true,
departmentIsolation: true,
apiAccess: true,
intranetPenetration: true,
},
expiresAt: null,
});
delete (legacyLicense.data as unknown as Record<string, unknown>).leaseExpiresAt;
(prisma.systemConfig.findUnique as jest.Mock).mockResolvedValue({
key: 'license',
value: JSON.stringify(createStoredLocalLicense({
signedLicense: legacyLicense,
})),
});
const { isFeatureEnabled, getLocalLicense } = await import('../license/license-service');
await expect(isFeatureEnabled('customTemplates')).resolves.toBe(true);
await expect(getLocalLicense()).resolves.toMatchObject({
cachedConfig: {
leaseExpiresAt: null,
},
});
});
it('业务功能检查每次以本地已验签许可证为准,降级后不继续信旧缓存', async () => {
const proLicense = createStoredLocalLicense({
signedLicenseData: {
type: 'PRO',
limits: { maxUsers: -1, maxMaterials: -1 },
features: {
customTemplates: true,
systemSettings: true,
departmentIsolation: true,
apiAccess: true,
intranetPenetration: true,
},
expiresAt: null,
},
});
const freeLicense = createStoredLocalLicense({
signedLicenseData: {
type: 'FREE',
limits: { maxUsers: 10, maxMaterials: 100 },
features: {
customTemplates: false,
systemSettings: false,
departmentIsolation: false,
apiAccess: false,
intranetPenetration: false,
},
expiresAt: null,
},
});
(prisma.systemConfig.findUnique as jest.Mock)
.mockResolvedValueOnce({ key: 'license', value: JSON.stringify(proLicense) })
.mockResolvedValueOnce({ key: 'license', value: JSON.stringify(freeLicense) });
const { isFeatureEnabled } = await import('../license/license-service');
await expect(isFeatureEnabled('customTemplates')).resolves.toBe(true);
await expect(isFeatureEnabled('customTemplates')).resolves.toBe(false);
});
});
describe('checkLimit', () => {
it('未激活时应该返回不允许', async () => {
(prisma.systemConfig.findUnique as jest.Mock).mockResolvedValue(null);
const { checkLimit } = await import('../license/license-service');
const result = await checkLimit('users');
expect(result.allowed).toBe(false);
});
});
describe('verify (许可证吊销检测)', () => {
const mockLocalLicense = createStoredLocalLicense();
it('许可证被吊销时应该返回 revoked: true', async () => {
// Mock 本地有许可证
(prisma.systemConfig.findUnique as jest.Mock).mockResolvedValue({
key: 'license',
value: JSON.stringify(mockLocalLicense),
});
// Mock 本地验证接口返回已吊销
mockFetch.mockResolvedValueOnce({
json: () => Promise.resolve({
valid: false,
revoked: true,
error: '许可证已被禁用'
}),
});
const { verify } = await import('../license/license-service');
const result = await verify();
expect(result.valid).toBe(false);
expect(result.revoked).toBe(true);
expect(result.error).toBe('许可证已被禁用');
});
it('许可证被删除时应该返回 revoked: true', async () => {
// Mock 本地有许可证
(prisma.systemConfig.findUnique as jest.Mock).mockResolvedValue({
key: 'license',
value: JSON.stringify(mockLocalLicense),
});
// Mock 本地验证接口返回已吊销
mockFetch.mockResolvedValueOnce({
json: () => Promise.resolve({
valid: false,
revoked: true,
error: '许可证不存在'
}),
});
const { verify } = await import('../license/license-service');
const result = await verify();
expect(result.valid).toBe(false);
expect(result.revoked).toBe(true);
expect(result.error).toBe('许可证不存在');
});
it('未找到本地许可证时应该返回错误', async () => {
(prisma.systemConfig.findUnique as jest.Mock).mockResolvedValue(null);
const { verify } = await import('../license/license-service');
const result = await verify();
expect(result.valid).toBe(false);
expect(result.error).toBe('未找到许可证');
});
it('在线租约过期后,网络失败也不应继续走本地宽限期', async () => {
const expiredLeaseAt = new Date(Date.now() - 60_000).toISOString();
(prisma.systemConfig.findUnique as jest.Mock).mockResolvedValue({
key: 'license',
value: JSON.stringify(createStoredLocalLicense({
lastVerified: new Date().toISOString(),
signedLicenseData: {
type: 'PRO',
limits: { maxUsers: -1, maxMaterials: -1 },
features: {
customTemplates: true,
systemSettings: true,
departmentIsolation: true,
apiAccess: true,
intranetPenetration: true,
},
expiresAt: null,
leaseExpiresAt: expiredLeaseAt,
},
})),
});
mockFetch.mockRejectedValueOnce(new Error('Network error'));
const { verify } = await import('../license/license-service');
const result = await verify();
expect(result.valid).toBe(false);
expect(result.error).toBe('网络错误');
});
});
describe('服务端许可证心跳', () => {
it('startHeartbeat 应直接调用内部心跳逻辑,不再依赖需要登录态的 HTTP 路由', async () => {
jest.useFakeTimers();
(prisma.systemConfig.findUnique as jest.Mock).mockResolvedValue({
key: 'license',
value: JSON.stringify(createStoredLocalLicense()),
});
(prisma.user.count as jest.Mock).mockResolvedValue(1);
(prisma.material.count as jest.Mock).mockResolvedValue(0);
mockFetch.mockResolvedValueOnce({
status: 200,
json: () => Promise.resolve({ acknowledged: true }),
});
const { startHeartbeat, stopHeartbeat } = await import('../license/license-service');
startHeartbeat();
await jest.advanceTimersByTimeAsync(60 * 60 * 1000);
stopHeartbeat();
expect(mockFetch).toHaveBeenCalledWith(
expect.stringContaining('/heartbeat'),
expect.objectContaining({
method: 'POST',
})
);
expect(mockFetch).not.toHaveBeenCalledWith(
'/api/license/heartbeat',
expect.anything()
);
});
});
describe('本地许可证验签收紧', () => {
it('应优先使用验签后的许可证内容,而不是本地 cachedConfig', async () => {
const tamperedLocalLicense = createStoredLocalLicense({
cachedConfig: {
type: 'PRO',
limits: { maxUsers: -1, maxMaterials: -1 },
features: {
customTemplates: true,
systemSettings: true,
departmentIsolation: true,
apiAccess: true,
intranetPenetration: true,
},
expiresAt: null,
},
});
(prisma.systemConfig.findUnique as jest.Mock).mockResolvedValue({
key: 'license',
value: JSON.stringify(tamperedLocalLicense),
});
const { getLicenseType, isFeatureEnabled } = await import('../license/license-service');
expect(await getLicenseType()).toBe('FREE');
expect(await isFeatureEnabled('customTemplates')).toBe(false);
});
it('本地签名无效时应视为无许可证', async () => {
mockVerifyLicenseSignature.mockReturnValue(false);
(prisma.systemConfig.findUnique as jest.Mock).mockResolvedValue({
key: 'license',
value: JSON.stringify(createStoredLocalLicense()),
});
const { getLocalLicense } = await import('../license/license-service');
const localLicense = await getLocalLicense();
expect(localLicense).toBeNull();
});
});
describe('本地时间回拨检测', () => {
const now = new Date('2026-05-26T08:00:00.000Z');
beforeEach(() => {
jest.useFakeTimers();
jest.setSystemTime(now);
(prisma.systemConfig.update as jest.Mock).mockResolvedValue({});
(prisma.systemConfig.upsert as jest.Mock).mockResolvedValue({});
});
it('旧本地许可证没有时间锚点时应自动补齐并继续兼容', async () => {
const localLicense = createStoredLocalLicense();
delete (localLicense as Record<string, unknown>).lastSeenAt;
delete (localLicense as Record<string, unknown>).clockRollbackDetectedAt;
delete (localLicense as Record<string, unknown>).clockIntegrity;
(prisma.systemConfig.findUnique as jest.Mock).mockResolvedValue({
key: 'license',
value: JSON.stringify(localLicense),
});
const { getLocalLicense } = await import('../license/license-service');
const result = await getLocalLicense();
expect(result).toMatchObject({
lastSeenAt: now.toISOString(),
clockRollbackDetectedAt: null,
});
expect(result?.clockIntegrity).toEqual(expect.stringContaining('integrity:'));
expect(prisma.systemConfig.update).toHaveBeenCalledWith(expect.objectContaining({
where: { key: 'license' },
}));
});
it('只读读取许可证不应刷新本地时间状态', async () => {
const localLicense = createStoredLocalLicense();
delete (localLicense as Record<string, unknown>).lastSeenAt;
delete (localLicense as Record<string, unknown>).clockRollbackDetectedAt;
delete (localLicense as Record<string, unknown>).clockIntegrity;
(prisma.systemConfig.findUnique as jest.Mock).mockResolvedValue({
key: 'license',
value: JSON.stringify(localLicense),
});
const { getLocalLicenseReadOnly } = await import('../license/license-service');
const result = await getLocalLicenseReadOnly();
expect(result).toMatchObject({
licenseKey: 'FLNXI-FREE-TEST-1234-5678-ABCD',
});
expect(prisma.systemConfig.update).not.toHaveBeenCalled();
});
it('系统时间小幅回拨时不应误伤正常许可证', async () => {
const futureWithinTolerance = new Date(now.getTime() + 5 * 60 * 1000).toISOString();
const localLicense = addClockIntegrity(createStoredLocalLicense({
lastVerified: futureWithinTolerance,
lastSeenAt: futureWithinTolerance,
signedLicenseData: {
type: 'PRO',
limits: { maxUsers: -1, maxMaterials: -1 },
features: {
customTemplates: true,
systemSettings: true,
departmentIsolation: true,
apiAccess: true,
intranetPenetration: true,
},
expiresAt: null,
},
}));
(prisma.systemConfig.findUnique as jest.Mock).mockResolvedValue({
key: 'license',
value: JSON.stringify(localLicense),
});
const { isFeatureEnabled } = await import('../license/license-service');
await expect(isFeatureEnabled('customTemplates')).resolves.toBe(true);
});
it('系统时间明显回拨时应拒绝功能、额度和许可证类型读取', async () => {
jest.spyOn(console, 'warn').mockImplementation(() => undefined);
const futureBeyondTolerance = new Date(now.getTime() + 60 * 60 * 1000).toISOString();
const localLicense = addClockIntegrity(createStoredLocalLicense({
lastVerified: futureBeyondTolerance,
lastSeenAt: futureBeyondTolerance,
signedLicenseData: {
type: 'PRO',
limits: { maxUsers: -1, maxMaterials: -1 },
features: {
customTemplates: true,
systemSettings: true,
departmentIsolation: true,
apiAccess: true,
intranetPenetration: true,
},
expiresAt: null,
},
}));
(prisma.systemConfig.findUnique as jest.Mock).mockResolvedValue({
key: 'license',
value: JSON.stringify(localLicense),
});
const { isFeatureEnabled, getLicenseType, checkLimit } = await import('../license/license-service');
await expect(isFeatureEnabled('customTemplates')).resolves.toBe(false);
await expect(getLicenseType()).resolves.toBe('FREE');
await expect(checkLimit('materials')).resolves.toEqual({ allowed: false, current: 0, max: 0 });
expect(prisma.systemConfig.update).toHaveBeenCalledWith(expect.objectContaining({
where: { key: 'license' },
}));
});
it('本地时间状态被直接篡改时应视为无许可证', async () => {
jest.spyOn(console, 'warn').mockImplementation(() => undefined);
const localLicense = {
...addClockIntegrity(createStoredLocalLicense({
lastSeenAt: now.toISOString(),
})),
clockIntegrity: 'tampered-integrity',
};
(prisma.systemConfig.findUnique as jest.Mock).mockResolvedValue({
key: 'license',
value: JSON.stringify(localLicense),
});
const { getLocalLicense, isFeatureEnabled } = await import('../license/license-service');
await expect(getLocalLicense()).resolves.toBeNull();
await expect(isFeatureEnabled('customTemplates')).resolves.toBe(false);
});
it('保存新许可证时应写入本地时间锚点和校验签名', async () => {
const signedLicense = createSignedLicense();
const { saveLicenseLocally } = await import('../license/license-service');
await saveLicenseLocally('FLNXI-FREE-TEST-1234-5678-ABCD', signedLicense);
const upsertArg = (prisma.systemConfig.upsert as jest.Mock).mock.calls[0]?.[0];
const savedData = JSON.parse(upsertArg.create.value);
expect(savedData.lastSeenAt).toBe(now.toISOString());
expect(savedData.clockRollbackDetectedAt).toBeNull();
expect(savedData.clockIntegrity).toEqual(expect.stringContaining('integrity:'));
});
it('网络失败走宽限期前,如果本地时间明显回拨也不应放行', async () => {
jest.spyOn(console, 'error').mockImplementation(() => undefined);
jest.spyOn(console, 'warn').mockImplementation(() => undefined);
const futureBeyondTolerance = new Date(now.getTime() + 60 * 60 * 1000).toISOString();
const localLicense = addClockIntegrity(createStoredLocalLicense({
lastVerified: futureBeyondTolerance,
lastSeenAt: futureBeyondTolerance,
}));
(prisma.systemConfig.findUnique as jest.Mock).mockResolvedValue({
key: 'license',
value: JSON.stringify(localLicense),
});
mockFetch.mockRejectedValueOnce(new Error('Network error'));
const { verify } = await import('../license/license-service');
const result = await verify();
expect(result).toEqual({ valid: false, error: '未找到许可证' });
expect(mockFetch).not.toHaveBeenCalled();
});
});
});
describe('LICENSE_CONFIGS 免费版配置', () => {
it('FREE 版本应该有正确的限制', () => {
expect(LICENSE_CONFIGS.FREE.limits.maxUsers).toBe(10);
expect(LICENSE_CONFIGS.FREE.limits.maxMaterials).toBe(100);
});
it('FREE 版本应该禁用高级功能', () => {
expect(LICENSE_CONFIGS.FREE.features.customTemplates).toBe(false);
expect(LICENSE_CONFIGS.FREE.features.departmentIsolation).toBe(false);
expect(LICENSE_CONFIGS.FREE.features.intranetPenetration).toBe(false);
});
});