Skip to content
File

Blob: worker/src/server/publisher-metadata.test.ts

typescript52 lines
1import assert from 'node:assert/strict';
2import { test } from 'node:test';
3import { checkStartupMetadata, heartbeatMetadata, startupMetadata } from './publisher-metadata.ts';
4import type { Publisher } from './room-state.ts';
5 
6const track = { title: 'First', artist: '', durationMs: 2000 };
7const nowPlaying = { revision: 0, trackIndex: 0, trackCount: 2, track };
8const offer = { type: 'offer' as const, sdp: 'v=0' };
9const publisher: Publisher = {
10 sessionId: 'test',
11 generation: 'test',
12 ready: true,
13 seen: 0,
14 channels: [],
15 track,
16 nowPlaying,
17 initialNowPlaying: nowPlaying,
18};
19 
20test('startup normalization supports legacy, playlist-only and agreeing dual metadata', () => {
21 for (const fields of [{ nowPlaying }, { nowPlaying, track }]) {
22 const normalized = startupMetadata({ sessionDescription: offer, ...fields });
23 checkStartupMetadata(publisher, normalized);
24 assert.equal(normalized.track, track);
25 }
26 const legacy = { ...publisher, nowPlaying: undefined, initialNowPlaying: undefined };
27 checkStartupMetadata(legacy, startupMetadata({ sessionDescription: offer, track }));
28 assert.throws(() => startupMetadata({ sessionDescription: offer, nowPlaying, track: null }));
29 assert.throws(() =>
30 startupMetadata({ sessionDescription: offer, nowPlaying, track: { ...track, title: 'Other' } }),
31 );
32 assert.equal(
33 startupMetadata({ sessionDescription: offer, nowPlaying: { ...nowPlaying, track: null } })
34 .track,
35 undefined,
36 );
37});
38 
39test('heartbeat accepts wrapping revisions but rejects conflicts and playlist resizing', () => {
40 const wrapped = { ...nowPlaying, revision: 0xffff_ffff };
41 assert.equal(heartbeatMetadata(wrapped, nowPlaying), nowPlaying);
42 assert.equal(heartbeatMetadata(nowPlaying, wrapped), nowPlaying);
43 assert.throws(() => heartbeatMetadata(nowPlaying, { ...nowPlaying, trackIndex: 1 }));
44 assert.throws(() => heartbeatMetadata(nowPlaying, { ...nowPlaying, revision: 1, trackCount: 3 }));
45 const playing = {
46 ...publisher,
47 track: { ...track, title: 'Second' },
48 nowPlaying: { ...nowPlaying, revision: 1 },
49 };
50 checkStartupMetadata(playing, startupMetadata({ sessionDescription: offer, nowPlaying }));
51});