import test from 'node:test'; import assert from 'node:assert/strict'; import {promisify} from 'node:util'; import {execFile} from 'node:child_process'; import {mkdtemp,writeFile,readFile,access,rm} from 'node:fs/promises'; import os from 'node:os'; import path from 'node:path'; import {gameArchive,engineResource} from '../engine/archive.ts'; import {buildKit} from '../engine/build-kit.ts'; import {defaultProject} from '../engine/templates.ts'; test('hosted editor HTML and downloadable builds resolve inside a nested publication',async()=>{ const dir=await mkdtemp(path.join(os.tmpdir(),'forma-hosted-')); const previous=Object.getOwnPropertyDescriptor(globalThis,'document'); try{ const project=defaultProject(true),source=path.join(dir,'source.forma.json'),out=path.join(dir,'demo'); await writeFile(source,JSON.stringify(project)); await promisify(execFile)(process.execPath,['--import','tsx','scripts/export-editor.ts',source,out]); const html=await readFile(path.join(out,'index.html'),'utf8'); for(const match of html.matchAll(/(?:src|href)="([^"]+)"/g)){ assert.ok(match[1].startsWith('./'),match[1]);await access(path.join(out,match[1])); } Object.defineProperty(globalThis,'document',{value:{baseURI:'https://example.test/demo/index.html'},configurable:true}); const requested:string[]=[]; const read=async(uri:string)=>{requested.push(uri);assert.ok(uri.startsWith('https://example.test/demo/'),uri);return new Uint8Array(await readFile(path.join(out,new URL(uri).pathname.slice('/demo/'.length))));}; await gameArchive(project,read);await buildKit(project,{target:'linux',name:'Fixture'},read); assert.ok(requested.includes('https://example.test/demo/engine/player.js')); assert.ok(requested.includes('https://example.test/demo/build-targets/manifest.json')); assert.equal(engineResource('/engine/player.js','https://example.test/demo/'),'https://example.test/demo/engine/player.js'); }finally{ if(previous)Object.defineProperty(globalThis,'document',previous);else delete (globalThis as any).document; await rm(dir,{recursive:true,force:true}); } });