diff --git a/electron/main.cts b/electron/main.cts index cb9e22c..e5b2b4e 100644 --- a/electron/main.cts +++ b/electron/main.cts @@ -10,6 +10,7 @@ const { validateRenderRequest } = require('../shared/renderValidation.cjs') as { } const isDev = !app.isPackaged +const isE2E = process.env.RUWIO_E2E === '1' const devServerUrl = process.env.VITE_DEV_SERVER_URL ?? 'http://localhost:5200' const devServerOrigin = new URL(devServerUrl).origin const appIconPath = isDev @@ -43,6 +44,12 @@ function sendAppCommand(command: string): void { mainWindow.webContents.send('ruwio:menu-command', command) } +declare global { + // Playwright's Electron runner can evaluate in the main process and call this + // env-gated hook without expanding the preload bridge surface. + var __ruwioTestMenuCommand: ((command: string) => void) | undefined +} + function sendRenderProgress( target: Electron.WebContents, event: { jobId: string; progress: number; done: boolean; error?: string }, @@ -101,9 +108,14 @@ async function runRenderMp4(event: IpcMainInvokeEvent, payload: RenderMp4Payload defaultPath: sanitizeMp4Name(payload?.suggestedName), filters: [{ name: 'MP4 Video', extensions: ['mp4'] }], } - const saveResult = window - ? await dialog.showSaveDialog(window, saveOptions) - : await dialog.showSaveDialog(saveOptions) + const e2eSavePath = isE2E + ? process.env.RUWIO_E2E_SAVE_PATH || path.join(app.getPath('temp'), saveOptions.defaultPath) + : '' + const saveResult = e2eSavePath + ? { canceled: false, filePath: e2eSavePath } + : window + ? await dialog.showSaveDialog(window, saveOptions) + : await dialog.showSaveDialog(saveOptions) if (saveResult.canceled || !saveResult.filePath) return null const jobId = randomUUID() @@ -379,6 +391,9 @@ app.setName('RUWIO') app.whenReady().then(() => { ipcMain.handle('ruwio:render-mp4', handleRenderMp4) ipcMain.handle('ruwio:render-cancel', handleRenderCancel) + if (isE2E) { + globalThis.__ruwioTestMenuCommand = (command: string) => sendAppCommand(command) + } createMenu() createMainWindow() diff --git a/package.json b/package.json index 971fc0c..3f29cfa 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "test:render-server": "node --test server/server.smoke.test.cjs", "test:render-server:e2e": "node --test server/render.e2e.test.cjs", "test:render-desktop": "tsc -p tsconfig.electron.json && node scripts/verify-desktop-render.cjs", - "test:capture-fidelity": "tsc -p tsconfig.electron.json && electron scripts/verify-capture-fidelity.cjs", + "test:capture-fidelity": "tsc -p tsconfig.electron.json && node scripts/run-electron-harness.cjs scripts/verify-capture-fidelity.cjs", "stage:ffmpeg": "node scripts/stage-ffmpeg.cjs" }, "dependencies": { diff --git a/scripts/run-electron-harness.cjs b/scripts/run-electron-harness.cjs new file mode 100644 index 0000000..1ad5645 --- /dev/null +++ b/scripts/run-electron-harness.cjs @@ -0,0 +1,21 @@ +const { spawnSync } = require('node:child_process') + +const electron = require('electron') +const args = process.argv.slice(2) + +if (!args.length) { + console.error('usage: node scripts/run-electron-harness.cjs