117 lines
3.6 KiB
JavaScript
117 lines
3.6 KiB
JavaScript
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
|
|
require('../src/common');
|
|
|
|
const { createWebBootstrap, mergePlayerSnapshotConnections } = require('../src/web/bootstrap');
|
|
const { createWebConfig } = require('../src/web/lib/config');
|
|
|
|
test('dashboard combines player and bridge snapshots without duplicating clients', () => {
|
|
const localClient = { id: 'connection-1', clientId: 'client-1', deviceId: 'device-1', playerPublicBaseUrl: 'http://player.local' };
|
|
const bridgeClient = { id: 'connection-2', clientId: 'client-2', deviceId: 'device-2', playerPublicBaseUrl: 'https://player.example' };
|
|
const connections = mergePlayerSnapshotConnections([
|
|
[localClient, bridgeClient],
|
|
[localClient]
|
|
]);
|
|
|
|
assert.deepEqual(connections, [localClient, bridgeClient]);
|
|
});
|
|
|
|
test('web config uses the player directly when no bridge URL is configured', () => {
|
|
const previousBridgeUrl = process.env.BRIDGE_INTERNAL_URL;
|
|
delete process.env.BRIDGE_INTERNAL_URL;
|
|
try {
|
|
assert.equal(createWebConfig().bridgeInternalUrl, 'http://player-bridge:8090');
|
|
process.env.BRIDGE_INTERNAL_URL = '';
|
|
const config = createWebConfig();
|
|
assert.equal(config.bridgeInternalUrl, '');
|
|
assert.equal(config.playerInternalUrl, 'http://player:8081');
|
|
} finally {
|
|
if (previousBridgeUrl === undefined) {
|
|
delete process.env.BRIDGE_INTERNAL_URL;
|
|
} else {
|
|
process.env.BRIDGE_INTERNAL_URL = previousBridgeUrl;
|
|
}
|
|
}
|
|
});
|
|
|
|
test('dashboard websocket broadcasts keep the last successful snapshot when refreshes fail', async () => {
|
|
let adminDataCalls = 0;
|
|
|
|
const bootstrap = createWebBootstrap({
|
|
pool: {
|
|
async query(sql) {
|
|
if (String(sql || '').includes('COUNT(*) AS connected_count')) {
|
|
return [[{ connected_count: 1 }]];
|
|
}
|
|
if (String(sql || '').includes('SELECT s.slug, pod.device_id, pod.client_name')) {
|
|
return [[]];
|
|
}
|
|
return [[]];
|
|
}
|
|
},
|
|
common: {
|
|
async fetchAdminData() {
|
|
adminDataCalls += 1;
|
|
if (adminDataCalls === 1) {
|
|
return {
|
|
screens: [
|
|
{
|
|
slug: 'alpha',
|
|
name: 'Alpha',
|
|
playlist_name: 'Main Loop'
|
|
}
|
|
],
|
|
playlists: [],
|
|
slides: []
|
|
};
|
|
}
|
|
|
|
throw new Error('dashboard refresh failed');
|
|
},
|
|
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()
|
|
}
|
|
];
|
|
}
|
|
},
|
|
playerSnapshotCache: new Map([
|
|
['alpha', {
|
|
count: 1,
|
|
connections: [
|
|
{
|
|
id: 'conn-1',
|
|
playerPublicBaseUrl: 'http://player.local'
|
|
}
|
|
]
|
|
}]
|
|
]),
|
|
playerSnapshotSockets: new Map(),
|
|
ensurePlayerSnapshotSubscription() {},
|
|
formatDashboardDate(value) {
|
|
return String(value || '');
|
|
},
|
|
notifyPlayerScreens() {},
|
|
backgroundTaskQueue: null,
|
|
uploadDir: 'media/uploads',
|
|
playerInternalBaseUrl: 'http://player.local'
|
|
});
|
|
|
|
const firstState = await bootstrap.broadcastDashboardState();
|
|
const secondState = await bootstrap.broadcastDashboardState();
|
|
|
|
assert.equal(firstState.screens[0].slug, 'alpha');
|
|
assert.equal(firstState.clients.length, 1);
|
|
assert.equal(secondState.screens[0].slug, 'alpha');
|
|
assert.equal(secondState.clients.length, 1);
|
|
assert.equal(adminDataCalls, 2);
|
|
}); |