import assert from 'node:assert/strict'; import { readFile } from 'node:fs/promises'; import { test } from 'node:test'; import vm from 'node:vm'; import ts from 'typescript'; const source = await readFile(new URL('../src/main.ts', import.meta.url), 'utf8'); const body = source.slice(source.indexOf('async function loadSample('), source.indexOf("sampleButton?.addEventListener('click'", source.indexOf('async function loadSample('))); function harness() { const calls = [], pending = []; const context = { renderLost: false, disposed: false, mediaRequest: 0, mediaBusy: false, pendingCutout: null, pendingPairDepth: null, pendingSampleDebugImage: null, pendingSampleFraming: false, pendingTestPhotoHasNoDepth: false, testPhotoInput: { value: '' }, sampleButton: { textContent: '' }, resetHintForMedia() { calls.push('hint-reset'); }, peekingUI: { cancel() {} }, invalidateDepthRequests() { calls.push('depth-invalidate'); }, cancelArrivalJourney() {}, beginMediaLoad(origin) { calls.push('loading'); context.mediaOrigin = origin; }, syncAIDepthButton() {}, clearPendingTestState() {}, setStatus(text) { calls.push(['status', text]); }, experience: { setState(state) { calls.push(['state', state]); } }, loader: { cancelPending() { calls.push('cancel-old'); }, load(file) { calls.push(['load', file.name]); } }, fetch(path) { calls.push(['fetch', path]); return new Promise(resolve => pending.push(resolve)); }, File: class { constructor(_, name) { this.name = name; } }, Image: class { async decode() {} }, URL: { createObjectURL() { return 'blob:depth'; }, revokeObjectURL(url) { calls.push(['revoke', url]); } }, sampleDepthProvider: { async getDepthMap() { return { dispose() { calls.push('depth-dispose'); } }; } }, }; vm.createContext(context); vm.runInContext(ts.transpileModule(body, { compilerOptions: { target: ts.ScriptTarget.ES2022 } }).outputText, context); const respond = (ok = true) => pending.shift()({ ok, async blob() { return {}; }, headers: { get() { return 'image/jpeg'; } } }); return { context, calls, pending, respond }; } test('confirmed sample uses the shared loader and preserves loading/invalidation and final pipeline', async () => { const h = harness(), request = h.context.loadSample('dog1'); assert.equal(h.context.testPhotoInput.value, 'dog1'); assert.equal(h.context.mediaOrigin, 'sample', 'shared loader marks sample presentation before asynchronous fetching'); assert.deepEqual(h.calls.slice(0, 4), ['hint-reset', 'depth-invalidate', 'loading', 'cancel-old']); assert.deepEqual(h.calls.find(c => c[0] === 'fetch'), ['fetch', '/assets/samples/dog1.jpg']); h.respond(); await request; assert.deepEqual(h.calls.find(c => c[0] === 'load'), ['load', 'dog1.jpg']); assert.equal(h.context.pendingTestPhotoHasNoDepth, true); }); test('superseded sample fetch cannot replace the newer media', async () => { const h = harness(), first = h.context.loadSample('dog1'), second = h.context.loadSample('dog3'); h.respond(); await first; assert.equal(h.calls.some(c => c[0] === 'load'), false); h.respond(); await second; assert.deepEqual(h.calls.filter(c => c[0] === 'load'), [['load', 'dog3.jpg']]); }); test('sample failure exposes existing error flow, and render loss or teardown forbids starting', async () => { const h = harness(), request = h.context.loadSample('dog2'); h.respond(false); await request; assert.deepEqual(h.calls.find(c => c[0] === 'state'), ['state', 'error']); assert.equal(h.context.mediaBusy, false); for (const key of ['renderLost', 'disposed']) { const blocked = harness(); blocked.context[key] = true; await blocked.context.loadSample('dog1'); assert.deepEqual(blocked.calls, []); } }); test('all five samples start without mismatched manual depth', async () => { for (const id of ['dog1', 'dog2', 'dog3', 'dog4', 'dog5']) { const h = harness(), request = h.context.loadSample(id); h.respond(); await request; assert.deepEqual(h.calls.filter(c => c[0] === 'fetch'), [['fetch', `/assets/samples/${id}.jpg`]]); assert.equal(h.context.pendingPairDepth, null); assert.equal(h.context.pendingSampleFraming, false); assert.equal(h.context.pendingTestPhotoHasNoDepth, true); } }); test('unknown sample IDs cannot fetch arbitrary or retired photo paths', async () => { for (const id of ['sample', '../private', 'dog6']) { const h = harness(); await h.context.loadSample(id); assert.equal(h.calls.some(c => c[0] === 'fetch'), false); } }); test('returning home invalidates the pending sample response without another load', async () => { const h = harness(), request = h.context.loadSample('dog1'); const returning = source.slice(source.indexOf('function returnFromSample('), source.indexOf('function beginMediaLoad(')); Object.assign(h.context, { photoArrivalSnapshot: {origin:'sample'}, photoArrivalTexture: {}, cancelDoorInteraction(){}, gyro:{setPaused(){}}, hideHintAfterDrag(){} }); vm.runInContext(ts.transpileModule(returning, { compilerOptions:{target:ts.ScriptTarget.ES2022} }).outputText, h.context); h.context.returnFromSample(); h.respond(); await request; assert.equal(h.calls.some(c => c[0] === 'load'), false); assert.equal(h.context.mediaBusy, false); assert.equal(h.context.photoArrivalSnapshot, null); assert.equal(h.context.photoArrivalTexture, null); });