Some checks failed
Deploy / deploy (push) Has been cancelled
Full-stack web application for Telegram management - Frontend: Vue 3 + Vben Admin - Backend: NestJS - Features: User management, group broadcast, statistics 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
532 lines
19 KiB
JavaScript
532 lines
19 KiB
JavaScript
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('不支持的导出格式');
|
|
});
|
|
});
|
|
}); |