import { startSocksProxy } from './socks-proxy'; import type { BrowserHandle, BrowserOptions, SocksProxyHandle } from './types'; /** * Launch a browser routed through a SOCKS proxy attached to the test * network. The consumer passes their own playwright `chromium` launcher * (or another `BrowserType`) — @celilo/e2e has no playwright dep, so * version alignment between the playwright runtime and the cached * browser binaries is the consumer's responsibility. */ export async function startBrowser( projectName: string, options: BrowserOptions, ): Promise { if (!options.chromium) { throw new Error( 'net.browser() requires a `chromium` launcher in options.\n\n' + 'Pass it from your own playwright install:\n' + " import { chromium } from 'playwright-core';\n" + ' const browser = await net.browser({ vantage, chromium });', ); } const proxy = await startSocksProxy(projectName, options); let browser: unknown; try { browser = await options.chromium.launch({ proxy: { server: proxy.hostUrl } }); } catch (err) { // If the launcher fails (commonly: chromium binary not installed // for the consumer's playwright version), tear the proxy down so // we don't leak it. await proxy.stop(); throw err; } return makeHandle(browser, proxy); } function makeHandle(browser: unknown, proxy: SocksProxyHandle): BrowserHandle { let closed = false; return { browser, proxy, async close(): Promise { if (closed) return; closed = true; try { await (browser as { close(): Promise }).close(); } catch { // best-effort } await proxy.stop(); }, }; }