Refine player control-plane flow
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
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;
|
||||
},
|
||||
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('<div class="slide">visible</div>', false);
|
||||
|
||||
assert.equal(app.innerHTMLValue, '<div class="slide">visible</div>');
|
||||
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);
|
||||
});
|
||||
Reference in New Issue
Block a user