2026-07-04 11:42:53 +04:00
|
|
|
import {describe, it, expect, vi, afterEach} from 'vitest'
|
|
|
|
|
import {GET} from '../route'
|
|
|
|
|
|
|
|
|
|
function fakeUpstreamResponse({status = 200, headers = {}, body = 'audio-bytes'} = {}) {
|
|
|
|
|
return {
|
|
|
|
|
status,
|
2026-07-15 23:04:19 +04:00
|
|
|
ok: status >= 200 && status < 300,
|
2026-07-04 11:42:53 +04:00
|
|
|
body,
|
|
|
|
|
headers: {
|
|
|
|
|
get: key => headers[key.toLowerCase()] ?? null
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
describe('GET /api/mizik-stream/[id]', () => {
|
|
|
|
|
const originalFetch = global.fetch
|
|
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
|
global.fetch = originalFetch
|
|
|
|
|
vi.restoreAllMocks()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('n\'expose pas les identifiants au client, uniquement l\'id dans l\'URL amont', async () => {
|
|
|
|
|
global.fetch = vi.fn(async () => fakeUpstreamResponse())
|
|
|
|
|
|
|
|
|
|
const request = new Request('http://localhost/api/mizik-stream/42')
|
|
|
|
|
await GET(request, {params: Promise.resolve({id: '42'})})
|
|
|
|
|
|
|
|
|
|
const [calledUrl] = global.fetch.mock.calls[0]
|
|
|
|
|
expect(calledUrl).toContain('id=42')
|
|
|
|
|
expect(calledUrl).toMatch(/[?&]u=/)
|
|
|
|
|
expect(calledUrl).toMatch(/[?&]p=/)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('transmet l\'en-tête Range pour permettre le seek audio', async () => {
|
|
|
|
|
global.fetch = vi.fn(async () => fakeUpstreamResponse({status: 206, headers: {'content-range': 'bytes 0-99/200'}}))
|
|
|
|
|
|
|
|
|
|
const request = new Request('http://localhost/api/mizik-stream/42', {headers: {range: 'bytes=0-99'}})
|
|
|
|
|
const response = await GET(request, {params: Promise.resolve({id: '42'})})
|
|
|
|
|
|
|
|
|
|
const [, options] = global.fetch.mock.calls[0]
|
|
|
|
|
expect(options.headers.range).toBe('bytes=0-99')
|
|
|
|
|
expect(response.status).toBe(206)
|
|
|
|
|
expect(response.headers.get('content-range')).toBe('bytes 0-99/200')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('renvoie le flux et le statut renvoyés par le serveur Funkwhale', async () => {
|
|
|
|
|
global.fetch = vi.fn(async () => fakeUpstreamResponse({status: 200, headers: {'content-type': 'audio/mpeg'}}))
|
|
|
|
|
|
|
|
|
|
const request = new Request('http://localhost/api/mizik-stream/7')
|
|
|
|
|
const response = await GET(request, {params: Promise.resolve({id: '7'})})
|
|
|
|
|
|
|
|
|
|
expect(response.status).toBe(200)
|
|
|
|
|
expect(response.headers.get('content-type')).toBe('audio/mpeg')
|
|
|
|
|
})
|
2026-07-15 23:04:19 +04:00
|
|
|
|
|
|
|
|
it('renvoie une erreur JSON si le serveur audio répond en erreur', async () => {
|
|
|
|
|
global.fetch = vi.fn(async () => fakeUpstreamResponse({status: 401, headers: {'content-type': 'application/json'}, body: '{"error": "unauthorized"}'}))
|
|
|
|
|
|
|
|
|
|
const request = new Request('http://localhost/api/mizik-stream/7')
|
|
|
|
|
const response = await GET(request, {params: Promise.resolve({id: '7'})})
|
|
|
|
|
|
|
|
|
|
expect(response.status).toBe(401)
|
|
|
|
|
expect(response.headers.get('content-type')).toContain('application/json')
|
|
|
|
|
const json = await response.json()
|
|
|
|
|
expect(json.error).toContain('401')
|
|
|
|
|
})
|
2026-07-04 11:42:53 +04:00
|
|
|
})
|