Files
dwg-dxf-viewer-sample/apps/viewer-3d/tools/dnd-smoke.mjs
T
lectom bedb357259 chore(monorepo): import hmwebviewer history at a717900
git-subtree-dir: apps/viewer-3d
git-subtree-mainline: 5e10bb1be4
git-subtree-split: a71790070d
2026-07-29 09:04:52 +09:00

85 lines
3.9 KiB
JavaScript

#!/usr/bin/env node
/**
* tools/dnd-smoke.mjs — CSR (Path B / drag&drop) load smoke.
*
* The per-format perf-smoke only exercised Path A (?model=). This drives the
* REAL local-file path: fetch each sample into a File, hand it to
* window.__viewer.loadLocalFile(file) (exactly what the dropzone does), and wait
* for hmw:ready. Catches the blob:-URL-has-no-extension class of bug.
*
* USAGE: node tools/dnd-smoke.mjs [--url URL] [--asset /samples/x ...]
* (run `npm run build && npm run preview` first)
*/
import puppeteer from 'puppeteer-core';
import { existsSync } from 'node:fs';
const CHROME_CANDIDATES = [
'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',
];
function findBrowser() {
if (process.env.PUPPETEER_EXECUTABLE_PATH && existsSync(process.env.PUPPETEER_EXECUTABLE_PATH)) return process.env.PUPPETEER_EXECUTABLE_PATH;
for (const p of CHROME_CANDIDATES) if (existsSync(p)) return p;
return null;
}
function parseArgs(argv) {
const a = argv.slice(2); let url = 'http://127.0.0.1:4173'; const assets = [];
for (let i = 0; i < a.length; i++) {
if (a[i] === '--url') url = a[++i]; else if (a[i] === '--asset') assets.push(a[++i]);
}
if (!assets.length) assets.push('/samples/Box.glb', '/samples/Duck.glb', '/samples/Avocado.glb', '/samples/Cube.obj', '/samples/Cube.fbx', '/samples/Cube.dae', '/samples/Cube.ifc');
return { url, assets };
}
async function dropOne(page, base, asset) {
await page.goto(base, { waitUntil: 'domcontentloaded', timeout: 30000 });
await page.waitForFunction('window.__viewer != null', { timeout: 15000 });
try {
const res = await page.evaluate(async (assetPath) => {
const name = assetPath.split('/').pop();
const resp = await fetch(assetPath);
if (!resp.ok) return { ok: false, err: 'fetch ' + resp.status };
const blob = await resp.blob();
const file = new File([blob], name, { type: blob.type || 'application/octet-stream' });
const ready = new Promise((resolve) => {
const onErr = (e) => resolve({ ok: false, err: 'viewer error: ' + (e.detail || 'unknown') });
window.addEventListener('hmw:ready', () => resolve({ ok: true }), { once: true });
// surface our own onError via console; also time out below
window.__dndTimeout = setTimeout(() => resolve({ ok: false, err: 'timeout (no hmw:ready)' }), 20000);
});
window.__viewer.loadLocalFile(file);
return ready;
}, asset);
return { asset, ...res };
} catch (e) {
return { asset, ok: false, err: (e && e.message) || String(e) };
}
}
async function main() {
const o = parseArgs(process.argv);
const exe = findBrowser();
if (!exe) { console.error('[dnd-smoke] No Chrome/Edge found.'); process.exit(1); }
const browser = await puppeteer.launch({ executablePath: exe, headless: 'new', args: ['--no-sandbox', '--use-gl=swiftshader', '--enable-webgl', '--ignore-gpu-blocklist'] });
const page = await browser.newPage();
const errs = [];
page.on('console', (m) => { const t = m.text(); if (t.includes('load failed') || t.includes('Failed to load')) errs.push(t); });
console.log('[dnd-smoke] CSR drag&drop path, base=' + o.url);
const results = [];
for (const asset of o.assets) {
process.stdout.write(' drop ' + asset + ' ... ');
const r = await dropOne(page, o.url, asset);
results.push(r);
console.log(r.ok ? 'OK' : 'FAIL (' + r.err + ')');
}
await browser.close();
const failed = results.filter((r) => !r.ok);
console.log('\n[dnd-smoke] ' + (results.length - failed.length) + '/' + results.length + ' passed');
if (failed.length) { console.error('[dnd-smoke] FAILURES: ' + failed.map((f) => f.asset).join(', ')); process.exit(1); }
console.log('[dnd-smoke] all local drops load.');
}
main().catch((e) => { console.error('[dnd-smoke] Fatal: ' + (e && e.stack ? e.stack : e)); process.exit(1); });