log-vista
Version:
LogVista Agent - Lightweight system monitoring and log collection for any project/language
224 lines (189 loc) • 7.06 kB
JavaScript
/**
* Integration Tests
* Tests the complete agent functionality end-to-end
*/
const fs = require('fs');
const path = require('path');
const os = require('os');
const { execSync } = require('child_process');
describe('LogVista Agent Integration', () => {
let tempDir;
let configPath;
beforeEach(() => {
tempDir = path.join(os.tmpdir(), 'logvista-integration-test-' + Date.now());
fs.mkdirSync(tempDir, { recursive: true });
configPath = path.join(tempDir, '.logvista', 'config.json');
// Create .logvista directory
fs.mkdirSync(path.dirname(configPath), { recursive: true });
});
afterEach(() => {
if (fs.existsSync(tempDir)) {
fs.rmSync(tempDir, { recursive: true, force: true });
}
});
test('should complete full initialization workflow', () => {
// Create a mock project structure
const packageJsonPath = path.join(tempDir, 'package.json');
fs.writeFileSync(packageJsonPath, JSON.stringify({
name: 'test-integration-project',
version: '1.0.0',
scripts: {
start: 'node app.js'
}
}, null, 2));
// Create logs directory
const logsDir = path.join(tempDir, 'logs');
fs.mkdirSync(logsDir);
// Create sample log file
const logFile = path.join(logsDir, 'app.log');
fs.writeFileSync(logFile, '[2025-01-01 12:00:00] INFO: Application started\n');
// Create basic config
const config = {
central_system: {
url: 'http://localhost:3001',
token: 'test-integration-token'
},
collection: {
interval: 30,
batch_size: 100,
retry_attempts: 3,
retry_delay: 5000
},
projects: [{
project_name: 'Test Integration Project',
pwd_path: tempDir,
custom_log_paths: [
path.join(logsDir, '*.log')
],
enabled: true
}]
};
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
// Verify configuration was created
expect(fs.existsSync(configPath)).toBe(true);
const savedConfig = JSON.parse(fs.readFileSync(configPath, 'utf8'));
expect(savedConfig.projects).toHaveLength(1);
expect(savedConfig.projects[0].project_name).toBe('Test Integration Project');
});
test('should handle multiple project types in same directory', () => {
// Create multiple project indicators
fs.writeFileSync(path.join(tempDir, 'package.json'), '{"name": "node-project"}');
fs.writeFileSync(path.join(tempDir, 'composer.json'), '{"name": "php-project"}');
fs.writeFileSync(path.join(tempDir, 'requirements.txt'), 'django>=4.0');
// The agent should detect the primary project type (Node.js in this case)
expect(fs.existsSync(path.join(tempDir, 'package.json'))).toBe(true);
expect(fs.existsSync(path.join(tempDir, 'composer.json'))).toBe(true);
expect(fs.existsSync(path.join(tempDir, 'requirements.txt'))).toBe(true);
});
test('should create proper log path patterns for different project types', () => {
const testCases = [
{
type: 'nodejs',
files: ['package.json'],
expectedPaths: ['logs/*.log', '*.log']
},
{
type: 'php',
files: ['composer.json'],
expectedPaths: ['storage/logs/*.log', 'logs/*.log', '*.log']
},
{
type: 'python',
files: ['requirements.txt'],
expectedPaths: ['logs/*.log', 'log/*.log', '*.log']
},
{
type: 'dotnet',
files: ['*.csproj', '*.sln'],
expectedPaths: ['logs/*.log', 'Logs/*.log', '*.log']
}
];
testCases.forEach(testCase => {
// Create a new temp directory for each test case
const testDir = path.join(tempDir, testCase.type);
fs.mkdirSync(testDir, { recursive: true });
// Create project indicator files
testCase.files.forEach(file => {
if (file.includes('*')) {
// Handle wildcard files like *.csproj
const fileName = file.replace('*', 'test');
fs.writeFileSync(path.join(testDir, fileName), 'test content');
} else {
fs.writeFileSync(path.join(testDir, file), 'test content');
}
});
// Verify files were created
const createdFiles = fs.readdirSync(testDir);
expect(createdFiles.length).toBeGreaterThan(0);
});
});
test('should handle configuration validation', () => {
// Test valid configuration
const validConfig = {
central_system: {
url: 'http://localhost:3001',
token: 'valid-token'
},
collection: {
interval: 30,
batch_size: 100
},
projects: [{
project_name: 'Valid Project',
pwd_path: tempDir,
custom_log_paths: ['logs/*.log'],
enabled: true
}]
};
fs.writeFileSync(configPath, JSON.stringify(validConfig, null, 2));
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
expect(config.central_system.url).toBeTruthy();
expect(config.central_system.token).toBeTruthy();
expect(config.projects).toHaveLength(1);
expect(config.projects[0].enabled).toBe(true);
});
test('should create offline storage directory', () => {
const offlineDir = path.join(tempDir, '.logvista', 'offline');
fs.mkdirSync(offlineDir, { recursive: true });
expect(fs.existsSync(offlineDir)).toBe(true);
// Test offline file creation
const offlineFile = path.join(offlineDir, 'metrics-test.json');
fs.writeFileSync(offlineFile, JSON.stringify({
timestamp: new Date().toISOString(),
data: 'test metrics'
}));
expect(fs.existsSync(offlineFile)).toBe(true);
});
test('should handle log file watching', (done) => {
const logFile = path.join(tempDir, 'test.log');
fs.writeFileSync(logFile, '');
// Simulate file watching by checking file changes
const initialStats = fs.statSync(logFile);
setTimeout(() => {
fs.appendFileSync(logFile, 'New log entry\n');
const newStats = fs.statSync(logFile);
expect(newStats.mtime.getTime()).toBeGreaterThan(initialStats.mtime.getTime());
expect(newStats.size).toBeGreaterThan(initialStats.size);
done();
}, 100);
}, 5000);
test('should maintain proper directory structure', () => {
const expectedDirs = [
'.logvista',
'.logvista/offline'
];
expectedDirs.forEach(dir => {
const fullPath = path.join(tempDir, dir);
fs.mkdirSync(fullPath, { recursive: true });
expect(fs.existsSync(fullPath)).toBe(true);
});
const expectedFiles = [
'.logvista/config.json'
];
expectedFiles.forEach(file => {
const fullPath = path.join(tempDir, file);
fs.writeFileSync(fullPath, '{}');
expect(fs.existsSync(fullPath)).toBe(true);
});
});
});