Files
gridpilot.gg/tests/smoke/helpers/console-monitor.ts
2025-12-12 21:39:48 +01:00

134 lines
3.0 KiB
TypeScript

import { Page, ConsoleMessage } from '@playwright/test';
export interface ConsoleError {
type: 'error' | 'warning' | 'pageerror';
message: string;
location?: string;
timestamp: Date;
}
/**
* ConsoleMonitor - Aggregates and tracks all console output
*
* Purpose: Catch ANY runtime errors during Electron app lifecycle
*
* Critical Detections:
* - "Module has been externalized for browser compatibility"
* - "__dirname is not defined"
* - "require is not defined"
* - Any uncaught exceptions
*/
export class ConsoleMonitor {
private errors: ConsoleError[] = [];
private warnings: ConsoleError[] = [];
private isMonitoring = false;
/**
* Start monitoring console output on the page
*/
startMonitoring(page: Page): void {
if (this.isMonitoring) {
return;
}
// Monitor console.error calls
page.on('console', (msg: ConsoleMessage) => {
if (msg.type() === 'error') {
this.errors.push({
type: 'error',
message: msg.text(),
location: msg.location()?.url,
timestamp: new Date(),
});
} else if (msg.type() === 'warning') {
this.warnings.push({
type: 'warning',
message: msg.text(),
location: msg.location()?.url,
timestamp: new Date(),
});
}
});
// Monitor uncaught exceptions
page.on('pageerror', (error: Error) => {
const errorObj: ConsoleError = {
type: 'pageerror',
message: error.message,
timestamp: new Date(),
};
if (error.stack) {
errorObj.location = error.stack;
}
this.errors.push(errorObj);
});
this.isMonitoring = true;
}
/**
* Check if any errors were detected
*/
hasErrors(): boolean {
return this.errors.length > 0;
}
/**
* Get all detected errors
*/
getErrors(): ConsoleError[] {
return [...this.errors];
}
/**
* Get all detected warnings
*/
getWarnings(): ConsoleError[] {
return [...this.warnings];
}
/**
* Format errors for test output
*/
formatErrors(): string {
if (this.errors.length === 0) {
return 'No errors detected';
}
const lines = ['Console errors detected during test:', ''];
this.errors.forEach((error, index) => {
lines.push(`${index + 1}. [${error.type}] ${error.message}`);
if (error.location) {
lines.push(` Location: ${error.location}`);
}
lines.push('');
});
return lines.join('\n');
}
/**
* Check for specific browser context errors
*/
hasBrowserContextErrors(): boolean {
const contextErrorPatterns = [
/has been externalized for browser compatibility/i,
/__dirname is not defined/i,
/require is not defined/i,
/Cannot access .* in client code/i,
];
return this.errors.some(error =>
contextErrorPatterns.some(pattern => pattern.test(error.message))
);
}
/**
* Reset monitoring state
*/
reset(): void {
this.errors = [];
this.warnings = [];
}
}