298 lines
7.7 KiB
JavaScript
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');
|
|
}); |