Files
pulse-signage/test/player-preload-helpers.test.js
T
2026-08-08 13:02:31 +01:00

298 lines
7.7 KiB
JavaScript

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 loadScript(scriptPath, sandbox) {
const source = fs.readFileSync(scriptPath, 'utf8');
vm.runInNewContext(source, sandbox, { filename: scriptPath });
}
function loadHtmlScript(scriptPath, sandbox) {
const source = fs.readFileSync(scriptPath, 'utf8').match(/<script>([\s\S]*)<\/script>/);
if (!source) {
throw new Error(`Unable to extract script body from ${scriptPath}`);
}
const script = source[1].trim();
vm.runInNewContext(script, sandbox, { filename: scriptPath });
}
test('webpage preloading only targets the next slide', () => {
const sandbox = {
window: null,
Date,
Array,
Number,
String,
Boolean,
Object,
Math,
console,
escapeHtml(value) {
return String(value || '');
},
currentPlaylistSignature: 'signature',
slides: [],
index: 0,
activeSlidesCacheKey: '',
activeSlidesCacheValue: [],
renderCacheViewportKey: '',
preloadSignature: '',
preloadContainer: null
};
sandbox.window = sandbox;
loadScript(path.join(__dirname, '..', 'src', 'player', 'public', 'js', 'player-page-playlist.js'), sandbox);
const current = { id: 1 };
const next = { id: 2 };
const later = { id: 3 };
assert.equal(sandbox.getWebpagePreloadSlides([current, next, later], 0).map((slide) => slide.id).join(','), '2');
assert.equal(sandbox.getWebpagePreloadSlides([current, next, later], 1).map((slide) => slide.id).join(','), '3');
assert.equal(sandbox.getWebpagePreloadSlides([current, next, later], 2).map((slide) => slide.id).join(','), '');
});
test('rtmp warmups only target the next slide', () => {
const sandbox = {
window: null,
Date,
Array,
Number,
String,
Boolean,
Object,
Math,
console,
fetch() {
throw new Error('not expected');
},
currentPlaylistSkipUnavailableRtmp: false,
videoRegionRenderVersion: 0,
slideMarkupCache: Object.create(null),
slides: [],
index: 0,
setTimeout,
clearTimeout,
document: {
createElement() {
return {
className: '',
setAttribute() {},
appendChild() {},
parentNode: null,
addEventListener() {}
};
},
body: {
appendChild() {}
}
},
pulsePlayerRegionTypes: {
register() {}
}
};
sandbox.window = sandbox;
loadScript(path.join(__dirname, '..', 'src', 'player', 'regions', 'rtmp.js'), sandbox);
const current = { id: 1 };
const next = { id: 2 };
const later = { id: 3 };
assert.equal(sandbox.getRtmpWarmupSlides([current, next, later], 0).map((slide) => slide.id).join(','), '2');
assert.equal(sandbox.getRtmpWarmupSlides([current, next, later], 1).map((slide) => slide.id).join(','), '3');
assert.equal(sandbox.getRtmpWarmupSlides([current, next, later], 2).map((slide) => slide.id).join(','), '');
});
test('command client ids stay scoped to the screen session', () => {
const sessionStorage = (() => {
const values = new Map();
return {
getItem(key) {
return values.has(key) ? values.get(key) : null;
},
setItem(key, value) {
values.set(String(key), String(value));
}
};
})();
const localStorage = (() => {
const values = new Map();
return {
getItem(key) {
return values.has(key) ? values.get(key) : null;
},
setItem(key, value) {
values.set(String(key), String(value));
}
};
})();
const sandbox = {
window: null,
Date,
Array,
Number,
String,
Boolean,
Object,
Math,
console,
crypto: {
randomUUID() {
return 'tab-session-client-id';
}
},
localStorage,
sessionStorage,
commandClientId: null,
commandClientStorageKey: 'pulse-command-client-id',
currentPlaylistSignature: 'signature',
slides: [],
index: 0,
activeSlidesCacheKey: '',
activeSlidesCacheValue: [],
renderCacheViewportKey: '',
preloadSignature: '',
preloadContainer: null
};
sandbox.window = sandbox;
loadScript(path.join(__dirname, '..', 'src', 'player', 'public', 'js', 'player-page-playlist.js'), sandbox);
assert.equal(sandbox.getCommandClientId(), 'tab-session-client-id');
assert.equal(sessionStorage.getItem('pulse-command-client-id'), 'tab-session-client-id');
assert.equal(localStorage.getItem('pulse-command-client-id'), null);
});
test('player client names stay scoped to the tab session', () => {
const sessionStorage = (() => {
const values = new Map([['pulse-signage-player-client-name', 'tab-only-name']]);
return {
getItem(key) {
return values.has(key) ? values.get(key) : null;
},
setItem(key, value) {
values.set(String(key), String(value));
}
};
})();
const localStorage = (() => {
const values = new Map([['pulse-signage-player-client-name', 'shared-name']]);
return {
getItem(key) {
return values.has(key) ? values.get(key) : null;
},
setItem(key, value) {
values.set(String(key), String(value));
}
};
})();
const sandbox = {
window: null,
Date,
Array,
Number,
String,
Boolean,
Object,
Math,
console,
sessionStorage,
localStorage,
WebSocket: { OPEN: 1 },
sendCommandState() {}
};
sandbox.window = sandbox;
loadHtmlScript(path.join(__dirname, '..', 'src', 'player', 'player-client-name.script.html'), sandbox);
assert.equal(sandbox.getOnboardingClientName(), 'tab-only-name');
assert.equal(localStorage.getItem('pulse-signage-player-client-name'), 'shared-name');
sandbox.applyOnboardingClientName('Renamed Tab Client', null);
assert.equal(sessionStorage.getItem('pulse-signage-player-client-name'), 'Renamed Tab Client');
assert.equal(localStorage.getItem('pulse-signage-player-client-name'), 'shared-name');
});
test('onboarding device ids stay scoped to the tab session', () => {
const sessionStorage = (() => {
const values = new Map();
return {
getItem(key) {
return values.has(key) ? values.get(key) : null;
},
setItem(key, value) {
values.set(String(key), String(value));
}
};
})();
const localStorage = (() => {
const values = new Map([['pulse-signage-player-device-id', 'shared-device-id']]);
return {
getItem(key) {
return values.has(key) ? values.get(key) : null;
},
setItem(key, value) {
values.set(String(key), String(value));
}
};
})();
const sandbox = {
window: null,
Date,
Array,
Number,
String,
Boolean,
Object,
Math,
console,
sessionStorage,
localStorage,
crypto: {
randomUUID() {
return 'tab-device-id';
}
},
fetch() {
return Promise.resolve({
ok: true,
json() {
return Promise.resolve({ onboarded: false, screens: [] });
},
text() {
return Promise.resolve('');
}
});
},
document: {
getElementById() {
return null;
},
createElement() {
return { appendChild() {}, removeChild() {} };
}
},
location: {
replace() {}
},
setInterval() {
return 1;
},
clearInterval() {}
};
sandbox.window = sandbox;
loadHtmlScript(path.join(__dirname, '..', 'src', 'player', 'onboarding', 'player-onboarding-landing.script.html'), sandbox);
assert.equal(sessionStorage.getItem('pulse-signage-player-device-id'), 'tab-device-id');
assert.equal(localStorage.getItem('pulse-signage-player-device-id'), 'shared-device-id');
});