Rthur2003 commited on
Commit
e57b8bb
·
1 Parent(s): c5dd8f6

test: add tests for YouTubeDownloader error handling and authentication

Browse files
Files changed (1) hide show
  1. tests/test_youtube_downloader.py +108 -0
tests/test_youtube_downloader.py ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Tests for YouTube downloader error handling and auth configuration."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+
7
+ from app.services.youtube_analysis import YouTubeAnalysisService
8
+ from app.services.youtube_downloader import (
9
+ DownloadAttemptFailure,
10
+ DownloadAttemptResult,
11
+ YouTubeDownloadError,
12
+ YouTubeDownloader,
13
+ )
14
+
15
+
16
+ _BOT_CHECK_MESSAGE = (
17
+ "Sign in to confirm you're not a bot. "
18
+ "Use --cookies-from-browser or --cookies for the authentication."
19
+ )
20
+
21
+
22
+ def test_base_options_supports_browser_cookies_from_env(tmp_path, monkeypatch) -> None:
23
+ monkeypatch.delenv("YOUTUBE_COOKIES_FILE", raising=False)
24
+ monkeypatch.delenv("YOUTUBE_COOKIES_BASE64", raising=False)
25
+ monkeypatch.setenv("YOUTUBE_COOKIES_FROM_BROWSER", "edge:Default")
26
+
27
+ downloader = YouTubeDownloader(output_dir=tmp_path)
28
+
29
+ opts = downloader._base_options("tDN-u5gporg")
30
+
31
+ assert opts["cookiesfrombrowser"] == ("edge", "Default", None, None)
32
+
33
+
34
+ def test_download_raises_auth_required_for_bot_check(tmp_path, monkeypatch) -> None:
35
+ failures = [DownloadAttemptFailure(client_label="android+web", message=_BOT_CHECK_MESSAGE)]
36
+
37
+ def fake_with_ffmpeg(self, url: str, video_id: str) -> DownloadAttemptResult:
38
+ return DownloadAttemptResult(info=None, failures=failures)
39
+
40
+ def fake_without_ffmpeg(self, url: str, video_id: str) -> DownloadAttemptResult:
41
+ return DownloadAttemptResult(info=None, failures=failures)
42
+
43
+ monkeypatch.setattr(YouTubeDownloader, "_download_with_ffmpeg", fake_with_ffmpeg)
44
+ monkeypatch.setattr(YouTubeDownloader, "_download_without_ffmpeg", fake_without_ffmpeg)
45
+
46
+ downloader = YouTubeDownloader(output_dir=tmp_path)
47
+
48
+ try:
49
+ downloader.download("https://www.youtube.com/watch?v=tDN-u5gporg", "tDN-u5gporg")
50
+ raise AssertionError("Expected YouTubeDownloadError")
51
+ except YouTubeDownloadError as exc:
52
+ assert exc.error_code == "youtube_authentication_required"
53
+ assert "youtube_authentication_required" in exc.warnings
54
+
55
+
56
+ def test_download_falls_back_without_ffmpeg_and_keeps_real_warning(tmp_path, monkeypatch) -> None:
57
+ ffmpeg_failure = DownloadAttemptFailure(
58
+ client_label="android+web",
59
+ message=(
60
+ "Postprocessing: ffprobe and ffmpeg not found. "
61
+ "Please install or provide the path using --ffmpeg-location"
62
+ ),
63
+ )
64
+
65
+ def fake_with_ffmpeg(self, url: str, video_id: str) -> DownloadAttemptResult:
66
+ return DownloadAttemptResult(info=None, failures=[ffmpeg_failure])
67
+
68
+ def fake_without_ffmpeg(self, url: str, video_id: str) -> DownloadAttemptResult:
69
+ output_file = self.output_dir / f"{video_id}.m4a"
70
+ output_file.write_bytes(b"fake audio")
71
+ return DownloadAttemptResult(
72
+ info={"ext": "m4a", "title": "Example Title", "duration": 12.5},
73
+ failures=[],
74
+ )
75
+
76
+ monkeypatch.setattr(YouTubeDownloader, "_download_with_ffmpeg", fake_with_ffmpeg)
77
+ monkeypatch.setattr(YouTubeDownloader, "_download_without_ffmpeg", fake_without_ffmpeg)
78
+
79
+ downloader = YouTubeDownloader(output_dir=tmp_path)
80
+ result = downloader.download("https://www.youtube.com/watch?v=tDN-u5gporg", "tDN-u5gporg")
81
+
82
+ assert result.audio_format == "m4a"
83
+ assert result.warnings == ["ffmpeg_unavailable"]
84
+
85
+
86
+ def test_youtube_analysis_surfaces_auth_required_error(monkeypatch) -> None:
87
+ def fake_download(self, url: str, video_id: str):
88
+ raise YouTubeDownloadError(
89
+ error_code="youtube_authentication_required",
90
+ message=_BOT_CHECK_MESSAGE,
91
+ warnings=["youtube_authentication_required"],
92
+ )
93
+
94
+ monkeypatch.setattr(YouTubeDownloader, "download", fake_download)
95
+
96
+ response = asyncio.run(
97
+ YouTubeAnalysisService().analyze(
98
+ "https://www.youtube.com/watch?v=tDN-u5gporg",
99
+ include_raw=True,
100
+ )
101
+ )
102
+
103
+ assert response.status == "partial"
104
+ assert "youtube_authentication_required" in response.errors
105
+ assert "youtube_analysis_failed" in response.errors
106
+ assert "youtube_authentication_required" in response.warnings
107
+ assert response.music_ai.error == "youtube_authentication_required"
108
+ assert response.ses_analizi.error == "youtube_authentication_required"