const { Sequelize } = require('sequelize'); const Redis = require('ioredis'); // Test database configuration const testDb = new Sequelize({ dialect: 'sqlite', storage: ':memory:', logging: false, // Disable logging during tests define: { timestamps: true, underscored: false } }); // Test Redis client (using redis-mock for testing) const MockRedis = require('ioredis-mock'); const testRedis = new MockRedis(); // Mock services for testing class TestSetup { static async setupDatabase() { try { // Import all models const MAccountPool = require('../src/modes/MAccountPool'); const MAccountHealthScore = require('../src/modes/MAccountHealthScore'); const MAccountUsageRecord = require('../src/modes/MAccountUsageRecord'); const MGroupTask = require('../src/modes/MGroupTask'); const MRiskRule = require('../src/modes/MRiskRule'); const MRiskLog = require('../src/modes/MRiskLog'); const MAnomalyLog = require('../src/modes/MAnomalyLog'); // Override database instance for testing const models = [ MAccountPool, MAccountHealthScore, MAccountUsageRecord, MGroupTask, MRiskRule, MRiskLog, MAnomalyLog ]; // Recreate models with test database for (const model of models) { if (model.sequelize) { // Re-define model with test database const modelName = model.name; const attributes = model.rawAttributes; const options = model.options; testDb.define(modelName, attributes, { ...options, tableName: options.tableName || modelName }); } } // Sync database await testDb.sync({ force: true }); console.log('Test database setup complete'); } catch (error) { console.error('Test database setup failed:', error); throw error; } } static async setupRedis() { // Clear all Redis data await testRedis.flushall(); console.log('Test Redis setup complete'); } static async createTestData() { try { // Create test accounts const testAccounts = [ { accountId: 1, phone: '+1234567890', status: 'active', tier: 'normal', healthScore: 85, dailyLimit: 50, hourlyLimit: 10, totalSentCount: 100, todaySentCount: 5, consecutiveFailures: 0, riskScore: 15, priority: 60, isActive: true }, { accountId: 2, phone: '+1234567891', status: 'warning', tier: 'new', healthScore: 65, dailyLimit: 30, hourlyLimit: 5, totalSentCount: 20, todaySentCount: 2, consecutiveFailures: 1, riskScore: 35, priority: 40, isActive: true }, { accountId: 3, phone: '+1234567892', status: 'limited', tier: 'trusted', healthScore: 45, dailyLimit: 100, hourlyLimit: 15, totalSentCount: 500, todaySentCount: 8, consecutiveFailures: 3, riskScore: 75, priority: 20, isActive: false } ]; // Insert test accounts using raw SQL to avoid model issues for (const account of testAccounts) { await testDb.query(` INSERT INTO accounts_pool (accountId, phone, status, tier, healthScore, dailyLimit, hourlyLimit, totalSentCount, todaySentCount, consecutiveFailures, riskScore, priority, isActive, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now'), datetime('now')) `, { replacements: [ account.accountId, account.phone, account.status, account.tier, account.healthScore, account.dailyLimit, account.hourlyLimit, account.totalSentCount, account.todaySentCount, account.consecutiveFailures, account.riskScore, account.priority, account.isActive ] }); } // Create test tasks const testTasks = [ { name: 'Test Task 1', status: 'completed', targetInfo: JSON.stringify({ targets: [{ id: 1, name: 'Group 1' }] }), messageContent: JSON.stringify({ content: 'Test message 1' }), sendingStrategy: JSON.stringify({ type: 'sequential', interval: 1000 }), successCount: 10, failureCount: 2, processedCount: 12 }, { name: 'Test Task 2', status: 'running', targetInfo: JSON.stringify({ targets: [{ id: 2, name: 'Group 2' }] }), messageContent: JSON.stringify({ content: 'Test message 2' }), sendingStrategy: JSON.stringify({ type: 'parallel', interval: 2000 }), successCount: 5, failureCount: 1, processedCount: 6 } ]; for (const task of testTasks) { await testDb.query(` INSERT INTO group_tasks (name, status, targetInfo, messageContent, sendingStrategy, successCount, failureCount, processedCount, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?, ?, ?, ?, datetime('now'), datetime('now')) `, { replacements: [ task.name, task.status, task.targetInfo, task.messageContent, task.sendingStrategy, task.successCount, task.failureCount, task.processedCount ] }); } // Create test risk rules const testRiskRules = [ { name: 'Frequency Limit', type: 'behavior', category: 'frequency', conditions: JSON.stringify({ timeWindow: 3600, threshold: 10 }), action: 'delayed', severity: 'medium', priority: 70, enabled: true }, { name: 'Account Health Check', type: 'account', category: 'health', conditions: JSON.stringify({ healthThreshold: 50 }), action: 'switched', severity: 'high', priority: 80, enabled: true } ]; for (const rule of testRiskRules) { await testDb.query(` INSERT INTO risk_rules (name, type, category, conditions, action, severity, priority, enabled, triggerCount, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 0, datetime('now'), datetime('now')) `, { replacements: [ rule.name, rule.type, rule.category, rule.conditions, rule.action, rule.severity, rule.priority, rule.enabled ] }); } console.log('Test data created successfully'); } catch (error) { console.error('Failed to create test data:', error); throw error; } } static async cleanup() { try { await testDb.close(); await testRedis.disconnect(); console.log('Test cleanup complete'); } catch (error) { console.error('Test cleanup failed:', error); } } static getTestDb() { return testDb; } static getTestRedis() { return testRedis; } } module.exports = TestSetup;