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:
408
marketing-agent/test/integration/orchestration.test.js
Normal file
408
marketing-agent/test/integration/orchestration.test.js
Normal file
@@ -0,0 +1,408 @@
|
||||
// Orchestration Integration Tests
|
||||
const TestEnvironment = require('./setup');
|
||||
const TestHelpers = require('./helpers');
|
||||
const apiGatewayApp = require('../../services/api-gateway/src/app');
|
||||
const orchestratorApp = require('../../services/orchestrator/src/app');
|
||||
const claudeAgentApp = require('../../services/claude-agent/src/app');
|
||||
const gramjsAdapterApp = require('../../services/gramjs-adapter/src/app');
|
||||
|
||||
describe('Orchestration Integration Tests', () => {
|
||||
let testEnv;
|
||||
let helpers;
|
||||
let apiClient;
|
||||
let testUser;
|
||||
const SERVICES = {
|
||||
'api-gateway': { app: apiGatewayApp, port: 13000 },
|
||||
'orchestrator': { app: orchestratorApp, port: 13001 },
|
||||
'claude-agent': { app: claudeAgentApp, port: 13002 },
|
||||
'gramjs-adapter': { app: gramjsAdapterApp, port: 13003 }
|
||||
};
|
||||
|
||||
beforeAll(async () => {
|
||||
testEnv = new TestEnvironment();
|
||||
helpers = new TestHelpers(testEnv);
|
||||
|
||||
// Setup test environment
|
||||
await testEnv.setup();
|
||||
|
||||
// Setup mocks
|
||||
helpers.setupMocks();
|
||||
|
||||
// Start all services
|
||||
for (const [name, config] of Object.entries(SERVICES)) {
|
||||
await testEnv.startService(name, config.app, config.port);
|
||||
}
|
||||
|
||||
// Wait for services to be ready
|
||||
await helpers.sleep(2000);
|
||||
|
||||
// Create test user
|
||||
testUser = await testEnv.createTestUser();
|
||||
|
||||
// Create authenticated client
|
||||
apiClient = await helpers.createAuthenticatedClient(
|
||||
`http://localhost:${SERVICES['api-gateway'].port}`,
|
||||
testUser
|
||||
);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
helpers.cleanupMocks();
|
||||
await testEnv.cleanup();
|
||||
});
|
||||
|
||||
describe('Campaign Orchestration', () => {
|
||||
test('should create and execute a campaign', async () => {
|
||||
// Create campaign
|
||||
const campaignData = {
|
||||
name: 'Integration Test Campaign',
|
||||
description: 'Testing full orchestration flow',
|
||||
targetAudience: {
|
||||
groups: ['test-group-1'],
|
||||
tags: ['integration-test']
|
||||
},
|
||||
messages: [
|
||||
{
|
||||
content: 'Hello from integration test!',
|
||||
type: 'text',
|
||||
delay: 0
|
||||
},
|
||||
{
|
||||
content: 'This is the second message',
|
||||
type: 'text',
|
||||
delay: 1000
|
||||
}
|
||||
],
|
||||
schedule: {
|
||||
startTime: new Date(),
|
||||
endTime: new Date(Date.now() + 3600000),
|
||||
timezone: 'UTC'
|
||||
},
|
||||
goals: {
|
||||
impressions: 100,
|
||||
clicks: 10
|
||||
}
|
||||
};
|
||||
|
||||
const createResponse = await apiClient.post('/api/v1/campaigns', campaignData);
|
||||
const { campaign } = helpers.expectApiSuccess(createResponse, 201);
|
||||
|
||||
expect(campaign.campaignId).toBeDefined();
|
||||
expect(campaign.status).toBe('draft');
|
||||
|
||||
// Start campaign
|
||||
const startResponse = await apiClient.post(
|
||||
`/api/v1/campaigns/${campaign.campaignId}/start`
|
||||
);
|
||||
helpers.expectApiSuccess(startResponse);
|
||||
|
||||
// Wait for campaign to start processing
|
||||
await helpers.sleep(2000);
|
||||
|
||||
// Check campaign status
|
||||
const statusResponse = await apiClient.get(
|
||||
`/api/v1/campaigns/${campaign.campaignId}`
|
||||
);
|
||||
const updatedCampaign = helpers.expectApiSuccess(statusResponse).campaign;
|
||||
|
||||
expect(['active', 'completed']).toContain(updatedCampaign.status);
|
||||
|
||||
// Check that tasks were created
|
||||
const tasksResponse = await apiClient.get(
|
||||
`/api/v1/campaigns/${campaign.campaignId}/tasks`
|
||||
);
|
||||
const { tasks } = helpers.expectApiSuccess(tasksResponse);
|
||||
|
||||
expect(tasks).toBeDefined();
|
||||
expect(tasks.length).toBeGreaterThan(0);
|
||||
expect(tasks[0].type).toBe('SEND_MESSAGE');
|
||||
});
|
||||
|
||||
test('should handle campaign pause and resume', async () => {
|
||||
// Create and start campaign
|
||||
const campaign = await helpers.createTestCampaign({
|
||||
status: 'active'
|
||||
});
|
||||
|
||||
// Pause campaign
|
||||
const pauseResponse = await apiClient.post(
|
||||
`/api/v1/campaigns/${campaign.campaignId}/pause`
|
||||
);
|
||||
helpers.expectApiSuccess(pauseResponse);
|
||||
|
||||
// Verify paused status
|
||||
const pausedResponse = await apiClient.get(
|
||||
`/api/v1/campaigns/${campaign.campaignId}`
|
||||
);
|
||||
const pausedCampaign = helpers.expectApiSuccess(pausedResponse).campaign;
|
||||
expect(pausedCampaign.status).toBe('paused');
|
||||
|
||||
// Resume campaign
|
||||
const resumeResponse = await apiClient.post(
|
||||
`/api/v1/campaigns/${campaign.campaignId}/resume`
|
||||
);
|
||||
helpers.expectApiSuccess(resumeResponse);
|
||||
|
||||
// Verify active status
|
||||
const activeResponse = await apiClient.get(
|
||||
`/api/v1/campaigns/${campaign.campaignId}`
|
||||
);
|
||||
const activeCampaign = helpers.expectApiSuccess(activeResponse).campaign;
|
||||
expect(activeCampaign.status).toBe('active');
|
||||
});
|
||||
|
||||
test('should handle campaign cancellation', async () => {
|
||||
// Create and start campaign
|
||||
const campaign = await helpers.createTestCampaign({
|
||||
status: 'active'
|
||||
});
|
||||
|
||||
// Cancel campaign
|
||||
const cancelResponse = await apiClient.post(
|
||||
`/api/v1/campaigns/${campaign.campaignId}/cancel`
|
||||
);
|
||||
helpers.expectApiSuccess(cancelResponse);
|
||||
|
||||
// Verify cancelled status
|
||||
const cancelledResponse = await apiClient.get(
|
||||
`/api/v1/campaigns/${campaign.campaignId}`
|
||||
);
|
||||
const cancelledCampaign = helpers.expectApiSuccess(cancelledResponse).campaign;
|
||||
expect(cancelledCampaign.status).toBe('cancelled');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Task Execution', () => {
|
||||
test('should execute message sending task', async () => {
|
||||
// Create a message task
|
||||
const task = await helpers.createTestTask({
|
||||
type: 'SEND_MESSAGE',
|
||||
payload: {
|
||||
message: 'Test message from integration test',
|
||||
chatId: 'test-chat-123',
|
||||
options: {
|
||||
parseMode: 'HTML'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Execute task
|
||||
const executeResponse = await apiClient.post(
|
||||
`/api/v1/tasks/${task.taskId}/execute`
|
||||
);
|
||||
helpers.expectApiSuccess(executeResponse);
|
||||
|
||||
// Wait for execution
|
||||
await helpers.sleep(1000);
|
||||
|
||||
// Check task status
|
||||
const statusResponse = await apiClient.get(
|
||||
`/api/v1/tasks/${task.taskId}`
|
||||
);
|
||||
const executedTask = helpers.expectApiSuccess(statusResponse).task;
|
||||
|
||||
expect(['completed', 'processing']).toContain(executedTask.status);
|
||||
expect(executedTask.result).toBeDefined();
|
||||
});
|
||||
|
||||
test('should handle task retry on failure', async () => {
|
||||
// Create a task that will fail
|
||||
const task = await helpers.createTestTask({
|
||||
type: 'SEND_MESSAGE',
|
||||
payload: {
|
||||
message: 'Test message',
|
||||
chatId: 'invalid-chat-id', // This should cause a failure
|
||||
options: {}
|
||||
},
|
||||
maxRetries: 3
|
||||
});
|
||||
|
||||
// Execute task
|
||||
const executeResponse = await apiClient.post(
|
||||
`/api/v1/tasks/${task.taskId}/execute`
|
||||
);
|
||||
helpers.expectApiSuccess(executeResponse);
|
||||
|
||||
// Wait for retries
|
||||
await helpers.sleep(3000);
|
||||
|
||||
// Check task status
|
||||
const statusResponse = await apiClient.get(
|
||||
`/api/v1/tasks/${task.taskId}`
|
||||
);
|
||||
const retriedTask = helpers.expectApiSuccess(statusResponse).task;
|
||||
|
||||
expect(retriedTask.retryCount).toBeGreaterThan(0);
|
||||
expect(['failed', 'pending']).toContain(retriedTask.status);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Claude Agent Integration', () => {
|
||||
test('should generate campaign strategy using Claude', async () => {
|
||||
const strategyRequest = {
|
||||
goal: 'Increase user engagement',
|
||||
targetAudience: {
|
||||
demographics: {
|
||||
age: '25-35',
|
||||
interests: ['technology', 'startups']
|
||||
},
|
||||
size: 1000
|
||||
},
|
||||
constraints: {
|
||||
budget: 1000,
|
||||
duration: '7 days'
|
||||
}
|
||||
};
|
||||
|
||||
const response = await apiClient.post(
|
||||
'/api/v1/ai/strategy/generate',
|
||||
strategyRequest
|
||||
);
|
||||
|
||||
const { strategy } = helpers.expectApiSuccess(response);
|
||||
|
||||
expect(strategy).toBeDefined();
|
||||
expect(strategy.messages).toBeDefined();
|
||||
expect(strategy.schedule).toBeDefined();
|
||||
expect(strategy.expectedOutcomes).toBeDefined();
|
||||
});
|
||||
|
||||
test('should analyze campaign performance', async () => {
|
||||
// Create a completed campaign with some metrics
|
||||
const campaign = await helpers.createTestCampaign({
|
||||
status: 'completed',
|
||||
metrics: {
|
||||
impressions: 500,
|
||||
clicks: 50,
|
||||
conversions: 5
|
||||
}
|
||||
});
|
||||
|
||||
const analysisRequest = {
|
||||
campaignId: campaign.campaignId,
|
||||
metrics: campaign.metrics
|
||||
};
|
||||
|
||||
const response = await apiClient.post(
|
||||
'/api/v1/ai/analysis/campaign',
|
||||
analysisRequest
|
||||
);
|
||||
|
||||
const { analysis } = helpers.expectApiSuccess(response);
|
||||
|
||||
expect(analysis).toBeDefined();
|
||||
expect(analysis.performance).toBeDefined();
|
||||
expect(analysis.recommendations).toBeDefined();
|
||||
expect(analysis.insights).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Message Queue Integration', () => {
|
||||
test('should process messages through RabbitMQ', async () => {
|
||||
if (!testEnv.getRabbitChannel()) {
|
||||
console.log('Skipping RabbitMQ test - not available');
|
||||
return;
|
||||
}
|
||||
|
||||
const channel = testEnv.getRabbitChannel();
|
||||
const testQueue = 'test-integration-queue';
|
||||
const testMessage = {
|
||||
type: 'TEST_MESSAGE',
|
||||
data: {
|
||||
value: 'Integration test message',
|
||||
timestamp: new Date().toISOString()
|
||||
}
|
||||
};
|
||||
|
||||
// Create queue
|
||||
await channel.assertQueue(testQueue, { durable: false });
|
||||
|
||||
// Set up consumer
|
||||
const receivedMessages = [];
|
||||
await channel.consume(testQueue, (msg) => {
|
||||
if (msg) {
|
||||
receivedMessages.push(JSON.parse(msg.content.toString()));
|
||||
channel.ack(msg);
|
||||
}
|
||||
});
|
||||
|
||||
// Send message
|
||||
channel.sendToQueue(
|
||||
testQueue,
|
||||
Buffer.from(JSON.stringify(testMessage))
|
||||
);
|
||||
|
||||
// Wait for message to be processed
|
||||
await helpers.sleep(1000);
|
||||
|
||||
// Verify message was received
|
||||
expect(receivedMessages).toHaveLength(1);
|
||||
expect(receivedMessages[0]).toEqual(testMessage);
|
||||
|
||||
// Cleanup
|
||||
await channel.deleteQueue(testQueue);
|
||||
});
|
||||
});
|
||||
|
||||
describe('End-to-End Workflow', () => {
|
||||
test('should complete full marketing workflow', async () => {
|
||||
// 1. Generate strategy with Claude
|
||||
const strategyResponse = await apiClient.post('/api/v1/ai/strategy/generate', {
|
||||
goal: 'Product launch announcement',
|
||||
targetAudience: {
|
||||
demographics: { interests: ['tech'] },
|
||||
size: 500
|
||||
}
|
||||
});
|
||||
const { strategy } = helpers.expectApiSuccess(strategyResponse);
|
||||
|
||||
// 2. Create campaign based on strategy
|
||||
const campaignData = {
|
||||
name: 'Product Launch Campaign',
|
||||
description: 'Generated from AI strategy',
|
||||
targetAudience: strategy.targetAudience,
|
||||
messages: strategy.messages,
|
||||
schedule: strategy.schedule,
|
||||
goals: strategy.expectedOutcomes
|
||||
};
|
||||
|
||||
const createResponse = await apiClient.post('/api/v1/campaigns', campaignData);
|
||||
const { campaign } = helpers.expectApiSuccess(createResponse, 201);
|
||||
|
||||
// 3. Start campaign
|
||||
await apiClient.post(`/api/v1/campaigns/${campaign.campaignId}/start`);
|
||||
|
||||
// 4. Wait for some execution
|
||||
await helpers.sleep(3000);
|
||||
|
||||
// 5. Get analytics
|
||||
const analyticsResponse = await apiClient.get(
|
||||
`/api/v1/analytics/campaigns/${campaign.campaignId}/metrics`
|
||||
);
|
||||
const { metrics } = helpers.expectApiSuccess(analyticsResponse);
|
||||
|
||||
expect(metrics).toBeDefined();
|
||||
expect(metrics.totalMessages).toBeGreaterThanOrEqual(0);
|
||||
|
||||
// 6. Get AI analysis
|
||||
const analysisResponse = await apiClient.post('/api/v1/ai/analysis/campaign', {
|
||||
campaignId: campaign.campaignId,
|
||||
metrics: metrics
|
||||
});
|
||||
const { analysis } = helpers.expectApiSuccess(analysisResponse);
|
||||
|
||||
expect(analysis).toBeDefined();
|
||||
expect(analysis.performance).toBeDefined();
|
||||
|
||||
// 7. Stop campaign
|
||||
await apiClient.post(`/api/v1/campaigns/${campaign.campaignId}/cancel`);
|
||||
|
||||
// Verify final state
|
||||
const finalResponse = await apiClient.get(
|
||||
`/api/v1/campaigns/${campaign.campaignId}`
|
||||
);
|
||||
const finalCampaign = helpers.expectApiSuccess(finalResponse).campaign;
|
||||
expect(finalCampaign.status).toBe('cancelled');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user