11import pytest
2- import time
32from pytest_mock import MockerFixture
4- from unittest . mock import MagicMock
5- from ytfetcher .models .channel import VideoTranscript , Transcript , ChannelData
3+ from youtube_transcript_api . _errors import NoTranscriptFound
4+ from ytfetcher .models .channel import VideoTranscript , Transcript
65from ytfetcher ._transcript_fetcher import TranscriptFetcher
76from ytfetcher .config .http_config import HTTPConfig
8- from youtube_transcript_api import YouTubeTranscriptApi
9- from youtube_transcript_api ._transcripts import FetchedTranscript , FetchedTranscriptSnippet
107from youtube_transcript_api .proxies import GenericProxyConfig
118
129@pytest .fixture
@@ -46,42 +43,48 @@ def test_fetch_method_returns_correct_data(mocker: MockerFixture, mock_video_ids
4643 assert results [0 ].transcripts [0 ].text == 'text1'
4744 assert results [0 ].video_id == 'video_id'
4845
49- def test_fetch_single_returns_correct_data (mocker : MockerFixture , mock_video_ids ):
46+ def test_fetch_single_returns_correct_data (mocker , mock_video_ids ):
5047 fetcher = TranscriptFetcher (mock_video_ids )
5148
52- mocker .patch .object (YouTubeTranscriptApi , "fetch" ,
53- return_value = FetchedTranscript ([FetchedTranscriptSnippet (text = "text" , start = 1 , duration = 1 )], fetcher .video_ids [0 ], "en" , "" , True )
54- )
49+ video_id = mock_video_ids [0 ]
5550
56- results = fetcher ._fetch_single (fetcher .video_ids [0 ])
51+ mock_transcripts = [
52+ Transcript (text = "text" , start = 1 , duration = 1 )
53+ ]
5754
58- assert isinstance (results .transcripts [0 ], Transcript )
59- assert results .video_id == fetcher .video_ids [0 ]
60- assert results .transcripts [0 ] == Transcript (
61- text = 'text' ,
62- start = 1 ,
63- duration = 1
55+ mocker .patch .object (
56+ fetcher ,
57+ "_decide_fetch_method" ,
58+ return_value = mock_transcripts
6459 )
65- assert results .transcripts [0 ].text == 'text'
60+
61+ result = fetcher ._fetch_single (video_id )
62+
63+ assert isinstance (result , VideoTranscript )
64+ assert result .video_id == video_id
65+ assert result .transcripts == mock_transcripts
66+ assert result .transcripts [0 ].text == "text"
67+
6668
6769def test_concurrent_fetching (mocker , mock_video_ids ):
68- mock_fetch = mocker .patch .object (
69- YouTubeTranscriptApi ,
70- "fetch" ,
71- side_effect = lambda * args , ** kwargs : MagicMock (
72- to_raw_data = lambda : [{"text" : "test" , "start" : 0 , "duration" : 1 }]
73- )
74- )
75-
7670 fetcher = TranscriptFetcher (mock_video_ids )
77-
78- start_time = time .time ()
71+
72+ mock_result = VideoTranscript (
73+ video_id = "dummy" ,
74+ transcripts = [Transcript (text = "test" , start = 0 , duration = 1 )]
75+ )
76+
77+ mock_fetch_single = mocker .patch .object (
78+ fetcher ,
79+ "_fetch_single" ,
80+ return_value = mock_result
81+ )
82+
7983 results = fetcher .fetch ()
80- elapsed = time .time () - start_time
81-
82- assert len (results ) == 2
83- assert elapsed < 1.5
84- assert mock_fetch .call_count == 2
84+
85+ assert len (results ) == len (mock_video_ids )
86+ assert mock_fetch_single .call_count == len (mock_video_ids )
87+
8588
8689def test_custom_ytt_api_client_initialized_correctly (mocker ):
8790 mock_api = mocker .patch ("ytfetcher._transcript_fetcher.YouTubeTranscriptApi" )
@@ -117,15 +120,93 @@ def test_clean_transcripts():
117120
118121 assert cleaned_response [0 ].text == 'This is some text'
119122
120- def test_clean_transcripts_with_multiple_text ():
121- test_response = [
122- Transcript (
123- text = "[Music][Applause] and that happened!" ,
124- duration = 1 ,
125- start = 1
126- )
127- ]
123+ def test_decide_fetch_method_manual_branch (mocker ):
124+ fetcher = TranscriptFetcher (
125+ video_ids = ["abc" ],
126+ manually_created = True ,
127+ languages = ["en" ]
128+ )
128129
129- cleaned_response = TranscriptFetcher ._clean_transcripts (test_response )
130-
131- assert cleaned_response [0 ].text == 'and that happened!'
130+ mock_manual = mocker .patch .object (
131+ fetcher ,
132+ "_fetch_manual_transcript" ,
133+ return_value = ["manual" ]
134+ )
135+
136+ mock_api = mocker .MagicMock ()
137+
138+ result = fetcher ._decide_fetch_method (mock_api , "abc" )
139+
140+ assert result == ["manual" ]
141+ mock_manual .assert_called_once_with (yt_api = mock_api , video_id = "abc" )
142+
143+ def test_decide_fetch_method_first_available_branch (mocker ):
144+ fetcher = TranscriptFetcher (
145+ video_ids = ["abc" ],
146+ manually_created = False ,
147+ languages = None
148+ )
149+
150+ mock_first = mocker .patch .object (
151+ fetcher ,
152+ "_fetch_first_available_transcript" ,
153+ return_value = ["first" ]
154+ )
155+
156+ mock_api = mocker .MagicMock ()
157+
158+ result = fetcher ._decide_fetch_method (mock_api , "abc" )
159+
160+ assert result == ["first" ]
161+ mock_first .assert_called_once_with (yt_api = mock_api , video_id = "abc" )
162+
163+ def test_decide_fetch_method_by_languages_branch (mocker ):
164+ fetcher = TranscriptFetcher (
165+ video_ids = ["abc" ],
166+ manually_created = False ,
167+ languages = ["en" ]
168+ )
169+
170+ mock_lang = mocker .patch .object (
171+ fetcher ,
172+ "_fetch_by_languages" ,
173+ return_value = ["lang" ]
174+ )
175+
176+ mock_api = mocker .MagicMock ()
177+
178+ result = fetcher ._decide_fetch_method (mock_api , "abc" )
179+
180+ assert result == ["lang" ]
181+ mock_lang .assert_called_once_with (yt_api = mock_api , video_id = "abc" )
182+
183+ def test_fetch_manual_transcript_no_transcript (mocker ):
184+ video_id = "abc"
185+
186+ mock_api = mocker .MagicMock ()
187+ mock_list = mocker .MagicMock ()
188+
189+ mock_api .list .return_value = mock_list
190+ mock_list .find_manually_created_transcript .side_effect = NoTranscriptFound (video_id , requested_language_codes = ['en' ], transcript_data = None )
191+
192+ fetcher = TranscriptFetcher (
193+ video_ids = [video_id ],
194+ manually_created = True ,
195+ languages = ["en" ]
196+ )
197+
198+ result = fetcher ._fetch_manual_transcript (mock_api , video_id )
199+
200+ assert result is None
201+
202+ def test_fetch_first_available_transcript_empty (mocker ):
203+ video_id = "abc"
204+
205+ mock_api = mocker .MagicMock ()
206+ mock_api .list .return_value = []
207+
208+ fetcher = TranscriptFetcher (video_ids = [video_id ])
209+
210+ result = fetcher ._fetch_first_available_transcript (mock_api , video_id )
211+
212+ assert result is None
0 commit comments