chore(monorepo): import hmwebviewer history at a717900

git-subtree-dir: apps/viewer-3d
git-subtree-mainline: 5e10bb1be4
git-subtree-split: a71790070d
This commit is contained in:
2026-07-29 09:04:52 +09:00
78 changed files with 15921 additions and 0 deletions
+78
View File
@@ -0,0 +1,78 @@
#!/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();