175 lines
4.9 KiB
TypeScript
175 lines
4.9 KiB
TypeScript
import { ElectronApplication } from '@playwright/test';
|
|
|
|
type IpcHandlerResult = {
|
|
error?: string;
|
|
[key: string]: unknown;
|
|
};
|
|
|
|
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<IPCTestResult> {
|
|
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) }));
|
|
}
|
|
});
|
|
});
|
|
|
|
const typed: IpcHandlerResult = result as IpcHandlerResult;
|
|
|
|
return {
|
|
channel,
|
|
success: !typed.error,
|
|
error: typed.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<IPCTestResult> {
|
|
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) }));
|
|
}
|
|
});
|
|
});
|
|
|
|
const typed: IpcHandlerResult = result as IpcHandlerResult;
|
|
|
|
return {
|
|
channel,
|
|
success: !typed.error,
|
|
error: typed.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<IPCTestResult> {
|
|
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) }));
|
|
}
|
|
});
|
|
});
|
|
|
|
const typed: IpcHandlerResult = result as IpcHandlerResult;
|
|
|
|
return {
|
|
channel,
|
|
success: !typed.error,
|
|
error: typed.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<IPCTestResult[]> {
|
|
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');
|
|
}
|
|
} |