#!/usr/bin/env node /** * Diagnostic: load a huge OBJ (+mtl) through the REAL drag&drop path in headless * Chrome, capture console ([recenter]/[hmw] bbox) and a screenshot. Confirms * whether the in-viewer recenter ran and whether faces crack. * * USAGE: node tools/girder-smoke.mjs [--url http://localhost:3333] [obj] [mtl] */ import puppeteer from 'puppeteer-core'; import { existsSync } from 'node:fs'; import { resolve } from 'node:path'; const CHROME = [ 'C:/Program Files/Google/Chrome/Application/chrome.exe', 'C:/Program Files (x86)/Google/Chrome/Application/chrome.exe', 'C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe', ].find((p) => existsSync(p)); const args = process.argv.slice(2); let url = 'http://localhost:3333'; const files = []; for (let i = 0; i < args.length; i++) { if (args[i] === '--url') url = args[++i]; else files.push(args[i]); } if (files.length === 0) { files.push('samples/GirderObjs/part01.obj', 'samples/GirderObjs/part01.mtl'); } const paths = files.map((f) => resolve(f)); for (const p of paths) if (!existsSync(p)) { console.error('missing', p); process.exit(1); } const browser = await puppeteer.launch({ executablePath: CHROME, headless: 'new', args: ['--no-sandbox', '--use-gl=swiftshader', '--enable-webgl', '--ignore-gpu-blocklist', '--disable-dev-shm-usage', '--window-size=1400,900'], }); const page = await browser.newPage(); await page.setViewport({ width: 1400, height: 900 }); page.on('console', (m) => console.log(' [browser]', m.text())); page.on('pageerror', (e) => console.log(' [pageerror]', e.message)); await page.evaluateOnNewDocument(() => { window.__hmwReady = null; window.addEventListener('hmw:ready', (e) => { window.__hmwReady = e.detail; }); }); console.log('goto', url); await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30000 }); await page.waitForSelector('#file-input', { timeout: 10000 }); const input = await page.$('#file-input'); console.log('uploading', paths.join(', ')); await input.uploadFile(...paths); await page.evaluate(() => document.getElementById('file-input') .dispatchEvent(new Event('change', { bubbles: true }))); console.log('waiting for hmw:ready (up to 240s)...'); const t0 = Date.now(); try { await page.waitForFunction('window.__hmwReady != null', { timeout: 240000, polling: 1000 }); console.log('READY in', ((Date.now() - t0) / 1000).toFixed(1) + 's'); } catch { console.log('TIMEOUT after', ((Date.now() - t0) / 1000).toFixed(1) + 's — capturing anyway'); } await new Promise((r) => setTimeout(r, 1500)); await page.screenshot({ path: resolve('girder-smoke.png') }); console.log('screenshot -> girder-smoke.png (full)'); // Medium zoom (reproduce user's close inspection) via OrbitControls wheel. await page.mouse.move(700, 450); for (let i = 0; i < 14; i++) { await page.mouse.wheel({ deltaY: -200 }); await new Promise((r) => setTimeout(r, 20)); } await new Promise((r) => setTimeout(r, 1000)); await page.screenshot({ path: resolve('girder-zoom.png') }); console.log('screenshot -> girder-zoom.png (zoomed in)'); await browser.close();