|
9 | 9 | type Benchmark, |
10 | 10 | type BenchmarkStats, |
11 | 11 | } from "@codspeed/core"; |
| 12 | +import { createRequire } from "node:module"; |
| 13 | +import { pathToFileURL } from "node:url"; |
12 | 14 | import { _electron as electron } from "playwright"; |
13 | 15 | import type { ElectronApplication, Page } from "playwright-core"; |
14 | 16 |
|
@@ -52,20 +54,18 @@ export interface BenchOptions { |
52 | 54 | */ |
53 | 55 | appPath: string; |
54 | 56 | /** |
55 | | - * Additional CLI flags forwarded to Electron. |
| 57 | + * CLI flags forwarded to Electron. |
56 | 58 | */ |
57 | 59 | electronArgs?: string[]; |
58 | 60 | /** |
59 | 61 | * Working directory for the Electron process. Defaults to `process.cwd()`. |
60 | 62 | */ |
61 | 63 | cwd?: string; |
62 | 64 | /** |
63 | | - * Absolute path to the Electron executable. When omitted, Playwright resolves |
64 | | - * it via `require("electron")`. Set this when running under package managers |
65 | | - * (e.g. pnpm) where Playwright cannot resolve `electron` from its own |
66 | | - * directory. |
| 65 | + * Absolute path to the Electron executable. When omitted, it is resolved from |
| 66 | + * the `electron` package in `cwd`. Set this only to override that default. |
67 | 67 | */ |
68 | | - executablePath?: string; |
| 68 | + electronExecutablePath?: string; |
69 | 69 | /** |
70 | 70 | * Run before each round, after the window opens. Use it to bring the app to |
71 | 71 | * a steady state (initial render done, data loaded, …). Not measured. |
@@ -106,15 +106,32 @@ function resolveRounds(optionRounds: number | undefined): number { |
106 | 106 | return n; |
107 | 107 | } |
108 | 108 |
|
| 109 | +/** |
| 110 | + * Resolve the path to the Electron binary. |
| 111 | + * |
| 112 | + * Playwright resolves Electron via `require("electron/index.js")` from inside |
| 113 | + * its own package directory. Under isolated installs (e.g. pnpm), Playwright |
| 114 | + * cannot see the project's `electron` dependency and bails out with |
| 115 | + * "Electron executablePath not found!". We resolve it ourselves from the |
| 116 | + * benchmark's working directory, where `electron` is a real dependency. |
| 117 | + */ |
| 118 | +function resolveElectronExecutable(cwd: string): string { |
| 119 | + const require = createRequire(pathToFileURL(`${cwd}/`)); |
| 120 | + // `electron`'s main module exports the absolute path to its binary. |
| 121 | + return require("electron") as string; |
| 122 | +} |
| 123 | + |
109 | 124 | async function launchApp(options: BenchOptions): Promise<ElectronApplication> { |
| 125 | + const cwd = options.cwd ?? process.cwd(); |
110 | 126 | return electron.launch({ |
111 | 127 | args: [ |
112 | 128 | options.appPath, |
113 | 129 | ...(options.electronArgs ?? []), |
114 | 130 | `--js-flags=${DEFAULT_PROFILING_JS_FLAGS}`, |
115 | 131 | ], |
116 | | - cwd: options.cwd ?? process.cwd(), |
117 | | - executablePath: options.executablePath, |
| 132 | + cwd, |
| 133 | + executablePath: |
| 134 | + options.electronExecutablePath ?? resolveElectronExecutable(cwd), |
118 | 135 | }); |
119 | 136 | } |
120 | 137 |
|
|
0 commit comments