mirror of
https://github.com/Boof2015/prism.git
synced 2026-08-16 16:21:11 +02:00
api memory regression fix
This commit is contained in:
@@ -232,6 +232,193 @@ test('service initializes from config, hydrates artwork, and applies SSE updates
|
||||
}
|
||||
})
|
||||
|
||||
test('service emits a single state update when reusing cached artwork on SSE updates', async () => {
|
||||
const harness = await createConfigFile({
|
||||
baseUrl: DEFAULT_ASTRA_BASE_URL,
|
||||
token: 'secret-token',
|
||||
})
|
||||
const sse = createSseStream()
|
||||
const artworkUrl = `${DEFAULT_ASTRA_BASE_URL}/v1/artwork/current?trackId=track-1`
|
||||
let stateUpdateCount = 0
|
||||
|
||||
const fetchImpl: typeof fetch = async (input, init) => {
|
||||
const url = String(input)
|
||||
const pathname = new URL(url).pathname
|
||||
const headers = createHeaders(init)
|
||||
assert.equal(headers.get('authorization'), 'Bearer secret-token')
|
||||
|
||||
if (pathname === '/v1/now-playing') {
|
||||
return createJsonResponse({
|
||||
playbackState: 'playing',
|
||||
currentTime: 15,
|
||||
duration: 180,
|
||||
queueLength: 2,
|
||||
outputDeviceLabel: 'Built-in Output',
|
||||
visualizerLineColor: '#4ade80',
|
||||
updatedAt: 1000,
|
||||
currentTrack: {
|
||||
id: 'track-1',
|
||||
title: 'Song One',
|
||||
artist: 'Artist One',
|
||||
album: 'Album One',
|
||||
isFavorite: false,
|
||||
artworkUrl,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if (pathname === '/v1/artwork/current') {
|
||||
return createPngResponse('cover-one')
|
||||
}
|
||||
|
||||
if (pathname === '/v1/events') {
|
||||
return sse.response
|
||||
}
|
||||
|
||||
throw new Error(`Unexpected request: ${url}`)
|
||||
}
|
||||
|
||||
const service = new AstraIntegrationService({
|
||||
configPath: harness.configPath,
|
||||
fetchImpl,
|
||||
now: () => 1000,
|
||||
})
|
||||
|
||||
try {
|
||||
service.subscribe((state) => {
|
||||
void state
|
||||
stateUpdateCount += 1
|
||||
})
|
||||
|
||||
await service.initialize()
|
||||
await service.setConsumerActive(1, true)
|
||||
await waitFor(() => service.getState().connectionState === 'connected', 'expected connected Astra state')
|
||||
|
||||
const baseUpdateCount = stateUpdateCount
|
||||
|
||||
sse.pushEvent('now-playing', {
|
||||
playbackState: 'playing',
|
||||
currentTime: 42,
|
||||
duration: 180,
|
||||
queueLength: 2,
|
||||
outputDeviceLabel: 'Built-in Output',
|
||||
visualizerLineColor: '#4ade80',
|
||||
updatedAt: 2000,
|
||||
currentTrack: {
|
||||
id: 'track-1',
|
||||
title: 'Song One',
|
||||
artist: 'Artist One',
|
||||
album: 'Album One',
|
||||
isFavorite: false,
|
||||
artworkUrl,
|
||||
},
|
||||
})
|
||||
|
||||
await waitFor(() => service.getState().snapshot?.updatedAt === 2000, 'expected SSE update to apply')
|
||||
assert.equal(stateUpdateCount - baseUpdateCount, 1)
|
||||
} finally {
|
||||
await service.dispose()
|
||||
await harness.cleanup()
|
||||
}
|
||||
})
|
||||
|
||||
test('service does not refetch identical artwork after a failed attempt', async () => {
|
||||
const harness = await createConfigFile({
|
||||
baseUrl: DEFAULT_ASTRA_BASE_URL,
|
||||
token: 'secret-token',
|
||||
})
|
||||
const sse = createSseStream()
|
||||
const artworkUrl = `${DEFAULT_ASTRA_BASE_URL}/v1/artwork/current?trackId=track-2`
|
||||
let artworkRequests = 0
|
||||
|
||||
const fetchImpl: typeof fetch = async (input, init) => {
|
||||
const url = String(input)
|
||||
const pathname = new URL(url).pathname
|
||||
const headers = createHeaders(init)
|
||||
assert.equal(headers.get('authorization'), 'Bearer secret-token')
|
||||
|
||||
if (pathname === '/v1/now-playing') {
|
||||
return createJsonResponse({
|
||||
playbackState: 'paused',
|
||||
currentTime: 0,
|
||||
duration: 0,
|
||||
queueLength: 0,
|
||||
outputDeviceLabel: null,
|
||||
visualizerLineColor: '#38bdf8',
|
||||
updatedAt: 1000,
|
||||
currentTrack: null,
|
||||
})
|
||||
}
|
||||
|
||||
if (pathname === '/v1/artwork/current') {
|
||||
artworkRequests += 1
|
||||
return createJsonResponse({ error: 'missing artwork' }, 404)
|
||||
}
|
||||
|
||||
if (pathname === '/v1/events') {
|
||||
return sse.response
|
||||
}
|
||||
|
||||
throw new Error(`Unexpected request: ${url}`)
|
||||
}
|
||||
|
||||
const service = new AstraIntegrationService({
|
||||
configPath: harness.configPath,
|
||||
fetchImpl,
|
||||
})
|
||||
|
||||
try {
|
||||
await service.initialize()
|
||||
await service.setConsumerActive(1, true)
|
||||
await waitFor(() => service.getState().connectionState === 'connected', 'expected connected Astra state')
|
||||
|
||||
sse.pushEvent('now-playing', {
|
||||
playbackState: 'playing',
|
||||
currentTime: 5,
|
||||
duration: 180,
|
||||
queueLength: 1,
|
||||
outputDeviceLabel: 'Built-in Output',
|
||||
visualizerLineColor: '#4ade80',
|
||||
updatedAt: 2000,
|
||||
currentTrack: {
|
||||
id: 'track-2',
|
||||
title: 'Song Two',
|
||||
artist: 'Artist Two',
|
||||
album: 'Album Two',
|
||||
isFavorite: false,
|
||||
artworkUrl,
|
||||
},
|
||||
})
|
||||
|
||||
await waitFor(() => service.getState().snapshot?.currentTrack?.id === 'track-2', 'expected first artwork-bearing track update')
|
||||
await waitFor(() => artworkRequests === 1, 'expected first failed artwork request')
|
||||
|
||||
sse.pushEvent('now-playing', {
|
||||
playbackState: 'playing',
|
||||
currentTime: 15,
|
||||
duration: 180,
|
||||
queueLength: 1,
|
||||
outputDeviceLabel: 'Built-in Output',
|
||||
visualizerLineColor: '#4ade80',
|
||||
updatedAt: 3000,
|
||||
currentTrack: {
|
||||
id: 'track-2',
|
||||
title: 'Song Two',
|
||||
artist: 'Artist Two',
|
||||
album: 'Album Two',
|
||||
isFavorite: false,
|
||||
artworkUrl,
|
||||
},
|
||||
})
|
||||
|
||||
await waitFor(() => service.getState().snapshot?.updatedAt === 3000, 'expected second track update')
|
||||
assert.equal(artworkRequests, 1)
|
||||
} finally {
|
||||
await service.dispose()
|
||||
await harness.cleanup()
|
||||
}
|
||||
})
|
||||
|
||||
test('service schedules reconnect when the SSE stream closes', async () => {
|
||||
const harness = await createConfigFile({
|
||||
baseUrl: DEFAULT_ASTRA_BASE_URL,
|
||||
|
||||
Reference in New Issue
Block a user