anonpenguin 64ed9e82a7 Add integration tests for blog workflow and supporting infrastructure
- Implemented comprehensive integration tests for user management, category management, content publishing, comment system, performance, scalability, and network resilience.
- Created DockerNodeManager to manage Docker containers for testing.
- Developed ApiClient for API interactions and health checks.
- Introduced SyncWaiter for synchronizing node states and ensuring data consistency.
- Enhanced test reliability with increased timeouts and detailed logging.
2025-06-21 11:15:33 +03:00

166 lines
4.7 KiB
TypeScript

import { ApiClient } from './ApiClient';
export interface SyncMetrics {
nodeId: string;
peerCount: number;
dataCount: {
users: number;
posts: number;
comments: number;
categories: number;
};
}
export class SyncWaiter {
constructor(private apiClients: ApiClient[]) {}
async waitForSync(timeout: number = 10000): Promise<void> {
await new Promise(resolve => setTimeout(resolve, timeout));
}
async waitForPeerConnections(minPeers: number = 2, timeout: number = 30000): Promise<boolean> {
const startTime = Date.now();
console.log(`Waiting for nodes to connect to at least ${minPeers} peers...`);
while (Date.now() - startTime < timeout) {
let allConnected = true;
for (const client of this.apiClients) {
try {
const health = await client.health();
if (!health.data || health.data.peers < minPeers) {
allConnected = false;
break;
}
} catch (error) {
allConnected = false;
break;
}
}
if (allConnected) {
console.log('✅ All nodes have sufficient peer connections');
return true;
}
await new Promise(resolve => setTimeout(resolve, 2000));
}
console.log('❌ Timeout waiting for peer connections');
return false;
}
async waitForDataConsistency(
dataType: 'users' | 'posts' | 'comments' | 'categories',
expectedCount: number,
timeout: number = 15000,
tolerance: number = 0
): Promise<boolean> {
const startTime = Date.now();
console.log(`Waiting for ${dataType} count to reach ${expectedCount} across all nodes...`);
while (Date.now() - startTime < timeout) {
let isConsistent = true;
const counts: number[] = [];
for (const client of this.apiClients) {
try {
const response = await client.get('/api/metrics/data');
if (response.data && response.data.counts) {
const count = response.data.counts[dataType];
counts.push(count);
if (Math.abs(count - expectedCount) > tolerance) {
isConsistent = false;
}
} else {
isConsistent = false;
break;
}
} catch (error) {
isConsistent = false;
break;
}
}
if (isConsistent) {
console.log(`✅ Data consistency achieved: ${dataType} = ${expectedCount} across all nodes`);
return true;
}
console.log(`Data counts: ${counts.join(', ')}, expected: ${expectedCount}`);
await new Promise(resolve => setTimeout(resolve, 2000));
}
console.log(`❌ Timeout waiting for data consistency: ${dataType}`);
return false;
}
async getSyncMetrics(): Promise<SyncMetrics[]> {
const metrics: SyncMetrics[] = [];
for (const client of this.apiClients) {
try {
const [healthResponse, dataResponse] = await Promise.all([
client.health(),
client.get('/api/metrics/data')
]);
if (healthResponse.data && dataResponse.data) {
metrics.push({
nodeId: healthResponse.data.nodeId,
peerCount: healthResponse.data.peers,
dataCount: dataResponse.data.counts
});
}
} catch (error) {
console.warn(`Failed to get metrics from node: ${error.message}`);
}
}
return metrics;
}
async logSyncStatus(): Promise<void> {
console.log('\n📊 Current Sync Status:');
const metrics = await this.getSyncMetrics();
metrics.forEach(metric => {
console.log(`Node: ${metric.nodeId}`);
console.log(` Peers: ${metric.peerCount}`);
console.log(` Data: Users=${metric.dataCount.users}, Posts=${metric.dataCount.posts}, Comments=${metric.dataCount.comments}, Categories=${metric.dataCount.categories}`);
});
console.log('');
}
async waitForNodesReady(timeout: number = 60000): Promise<boolean> {
const startTime = Date.now();
console.log('Waiting for all nodes to be ready...');
while (Date.now() - startTime < timeout) {
let allReady = true;
for (let i = 0; i < this.apiClients.length; i++) {
const isReady = await this.apiClients[i].waitForHealth(5000);
if (!isReady) {
console.log(`Node ${i} not ready yet...`);
allReady = false;
break;
}
}
if (allReady) {
console.log('✅ All nodes are ready');
return true;
}
await new Promise(resolve => setTimeout(resolve, 3000));
}
console.log('❌ Timeout waiting for nodes to be ready');
return false;
}
}