Angular puppeteer issue
01:01 16 May 2026

localhost:4200 says

X Error: Could not find Chrome (ver. 148.0.7778.97). This can occur if either

1. you did not perform an installation before running the script (e.g. `npx puppeteer browsers install chrome') or

2. your cache path is incorrectly configured (which is: /opt/

render/.cache/puppeteer).

For (2), check out our guide on configuring puppeteer at https:// pptr.dev/guides/configuration.

OK

Localhost:4200 says

here code server.js

* ═══════════════════════════════════════════
   PDF ENGINE
═══════════════════════════════════════════ */
/**
 * Opens the dashboard URL in a headless browser, waits for it to fully
 * render, then exports it as an A4 PDF to `storage/reports/`.
 *
 * @param {string} url          - Full URL Puppeteer should visit
 * @param {string} token        - JWT stored in localStorage so the page authenticates
 * @param {string} fileName     - Output filename (no path, just "Report_xxx.pdf")
 * @returns {Promise}   - Resolves with fileName on success
 */
async function generateDashboardPDF(url, token, fileName) {
  // const browser = await puppeteer.launch({
  //   headless: 'new',
  //   args: [
  //     '--no-sandbox',
  //     '--disable-setuid-sandbox',
  //     '--disable-dev-shm-usage',   // prevents crashes on low-memory VMs
  //     '--disable-gpu',
  //   ],
  // });
  const browser = await puppeteer.launch({
    headless: 'new',
    // Windows path – change to match your actual Chrome install
    executablePath: process.env.CHROME_PATH || 
      'C:\\Users\\admin\\.cache\\puppeteer\\chrome\\win64-148.0.7778.167\\chrome-win64\\chrome.exe',
    args: [
      '--no-sandbox',
      '--disable-setuid-sandbox',
      '--disable-dev-shm-usage',
      '--disable-gpu',
    ],
  });

  const page = await browser.newPage();

  try {
    const origin = new URL(url).origin;

    // 1. Land on the origin first so we can write localStorage
    await page.goto(origin, { waitUntil: 'domcontentloaded', timeout: 60_000 });
    await page.evaluate(t => localStorage.setItem('token', t), token);

    // 2. Navigate to the real report page
    await page.setViewport({ width: 1400, height: 1800 });
    await page.goto(url, { waitUntil: 'networkidle2', timeout: 90_000 });

    // 3. Strip UI chrome that should not appear in the PDF
    await page.addStyleTag({
      content: `
        .report-toolbar,
        .btn-primary,
        .mat-icon,
        .btn-whatsapp,
        input,
        button { display: none !important; }

        #pdf-root {
          box-shadow: none  !important;
          margin:     0     !important;
          width:      100%  !important;
          border:     none  !important;
        }

        body {
          background: white   !important;
          overflow:   hidden  !important;
        }
      `,
    });

    // 4. Wait for Angular to finish rendering
    await page.waitForSelector('#pdf-root', { timeout: 30_000 });
    await new Promise(r => setTimeout(r, 5_000)); // allow charts/animations to settle

    // 5. Write PDF
    const pdfPath = path.join(reportsDir, fileName);
    await page.pdf({
      path: pdfPath,
      format: 'A4',
      printBackground: true,
      margin: { top: '10mm', right: '10mm', bottom: '10mm', left: '10mm' },
    });

    // 6. Sanity-check: reject obviously empty files
    const { size } = fs.statSync(pdfPath);
    if (size < 5_000) {
      throw new Error(`Generated PDF is suspiciously small (${size} bytes). The page may not have rendered correctly.`);
    }

    console.log(`✅  PDF created: ${fileName}  (${(size / 1024).toFixed(1)} KB)`);
    return fileName;

  } finally {
    await browser.close();
  }
}
javascript angular frontend backend puppeteer