Add player control-plane and dashboard updates
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
|
||||
require('../src/common');
|
||||
|
||||
const { createDashboardStateService } = require('../src/web/lib/dashboard-state');
|
||||
|
||||
test('dashboard state counts active players from the registry heartbeat', async () => {
|
||||
const service = createDashboardStateService({
|
||||
pool: {
|
||||
async query(sql) {
|
||||
if (String(sql || '').includes('COUNT(*) AS connected_count')) {
|
||||
return [[{ connected_count: 6 }]];
|
||||
}
|
||||
if (String(sql || '').includes('SELECT s.slug, pod.device_id, pod.client_name')) {
|
||||
return [[]];
|
||||
}
|
||||
return [[]];
|
||||
}
|
||||
},
|
||||
common: {
|
||||
async fetchAdminData() {
|
||||
return {
|
||||
screens: [
|
||||
{
|
||||
slug: 'alpha',
|
||||
name: 'Alpha',
|
||||
playlist_name: 'Main Loop'
|
||||
}
|
||||
],
|
||||
playlists: [],
|
||||
slides: []
|
||||
};
|
||||
},
|
||||
async fetchScreenPlayerUrls() {
|
||||
return {
|
||||
alpha: 'http://player.local/screen/alpha'
|
||||
};
|
||||
},
|
||||
async fetchPlayerRegistrations() {
|
||||
return [
|
||||
{
|
||||
identifier: 'player-alpha',
|
||||
public_base_url: 'http://player.local',
|
||||
last_seen_at: new Date(Date.now() - 10 * 1000)
|
||||
},
|
||||
{
|
||||
identifier: 'player-stale',
|
||||
public_base_url: 'http://stale.player.local',
|
||||
last_seen_at: new Date(Date.now() - 10 * 60 * 1000)
|
||||
}
|
||||
];
|
||||
}
|
||||
},
|
||||
playerSnapshotCache: new Map([
|
||||
['alpha', { count: 1, connections: [{ id: 1, playerPublicBaseUrl: 'http://player.local' }] }]
|
||||
]),
|
||||
playerSnapshotSockets: new Map(),
|
||||
ensurePlayerSnapshotSubscription() {},
|
||||
formatDashboardDate(value) {
|
||||
return String(value || '');
|
||||
}
|
||||
});
|
||||
const state = await service.buildDashboardState();
|
||||
|
||||
assert.equal(state.connectedPlayersCount, 6);
|
||||
assert.equal(state.connectedClientsCount, 1);
|
||||
assert.equal(state.clients[0].player_identifier, 'player-alpha');
|
||||
assert.equal(state.kioskPlayers.length, 1);
|
||||
assert.deepEqual(state.kioskPlayers[0], {
|
||||
player_identifier: 'player-alpha',
|
||||
player_url: 'http://player.local'
|
||||
});
|
||||
});
|
||||
|
||||
test('dashboard state keeps other screens when one subscription fails', async () => {
|
||||
const service = createDashboardStateService({
|
||||
pool: {
|
||||
async query(sql) {
|
||||
if (String(sql || '').includes('COUNT(*) AS connected_count')) {
|
||||
return [[{ connected_count: 0 }]];
|
||||
}
|
||||
if (String(sql || '').includes('SELECT s.slug, pod.device_id, pod.client_name')) {
|
||||
return [[]];
|
||||
}
|
||||
return [[]];
|
||||
}
|
||||
},
|
||||
common: {
|
||||
async fetchAdminData() {
|
||||
return {
|
||||
screens: [
|
||||
{ slug: 'alpha', name: 'Alpha' },
|
||||
{ slug: 'beta', name: 'Beta' }
|
||||
],
|
||||
playlists: [],
|
||||
slides: []
|
||||
};
|
||||
},
|
||||
async fetchScreenPlayerUrls() {
|
||||
return {};
|
||||
},
|
||||
async fetchPlayerRegistrations() {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
playerSnapshotCache: new Map([
|
||||
['beta', { count: 1, connections: [{ id: 'beta-conn', clientId: 'beta-conn' }] }]
|
||||
]),
|
||||
playerSnapshotSockets: new Map(),
|
||||
ensurePlayerSnapshotSubscription(slug) {
|
||||
if (slug === 'alpha') {
|
||||
throw new Error('subscription failed');
|
||||
}
|
||||
},
|
||||
formatDashboardDate(value) {
|
||||
return String(value || '');
|
||||
}
|
||||
});
|
||||
|
||||
const state = await service.buildDashboardState();
|
||||
|
||||
assert.equal(state.screens.length, 2);
|
||||
assert.equal(state.clients.length, 1);
|
||||
assert.equal(state.clients[0].screen_slug, 'beta');
|
||||
});
|
||||
Reference in New Issue
Block a user