Initial commit: Telegram Management System
Some checks failed
Deploy / deploy (push) Has been cancelled
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>
This commit is contained in:
532
backend/test/routers/SystemConfigRouter.test.js
Normal file
532
backend/test/routers/SystemConfigRouter.test.js
Normal file
@@ -0,0 +1,532 @@
|
||||
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('不支持的导出格式');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user