import { describe, it, expect, beforeEach, vi } from 'vitest'; import { testClient } from 'hono/testing'; import { IntegrationTestDatabase, setupIntegrationDatabaseHooksWithEntities } from '@d8d/shared-test-util'; import { systemConfigRoutes } from '../../src/routes/system-config.routes'; import { SystemConfig } from '../../src/entities/system-config.entity'; import { SystemConfigService } from '../../src/services/system-config.service'; import { UserEntity, Role } from '@d8d/core-module/user-module'; import { File } from '@d8d/core-module/file-module'; import { TestDataFactory } from '../utils/integration-test-db'; import { AuthService } from '@d8d/core-module/auth-module'; import { UserService } from '@d8d/core-module/user-module'; import { redisUtil } from '@d8d/shared-utils'; // 设置集成测试钩子 setupIntegrationDatabaseHooksWithEntities([SystemConfig, UserEntity, Role, File]) describe('系统配置路由API集成测试 (使用hono/testing)', () => { let client: ReturnType>; let authService: AuthService; let userService: UserService; let testToken: string; let testUser: any; beforeEach(async () => { // 创建测试客户端 client = testClient(systemConfigRoutes); // 获取数据源 const dataSource = await IntegrationTestDatabase.getDataSource(); if (!dataSource) throw new Error('Database not initialized'); // 初始化服务 userService = new UserService(dataSource); authService = new AuthService(userService); // 创建测试用户并生成token testUser = await TestDataFactory.createTestUser(dataSource, { username: 'testuser_systemconfig', password: 'TestPassword123!', email: 'testuser_systemconfig@example.com' }); // 生成测试用户的token testToken = authService.generateToken(testUser); }); describe('CRUD Operations', () => { it('应该成功创建系统配置', async () => { const configData = { configKey: 'app.login.enabled', configValue: 'true', description: '控制小程序登录功能是否开启' }; const response = await client.index.$post({ json: configData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(201); const result = await response.json(); if ('configKey' in result) { expect(result.configKey).toBe(configData.configKey); expect(result.configValue).toBe(configData.configValue); } }); it('应该根据ID获取系统配置', async () => { // 先创建配置 const dataSource = await IntegrationTestDatabase.getDataSource(); if (!dataSource) throw new Error('Database not initialized'); const systemConfigService = new SystemConfigService(dataSource); const config = await systemConfigService.create({ configKey: 'app.payment.enabled', configValue: 'true', description: '控制支付功能是否开启', } as SystemConfig); const response = await client[':id'].$get({ param: { id: config.id } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); const result = await response.json(); if ('id' in result) { expect(result.id).toBe(config.id); expect(result.configKey).toBe(config.configKey); } }); it('应该更新系统配置', async () => { // 先创建配置 const dataSource = await IntegrationTestDatabase.getDataSource(); if (!dataSource) throw new Error('Database not initialized'); const systemConfigService = new SystemConfigService(dataSource); const config = await systemConfigService.create({ configKey: 'app.notification.enabled', configValue: 'true', description: '控制通知功能是否开启', } as SystemConfig); const updateData = { configValue: 'false', description: '通知功能已关闭' }; const response = await client[':id'].$put({ param: { id: config.id }, json: updateData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); const result = await response.json(); if ('configValue' in result) { expect(result.configValue).toBe(updateData.configValue); expect(result.description).toBe(updateData.description); } }); it('应该删除系统配置', async () => { // 先创建配置 const dataSource = await IntegrationTestDatabase.getDataSource(); if (!dataSource) throw new Error('Database not initialized'); const systemConfigService = new SystemConfigService(dataSource); const config = await systemConfigService.create({ configKey: 'app.analytics.enabled', configValue: 'true', description: '控制分析功能是否开启', } as SystemConfig); const response = await client[':id'].$delete({ param: { id: config.id } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(204); // 验证配置已被删除 const deletedConfig = await systemConfigService.getById(config.id); expect(deletedConfig).toBeNull(); }); it('应该列出系统配置列表', async () => { // 创建多个配置 const dataSource = await IntegrationTestDatabase.getDataSource(); if (!dataSource) throw new Error('Database not initialized'); const systemConfigService = new SystemConfigService(dataSource); await systemConfigService.create({ configKey: 'app.feature1.enabled', configValue: 'true', } as SystemConfig); await systemConfigService.create({ configKey: 'app.feature2.enabled', configValue: 'false', } as SystemConfig); const response = await client.index.$get({ query: {} }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); const result = await response.json(); if ('data' in result) { expect(result.data).toHaveLength(2); } }); }); describe('Data Validation', () => { it('应该验证必填字段', async () => { const invalidData = { configKey: '', // 空字符串 configValue: 'true' }; const response = await client.index.$post({ json: invalidData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(400); }); it('应该验证字段长度', async () => { const invalidData = { configKey: 'a'.repeat(256), // 超过255字符 configValue: 'true' }; const response = await client.index.$post({ json: invalidData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(400); }); }); describe('自定义路由缓存刷新验证', () => { beforeEach(async () => { // 清除测试缓存 await redisUtil.deleteSystemConfig('app.login.enabled'); await redisUtil.deleteSystemConfig('app.payment.enabled'); await redisUtil.deleteSystemConfig('app.analytics.enabled'); }); it('应该通过自定义创建路由刷新缓存', async () => { const configData = { configKey: 'app.login.enabled', configValue: 'true', description: '控制小程序登录功能是否开启' }; // 验证缓存初始为空 const initialCache = await redisUtil.getSystemConfig(configData.configKey); expect(initialCache).toBeNull(); // 通过自定义路由创建配置 const response = await client.index.$post({ json: configData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); if (response.status !== 201) { const errorText = await response.text(); console.debug('Response error:', response.status, errorText); } expect(response.status).toBe(201); const result = await response.json() as any; expect(result.configKey).toBe(configData.configKey); expect(result.configValue).toBe(configData.configValue); // 验证缓存已被刷新(为空,因为setConfig会删除缓存) const afterCreateCache = await redisUtil.getSystemConfig(configData.configKey); expect(afterCreateCache).toBeNull(); }); it('应该通过自定义更新路由刷新缓存', async () => { // 先创建配置 const dataSource = await IntegrationTestDatabase.getDataSource(); if (!dataSource) throw new Error('Database not initialized'); const systemConfigService = new SystemConfigService(dataSource); const config = await systemConfigService.create({ configKey: 'app.payment.enabled', configValue: 'true', description: '控制支付功能是否开启', } as any); // 设置缓存 await redisUtil.setSystemConfig('app.payment.enabled', 'cached-value'); const initialCache = await redisUtil.getSystemConfig('app.payment.enabled'); expect(initialCache).toBe('cached-value'); // 通过自定义路由更新配置 const updateData = { configValue: 'false', description: '支付功能已关闭' }; const response = await client[':id'].$put({ param: { id: config.id }, json: updateData }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(200); const result = await response.json() as any; expect(result.configValue).toBe(updateData.configValue); // 验证缓存已被刷新 const afterUpdateCache = await redisUtil.getSystemConfig('app.payment.enabled'); expect(afterUpdateCache).toBeNull(); }); it('应该通过自定义删除路由刷新缓存', async () => { // 先创建配置 const dataSource = await IntegrationTestDatabase.getDataSource(); if (!dataSource) throw new Error('Database not initialized'); const systemConfigService = new SystemConfigService(dataSource); const config = await systemConfigService.create({ configKey: 'app.analytics.enabled', configValue: 'true', description: '控制分析功能是否开启', } as any); // 设置缓存 await redisUtil.setSystemConfig('app.analytics.enabled', 'cached-value'); const initialCache = await redisUtil.getSystemConfig('app.analytics.enabled'); expect(initialCache).toBe('cached-value'); // 通过自定义路由删除配置 const response = await client[':id'].$delete({ param: { id: config.id } }, { headers: { 'Authorization': `Bearer ${testToken}` } }); expect(response.status).toBe(204); // 验证缓存已被刷新 const afterDeleteCache = await redisUtil.getSystemConfig('app.analytics.enabled'); expect(afterDeleteCache).toBeNull(); }); }); });