import { describe, it, expect } from 'vitest' import { buildTestApp, setupAdmin, auth } from './helpers.js' function stubWithRecent(recent: { id: number; name: string; artist: string; played?: string }[]): typeof fetch { return (async (input: any) => { const url = new URL(String(input)) if (url.pathname.endsWith('/rest/ping')) { return new Response(JSON.stringify({ 'subsonic-response': { status: 'ok' } }), { status: 200, headers: { 'content-type': 'application/json' }, }) } if (url.pathname.endsWith('/rest/getAlbumList2')) { const type = url.searchParams.get('type') const body = type === 'recent' ? { 'subsonic-response': { status: 'ok', albumList2: { album: recent } } } : { 'subsonic-response': { status: 'ok', albumList2: { album: [{ id: 1, name: 'Album 1', artist: 'Artist 0' }] } } } return new Response(JSON.stringify(body), { status: 200, headers: { 'content-type': 'application/json' } }) } return new Response('nope', { status: 404 }) }) as typeof fetch } async function waitForDone(app: any, cookie: string, timeoutMs = 2000) { const start = Date.now() while (Date.now() - start < timeoutMs) { const state = (await app.inject({ method: 'GET', url: '/api/library/sync', ...auth(cookie) })).json() if (state.status !== 'running') return state await new Promise((r) => setTimeout(r, 10)) } throw new Error('sync did not finish') } describe('last_played_at stamping', () => { it('sync stamps played timestamps from the recent list', async () => { const app = await buildTestApp( stubWithRecent([{ id: 1, name: 'Album 1', artist: 'Artist 0', played: '2026-09-01T10:00:00Z' }]) ) const cookie = await setupAdmin(app) await app.inject({ method: 'PUT', url: '/api/settings', ...auth(cookie), payload: { subsonicUrl: 'http://n.local', subsonicUsername: 'sam', subsonicPassword: 'pass' }, }) await waitForDone(app, cookie) const row = app.db .prepare("SELECT last_played_at FROM digital_albums WHERE subsonic_id = '1'") .get() as { last_played_at: string | null } expect(row.last_played_at).toBe('2026-09-01T10:00:00Z') await app.close() }) it('played endpoint stamps now and returns 404 for unknown albums', async () => { const app = await buildTestApp() const cookie = await setupAdmin(app) await app.inject({ method: 'POST', url: '/api/library/albums/test-seed', ...auth(cookie), payload: { albums: [{ subsonicId: 'a1', title: 'Motion', artist: 'TCO' }] }, }) const before = ( app.db.prepare("SELECT last_played_at FROM digital_albums WHERE subsonic_id = 'a1'").get() as { last_played_at: string | null } ).last_played_at expect(before).toBeNull() const res = await app.inject({ method: 'POST', url: '/api/album/a1/played', ...auth(cookie) }) expect(res.statusCode).toBe(200) const after = ( app.db.prepare("SELECT last_played_at FROM digital_albums WHERE subsonic_id = 'a1'").get() as { last_played_at: string | null } ).last_played_at expect(after).toBeTruthy() const missing = await app.inject({ method: 'POST', url: '/api/album/zzz/played', ...auth(cookie) }) expect(missing.statusCode).toBe(404) await app.close() }) })