/** * System Config Service Tests * * Unit tests for SystemConfigService */ import { describe, it, expect, beforeAll, afterAll } from 'vitest'; import { PrismaClient } from '@prisma/client'; import { SystemConfigService } from '../src/modules/system-config/system-config.service'; const prisma = new PrismaClient(); const service = new SystemConfigService(prisma); describe('SystemConfigService', () => { beforeAll(async () => { // Clean up test configs await prisma.systemConfig.deleteMany({ where: { key: { startsWith: 'test.' } }, }); }); afterAll(async () => { // Clean up after tests await prisma.systemConfig.deleteMany({ where: { key: { startsWith: 'test.' } }, }); await prisma.$disconnect(); }); describe('upsert', () => { it('should create a new config', async () => { await service.upsert({ key: 'test.create', value: 'test-value', category: 'platform', dataType: 'string', }); const value = await service.get('test.create'); expect(value).toBe('test-value'); }); it('should update existing config', async () => { await service.upsert({ key: 'test.update', value: 'original', category: 'platform', }); await service.upsert({ key: 'test.update', value: 'updated', category: 'platform', }); const value = await service.get('test.update'); expect(value).toBe('updated'); }); it('should track change history', async () => { await service.upsert({ key: 'test.history', value: 'v1', category: 'platform', }, 'user-1'); await service.upsert({ key: 'test.history', value: 'v2', category: 'platform', }, 'user-2'); const history = await service.getChangeHistory('test.history'); expect(history).toHaveLength(1); expect(history[0].value).toBe('v1'); expect(history[0].user).toBe('user-1'); }); }); describe('getParsed', () => { it('should parse boolean values', async () => { await service.upsert({ key: 'test.bool.true', value: 'true', category: 'platform', dataType: 'boolean', }); await service.upsert({ key: 'test.bool.false', value: 'false', category: 'platform', dataType: 'boolean', }); expect(await service.getParsed('test.bool.true')).toBe(true); expect(await service.getParsed('test.bool.false')).toBe(false); }); it('should parse number values', async () => { await service.upsert({ key: 'test.number', value: '42.5', category: 'platform', dataType: 'number', }); const value = await service.getParsed('test.number'); expect(value).toBe(42.5); }); it('should parse json values', async () => { await service.upsert({ key: 'test.json', value: '{"key": "value", "num": 123}', category: 'platform', dataType: 'json', }); const value = await service.getParsed('test.json'); expect(value).toEqual({ key: 'value', num: 123 }); }); }); describe('getByCategory', () => { it('should filter by category', async () => { await service.upsert({ key: 'test.cat.platform', value: '1', category: 'platform', isPublic: true, }); await service.upsert({ key: 'test.cat.ai', value: '2', category: 'ai', isPublic: true, }); const platformConfigs = await service.getByCategory('platform'); expect(platformConfigs.some(c => c.key === 'test.cat.platform')).toBe(true); expect(platformConfigs.some(c => c.key === 'test.cat.ai')).toBe(false); }); it('should filter public/private configs', async () => { await service.upsert({ key: 'test.public', value: 'public', category: 'platform', isPublic: true, }); await service.upsert({ key: 'test.private', value: 'private', category: 'platform', isPublic: false, }); const publicConfigs = await service.getByCategory('platform'); expect(publicConfigs.some(c => c.key === 'test.public')).toBe(true); expect(publicConfigs.some(c => c.key === 'test.private')).toBe(false); const allConfigs = await service.getByCategory('platform', true); expect(allConfigs.some(c => c.key === 'test.private')).toBe(true); }); }); describe('getPublicConfigs', () => { it('should return only public configs', async () => { await service.upsert({ key: 'test.public.all', value: 'visible', category: 'platform', isPublic: true, }); await service.upsert({ key: 'test.private.all', value: 'hidden', category: 'platform', isPublic: false, }); const configs = await service.getPublicConfigs(); expect(configs.some(c => c.key === 'test.public.all')).toBe(true); expect(configs.some(c => c.key === 'test.private.all')).toBe(false); }); }); describe('updateValue', () => { it('should update only the value', async () => { await service.upsert({ key: 'test.update.value', value: 'original', description: 'Original description', category: 'platform', }); await service.updateValue('test.update.value', 'new-value', 'admin-1'); const config = await prisma.systemConfig.findUnique({ where: { key: 'test.update.value' }, }); expect(config?.value).toBe('new-value'); expect(config?.description).toBe('Original description'); expect(config?.category).toBe('platform'); }); it('should throw error for non-existent key', async () => { await expect( service.updateValue('test.nonexistent', 'value') ).rejects.toThrow("Config with key 'test.nonexistent' not found"); }); }); describe('delete', () => { it('should delete config', async () => { await service.upsert({ key: 'test.delete', value: 'to-delete', category: 'platform', }); await service.delete('test.delete'); const value = await service.get('test.delete'); expect(value).toBeNull(); }); }); describe('parseValue', () => { it('should parse different data types correctly', () => { expect(service.parseValue('123', 'number')).toBe(123); expect(service.parseValue('45.67', 'number')).toBe(45.67); expect(service.parseValue('true', 'boolean')).toBe(true); expect(service.parseValue('1', 'boolean')).toBe(true); expect(service.parseValue('false', 'boolean')).toBe(false); expect(service.parseValue('{"a":1}', 'json')).toEqual({ a: 1 }); expect(service.parseValue('2024-01-01', 'date')).toEqual(new Date('2024-01-01')); expect(service.parseValue('plain string', 'string')).toBe('plain string'); }); it('should handle invalid json gracefully', () => { expect(service.parseValue('invalid json', 'json')).toBe('invalid json'); }); }); });