const fs = require('node:fs'); const path = require('node:path'); const vm = require('node:vm'); const test = require('node:test'); const assert = require('node:assert/strict'); function loadCommandsScript(sandbox) { const commandsPath = path.join(__dirname, '..', 'src', 'player', 'public', 'js', 'player-page-commands.js'); const commandsScript = fs.readFileSync(commandsPath, 'utf8'); vm.runInNewContext(commandsScript, sandbox, { filename: commandsPath }); } function createSandbox() { const rafCallbacks = []; const calls = { syncRtmpRegions: 0, initRegion: 0, playRegionAnimations: 0 }; const app = { children: [], firstElementChild: null, innerHTMLValue: '', classList: { contains() { return false; } }, set innerHTML(value) { this.innerHTMLValue = String(value || ''); this.firstElementChild = this.innerHTMLValue ? { isConnected: true } : null; }, get innerHTML() { return this.innerHTMLValue; }, appendChild(node) { if (node) { node.isConnected = true; this.children.push(node); this.firstElementChild = this.firstElementChild || node; } return node; }, querySelectorAll() { return []; } }; const sandbox = { window: null, Date, JSON, Math, Number, String, Boolean, Array, Object, Promise, setTimeout, clearTimeout, console, requestAnimationFrame(callback) { rafCallbacks.push(callback); return rafCallbacks.length; }, app, slides: [], index: 0, currentPlaylistSignature: 'signature', currentPlaylistFadeBetweenSlides: false, currentPlaylistSkipUnavailableRtmp: false, pendingPlaylistUpdate: null, slideMarkupCache: Object.create(null), templateLayoutCache: Object.create(null), templateRenderPlanCache: Object.create(null), renderCacheViewportKey: '', slideTransitionTimer: null, slideFadeDurationMs: 560, slideExpiresAt: null, pausedRemainingMs: null, timer: null, lastRenderedSlide: null, destroyRtmpRegions() {}, syncRtmpRegions() { calls.syncRtmpRegions += 1; }, initializeRegionInstances() { calls.initializeRegionInstances += 1; }, playRegionAnimations() { calls.playRegionAnimations += 1; }, addEventListener() {}, pulsePlayerRegionTypes: { list() { return [ { definition: { initRegion() { calls.initRegion += 1; } } } ]; } }, isThumbnailPreview() { return false; } }; sandbox.window = sandbox; sandbox.window.requestAnimationFrame = sandbox.requestAnimationFrame; return { sandbox, calls, rafCallbacks, app }; } test('renderSlideMarkup runs post-render setup immediately', () => { const { sandbox, calls, rafCallbacks, app } = createSandbox(); loadCommandsScript(sandbox); const returned = sandbox.renderSlideMarkup('
visible
', false); assert.equal(app.innerHTMLValue, '
visible
'); assert.equal(calls.syncRtmpRegions, 1); assert.equal(calls.initRegion, 1); assert.equal(calls.playRegionAnimations, 1); assert.equal(rafCallbacks.length, 0); assert.equal(returned, app.firstElementChild); });