const { expect } = require('chai'); const Hapi = require('@hapi/hapi'); const TestSetup = require('../setup'); const SystemConfigRouter = require('../../src/routers/SystemConfigRouter'); describe('SystemConfigRouter', function() { let server; let testDb; before(async function() { this.timeout(10000); await TestSetup.setupDatabase(); await TestSetup.setupRedis(); testDb = TestSetup.getTestDb(); // Create Hapi server for testing server = Hapi.server({ port: 0, // Use random port for testing host: 'localhost' }); // Register routes const configRouter = new SystemConfigRouter(server); const routes = configRouter.routes(); server.route(routes); await server.start(); }); after(async function() { if (server) { await server.stop(); } await TestSetup.cleanup(); }); describe('Configuration Retrieval', function() { it('should get all configurations', async function() { const response = await server.inject({ method: 'GET', url: '/config' }); expect(response.statusCode).to.equal(200); const result = JSON.parse(response.payload); expect(result).to.have.property('success', true); expect(result.data).to.have.property('configs'); expect(result.data).to.have.property('total'); expect(result.data).to.have.property('timestamp'); }); it('should get specific configuration module', async function() { const response = await server.inject({ method: 'GET', url: '/config/system' }); expect(response.statusCode).to.equal(200); const result = JSON.parse(response.payload); expect(result).to.have.property('success', true); expect(result.data).to.have.property('configName', 'system'); expect(result.data).to.have.property('config'); expect(result.data.config).to.have.property('name'); expect(result.data.config).to.have.property('version'); }); it('should get specific configuration value', async function() { const response = await server.inject({ method: 'GET', url: '/config/system/debug' }); expect(response.statusCode).to.equal(200); const result = JSON.parse(response.payload); expect(result).to.have.property('success', true); expect(result.data).to.have.property('path', 'system.debug'); expect(result.data).to.have.property('value'); }); it('should return error for non-existent configuration', async function() { const response = await server.inject({ method: 'GET', url: '/config/nonexistent' }); expect(response.statusCode).to.equal(200); const result = JSON.parse(response.payload); expect(result).to.have.property('success', false); expect(result).to.have.property('message', '配置模块不存在'); }); }); describe('Configuration Updates', function() { it('should update configuration module', async function() { const updateData = { config: { name: 'Test System', version: '1.1.0', debug: true, maintenance: false }, persistent: false }; const response = await server.inject({ method: 'PUT', url: '/config/system', payload: updateData }); expect(response.statusCode).to.equal(200); const result = JSON.parse(response.payload); expect(result).to.have.property('success', true); expect(result.data).to.have.property('configName', 'system'); expect(result.data).to.have.property('updated', true); expect(result.data).to.have.property('persistent', false); }); it('should set specific configuration value', async function() { const updateData = { value: true, persistent: false }; const response = await server.inject({ method: 'PUT', url: '/config/system/maintenance', payload: updateData }); expect(response.statusCode).to.equal(200); const result = JSON.parse(response.payload); expect(result).to.have.property('success', true); expect(result.data).to.have.property('path', 'system.maintenance'); expect(result.data).to.have.property('value', true); }); it('should batch update configuration', async function() { const updateData = { updates: { debug: false, maintenance: true }, persistent: false }; const response = await server.inject({ method: 'POST', url: '/config/system/batch', payload: updateData }); expect(response.statusCode).to.equal(200); const result = JSON.parse(response.payload); expect(result).to.have.property('success', true); expect(result.data).to.have.property('configName', 'system'); expect(result.data).to.have.property('updatedKeys'); expect(result.data.updatedKeys).to.include('debug'); expect(result.data.updatedKeys).to.include('maintenance'); }); it('should validate configuration before update', async function() { const invalidData = { config: { name: '', // Invalid empty name version: null // Invalid version } }; const response = await server.inject({ method: 'PUT', url: '/config/system', payload: invalidData }); expect(response.statusCode).to.equal(200); const result = JSON.parse(response.payload); expect(result).to.have.property('success', false); expect(result.message).to.include('配置验证失败'); }); }); describe('Configuration Management', function() { it('should reset configuration to default', async function() { const response = await server.inject({ method: 'POST', url: '/config/system/reset' }); expect(response.statusCode).to.equal(200); const result = JSON.parse(response.payload); expect(result).to.have.property('success', true); expect(result.data).to.have.property('configName', 'system'); expect(result.data).to.have.property('reset', true); }); it('should validate configuration', async function() { const validationData = { config: { name: 'Valid System', version: '1.0.0', debug: false, maintenance: false } }; const response = await server.inject({ method: 'POST', url: '/config/system/validate', payload: validationData }); expect(response.statusCode).to.equal(200); const result = JSON.parse(response.payload); expect(result).to.have.property('success', true); expect(result.data).to.have.property('configName', 'system'); expect(result.data).to.have.property('valid', true); expect(result.data).to.have.property('errors'); expect(result.data.errors).to.be.an('array').that.is.empty; }); it('should save configuration to file', async function() { const response = await server.inject({ method: 'POST', url: '/config/system/save' }); expect(response.statusCode).to.equal(200); const result = JSON.parse(response.payload); expect(result).to.have.property('success', true); expect(result.data).to.have.property('configName', 'system'); expect(result.data).to.have.property('saved', true); }); it('should reload all configurations', async function() { const response = await server.inject({ method: 'POST', url: '/config/reload' }); expect(response.statusCode).to.equal(200); const result = JSON.parse(response.payload); expect(result).to.have.property('success', true); expect(result.data).to.have.property('reloaded', true); expect(result.data).to.have.property('configCount'); expect(result.data).to.have.property('configNames'); }); }); describe('Import/Export Operations', function() { it('should export configurations', async function() { const response = await server.inject({ method: 'GET', url: '/config/export?format=json' }); expect(response.statusCode).to.equal(200); const result = JSON.parse(response.payload); expect(result).to.have.property('success', true); expect(result.data).to.have.property('timestamp'); expect(result.data).to.have.property('version'); expect(result.data).to.have.property('configs'); }); it('should export specific configurations', async function() { const response = await server.inject({ method: 'GET', url: '/config/export?configNames=system,database&format=json' }); expect(response.statusCode).to.equal(200); const result = JSON.parse(response.payload); expect(result).to.have.property('success', true); expect(result.data.configs).to.have.property('system'); expect(result.data.configs).to.have.property('database'); }); it('should import configurations', async function() { const importData = { importData: { timestamp: new Date().toISOString(), version: '1.0.0', configs: { system: { name: 'Imported System', version: '1.2.0', debug: false, maintenance: false } } }, persistent: false }; const response = await server.inject({ method: 'POST', url: '/config/import', payload: importData }); expect(response.statusCode).to.equal(200); const result = JSON.parse(response.payload); expect(result).to.have.property('success', true); expect(result.data).to.have.property('imported', true); expect(result.data).to.have.property('results'); expect(result.data).to.have.property('summary'); expect(result.data.summary.success).to.be.at.least(1); }); it('should handle invalid import data', async function() { const invalidImportData = { importData: { // Missing configs property timestamp: new Date().toISOString(), version: '1.0.0' } }; const response = await server.inject({ method: 'POST', url: '/config/import', payload: invalidImportData }); expect(response.statusCode).to.equal(200); const result = JSON.parse(response.payload); expect(result).to.have.property('success', false); expect(result.message).to.include('导入配置失败'); }); }); describe('Service Management', function() { it('should get service status', async function() { const response = await server.inject({ method: 'GET', url: '/config/service/status' }); expect(response.statusCode).to.equal(200); const result = JSON.parse(response.payload); expect(result).to.have.property('success', true); expect(result.data).to.have.property('isInitialized'); expect(result.data).to.have.property('configCount'); expect(result.data).to.have.property('watchersCount'); expect(result.data).to.have.property('configNames'); }); it('should restart service', async function() { const response = await server.inject({ method: 'POST', url: '/config/service/restart' }); expect(response.statusCode).to.equal(200); const result = JSON.parse(response.payload); expect(result).to.have.property('success', true); expect(result.data).to.have.property('restarted', true); }); }); describe('Error Handling', function() { it('should handle missing configuration data', async function() { const response = await server.inject({ method: 'PUT', url: '/config/system', payload: {} // Missing config property }); expect(response.statusCode).to.equal(200); const result = JSON.parse(response.payload); expect(result).to.have.property('success', false); expect(result.message).to.include('无效的配置数据'); }); it('should handle missing batch update data', async function() { const response = await server.inject({ method: 'POST', url: '/config/system/batch', payload: {} // Missing updates property }); expect(response.statusCode).to.equal(200); const result = JSON.parse(response.payload); expect(result).to.have.property('success', false); expect(result.message).to.include('无效的更新数据'); }); it('should handle missing validation data', async function() { const response = await server.inject({ method: 'POST', url: '/config/system/validate', payload: {} // Missing config property }); expect(response.statusCode).to.equal(200); const result = JSON.parse(response.payload); expect(result).to.have.property('success', false); expect(result.message).to.include('缺少配置数据'); }); }); describe('Configuration Types Validation', function() { it('should validate database configuration', async function() { const databaseConfig = { config: { pool: { max: 25, min: 3, acquire: 30000, idle: 10000 }, retry: { max: 3, delay: 1000 } } }; const response = await server.inject({ method: 'PUT', url: '/config/database', payload: databaseConfig }); expect(response.statusCode).to.equal(200); const result = JSON.parse(response.payload); expect(result).to.have.property('success', true); }); it('should validate queue configuration', async function() { const queueConfig = { config: { concurrency: 8, retry: { attempts: 5, delay: 3000 }, timeout: 600000 } }; const response = await server.inject({ method: 'PUT', url: '/config/queue', payload: queueConfig }); expect(response.statusCode).to.equal(200); const result = JSON.parse(response.payload); expect(result).to.have.property('success', true); }); it('should reject invalid database configuration', async function() { const invalidConfig = { config: { pool: { max: -5, // Invalid negative value min: 10 // Min greater than max } } }; const response = await server.inject({ method: 'PUT', url: '/config/database', payload: invalidConfig }); expect(response.statusCode).to.equal(200); const result = JSON.parse(response.payload); expect(result).to.have.property('success', false); expect(result.message).to.include('配置验证失败'); }); }); describe('File Operations', function() { it('should handle export as file download', async function() { const response = await server.inject({ method: 'GET', url: '/config/export?format=file' }); expect(response.statusCode).to.equal(200); expect(response.headers['content-type']).to.include('application/json'); expect(response.headers['content-disposition']).to.include('attachment'); // Verify it's valid JSON content const content = JSON.parse(response.payload); expect(content).to.have.property('timestamp'); expect(content).to.have.property('configs'); }); it('should handle unsupported export format', async function() { const response = await server.inject({ method: 'GET', url: '/config/export?format=xml' }); expect(response.statusCode).to.equal(200); const result = JSON.parse(response.payload); expect(result).to.have.property('success', false); expect(result.message).to.include('不支持的导出格式'); }); }); });