import test from 'node:test'; import assert from 'node:assert/strict'; import {readFileSync} from 'node:fs'; import {createHash} from 'node:crypto'; import {createRequire} from 'node:module'; import {fileURLToPath} from 'node:url'; import {build} from 'esbuild'; import {DOMParser,XMLSerializer} from '@xmldom/xmldom'; import {createCanvas,loadImage} from '@napi-rs/canvas'; import {createElement} from 'react'; import {renderToStaticMarkup} from 'react-dom/server'; import { DESKTOP_HANDS,GESTURE_ANCHORS,GESTURE_WRISTS,GESTURE_BASELINE,GESTURE_CENSOR, DEFAULT_GESTURE_PALETTE,gestureAttributes,gestureCable,createGestureGeometry, serializeGestureGeometry, } from '../../apps/web/src/animation/desktop/gesture-geometry.mjs'; const root=fileURLToPath(new URL('../../',import.meta.url)); const source=readFileSync(new URL('../../apps/web/src/animation/desktop/ComputerGeometry.tsx',import.meta.url),'utf8'); const elements=doc=>[...Array.from(doc.getElementsByTagName('*'))]; const nodes=tree=>[tree,...tree.children.flatMap(nodes)]; const parse=svg=>new DOMParser().parseFromString(svg,'image/svg+xml'); const byId=doc=>new Map(elements(doc).map(n=>[n.getAttribute('data-rig-id'),n])); // Bundle just these two React geometry components in memory. No browser or app // host is involved; this is the actual component's server-rendered output. const bundle=await build({absWorkingDir:root,entryPoints:['apps/web/src/animation/desktop/ComputerGeometry.tsx'],bundle:true,write:false,format:'cjs',platform:'node',packages:'external',jsx:'automatic',logLevel:'silent'}); const exports={};const module={exports}; new Function('require','module','exports',bundle.outputFiles[0].text)(createRequire(import.meta.url),module,exports); const art=renderToStaticMarkup(createElement(module.exports.ComputerGeometry,{idPrefix:'proof',palette:DEFAULT_GESTURE_PALETTE,artRef:null})); test('all original desktop geometry bytes are preserved; only additive imports and components differ',()=>{ const original=source.replace("import { DesktopGestures } from './DesktopGestures';\n",'').replace(/^\s*(?:\r?\n)/gm,''); // 2026-09-13: the procedural cable path's separators are spaces instead of a literal backslash-n // inside the JSX string (Chromium/WebKit refused to parse that path). Geometry unchanged; bytes are. assert.equal(createHash('sha256').update(original).digest('hex'),'0051046ce962f6cbb31ab8b24d4f4381869272f5582cac2e1cc5ba620a518c8c'); assert.equal((source.match(/