Modularizes test helpers into separate files for assertions, generators, and mocks, and updates imports for platform tests. Adds new tests to verify Authorization header forwarding for authenticated requests. Cleans up and simplifies test setup, and updates fixtures for clarity and maintainability.
236 lines
6.8 KiB
JavaScript
236 lines
6.8 KiB
JavaScript
import { beforeEach, describe, expect, it } from 'vitest';
|
|
|
|
// Mock PerformanceMonitor class for testing
|
|
class MockPerformanceMonitor {
|
|
constructor() {
|
|
this.startTime = Date.now();
|
|
this.marks = new Map();
|
|
}
|
|
|
|
mark(name) {
|
|
if (this.marks.has(name)) {
|
|
console.warn(`Mark with name ${name} already exists.`);
|
|
}
|
|
this.marks.set(name, Date.now() - this.startTime);
|
|
}
|
|
|
|
getMetrics() {
|
|
return Object.fromEntries(this.marks.entries());
|
|
}
|
|
}
|
|
|
|
describe('Performance Monitoring', () => {
|
|
let monitor;
|
|
|
|
beforeEach(() => {
|
|
monitor = new MockPerformanceMonitor();
|
|
});
|
|
|
|
describe('PerformanceMonitor Class', () => {
|
|
it('should initialize with start time', () => {
|
|
expect(monitor.startTime).toBeDefined();
|
|
expect(typeof monitor.startTime).toBe('number');
|
|
});
|
|
|
|
it('should create timing marks', () => {
|
|
monitor.mark('test-mark');
|
|
|
|
const metrics = monitor.getMetrics();
|
|
expect(metrics).toHaveProperty('test-mark');
|
|
expect(typeof metrics['test-mark']).toBe('number');
|
|
});
|
|
|
|
it('should handle multiple marks', () => {
|
|
monitor.mark('mark1');
|
|
monitor.mark('mark2');
|
|
monitor.mark('mark3');
|
|
|
|
const metrics = monitor.getMetrics();
|
|
expect(Object.keys(metrics)).toHaveLength(3);
|
|
expect(metrics).toHaveProperty('mark1');
|
|
expect(metrics).toHaveProperty('mark2');
|
|
expect(metrics).toHaveProperty('mark3');
|
|
});
|
|
|
|
it('should warn on duplicate mark names', () => {
|
|
// Mock console.warn for this test
|
|
const originalWarn = console.warn;
|
|
const mockWarn = vi ? vi.fn() : jest.fn();
|
|
console.warn = mockWarn;
|
|
|
|
monitor.mark('duplicate');
|
|
monitor.mark('duplicate');
|
|
|
|
expect(mockWarn).toHaveBeenCalledWith('Mark with name duplicate already exists.');
|
|
|
|
// Restore original console.warn
|
|
console.warn = originalWarn;
|
|
});
|
|
|
|
it('should return metrics as plain object', () => {
|
|
monitor.mark('test');
|
|
|
|
const metrics = monitor.getMetrics();
|
|
expect(metrics).toBeTypeOf('object');
|
|
expect(Array.isArray(metrics)).toBe(false);
|
|
});
|
|
|
|
it('should track elapsed time correctly', async () => {
|
|
monitor.mark('start');
|
|
|
|
// Wait a small amount of time
|
|
await new Promise(resolve => setTimeout(resolve, 10));
|
|
|
|
monitor.mark('end');
|
|
|
|
const metrics = monitor.getMetrics();
|
|
expect(metrics.end).toBeGreaterThan(metrics.start);
|
|
});
|
|
});
|
|
|
|
describe('Performance Metrics Validation', () => {
|
|
it('should produce serializable metrics', () => {
|
|
monitor.mark('request-start');
|
|
monitor.mark('proxy-start');
|
|
monitor.mark('proxy-end');
|
|
monitor.mark('request-end');
|
|
|
|
const metrics = monitor.getMetrics();
|
|
|
|
expect(() => JSON.stringify(metrics)).not.toThrow();
|
|
});
|
|
|
|
it('should have reasonable timing values', () => {
|
|
monitor.mark('test-mark');
|
|
|
|
const metrics = monitor.getMetrics();
|
|
const timing = metrics['test-mark'];
|
|
|
|
// Should be a positive number and reasonable (less than 1 second for this test)
|
|
expect(timing).toBeGreaterThanOrEqual(0);
|
|
expect(timing).toBeLessThan(1000);
|
|
});
|
|
|
|
it('should maintain chronological order', async () => {
|
|
monitor.mark('first');
|
|
await new Promise(resolve => setTimeout(resolve, 5));
|
|
monitor.mark('second');
|
|
await new Promise(resolve => setTimeout(resolve, 5));
|
|
monitor.mark('third');
|
|
|
|
const metrics = monitor.getMetrics();
|
|
|
|
expect(metrics.first).toBeLessThan(metrics.second);
|
|
expect(metrics.second).toBeLessThan(metrics.third);
|
|
});
|
|
});
|
|
|
|
describe('Common Performance Scenarios', () => {
|
|
it('should track request lifecycle', () => {
|
|
// Simulate typical request flow
|
|
monitor.mark('request-received');
|
|
monitor.mark('validation-complete');
|
|
monitor.mark('proxy-start');
|
|
monitor.mark('proxy-response');
|
|
monitor.mark('response-sent');
|
|
|
|
const metrics = monitor.getMetrics();
|
|
|
|
expect(metrics).toHaveProperty('request-received');
|
|
expect(metrics).toHaveProperty('validation-complete');
|
|
expect(metrics).toHaveProperty('proxy-start');
|
|
expect(metrics).toHaveProperty('proxy-response');
|
|
expect(metrics).toHaveProperty('response-sent');
|
|
});
|
|
|
|
it('should track cache operations', () => {
|
|
monitor.mark('cache-check-start');
|
|
monitor.mark('cache-miss');
|
|
monitor.mark('upstream-request');
|
|
monitor.mark('cache-store');
|
|
|
|
const metrics = monitor.getMetrics();
|
|
|
|
expect(metrics).toHaveProperty('cache-check-start');
|
|
expect(metrics).toHaveProperty('cache-miss');
|
|
expect(metrics).toHaveProperty('upstream-request');
|
|
expect(metrics).toHaveProperty('cache-store');
|
|
});
|
|
|
|
it('should track error scenarios', () => {
|
|
monitor.mark('request-start');
|
|
monitor.mark('error-occurred');
|
|
monitor.mark('error-handled');
|
|
|
|
const metrics = monitor.getMetrics();
|
|
|
|
expect(metrics).toHaveProperty('request-start');
|
|
expect(metrics).toHaveProperty('error-occurred');
|
|
expect(metrics).toHaveProperty('error-handled');
|
|
});
|
|
});
|
|
|
|
describe('Performance Thresholds', () => {
|
|
it('should identify slow operations', () => {
|
|
monitor.mark('operation-start');
|
|
|
|
// Simulate slow operation
|
|
const slowTiming = 5000; // 5 seconds
|
|
monitor.marks.set('operation-end', slowTiming);
|
|
|
|
const metrics = monitor.getMetrics();
|
|
const operationTime = metrics['operation-end'] - (metrics['operation-start'] || 0);
|
|
|
|
// Should identify as slow (> 1 second)
|
|
expect(operationTime).toBeGreaterThan(1000);
|
|
});
|
|
|
|
it('should identify fast operations', () => {
|
|
monitor.mark('fast-operation');
|
|
|
|
const metrics = monitor.getMetrics();
|
|
const timing = metrics['fast-operation'];
|
|
|
|
// Should be fast (< 100ms for this test)
|
|
expect(timing).toBeLessThan(100);
|
|
});
|
|
});
|
|
|
|
describe('Memory and Resource Usage', () => {
|
|
it('should not leak memory with many marks', () => {
|
|
const initialSize = monitor.marks.size;
|
|
|
|
// Add many marks
|
|
for (let i = 0; i < 1000; i++) {
|
|
monitor.mark(`mark-${i}`);
|
|
}
|
|
|
|
expect(monitor.marks.size).toBe(initialSize + 1000);
|
|
|
|
// Clear marks (if such method existed)
|
|
monitor.marks.clear();
|
|
expect(monitor.marks.size).toBe(0);
|
|
});
|
|
|
|
it('should handle concurrent mark operations', () => {
|
|
const promises = [];
|
|
|
|
for (let i = 0; i < 10; i++) {
|
|
promises.push(
|
|
new Promise(resolve => {
|
|
setTimeout(() => {
|
|
monitor.mark(`concurrent-${i}`);
|
|
resolve();
|
|
}, Math.random() * 10);
|
|
})
|
|
);
|
|
}
|
|
|
|
return Promise.all(promises).then(() => {
|
|
const metrics = monitor.getMetrics();
|
|
expect(Object.keys(metrics)).toHaveLength(10);
|
|
});
|
|
});
|
|
});
|
|
});
|