- wxWidgets logs: tests/logs/wxwidgets/<test-file>/ - KiCad logs: tests/logs/kicad/<test-file>/ - Global setup now cleans all log subdirectories recursively - Added globalSetup to KiCad playwright config 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
104 lines
3.1 KiB
TypeScript
104 lines
3.1 KiB
TypeScript
import { Page } from '@playwright/test';
|
|
import * as fs from 'fs';
|
|
import * as path from 'path';
|
|
|
|
export const MAIN_CANVAS = '#canvas';
|
|
export const LOGS_BASE_DIR = path.join(__dirname, '..', '..', 'logs');
|
|
export const WXWIDGETS_LOGS_DIR = path.join(LOGS_BASE_DIR, 'wxwidgets');
|
|
export const KICAD_LOGS_DIR = path.join(LOGS_BASE_DIR, 'kicad');
|
|
|
|
export interface TestLogger {
|
|
consoleLogs: string[];
|
|
errors: string[];
|
|
cleanup: () => void;
|
|
}
|
|
|
|
// Ensure logs directory exists
|
|
export function ensureLogsDir(dir: string = LOGS_BASE_DIR) {
|
|
if (!fs.existsSync(dir)) {
|
|
fs.mkdirSync(dir, { recursive: true });
|
|
}
|
|
}
|
|
|
|
// Setup logging for a test - captures console and errors
|
|
export function setupTestLogger(page: Page): TestLogger {
|
|
const consoleLogs: string[] = [];
|
|
const errors: string[] = [];
|
|
|
|
const consoleHandler = (msg: any) => {
|
|
const type = msg.type();
|
|
const text = msg.text();
|
|
const timestamp = new Date().toISOString();
|
|
consoleLogs.push(`[${timestamp}] [${type.toUpperCase()}] ${text}`);
|
|
};
|
|
|
|
const errorHandler = (err: Error) => {
|
|
const timestamp = new Date().toISOString();
|
|
const stack = err.stack || 'No stack trace available';
|
|
errors.push(`[${timestamp}] [ERROR] ${err.message}\n${stack}`);
|
|
};
|
|
|
|
page.on('console', consoleHandler);
|
|
page.on('pageerror', errorHandler);
|
|
|
|
const cleanup = () => {
|
|
page.off('console', consoleHandler);
|
|
page.off('pageerror', errorHandler);
|
|
};
|
|
|
|
return { consoleLogs, errors, cleanup };
|
|
}
|
|
|
|
// Write logs to files after test completion
|
|
export function writeTestLogs(testName: string, logger: TestLogger, logsDir: string) {
|
|
// Ensure logs directory exists
|
|
if (!fs.existsSync(logsDir)) {
|
|
fs.mkdirSync(logsDir, { recursive: true });
|
|
}
|
|
|
|
// Sanitize test name for filesystem
|
|
const safeTestName = testName
|
|
.toLowerCase()
|
|
.replace(/[^a-z0-9]+/g, '-')
|
|
.replace(/^-+|-+$/g, '');
|
|
|
|
// Always write console log file
|
|
const logFile = path.join(logsDir, `${safeTestName}.log`);
|
|
fs.writeFileSync(logFile, logger.consoleLogs.join('\n'));
|
|
|
|
// Only write error file if there are errors (excluding favicon)
|
|
const realErrors = logger.errors.filter(e => !e.includes('favicon'));
|
|
if (realErrors.length > 0) {
|
|
const errorFile = path.join(logsDir, `${safeTestName}.errors.log`);
|
|
fs.writeFileSync(errorFile, realErrors.join('\n\n'));
|
|
}
|
|
}
|
|
|
|
// Helper to get test file name without extension
|
|
export function getTestFileName(filePath: string): string {
|
|
return path.basename(filePath, '.spec.ts');
|
|
}
|
|
|
|
// Helper to wait for app initialization
|
|
export async function waitForApp(page: Page, timeout = 30000) {
|
|
await page.waitForSelector(MAIN_CANVAS, { state: 'visible', timeout });
|
|
await page.waitForTimeout(500);
|
|
}
|
|
|
|
// Helper to try loading app with fallback
|
|
export async function tryLoadApp(page: Page, timeout = 15000): Promise<boolean> {
|
|
try {
|
|
await waitForApp(page, timeout);
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Get canvas bounding box helper
|
|
export async function getCanvasBox(page: Page) {
|
|
const canvas = page.locator(MAIN_CANVAS);
|
|
const box = await canvas.boundingBox();
|
|
if (!box) throw new Error('Canvas not found');
|
|
return box;
|
|
}
|