import { ElectronApplication } from '@playwright/test'; export interface IPCTestResult { channel: string; success: boolean; error?: string; duration: number; } /** * IPCVerifier - Tests IPC channel contracts * * Purpose: Verify main <-> renderer communication works * Scope: Core IPC channels required for app functionality */ export class IPCVerifier { constructor(private app: ElectronApplication) {} /** * Test checkAuth IPC channel */ async testCheckAuth(): Promise { const start = Date.now(); const channel = 'auth:check'; try { const result = await this.app.evaluate(async ({ ipcMain }) => { return new Promise((resolve) => { // Simulate IPC invoke handler by calling the first registered handler for the channel const handlers = (ipcMain as any).listeners('auth:check') || []; const handler = handlers[0]; if (!handler) { resolve({ error: 'Handler not registered' }); } else { // Invoke the handler similar to ipcMain.handle invocation signature // (event, ...args) => Promise const mockEvent = {} as any; Promise.resolve(handler(mockEvent)).then((res: any) => resolve(res)).catch((err: any) => resolve({ error: err && err.message ? err.message : String(err) })); } }); }); return { channel, success: !result.error, error: result.error, duration: Date.now() - start, }; } catch (error) { return { channel, success: false, error: error instanceof Error ? error.message : String(error), duration: Date.now() - start, }; } } /** * Test getBrowserMode IPC channel */ async testGetBrowserMode(): Promise { const start = Date.now(); const channel = 'browser-mode:get'; try { const result = await this.app.evaluate(async ({ ipcMain }) => { return new Promise((resolve) => { const handlers = (ipcMain as any).listeners('browser-mode:get') || []; const handler = handlers[0]; if (!handler) { resolve({ error: 'Handler not registered' }); } else { const mockEvent = {} as any; Promise.resolve(handler(mockEvent)).then((res: any) => resolve(res)).catch((err: any) => resolve({ error: err && err.message ? err.message : String(err) })); } }); }); return { channel, success: (result && !result.error) || typeof result === 'object', error: result && result.error, duration: Date.now() - start, }; } catch (error) { return { channel, success: false, error: error instanceof Error ? error.message : String(error), duration: Date.now() - start, }; } } /** * Test startAutomationSession IPC channel contract */ async testStartAutomationSession(): Promise { const start = Date.now(); const channel = 'start-automation'; try { const result = await this.app.evaluate(async ({ ipcMain }) => { return new Promise((resolve) => { const handlers = (ipcMain as any).listeners('start-automation') || []; const handler = handlers[0]; if (!handler) { resolve({ error: 'Handler not registered' }); } else { // Test with mock data const mockEvent = {} as any; Promise.resolve(handler(mockEvent, { sessionName: 'test', mode: 'test' })).then((res: any) => resolve(res)).catch((err: any) => resolve({ error: err && err.message ? err.message : String(err) })); } }); }); return { channel, success: !result.error, error: result.error, duration: Date.now() - start, }; } catch (error) { return { channel, success: false, error: error instanceof Error ? error.message : String(error), duration: Date.now() - start, }; } } /** * Run all IPC tests and return results */ async verifyAllChannels(): Promise { return Promise.all([ this.testCheckAuth(), this.testGetBrowserMode(), this.testStartAutomationSession(), ]); } /** * Format IPC test results for output */ static formatResults(results: IPCTestResult[]): string { const lines = ['IPC Channel Verification:', '']; results.forEach(result => { const status = result.success ? '✓' : '✗'; lines.push(`${status} ${result.channel} (${result.duration}ms)`); if (result.error) { lines.push(` Error: ${result.error}`); } }); return lines.join('\n'); } }