/**
* Performance Monitoring Integration Tests
* Tests the complete performance monitoring system with DebuggerCore integration
*/
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import { DebuggerCore } from '../src/core/DebuggerCore.js';
import { ConfigManager } from '../src/config/ConfigManager.js';
// Mock external dependencies
vi.mock('puppeteer', () => ({
default: {
launch: vi.fn().mockResolvedValue({
newPage: vi.fn().mockResolvedValue({
on: vi.fn(),
goto: vi.fn(),
evaluate: vi.fn(),
close: vi.fn()
}),
close: vi.fn(),
on: vi.fn()
})
}
}));
describe('Performance Monitoring Integration', () => {
let debuggerCore: DebuggerCore;
let configManager: ConfigManager;
beforeEach(async () => {
configManager = new ConfigManager();
await configManager.initialize();
debuggerCore = new DebuggerCore(configManager);
// Mock Chrome debugger initialization to avoid actual browser connection
vi.spyOn(debuggerCore as any, 'chromeDebugger', 'get').mockReturnValue({
initialize: vi.fn().mockResolvedValue(undefined),
getHeapUsage: vi.fn().mockResolvedValue({ usedSize: 5000000, totalSize: 10000000 }),
takeHeapSnapshot: vi.fn().mockResolvedValue({ nodes: [], edges: [], strings: [] }),
startHeapSampling: vi.fn().mockResolvedValue(undefined),
stopHeapSampling: vi.fn().mockResolvedValue({ samples: [{ size: 1024, nodeId: 1 }] }),
collectGarbage: vi.fn().mockResolvedValue(undefined),
clearBrowserCache: vi.fn().mockResolvedValue(undefined),
clearBrowserCookies: vi.fn().mockResolvedValue(undefined),
setNetworkThrottling: vi.fn().mockResolvedValue(undefined),
on: vi.fn(),
shutdown: vi.fn().mockResolvedValue(undefined)
});
});
afterEach(async () => {
await debuggerCore.shutdown();
});
describe('CPU Profiling Integration', () => {
it('should start and stop CPU profiling through DebuggerCore', async () => {
await debuggerCore.initialize();
const profileId = await debuggerCore.startCPUProfiling('integration-test');
expect(profileId).toMatch(/^cpu_\d+$/);
// Simulate some work
await new Promise(resolve => setTimeout(resolve, 100));
const profile = await debuggerCore.stopCPUProfiling(profileId);
expect(profile).toMatchObject({
id: profileId,
duration: expect.any(Number),
flameGraph: expect.any(Array)
});
});
it('should handle multiple concurrent CPU profiles', async () => {
await debuggerCore.initialize();
const profile1Id = await debuggerCore.startCPUProfiling('test-1');
const profile2Id = await debuggerCore.startCPUProfiling('test-2');
expect(profile1Id).not.toBe(profile2Id);
const [profile1, profile2] = await Promise.all([
debuggerCore.stopCPUProfiling(profile1Id),
debuggerCore.stopCPUProfiling(profile2Id)
]);
expect(profile1.id).toBe(profile1Id);
expect(profile2.id).toBe(profile2Id);
});
});
describe('Memory Monitoring Integration', () => {
it('should take detailed heap snapshots', async () => {
await debuggerCore.initialize();
const snapshot = await debuggerCore.takeDetailedHeapSnapshot();
expect(snapshot).toMatchObject({
nodes: expect.any(Array),
edges: expect.any(Array)
});
});
it('should perform heap sampling', async () => {
await debuggerCore.initialize();
await debuggerCore.startHeapSampling(32768);
// Simulate some memory allocation
await new Promise(resolve => setTimeout(resolve, 200));
const profile = await debuggerCore.stopHeapSampling();
expect(profile).toMatchObject({
samples: expect.any(Array)
});
});
it('should get memory snapshots over time', async () => {
await debuggerCore.initialize();
// Wait for some memory snapshots to be collected
await new Promise(resolve => setTimeout(resolve, 100));
const snapshots = await debuggerCore.getMemorySnapshots(5);
expect(Array.isArray(snapshots)).toBe(true);
});
it('should force garbage collection', async () => {
await debuggerCore.initialize();
await expect(debuggerCore.forceGarbageCollection()).resolves.not.toThrow();
});
});
describe('Network Performance Integration', () => {
it('should analyze network performance patterns', async () => {
await debuggerCore.initialize();
// Simulate network metrics collection
const analysis = await debuggerCore.analyzeNetworkPerformance(60000);
expect(analysis).toMatchObject({
totalRequests: expect.any(Number),
averageResponseTime: expect.any(Number),
slowRequests: expect.any(Array),
failedRequests: expect.any(Number),
largestRequests: expect.any(Array),
domainBreakdown: expect.any(Object),
recommendations: expect.any(Array)
});
});
it('should manage browser cache and cookies', async () => {
await debuggerCore.initialize();
await expect(debuggerCore.clearBrowserCache()).resolves.not.toThrow();
await expect(debuggerCore.clearBrowserCookies()).resolves.not.toThrow();
});
it('should configure network throttling', async () => {
await debuggerCore.initialize();
const throttlingOptions = {
offline: false,
downloadThroughput: 1000000,
uploadThroughput: 500000,
latency: 50
};
await expect(debuggerCore.setNetworkThrottling(throttlingOptions)).resolves.not.toThrow();
});
});
describe('Render Performance Integration', () => {
it('should analyze render performance', async () => {
await debuggerCore.initialize();
// Simulate some render tracking
await debuggerCore.startRenderTracking('test-component', 'props', ['data'], []);
await new Promise(resolve => setTimeout(resolve, 50));
await debuggerCore.trackComponentRender('test-component', 'props', ['data'], []);
const analysis = await debuggerCore.analyzeRenderPerformance(60000);
expect(analysis).toMatchObject({
totalRenders: expect.any(Number),
averageRenderTime: expect.any(Number),
slowRenders: expect.any(Array),
rendersByComponent: expect.any(Object),
renderReasons: expect.any(Object),
recommendations: expect.any(Array),
performanceScore: expect.any(Number)
});
});
it('should get detailed render metrics', async () => {
await debuggerCore.initialize();
const metrics = await debuggerCore.getDetailedRenderMetrics();
expect(metrics).toMatchObject({
totalRenders: expect.any(Number),
averageRenderTime: expect.any(Number),
heavyComponents: expect.any(Array),
recentRenders: expect.any(Array),
slowRenders: expect.any(Array),
renderTrends: expect.any(Array)
});
});
});
describe('Performance Alerts Integration', () => {
it('should generate and manage performance alerts', async () => {
await debuggerCore.initialize();
// Wait for potential alerts to be generated
await new Promise(resolve => setTimeout(resolve, 100));
const alerts = await debuggerCore.getPerformanceAlerts(false);
expect(Array.isArray(alerts)).toBe(true);
// Test alert resolution if any alerts exist
if (alerts.length > 0) {
const alertId = alerts[0].id;
const resolved = await debuggerCore.resolvePerformanceAlert(alertId);
expect(resolved).toBe(true);
}
});
});
describe('Comprehensive Performance Analysis', () => {
it('should generate performance optimization recommendations', async () => {
await debuggerCore.initialize();
// Simulate some performance data
await new Promise(resolve => setTimeout(resolve, 200));
const recommendations = await debuggerCore.getPerformanceOptimizationRecommendations(300000);
expect(recommendations).toMatchObject({
overallScore: expect.any(Number),
categories: {
render: {
score: expect.any(Number),
issues: expect.any(Array),
recommendations: expect.any(Array)
},
network: {
score: expect.any(Number),
issues: expect.any(Array),
recommendations: expect.any(Array)
},
memory: {
score: expect.any(Number),
issues: expect.any(Array),
recommendations: expect.any(Array)
},
cpu: {
score: expect.any(Number),
issues: expect.any(Array),
recommendations: expect.any(Array)
}
},
prioritizedActions: expect.any(Array),
quickWins: expect.any(Array),
longTermGoals: expect.any(Array)
});
expect(recommendations.overallScore).toBeGreaterThanOrEqual(0);
expect(recommendations.overallScore).toBeLessThanOrEqual(100);
});
it('should collect comprehensive performance metrics', async () => {
await debuggerCore.initialize();
const metrics = await debuggerCore.getPerformanceMetrics({
timeframe: '5m',
type: 'cpu',
limit: 10
});
expect(Array.isArray(metrics)).toBe(true);
});
});
describe('Error Handling and Edge Cases', () => {
it('should handle performance monitoring without Chrome debugger', async () => {
// Create debugger core without Chrome debugger
const coreWithoutChrome = new DebuggerCore(configManager);
// Mock failed Chrome initialization
vi.spyOn(coreWithoutChrome as any, 'chromeDebugger', 'get').mockReturnValue({
initialize: vi.fn().mockRejectedValue(new Error('Chrome not available')),
shutdown: vi.fn().mockResolvedValue(undefined)
});
await coreWithoutChrome.initialize();
// Should still work for basic performance metrics
const metrics = await coreWithoutChrome.getPerformanceMetrics();
expect(Array.isArray(metrics)).toBe(true);
await coreWithoutChrome.shutdown();
});
it('should handle concurrent performance operations', async () => {
await debuggerCore.initialize();
// Start multiple operations concurrently
const operations = [
debuggerCore.getPerformanceMetrics(),
debuggerCore.analyzeRenderPerformance(),
debuggerCore.analyzeNetworkPerformance(),
debuggerCore.getMemorySnapshots(5),
debuggerCore.getPerformanceAlerts()
];
const results = await Promise.all(operations);
// All operations should complete successfully
results.forEach(result => {
expect(result).toBeDefined();
});
});
it('should handle performance monitoring shutdown gracefully', async () => {
await debuggerCore.initialize();
// Start some operations
const profileId = await debuggerCore.startCPUProfiling('shutdown-test');
await debuggerCore.startHeapSampling();
// Shutdown should clean up properly
await expect(debuggerCore.shutdown()).resolves.not.toThrow();
});
});
});