Files
telegram-management-system/backend/test/services/AccountScheduler.test.js
你的用户名 237c7802e5
Some checks failed
Deploy / deploy (push) Has been cancelled
Initial commit: Telegram Management System
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>
2025-11-04 15:37:50 +08:00

253 lines
8.6 KiB
JavaScript

const { expect } = require('chai');
const TestSetup = require('../setup');
const AccountScheduler = require('../../src/service/AccountScheduler');
describe('AccountScheduler Service', function() {
let accountScheduler;
let testDb;
before(async function() {
this.timeout(10000);
// Setup test database and data
await TestSetup.setupDatabase();
await TestSetup.setupRedis();
await TestSetup.createTestData();
testDb = TestSetup.getTestDb();
accountScheduler = new AccountScheduler();
});
after(async function() {
await TestSetup.cleanup();
});
describe('Initialization', function() {
it('should initialize with default configuration', function() {
expect(accountScheduler).to.be.instanceOf(AccountScheduler);
expect(accountScheduler.schedulingStrategy).to.equal('health_priority');
expect(accountScheduler.isRunning).to.be.false;
});
it('should start and stop service correctly', async function() {
await accountScheduler.start();
expect(accountScheduler.isRunning).to.be.true;
await accountScheduler.stop();
expect(accountScheduler.isRunning).to.be.false;
});
});
describe('Account Selection', function() {
beforeEach(async function() {
await accountScheduler.start();
});
afterEach(async function() {
await accountScheduler.stop();
});
it('should select optimal account based on health priority', async function() {
const taskRequirements = {
tier: 'normal',
messageCount: 5,
urgency: 'medium'
};
const account = await accountScheduler.selectOptimalAccount(taskRequirements);
expect(account).to.not.be.null;
expect(account).to.have.property('accountId');
expect(account).to.have.property('healthScore');
expect(account.status).to.equal('active');
});
it('should exclude limited and banned accounts', async function() {
const taskRequirements = {
excludeStatuses: ['limited', 'banned'],
messageCount: 3
};
const account = await accountScheduler.selectOptimalAccount(taskRequirements);
if (account) {
expect(['active', 'warning']).to.include(account.status);
}
});
it('should respect account limits', async function() {
const taskRequirements = {
messageCount: 100, // Very high count
checkLimits: true
};
const account = await accountScheduler.selectOptimalAccount(taskRequirements);
if (account) {
expect(account.todaySentCount + taskRequirements.messageCount).to.be.at.most(account.dailyLimit);
}
});
});
describe('Load Balancing', function() {
beforeEach(async function() {
await accountScheduler.start();
});
afterEach(async function() {
await accountScheduler.stop();
});
it('should distribute tasks across multiple accounts', async function() {
const selections = [];
const taskRequirements = { messageCount: 1 };
// Select accounts multiple times
for (let i = 0; i < 5; i++) {
const account = await accountScheduler.selectOptimalAccount(taskRequirements);
if (account) {
selections.push(account.accountId);
}
}
// Should have some variety in account selection
const uniqueAccounts = new Set(selections);
expect(uniqueAccounts.size).to.be.greaterThan(0);
});
it('should update account usage after task completion', async function() {
const account = await accountScheduler.selectOptimalAccount({ messageCount: 5 });
if (account) {
const initialUsage = account.todaySentCount;
await accountScheduler.updateAccountUsage(account.accountId, {
sentCount: 5,
success: true,
executionTime: 1500
});
// Verify usage was updated
const updatedAccount = await accountScheduler.getAccountById(account.accountId);
expect(updatedAccount.todaySentCount).to.equal(initialUsage + 5);
}
});
});
describe('Risk Assessment', function() {
beforeEach(async function() {
await accountScheduler.start();
});
afterEach(async function() {
await accountScheduler.stop();
});
it('should calculate account risk score', async function() {
const account = await accountScheduler.selectOptimalAccount({ messageCount: 1 });
if (account) {
const riskScore = accountScheduler.calculateAccountRisk(account);
expect(riskScore).to.be.a('number');
expect(riskScore).to.be.at.least(0);
expect(riskScore).to.be.at.most(100);
}
});
it('should prefer lower risk accounts', async function() {
// Set strategy to risk-based
accountScheduler.setSchedulingStrategy('risk_balanced');
const account = await accountScheduler.selectOptimalAccount({
messageCount: 1,
riskTolerance: 'low'
});
if (account) {
expect(account.riskScore).to.be.at.most(50); // Low to medium risk
}
});
});
describe('Error Handling', function() {
it('should handle database connection errors gracefully', async function() {
// Mock database error
const originalQuery = testDb.query;
testDb.query = () => Promise.reject(new Error('Database connection lost'));
const account = await accountScheduler.selectOptimalAccount({ messageCount: 1 });
expect(account).to.be.null;
// Restore original query method
testDb.query = originalQuery;
});
it('should handle empty account pool', async function() {
// Clear all accounts
await testDb.query('DELETE FROM accounts_pool');
const account = await accountScheduler.selectOptimalAccount({ messageCount: 1 });
expect(account).to.be.null;
// Restore test data
await TestSetup.createTestData();
});
});
describe('Strategy Configuration', function() {
beforeEach(async function() {
await accountScheduler.start();
});
afterEach(async function() {
await accountScheduler.stop();
});
it('should support different scheduling strategies', function() {
const strategies = ['round_robin', 'health_priority', 'risk_balanced', 'random'];
strategies.forEach(strategy => {
accountScheduler.setSchedulingStrategy(strategy);
expect(accountScheduler.schedulingStrategy).to.equal(strategy);
});
});
it('should validate strategy parameters', function() {
expect(() => {
accountScheduler.setSchedulingStrategy('invalid_strategy');
}).to.throw();
});
});
describe('Performance Monitoring', function() {
beforeEach(async function() {
await accountScheduler.start();
});
afterEach(async function() {
await accountScheduler.stop();
});
it('should track selection performance metrics', async function() {
const startTime = Date.now();
await accountScheduler.selectOptimalAccount({ messageCount: 1 });
const endTime = Date.now();
const duration = endTime - startTime;
// Selection should be reasonably fast (under 100ms)
expect(duration).to.be.at.most(100);
});
it('should provide service statistics', function() {
const stats = accountScheduler.getServiceStats();
expect(stats).to.have.property('isRunning');
expect(stats).to.have.property('strategy');
expect(stats).to.have.property('totalSelections');
expect(stats.isRunning).to.be.true;
});
});
});