import { Page } from '@playwright/test'; import { PerformanceMetrics, NetworkTiming, ResourceTiming } from '../../types'; export class PerformanceMonitor { constructor(private page: Page) {} async measurePageLoad(): Promise { 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 { 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 { 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 }; }); } }