import fs from "node:fs"; import { execFileSync } from "node:child_process"; import path from "node:path"; import { pathToFileURL } from "node:url"; export const playwrightDependencyCommand = "npm install"; export const playwrightDependencySummary = "Install repository dependencies before running browser smokes: npm install provides the declared playwright package; the Code Queue image may also provide the same package globally."; const chromiumExecutableEnvKeys = Object.freeze([ "HWLAB_PLAYWRIGHT_CHROMIUM", "PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH", "CHROMIUM_PATH" ]); const chromiumExecutableCandidates = Object.freeze([ "/snap/bin/chromium", "/usr/bin/chromium-browser", "/usr/bin/chromium", "/usr/bin/google-chrome", "/usr/bin/google-chrome-stable" ]); export async function importPlaywright() { try { return normalizePlaywrightModule(await import("playwright")); } catch (localError) { const globalRoot = npmGlobalRoot(); if (globalRoot) { try { return normalizePlaywrightModule(await import(pathToFileURL(path.join(globalRoot, "playwright/index.js")).href)); } catch { // Keep the local resolution error so remediation points at this repository's package.json. } } throw localError; } } export async function launchChromium(chromium, options = {}) { const plan = chromiumLaunchPlan(); const launchOptions = { ...options, headless: options.headless ?? true, args: ["--no-sandbox", ...(options.args ?? [])], ...(plan.executablePath ? { executablePath: plan.executablePath } : {}) }; try { const browser = await chromium.launch(launchOptions); browser.hwlabLaunchPlan = { ...plan, failureCode: null }; return browser; } catch (error) { error.hwlabBrowserLaunch = { ...plan, failureCode: classifyBrowserLaunchFailure(error), remediation: browserLaunchRemediation(plan) }; throw error; } } export async function browserDoctor() { let playwright; try { playwright = await importPlaywright(); } catch (error) { return { status: "fail", failureCode: "playwright-import-failed", playwrightPackageSource: "missing", browser: chromiumLaunchPlan(), remediation: [playwrightDependencyCommand], error: error instanceof Error ? error.message : String(error) }; } const browser = await launchChromium(playwright.chromium).catch((error) => ({ error })); if (browser?.error) { const plan = browser.error.hwlabBrowserLaunch ?? chromiumLaunchPlan(); return { status: "fail", failureCode: plan.failureCode ?? classifyBrowserLaunchFailure(browser.error), playwrightPackageSource: "playwright", browser: plan, remediation: browserLaunchRemediation(plan), error: browser.error instanceof Error ? browser.error.message : String(browser.error) }; } try { const page = await browser.newPage(); await page.goto("data:text/html,