import { describe, expect, it } from 'vitest'; import { InvalidPlaylistUrlError, assertValidPlaylistUrl } from '../src/services/playlistUrl.js'; describe('assertValidPlaylistUrl', () => { it.each([ ['https://www.youtube.com/playlist?list=PLKDZ1ig0uz-U', 'PLKDZ1ig0uz-U'], ['https://youtube.com/playlist?list=PLKDZ1ig0uz-U', 'PLKDZ1ig0uz-U'], ['https://m.youtube.com/playlist?list=PLKDZ1ig0uz-U', 'PLKDZ1ig0uz-U'], ['https://music.youtube.com/playlist?list=OLAK5uy_abcDEF123', 'OLAK5uy_abcDEF123'], [ ' https://www.youtube.com/playlist?list=UUBR8-60-B28hp2BmDPdntcQ ', 'UUBR8-60-B28hp2BmDPdntcQ', ], ])('accepte %j et retourne l’URL canonique', (input, id) => { expect(assertValidPlaylistUrl(input)).toBe(`https://www.youtube.com/playlist?list=${id}`); }); it('ignore les paramètres annexes, quel que soit leur ordre', () => { expect( assertValidPlaylistUrl( 'https://youtube.com/playlist?si=abc123&list=PLxyz_-9&index=4&foo=bar', ), ).toBe('https://www.youtube.com/playlist?list=PLxyz_-9'); }); it.each([ ['un schéma http', 'http://www.youtube.com/playlist?list=PLabc'], ['un autre domaine', 'https://evil.com/playlist?list=PLabc'], ['un sous-domaine trompeur', 'https://youtube.com.evil.com/playlist?list=PLabc'], ['un domaine préfixé', 'https://evilyoutube.com/playlist?list=PLabc'], ['un domaine avec point final', 'https://www.youtube.com./playlist?list=PLabc'], ['des identifiants dans l’URL', 'https://user:pass@www.youtube.com/playlist?list=PLabc'], ['un port explicite', 'https://www.youtube.com:8443/playlist?list=PLabc'], [ 'un lien de vidéo avec paramètre list', 'https://www.youtube.com/watch?v=dQw4w9WgXcQ&list=PLabc', ], ['un lien court avec paramètre list', 'https://youtu.be/dQw4w9WgXcQ?list=PLabc'], ['un chemin voisin', 'https://www.youtube.com/playlists?list=PLabc'], ['un chemin plus profond', 'https://www.youtube.com/playlist/extra?list=PLabc'], ['un paramètre list absent', 'https://www.youtube.com/playlist'], ['un paramètre list vide', 'https://www.youtube.com/playlist?list='], ['un identifiant trop court', 'https://www.youtube.com/playlist?list=P'], ['un identifiant trop long', `https://www.youtube.com/playlist?list=${'a'.repeat(65)}`], ['un identifiant avec un slash encodé', 'https://www.youtube.com/playlist?list=PL%2Fabc'], ['un identifiant avec une espace encodée', 'https://www.youtube.com/playlist?list=PL%20abc'], ['un identifiant ressemblant à une option', 'https://www.youtube.com/playlist?list=--exec=rm'], ['un schéma javascript', 'javascript:alert(1)'], ['un schéma file', 'file:///etc/passwd'], ['du texte quelconque', 'pas une url'], ['une chaîne vide', ''], ])('rejette %s', (_label, input) => { expect(() => assertValidPlaylistUrl(input)).toThrow(InvalidPlaylistUrlError); }); });