Files
pulse-signage/test/system-status.test.js
T
lzstealth 726a7fedc7
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile, web, pulse-signage-web) (push) Successful in 1m48s
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile.player, player, pulse-signage-player) (push) Successful in 32s
Update connection status indicator
2026-10-25 02:06:06 +00:00

304 lines
7.4 KiB
JavaScript

const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const vm = require('node:vm');
test('system status shows connected player count in the player label', () => {
const script = fs.readFileSync(require.resolve('../src/web/public/js/shared/system-status.js'), 'utf8');
const dotClasses = new Set();
const elements = {
'sidebar-status-dot': {
classList: {
remove(...names) {
names.forEach((name) => dotClasses.delete(name));
},
add(name) {
dotClasses.add(name);
}
},
setAttribute() {}
},
'sidebar-status-text': {
textContent: ''
}
};
const sockets = [];
const context = {
document: {
getElementById(id) {
return elements[id] || null;
}
},
window: {
WebSocket: true,
location: {
protocol: 'http:',
host: 'example.test'
},
setTimeout() {
return 1;
},
clearTimeout() {},
webHandleDashboardState() {}
},
WebSocket: function MockWebSocket(url) {
this.url = url;
sockets.push(this);
this.close = function () {};
},
JSON: JSON,
Number: Number,
String: String,
Boolean: Boolean,
Array: Array,
Object: Object,
Math: Math,
setTimeout() {},
clearTimeout() {},
console: console
};
context.window.document = context.document;
context.window.WebSocket = context.WebSocket;
vm.runInNewContext(script, context);
assert.equal(sockets.length, 1);
sockets[0].onmessage({
data: JSON.stringify({
type: 'dashboard-state',
state: {
screens: [{ slug: 'alpha' }],
playerServiceName: 'Bridge',
playerServiceConnected: true,
connectedPlayersCount: 4
}
})
});
assert.equal(elements['sidebar-status-text'].textContent, 'Bridge online - 4 players connected');
assert.equal(dotClasses.has('status-dot--online'), true);
});
test('system status shows an explicit idle label when no players are connected', () => {
const script = fs.readFileSync(require.resolve('../src/web/public/js/shared/system-status.js'), 'utf8');
const dotClasses = new Set();
const elements = {
'sidebar-status-dot': {
classList: {
remove(...names) {
names.forEach((name) => dotClasses.delete(name));
},
add(name) {
dotClasses.add(name);
}
},
setAttribute() {}
},
'sidebar-status-text': {
textContent: ''
}
};
const sockets = [];
const context = {
document: {
getElementById(id) {
return elements[id] || null;
}
},
window: {
WebSocket: true,
location: {
protocol: 'http:',
host: 'example.test'
},
setTimeout() {
return 1;
},
clearTimeout() {},
webHandleDashboardState() {}
},
WebSocket: function MockWebSocket(url) {
this.url = url;
sockets.push(this);
this.close = function () {};
},
JSON: JSON,
Number: Number,
String: String,
Boolean: Boolean,
Array: Array,
Object: Object,
Math: Math,
setTimeout() {},
clearTimeout() {},
console: console
};
context.window.document = context.document;
context.window.WebSocket = context.WebSocket;
vm.runInNewContext(script, context);
assert.equal(sockets.length, 1);
sockets[0].onmessage({
data: JSON.stringify({
type: 'dashboard-state',
state: {
screens: [{ slug: 'alpha' }],
playerServiceName: 'Bridge',
playerServiceConnected: true,
connectedPlayersCount: 0
}
})
});
assert.equal(elements['sidebar-status-text'].textContent, 'Bridge online - no players connected');
assert.equal(dotClasses.has('status-dot--idle'), true);
sockets[0].onmessage({
data: JSON.stringify({
type: 'dashboard-state',
state: {
screens: [{ slug: 'alpha' }],
playerServiceName: 'Bridge',
playerServiceConnected: false,
connectedPlayersCount: 1
}
})
});
assert.equal(elements['sidebar-status-text'].textContent, 'No services connected');
assert.equal(dotClasses.has('status-dot--offline'), true);
});
test('system status keeps the last service label while a new page reconnects', () => {
const script = fs.readFileSync(require.resolve('../src/web/public/js/shared/system-status.js'), 'utf8');
const elements = {
'sidebar-status-dot': {
classList: {
remove() {},
add() {}
},
setAttribute() {}
},
'sidebar-status-text': {
textContent: 'Player service'
}
};
const storedValues = {
'pulse-player-service-status-v2': JSON.stringify({ status: 'online', label: 'Player service online - 1 player connected', serviceName: 'Player service' })
};
const sockets = [];
const context = {
document: {
getElementById(id) {
return elements[id] || null;
}
},
window: {
WebSocket: true,
location: {
protocol: 'http:',
host: 'example.test'
},
sessionStorage: {
getItem(key) {
return storedValues[key] || null;
},
setItem(key, value) {
storedValues[key] = value;
}
},
setTimeout() {
return 1;
},
clearTimeout() {},
webHandleDashboardState() {}
},
WebSocket: function MockWebSocket(url) {
this.url = url;
sockets.push(this);
this.close = function () {};
},
JSON: JSON,
Number: Number,
String: String,
Boolean: Boolean,
Array: Array,
Object: Object,
Math: Math,
setTimeout() {},
clearTimeout() {},
console: console
};
context.window.document = context.document;
context.window.WebSocket = context.WebSocket;
vm.runInNewContext(script, context);
assert.equal(elements['sidebar-status-text'].textContent, 'Player online - 1 player connected');
sockets[0].onopen();
assert.equal(elements['sidebar-status-text'].textContent, 'Player online - 1 player connected');
});
test('system status uses the same offline label after restoring a cached bridge status', () => {
const script = fs.readFileSync(require.resolve('../src/web/public/js/shared/system-status.js'), 'utf8');
const elements = {
'sidebar-status-dot': {
classList: {
remove() {},
add() {}
},
setAttribute() {}
},
'sidebar-status-text': {
textContent: ''
}
};
const context = {
document: {
getElementById(id) {
return elements[id] || null;
}
},
window: {
WebSocket: true,
location: {
protocol: 'http:',
host: 'example.test'
},
sessionStorage: {
getItem() {
return JSON.stringify({ status: 'offline', label: 'Bridge offline', serviceName: 'Bridge' });
},
setItem() {}
},
setTimeout() {
return 1;
},
clearTimeout() {},
webHandleDashboardState() {}
},
WebSocket: function MockWebSocket() {
this.close = function () {};
},
JSON: JSON,
Number: Number,
String: String,
Boolean: Boolean,
Array: Array,
Object: Object,
Math: Math,
setTimeout() {},
clearTimeout() {},
console: console
};
context.window.document = context.document;
context.window.WebSocket = context.WebSocket;
vm.runInNewContext(script, context);
assert.equal(elements['sidebar-status-text'].textContent, 'No services connected');
});