UNPKG

rwsdk

Version:

Build fast, server-driven webapps on Cloudflare with SSR, RSC, and realtime

128 lines (127 loc) 5.67 kB
import { computeExecutablePath, detectBrowserPlatform, install, Browser as PuppeteerBrowser, resolveBuildId, } from "@puppeteer/browsers"; import debug from "debug"; import { mkdirp, pathExists } from "fs-extra"; import { join } from "path"; import puppeteer from "puppeteer-core"; import { ensureTmpDir } from "./utils.mjs"; const log = debug("rwsdk:e2e:browser"); /** * Launch a browser instance */ export async function launchBrowser(browserPath, headless = true) { // Define a consistent cache directory path in system temp folder const rwCacheDir = join(await ensureTmpDir(), "redwoodjs-smoke-test-cache"); await mkdirp(rwCacheDir); log("Using cache directory: %s", rwCacheDir); // Get browser path if not provided if (!browserPath) { log("Getting browser executable path"); browserPath = await getBrowserPath({ headless }); } console.log(`🚀 Launching browser from ${browserPath} (headless: ${headless})`); log("Starting browser with puppeteer"); return await puppeteer.launch({ executablePath: browserPath, headless, args: ["--no-sandbox", "--disable-setuid-sandbox"], }); } /** * Get the browser executable path */ export async function getBrowserPath(testOptions) { console.log("Finding Chrome executable..."); // First try using environment variable if set if (process.env.CHROME_PATH) { console.log(`Using Chrome from environment variable: ${process.env.CHROME_PATH}`); return process.env.CHROME_PATH; } // Detect platform log("Detecting platform"); const platform = detectBrowserPlatform(); if (!platform) { log("ERROR: Failed to detect browser platform"); throw new Error("Failed to detect browser platform"); } log("Detected platform: %s", platform); // Define a consistent cache directory path in system temp folder const rwCacheDir = join(await ensureTmpDir(), "redwoodjs-smoke-test-cache"); await mkdirp(rwCacheDir); log("Using cache directory: %s", rwCacheDir); // Determine browser type based on headless option const browser = testOptions?.headless === false ? PuppeteerBrowser.CHROME : PuppeteerBrowser.CHROMEHEADLESSSHELL; log(`Using browser type: ${browser}`); // Resolve the buildId for the stable Chrome version - do this once log("Resolving Chrome buildId for stable channel"); const buildId = await resolveBuildId(browser, platform, "stable"); log("Resolved buildId: %s", buildId); // Create installation options - use them consistently const installOptions = { browser, platform, cacheDir: rwCacheDir, buildId, unpack: true, }; try { // Try to compute the path first (this will check if it's installed) log("Attempting to find existing Chrome installation"); const path = computeExecutablePath(installOptions); if (await pathExists(path)) { console.log(`Found existing Chrome at: ${path}`); return path; } else { throw new Error("Chrome not found at: " + path); } } catch (error) { // If path computation fails, install Chrome console.log("No Chrome installation found. Installing Chrome..."); // Add better error handling for the install step try { console.log("Downloading Chrome (this may take a few minutes)..."); const attempts = 10; let installError; for (let i = 0; i < attempts; i++) { try { await install(installOptions); installError = null; // Reset error on success break; // Exit loop on success } catch (e) { installError = e; console.log(`Attempt ${i + 1}/${attempts} failed. Retrying in 1 second...`); // Wait for 1 second before retrying await new Promise((resolve) => setTimeout(resolve, 1000)); } } if (installError) { throw installError; } console.log("✅ Chrome installation completed successfully"); // Now compute the path for the installed browser const path = computeExecutablePath(installOptions); console.log(`Installed and using Chrome at: ${path}`); return path; } catch (installError) { // Provide more detailed error about the browser download failure log("ERROR: Failed to download/install Chrome: %O", installError); console.error(`❌ Failed to download/install Chrome browser.`); console.error(`This is likely a network issue or the browser download URL is unavailable.`); console.error(`Error details: ${installError instanceof Error ? installError.message : String(installError)}`); // For debug builds, show the full error stack if available if (installError instanceof Error && installError.stack) { log("Error stack: %s", installError.stack); } console.log("\nPossible solutions:"); console.log("1. Check your internet connection"); console.log("2. Set CHROME_PATH environment variable to an existing Chrome installation"); console.log("3. Install Chrome manually and run the tests again"); throw new Error(`Failed to install Chrome browser: ${installError instanceof Error ? installError.message : String(installError)}`); } } }