Files
pulse-signage/test/player-announcement-marquee.test.js
T
2026-08-05 19:38:16 +01:00

108 lines
3.0 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 loadAnnouncementTemplateHelpers() {
const scriptPath = path.join(__dirname, '..', 'src', 'player', 'public', 'js', 'player-announcement-templates.js');
const script = fs.readFileSync(scriptPath, 'utf8');
const sandbox = {
window: {},
module: { exports: {} },
exports: {},
console
};
sandbox.window = sandbox;
vm.runInNewContext(script, sandbox, { filename: scriptPath });
return sandbox;
}
function createTextNode(width) {
return {
width: width,
attributes: {},
cloneNode() {
return createTextNode(width);
},
setAttribute(name, value) {
this.attributes[name] = String(value);
},
getBoundingClientRect() {
return { width: this.width };
}
};
}
test('announcement marquee helper repeats enough content and measures a real cycle width', () => {
const sandbox = loadAnnouncementTemplateHelpers();
assert.equal(typeof sandbox.initPlayerAnnouncementMarquee, 'function');
const textNodes = [createTextNode(100), createTextNode(100)];
const track = {
dataset: {},
style: {
values: {},
setProperty(name, value) {
this.values[name] = String(value);
}
},
attributes: { 'data-announcement-marquee-rate': '50' },
parentElement: null,
appended: [],
getAttribute(name) {
return this.attributes[name];
},
querySelectorAll() {
return textNodes.slice();
},
appendChild(node) {
this.appended.push(node);
textNodes.push(node);
return node;
},
getBoundingClientRect() {
const gap = 20;
const width = textNodes.length * 100 + Math.max(0, textNodes.length - 1) * gap;
return { width: width };
}
};
const messageContainer = {
getBoundingClientRect() {
return { width: 420 };
}
};
sandbox.window.getComputedStyle = function () {
return { columnGap: '20px', gap: '20px' };
};
sandbox.initPlayerAnnouncementMarquee(track, { container: messageContainer });
assert.equal(track.dataset.marqueeMeasured, 'true');
assert.equal(track.style.values['--announcement-scroll-distance'], '120.00px');
assert.equal(track.style.values['--announcement-scroll-duration'], '8.00s');
assert.equal(track.style.animationDuration, '8.00s');
assert.ok(track.appended.length >= 3);
});
test('announcement markup strips line breaks from the message', () => {
const sandbox = loadAnnouncementTemplateHelpers();
sandbox.playerAnnouncementTemplates = {
topBanner: '<div class="message">{{MESSAGE}}</div>'
};
const markup = sandbox.renderPlayerAnnouncementMarkup({
announcement_type: 'top-banner',
message: 'First line\nSecond line\r\nThird line',
short_label: 'Breaking News',
color_key: 'primary',
icon_key: 'info-circle'
});
assert.match(markup, /First line Second line Third line/);
assert.doesNotMatch(markup, /<br\s*\/?\s*>/i);
});