All checks were successful
Deploy production / deploy (push) Successful in 2m35s
81 lines
2.4 KiB
TypeScript
81 lines
2.4 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import {
|
|
detectChange,
|
|
estimateProgress,
|
|
formatClock,
|
|
nextDelay,
|
|
sseEvent,
|
|
toLive,
|
|
type PlayerSample
|
|
} from './now-playing';
|
|
|
|
const track = (id: string) => ({
|
|
spotifyId: id,
|
|
name: `Song ${id}`,
|
|
durationMs: 200_000,
|
|
explicit: false,
|
|
artists: [
|
|
{ spotifyId: null, name: 'A' },
|
|
{ spotifyId: null, name: 'B' }
|
|
],
|
|
album: {
|
|
spotifyId: null,
|
|
name: 'Album',
|
|
imageUrl: 'https://i/640',
|
|
imageUrlSmall: 'https://i/300',
|
|
releaseDate: null
|
|
}
|
|
});
|
|
const sample = (over: Partial<PlayerSample> = {}): PlayerSample => ({
|
|
trackId: 1,
|
|
track: track('x'),
|
|
isPlaying: true,
|
|
progressMs: 10_000,
|
|
sampledAt: 1_000_000,
|
|
...over
|
|
});
|
|
|
|
describe('now playing', () => {
|
|
it('builds the public payload', () => {
|
|
expect(toLive(sample())).toEqual({
|
|
isPlaying: true,
|
|
track: 'Song x',
|
|
artists: 'A, B',
|
|
album: 'Album',
|
|
image: 'https://i/300',
|
|
url: 'https://open.spotify.com/track/x',
|
|
progressMs: 10_000,
|
|
durationMs: 200_000,
|
|
sampledAt: 1_000_000
|
|
});
|
|
expect(toLive(sample({ track: null, trackId: null }))).toMatchObject({
|
|
isPlaying: false,
|
|
track: null
|
|
});
|
|
});
|
|
it('detects track changes, play/pause and seeks, not normal progress', () => {
|
|
const a = sample();
|
|
expect(detectChange(null, a).any).toBe(true);
|
|
expect(detectChange(a, sample({ progressMs: 15_000, sampledAt: 1_005_000 })).any).toBe(false);
|
|
expect(detectChange(a, sample({ progressMs: 90_000, sampledAt: 1_005_000 })).seek).toBe(true);
|
|
expect(detectChange(a, sample({ isPlaying: false })).playing).toBe(true);
|
|
expect(detectChange(a, sample({ track: track('y') })).track).toBe(true);
|
|
});
|
|
it('estimates progress between events and clamps to the duration', () => {
|
|
const l = toLive(sample());
|
|
expect(estimateProgress(l, 0, 5_000)).toBe(15_000);
|
|
expect(estimateProgress(l, 0, 10_000_000)).toBe(200_000);
|
|
expect(estimateProgress({ ...l, isPlaying: false }, 0, 5_000)).toBe(10_000);
|
|
expect(formatClock(75_000)).toBe('1:15');
|
|
});
|
|
it('formats SSE events with the sample age, and backs off when idle', () => {
|
|
const event = sseEvent(toLive(sample()), 1_002_000);
|
|
expect(event.startsWith('event: now\ndata: ')).toBe(true);
|
|
expect(event.endsWith('\n\n')).toBe(true);
|
|
expect(JSON.parse(event.split('data: ')[1]).ageMs).toBe(2_000);
|
|
expect(nextDelay(true, 9)).toBe(5_000);
|
|
expect(nextDelay(false, 0)).toBe(10_000);
|
|
expect(nextDelay(false, 50)).toBe(30_000);
|
|
});
|
|
});
|