MusicUtils / tests /test_youtube.py
sathvik77's picture
feat(backend): yt-dlp metadata + audio download wrappers
53e89b8
Raw
History Blame Contribute Delete
3.21 kB
import pytest
from youtube import extract_youtube_id, InvalidYoutubeUrl
@pytest.mark.parametrize("url,expected", [
("https://www.youtube.com/watch?v=dQw4w9WgXcQ", "dQw4w9WgXcQ"),
("https://youtu.be/dQw4w9WgXcQ", "dQw4w9WgXcQ"),
("https://www.youtube.com/watch?v=dQw4w9WgXcQ&list=PL", "dQw4w9WgXcQ"),
("https://m.youtube.com/watch?v=dQw4w9WgXcQ", "dQw4w9WgXcQ"),
("https://www.youtube.com/shorts/dQw4w9WgXcQ", "dQw4w9WgXcQ"),
])
def test_extract_youtube_id_valid(url, expected):
assert extract_youtube_id(url) == expected
@pytest.mark.parametrize("url", [
"https://example.com/watch?v=dQw4w9WgXcQ",
"not a url",
"https://www.youtube.com/",
"https://youtu.be/",
"",
])
def test_extract_youtube_id_invalid(url):
with pytest.raises(InvalidYoutubeUrl):
extract_youtube_id(url)
from unittest.mock import MagicMock, patch
from pathlib import Path
from youtube import fetch_metadata, download_audio, YoutubeFetchError, VideoTooLong
@patch("youtube.yt_dlp.YoutubeDL")
def test_fetch_metadata_returns_normalized_dict(mock_ydl_cls):
mock_ydl = MagicMock()
mock_ydl_cls.return_value.__enter__.return_value = mock_ydl
mock_ydl.extract_info.return_value = {
"id": "dQw4w9WgXcQ",
"title": "Rick Astley - Never Gonna Give You Up (Official Video)",
"uploader": "Rick Astley",
"artist": None,
"duration": 213,
"thumbnail": "https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg",
}
meta = fetch_metadata("https://youtu.be/dQw4w9WgXcQ")
assert meta["youtube_id"] == "dQw4w9WgXcQ"
assert meta["artist"] == "Rick Astley"
assert meta["title"] == "Never Gonna Give You Up (Official Video)"
assert meta["duration_sec"] == 213
assert meta["thumbnail_url"].startswith("https://i.ytimg.com/")
@patch("youtube.yt_dlp.YoutubeDL")
def test_fetch_metadata_raises_on_too_long(mock_ydl_cls):
mock_ydl = MagicMock()
mock_ydl_cls.return_value.__enter__.return_value = mock_ydl
mock_ydl.extract_info.return_value = {
"id": "abc12345678", "title": "x", "uploader": "x",
"duration": 99999, "thumbnail": "",
}
with pytest.raises(VideoTooLong):
fetch_metadata("https://youtu.be/abc12345678", max_duration_sec=600)
@patch("youtube.yt_dlp.YoutubeDL")
def test_fetch_metadata_raises_fetch_error(mock_ydl_cls):
from yt_dlp.utils import DownloadError
mock_ydl = MagicMock()
mock_ydl_cls.return_value.__enter__.return_value = mock_ydl
mock_ydl.extract_info.side_effect = DownloadError("Sign in to confirm you're not a bot")
with pytest.raises(YoutubeFetchError):
fetch_metadata("https://youtu.be/abc12345678")
@patch("youtube.yt_dlp.YoutubeDL")
def test_download_audio_writes_file(mock_ydl_cls, tmp_path):
mock_ydl = MagicMock()
mock_ydl_cls.return_value.__enter__.return_value = mock_ydl
# Simulate yt-dlp writing the output file:
def fake_download(urls):
(tmp_path / "dQw4w9WgXcQ.m4a").write_bytes(b"fake audio")
mock_ydl.download.side_effect = fake_download
out = download_audio("https://youtu.be/dQw4w9WgXcQ", "dQw4w9WgXcQ", tmp_path)
assert out.exists()
assert out.suffix == ".m4a"