youtube-rb 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,216 @@
1
+ # Mocked download tests based on real YouTube responses
2
+ # These tests use real response data but don't require internet connection
3
+
4
+ RSpec.describe "Download with mocks" do
5
+ let(:output_dir) { './spec/tmp/mocked_downloads' }
6
+ let(:rickroll_url) { 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' }
7
+ let(:rickroll_id) { 'dQw4w9WgXcQ' }
8
+
9
+ # Load real response data
10
+ let(:rickroll_info) { JSON.parse(File.read('./spec/fixtures/rickroll_full_info.json', encoding: 'UTF-8')) }
11
+ let(:segment_info) { JSON.parse(File.read('./spec/fixtures/rickroll_segment_info.json', encoding: 'UTF-8')) }
12
+
13
+ before(:each) do
14
+ FileUtils.mkdir_p(output_dir)
15
+
16
+ # Mock the Extractor to return real data
17
+ allow_any_instance_of(YoutubeRb::Extractor).to receive(:extract_info) do
18
+ YoutubeRb::VideoInfo.new(rickroll_info)
19
+ end
20
+ end
21
+
22
+ after(:each) do
23
+ FileUtils.rm_rf(output_dir) if Dir.exist?(output_dir)
24
+ end
25
+
26
+ describe "video information extraction" do
27
+ it "extracts full video information" do
28
+ client = YoutubeRb::Client.new
29
+ info = client.info(rickroll_url)
30
+
31
+ # Verify using real data from successful download
32
+ expect(info).to be_a(YoutubeRb::VideoInfo)
33
+ expect(info.id).to eq('dQw4w9WgXcQ')
34
+ expect(info.title).to eq('Rick Astley - Never Gonna Give You Up (Official Video) (4K Remaster)')
35
+ expect(info.duration).to eq(213)
36
+ expect(info.uploader).to eq('Rick Astley')
37
+ expect(info.view_count).to be > 1_700_000_000
38
+ end
39
+
40
+ it "returns correct duration format" do
41
+ client = YoutubeRb::Client.new
42
+ info = client.info(rickroll_url)
43
+
44
+ expect(info.duration_formatted).to eq('03:33')
45
+ end
46
+
47
+ it "has valid formats" do
48
+ client = YoutubeRb::Client.new
49
+ info = client.info(rickroll_url)
50
+
51
+ expect(info.formats).to be_an(Array)
52
+ expect(info.formats).not_to be_empty
53
+
54
+ # Check first format has required fields (keys can be strings or symbols)
55
+ first_format = info.formats.first
56
+ expect(first_format).to have_key(:format_id).or have_key('format_id')
57
+ expect(first_format).to have_key(:url).or have_key('url')
58
+ expect(first_format).to have_key(:ext).or have_key('ext')
59
+ end
60
+ end
61
+
62
+ describe "video download" do
63
+ it "downloads video with correct parameters" do
64
+ # Mock YtdlpWrapper to simulate successful download
65
+ allow_any_instance_of(YoutubeRb::YtdlpWrapper).to receive(:download) do |_instance, url|
66
+ # Create a fake video file
67
+ output_file = File.join(output_dir, "Rick Astley - Never Gonna Give You Up (Official Video) (4K Remaster)-dQw4w9WgXcQ.webm")
68
+ File.write(output_file, "fake video data" * 1000)
69
+ output_file
70
+ end
71
+
72
+ client = YoutubeRb::Client.new(
73
+ output_path: output_dir,
74
+ use_ytdlp: true
75
+ )
76
+
77
+ output_file = client.download(rickroll_url)
78
+
79
+ expect(output_file).to be_a(String)
80
+ expect(File.exist?(output_file)).to be true
81
+ expect(File.size(output_file)).to be > 0
82
+ end
83
+ end
84
+
85
+ describe "video segment download" do
86
+ let(:start_time) { 10 }
87
+ let(:end_time) { 25 }
88
+
89
+ it "downloads segment with correct parameters" do
90
+ # Mock YtdlpWrapper for segment download
91
+ allow_any_instance_of(YoutubeRb::YtdlpWrapper).to receive(:download_segment) do |_instance, url, s_time, e_time, output|
92
+ expect(url).to eq(rickroll_url)
93
+ expect(s_time).to eq(start_time)
94
+ expect(e_time).to eq(end_time)
95
+ expect(e_time - s_time).to eq(15)
96
+
97
+ # Create a fake segment file with realistic size (14.5MB from real download)
98
+ output_file = File.join(output_dir, "#{segment_info['output_file']}")
99
+ File.write(output_file, "fake segment data" * 1000)
100
+ output_file
101
+ end
102
+
103
+ client = YoutubeRb::Client.new(
104
+ output_path: output_dir,
105
+ use_ytdlp: true
106
+ )
107
+
108
+ output_file = client.download_segment(rickroll_url, start_time, end_time)
109
+
110
+ expect(output_file).to be_a(String)
111
+ expect(File.exist?(output_file)).to be true
112
+ expect(File.basename(output_file)).to include('Rick Astley')
113
+ end
114
+
115
+ it "validates segment duration constraints" do
116
+ client = YoutubeRb::Client.new(output_path: output_dir)
117
+
118
+ # Too short
119
+ expect {
120
+ client.download_segment(rickroll_url, 0, 5)
121
+ }.to raise_error(ArgumentError, /10 and 60 seconds/)
122
+
123
+ # Too long
124
+ expect {
125
+ client.download_segment(rickroll_url, 0, 65)
126
+ }.to raise_error(ArgumentError, /10 and 60 seconds/)
127
+
128
+ # Invalid range
129
+ expect {
130
+ client.download_segment(rickroll_url, 25, 10)
131
+ }.to raise_error(ArgumentError, /Start time must be less/)
132
+ end
133
+
134
+ it "calculates correct segment duration" do
135
+ expected_duration = end_time - start_time
136
+ expect(expected_duration).to eq(15)
137
+ expect(expected_duration).to be_between(10, 60)
138
+ end
139
+ end
140
+
141
+ describe "fallback mechanism" do
142
+ it "tries pure Ruby first when fallback enabled" do
143
+ skip "Complex integration test - covered by real_download_spec.rb"
144
+
145
+ # This test would require complex HTTP mocking for fallback behavior
146
+ # It's better tested in real_download_spec.rb with actual downloads
147
+ end
148
+
149
+ it "respects use_ytdlp: true option" do
150
+ tried_ytdlp = false
151
+
152
+ allow_any_instance_of(YoutubeRb::YtdlpWrapper).to receive(:download) do
153
+ tried_ytdlp = true
154
+ output_file = File.join(output_dir, "video.webm")
155
+ File.write(output_file, "fake data")
156
+ output_file
157
+ end
158
+
159
+ client = YoutubeRb::Client.new(
160
+ output_path: output_dir,
161
+ use_ytdlp: true
162
+ )
163
+
164
+ client.download(rickroll_url)
165
+
166
+ expect(tried_ytdlp).to be true
167
+ end
168
+ end
169
+
170
+ describe "error handling" do
171
+ it "raises DownloadError for invalid video" do
172
+ allow_any_instance_of(YoutubeRb::YtdlpWrapper).to receive(:download) do
173
+ raise YoutubeRb::YtdlpWrapper::YtdlpError, "Video unavailable"
174
+ end
175
+
176
+ allow_any_instance_of(YoutubeRb::Extractor).to receive(:extract_info) do
177
+ raise YoutubeRb::Extractor::ExtractionError, "Failed to extract"
178
+ end
179
+
180
+ client = YoutubeRb::Client.new(
181
+ output_path: output_dir,
182
+ use_ytdlp: true,
183
+ ytdlp_fallback: false
184
+ )
185
+
186
+ expect {
187
+ client.download('https://www.youtube.com/watch?v=invalid')
188
+ }.to raise_error(YoutubeRb::Downloader::DownloadError)
189
+ end
190
+
191
+ it "handles network errors" do
192
+ skip "Complex mock interaction - network errors are properly tested in unit tests"
193
+
194
+ # Network error handling is tested extensively in client_spec and downloader_spec
195
+ # This integration test would require complex mock reset logic
196
+ end
197
+ end
198
+
199
+ describe "real data validation" do
200
+ it "uses data from actual successful download" do
201
+ # These are the actual values from real download test
202
+ expect(rickroll_info['id']).to eq('dQw4w9WgXcQ')
203
+ expect(rickroll_info['duration']).to eq(213)
204
+ expect(rickroll_info['title']).to include('Never Gonna Give You Up')
205
+ expect(rickroll_info['uploader']).to eq('Rick Astley')
206
+ end
207
+
208
+ it "segment info matches real download" do
209
+ expect(segment_info['video_id']).to eq('dQw4w9WgXcQ')
210
+ expect(segment_info['start_time']).to eq(10)
211
+ expect(segment_info['end_time']).to eq(25)
212
+ expect(segment_info['duration']).to eq(15)
213
+ expect(segment_info['file_size']).to be > 14_000_000 # ~14.5 MB from real download
214
+ end
215
+ end
216
+ end