Release v2.14.1
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile, web, pulse-signage-web) (push) Successful in 1m53s
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile.player, player, pulse-signage-player) (push) Successful in 32s

This commit is contained in:
lzstealth committed 2026-10-11 18:54:43 +01:00
1 parent 635e1a9942
commit c3299abaac
174 files changed
+4483 -1687

No files matched your search

+81 -2
View File
@@ -5,17 +5,18 @@ const test = require('node:test');
const assert = require('node:assert/strict');
function loadAnnouncementTemplateHelpers() {
const sharedScriptPath = path.join(__dirname, '..', 'src', 'player', 'rendering-shared.js');
const scriptPath = path.join(__dirname, '..', 'src', 'player', 'public', 'js', 'player-announcement-templates.js');
const sharedScript = fs.readFileSync(sharedScriptPath, 'utf8');
const script = fs.readFileSync(scriptPath, 'utf8');
const sandbox = {
window: {},
module: { exports: {} },
exports: {},
console
};
sandbox.window = sandbox;
vm.runInNewContext(sharedScript, sandbox, { filename: sharedScriptPath });
vm.runInNewContext(script, sandbox, { filename: scriptPath });
return sandbox;
}
@@ -105,4 +106,82 @@ test('announcement markup strips line breaks from the message', () => {
assert.match(markup, /First line Second line Third line/);
assert.doesNotMatch(markup, /<br\s*\/?\s*>/i);
});
test('announcement fallback polling stops when the websocket opens and resumes when it closes', () => {
const intervals = new Map();
const listeners = new Map();
let nextTimerId = 1;
let announcementSocket = null;
let announcementRequests = 0;
class MockWebSocket {
constructor() {
this.readyState = MockWebSocket.CONNECTING;
announcementSocket = this;
}
open() {
this.readyState = MockWebSocket.OPEN;
if (this.onopen) this.onopen();
}
close() {
this.readyState = MockWebSocket.CLOSED;
if (this.onclose) this.onclose();
}
}
MockWebSocket.CONNECTING = 0;
MockWebSocket.OPEN = 1;
MockWebSocket.CLOSED = 3;
class MockXhr {
open() {}
setRequestHeader() {}
send() { announcementRequests += 1; }
}
const window = {
slug: 'test',
location: { origin: 'http://localhost:8081' },
WebSocket: MockWebSocket,
setInterval(callback, delay) {
const id = nextTimerId++;
intervals.set(id, { callback: callback, delay: delay });
return id;
},
clearInterval(id) { intervals.delete(id); },
setTimeout() { return nextTimerId++; },
clearTimeout() {},
addEventListener() {}
};
const sandbox = {
window: window,
document: {
readyState: 'loading',
addEventListener(name, callback) { listeners.set(name, callback); }
},
WebSocket: MockWebSocket,
XMLHttpRequest: MockXhr,
URL,
Date,
JSON,
String,
Array,
Math
};
const scriptPath = path.join(__dirname, '..', 'src', 'player', 'player-page-announcements.js');
vm.runInNewContext(fs.readFileSync(scriptPath, 'utf8'), sandbox, { filename: scriptPath });
listeners.get('DOMContentLoaded')();
assert.equal(announcementRequests, 0);
assert.equal(intervals.size, 1);
assert.equal(Array.from(intervals.values())[0].delay, 15000);
announcementSocket.open();
assert.equal(announcementRequests, 1);
assert.equal(intervals.size, 0);
announcementSocket.close();
assert.equal(intervals.size, 1);
});