Files
novalon-website/test-framework/shared/utils/performance/PerformanceMonitor.ts
T
2026-03-06 12:08:30 +08:00

60 lines
2.1 KiB
TypeScript

import { Page } from '@playwright/test';
import { PerformanceMetrics, NetworkTiming, ResourceTiming } from '../../types';
export class PerformanceMonitor {
constructor(private page: Page) {}
async measurePageLoad(): Promise<PerformanceMetrics> {
const metrics = await this.page.evaluate(() => {
const performance = window.performance;
const timing = performance.timing;
const navigation = performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming;
return {
loadTime: timing.loadEventEnd - timing.navigationStart,
domContentLoaded: timing.domContentLoadedEventEnd - timing.navigationStart,
firstPaint: navigation ? navigation.loadEventEnd - navigation.fetchStart : 0,
firstContentfulPaint: navigation ? navigation.domContentLoadedEventEnd - navigation.fetchStart : 0,
};
});
return metrics;
}
async measureNetworkTiming(): Promise<NetworkTiming> {
return await this.page.evaluate(() => {
const timing = performance.timing;
return {
dns: timing.domainLookupEnd - timing.domainLookupStart,
tcp: timing.connectEnd - timing.connectStart,
ssl: timing.connectEnd - timing.secureConnectionStart,
request: timing.responseStart - timing.requestStart,
response: timing.responseEnd - timing.responseStart,
total: timing.loadEventEnd - timing.navigationStart,
};
});
}
async measureResourceTiming(): Promise<ResourceTiming[]> {
return await this.page.evaluate(() => {
const resources = performance.getEntriesByType('resource') as PerformanceResourceTiming[];
return resources.map(r => ({
name: r.name,
duration: r.duration,
size: r.transferSize,
type: r.initiatorType
}));
});
}
async measureMemoryUsage(): Promise<{ usedJSHeapSize: number; totalJSHeapSize: number }> {
return await this.page.evaluate(() => {
const memory = (performance as any).memory;
return {
usedJSHeapSize: memory.usedJSHeapSize,
totalJSHeapSize: memory.totalJSHeapSize
};
});
}
}