youtube-transcript-rb 0.1.0 → 0.2.3
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +9 -0
- data/.rubocop_todo.yml +166 -0
- data/README.md +42 -42
- data/lib/youtube-transcript-rb.rb +4 -0
- data/lib/youtube_rb/formatters.rb +263 -0
- data/lib/youtube_rb/transcript/api.rb +144 -0
- data/lib/youtube_rb/transcript/errors.rb +215 -0
- data/lib/youtube_rb/transcript/settings.rb +26 -0
- data/lib/youtube_rb/transcript/transcript.rb +237 -0
- data/lib/youtube_rb/transcript/transcript_list.rb +168 -0
- data/lib/youtube_rb/transcript/transcript_list_fetcher.rb +220 -0
- data/lib/youtube_rb/transcript/transcript_parser.rb +81 -0
- data/lib/youtube_rb/transcript.rb +33 -0
- data/lib/youtube_rb/version.rb +5 -0
- data/sig/youtube_rb/transcript.rbs +4 -0
- data/spec/api_spec.rb +27 -27
- data/spec/errors_spec.rb +41 -41
- data/spec/formatters_spec.rb +45 -46
- data/spec/integration_spec.rb +39 -48
- data/spec/settings_spec.rb +16 -16
- data/spec/spec_helper.rb +52 -52
- data/spec/transcript_list_fetcher_spec.rb +38 -33
- data/spec/transcript_list_spec.rb +16 -19
- data/spec/transcript_parser_spec.rb +3 -3
- data/spec/transcript_spec.rb +23 -24
- metadata +17 -13
- data/lib/youtube/transcript/rb/api.rb +0 -150
- data/lib/youtube/transcript/rb/errors.rb +0 -217
- data/lib/youtube/transcript/rb/formatters.rb +0 -269
- data/lib/youtube/transcript/rb/settings.rb +0 -28
- data/lib/youtube/transcript/rb/transcript.rb +0 -239
- data/lib/youtube/transcript/rb/transcript_list.rb +0 -170
- data/lib/youtube/transcript/rb/transcript_list_fetcher.rb +0 -225
- data/lib/youtube/transcript/rb/transcript_parser.rb +0 -83
- data/lib/youtube/transcript/rb/version.rb +0 -9
- data/lib/youtube/transcript/rb.rb +0 -37
- data/sig/youtube/transcript/rb.rbs +0 -8
data/spec/errors_spec.rb
CHANGED
|
@@ -1,65 +1,65 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "spec_helper"
|
|
4
|
-
require "
|
|
4
|
+
require "youtube_rb/transcript"
|
|
5
5
|
|
|
6
|
-
RSpec.describe
|
|
6
|
+
RSpec.describe YoutubeRb::Transcript do
|
|
7
7
|
describe "Error hierarchy" do
|
|
8
8
|
it "has Error as the base class" do
|
|
9
|
-
expect(
|
|
9
|
+
expect(YoutubeRb::Transcript::Error).to be < StandardError
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
it "has CouldNotRetrieveTranscript inheriting from Error" do
|
|
13
|
-
expect(
|
|
13
|
+
expect(YoutubeRb::Transcript::CouldNotRetrieveTranscript).to be < YoutubeRb::Transcript::Error
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
describe "error classes inherit from CouldNotRetrieveTranscript" do
|
|
17
17
|
[
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
18
|
+
YoutubeRb::Transcript::YouTubeDataUnparsable,
|
|
19
|
+
YoutubeRb::Transcript::YouTubeRequestFailed,
|
|
20
|
+
YoutubeRb::Transcript::VideoUnplayable,
|
|
21
|
+
YoutubeRb::Transcript::VideoUnavailable,
|
|
22
|
+
YoutubeRb::Transcript::InvalidVideoId,
|
|
23
|
+
YoutubeRb::Transcript::RequestBlocked,
|
|
24
|
+
YoutubeRb::Transcript::IpBlocked,
|
|
25
|
+
YoutubeRb::Transcript::TooManyRequests,
|
|
26
|
+
YoutubeRb::Transcript::TranscriptsDisabled,
|
|
27
|
+
YoutubeRb::Transcript::AgeRestricted,
|
|
28
|
+
YoutubeRb::Transcript::NotTranslatable,
|
|
29
|
+
YoutubeRb::Transcript::TranslationLanguageNotAvailable,
|
|
30
|
+
YoutubeRb::Transcript::FailedToCreateConsentCookie,
|
|
31
|
+
YoutubeRb::Transcript::NoTranscriptFound,
|
|
32
|
+
YoutubeRb::Transcript::NoTranscriptAvailable,
|
|
33
|
+
YoutubeRb::Transcript::PoTokenRequired
|
|
34
34
|
].each do |error_class|
|
|
35
35
|
it "#{error_class} inherits from CouldNotRetrieveTranscript" do
|
|
36
|
-
expect(error_class).to be <
|
|
36
|
+
expect(error_class).to be < YoutubeRb::Transcript::CouldNotRetrieveTranscript
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
-
describe
|
|
42
|
+
describe YoutubeRb::Transcript::CouldNotRetrieveTranscript do
|
|
43
43
|
let(:video_id) { "test_video_123" }
|
|
44
44
|
|
|
45
45
|
it "stores the video_id" do
|
|
46
46
|
# Using a subclass since CouldNotRetrieveTranscript needs CAUSE_MESSAGE
|
|
47
|
-
error =
|
|
47
|
+
error = YoutubeRb::Transcript::VideoUnavailable.new(video_id)
|
|
48
48
|
expect(error.video_id).to eq(video_id)
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
it "includes video URL in error message" do
|
|
52
|
-
error =
|
|
52
|
+
error = YoutubeRb::Transcript::VideoUnavailable.new(video_id)
|
|
53
53
|
expect(error.message).to include("https://www.youtube.com/watch?v=#{video_id}")
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
it "includes cause message in error message" do
|
|
57
|
-
error =
|
|
57
|
+
error = YoutubeRb::Transcript::VideoUnavailable.new(video_id)
|
|
58
58
|
expect(error.message).to include("The video is no longer available")
|
|
59
59
|
end
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
-
describe
|
|
62
|
+
describe YoutubeRb::Transcript::VideoUnavailable do
|
|
63
63
|
let(:video_id) { "unavailable_video" }
|
|
64
64
|
let(:error) { described_class.new(video_id) }
|
|
65
65
|
|
|
@@ -68,7 +68,7 @@ RSpec.describe Youtube::Transcript::Rb do
|
|
|
68
68
|
end
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
-
describe
|
|
71
|
+
describe YoutubeRb::Transcript::TranscriptsDisabled do
|
|
72
72
|
let(:video_id) { "disabled_video" }
|
|
73
73
|
let(:error) { described_class.new(video_id) }
|
|
74
74
|
|
|
@@ -77,7 +77,7 @@ RSpec.describe Youtube::Transcript::Rb do
|
|
|
77
77
|
end
|
|
78
78
|
end
|
|
79
79
|
|
|
80
|
-
describe
|
|
80
|
+
describe YoutubeRb::Transcript::TooManyRequests do
|
|
81
81
|
let(:video_id) { "rate_limited" }
|
|
82
82
|
let(:error) { described_class.new(video_id) }
|
|
83
83
|
|
|
@@ -86,7 +86,7 @@ RSpec.describe Youtube::Transcript::Rb do
|
|
|
86
86
|
end
|
|
87
87
|
end
|
|
88
88
|
|
|
89
|
-
describe
|
|
89
|
+
describe YoutubeRb::Transcript::PoTokenRequired do
|
|
90
90
|
let(:video_id) { "po_token_video" }
|
|
91
91
|
let(:error) { described_class.new(video_id) }
|
|
92
92
|
|
|
@@ -95,7 +95,7 @@ RSpec.describe Youtube::Transcript::Rb do
|
|
|
95
95
|
end
|
|
96
96
|
end
|
|
97
97
|
|
|
98
|
-
describe
|
|
98
|
+
describe YoutubeRb::Transcript::InvalidVideoId do
|
|
99
99
|
let(:video_id) { "https://www.youtube.com/watch?v=1234" }
|
|
100
100
|
let(:error) { described_class.new(video_id) }
|
|
101
101
|
|
|
@@ -105,7 +105,7 @@ RSpec.describe Youtube::Transcript::Rb do
|
|
|
105
105
|
end
|
|
106
106
|
end
|
|
107
107
|
|
|
108
|
-
describe
|
|
108
|
+
describe YoutubeRb::Transcript::YouTubeRequestFailed do
|
|
109
109
|
let(:video_id) { "failed_request" }
|
|
110
110
|
let(:http_error) { StandardError.new("Connection refused") }
|
|
111
111
|
let(:error) { described_class.new(video_id, http_error) }
|
|
@@ -119,7 +119,7 @@ RSpec.describe Youtube::Transcript::Rb do
|
|
|
119
119
|
end
|
|
120
120
|
end
|
|
121
121
|
|
|
122
|
-
describe
|
|
122
|
+
describe YoutubeRb::Transcript::VideoUnplayable do
|
|
123
123
|
let(:video_id) { "unplayable_video" }
|
|
124
124
|
|
|
125
125
|
context "with reason only" do
|
|
@@ -157,14 +157,14 @@ RSpec.describe Youtube::Transcript::Rb do
|
|
|
157
157
|
end
|
|
158
158
|
end
|
|
159
159
|
|
|
160
|
-
describe
|
|
160
|
+
describe YoutubeRb::Transcript::NoTranscriptFound do
|
|
161
161
|
let(:video_id) { "no_transcript" }
|
|
162
|
-
let(:requested_languages) { [
|
|
162
|
+
let(:requested_languages) { %w[ko ja] }
|
|
163
163
|
let(:transcript_data) { double("TranscriptList", to_s: "Available: en, es") }
|
|
164
164
|
let(:error) { described_class.new(video_id, requested_languages, transcript_data) }
|
|
165
165
|
|
|
166
166
|
it "stores requested_language_codes" do
|
|
167
|
-
expect(error.requested_language_codes).to eq([
|
|
167
|
+
expect(error.requested_language_codes).to eq(%w[ko ja])
|
|
168
168
|
end
|
|
169
169
|
|
|
170
170
|
it "stores transcript_data" do
|
|
@@ -181,7 +181,7 @@ RSpec.describe Youtube::Transcript::Rb do
|
|
|
181
181
|
end
|
|
182
182
|
end
|
|
183
183
|
|
|
184
|
-
describe
|
|
184
|
+
describe YoutubeRb::Transcript::RequestBlocked do
|
|
185
185
|
let(:video_id) { "blocked_video" }
|
|
186
186
|
let(:error) { described_class.new(video_id) }
|
|
187
187
|
|
|
@@ -194,12 +194,12 @@ RSpec.describe Youtube::Transcript::Rb do
|
|
|
194
194
|
end
|
|
195
195
|
end
|
|
196
196
|
|
|
197
|
-
describe
|
|
197
|
+
describe YoutubeRb::Transcript::IpBlocked do
|
|
198
198
|
let(:video_id) { "ip_blocked" }
|
|
199
199
|
let(:error) { described_class.new(video_id) }
|
|
200
200
|
|
|
201
201
|
it "inherits from RequestBlocked" do
|
|
202
|
-
expect(described_class).to be <
|
|
202
|
+
expect(described_class).to be < YoutubeRb::Transcript::RequestBlocked
|
|
203
203
|
end
|
|
204
204
|
|
|
205
205
|
it "mentions IP or proxies as workaround" do
|
|
@@ -207,7 +207,7 @@ RSpec.describe Youtube::Transcript::Rb do
|
|
|
207
207
|
end
|
|
208
208
|
end
|
|
209
209
|
|
|
210
|
-
describe
|
|
210
|
+
describe YoutubeRb::Transcript::AgeRestricted do
|
|
211
211
|
let(:video_id) { "age_restricted" }
|
|
212
212
|
let(:error) { described_class.new(video_id) }
|
|
213
213
|
|
|
@@ -220,7 +220,7 @@ RSpec.describe Youtube::Transcript::Rb do
|
|
|
220
220
|
end
|
|
221
221
|
end
|
|
222
222
|
|
|
223
|
-
describe
|
|
223
|
+
describe YoutubeRb::Transcript::NotTranslatable do
|
|
224
224
|
let(:video_id) { "not_translatable" }
|
|
225
225
|
let(:error) { described_class.new(video_id) }
|
|
226
226
|
|
|
@@ -229,7 +229,7 @@ RSpec.describe Youtube::Transcript::Rb do
|
|
|
229
229
|
end
|
|
230
230
|
end
|
|
231
231
|
|
|
232
|
-
describe
|
|
232
|
+
describe YoutubeRb::Transcript::TranslationLanguageNotAvailable do
|
|
233
233
|
let(:video_id) { "translation_unavailable" }
|
|
234
234
|
let(:error) { described_class.new(video_id) }
|
|
235
235
|
|
data/spec/formatters_spec.rb
CHANGED
|
@@ -2,16 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
require "spec_helper"
|
|
4
4
|
|
|
5
|
-
RSpec.describe
|
|
5
|
+
RSpec.describe YoutubeRb::Formatters do
|
|
6
6
|
# Helper to create a FetchedTranscript with snippets
|
|
7
|
-
def create_transcript(video_id: "test123", language: "English", language_code: "en", is_generated: false,
|
|
7
|
+
def create_transcript(video_id: "test123", language: "English", language_code: "en", is_generated: false,
|
|
8
|
+
snippets: nil)
|
|
8
9
|
snippets ||= [
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
YoutubeRb::Transcript::TranscriptSnippet.new(text: "Hello world", start: 0.0, duration: 2.5),
|
|
11
|
+
YoutubeRb::Transcript::TranscriptSnippet.new(text: "This is a test", start: 2.5, duration: 3.0),
|
|
12
|
+
YoutubeRb::Transcript::TranscriptSnippet.new(text: "Thank you", start: 5.5, duration: 2.0)
|
|
12
13
|
]
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
YoutubeRb::Transcript::FetchedTranscript.new(
|
|
15
16
|
video_id: video_id,
|
|
16
17
|
language: language,
|
|
17
18
|
language_code: language_code,
|
|
@@ -24,7 +25,7 @@ RSpec.describe Youtube::Transcript::Rb::Formatters do
|
|
|
24
25
|
let(:transcript2) { create_transcript(video_id: "video2", language_code: "es", language: "Spanish") }
|
|
25
26
|
let(:transcripts) { [transcript, transcript2] }
|
|
26
27
|
|
|
27
|
-
describe
|
|
28
|
+
describe YoutubeRb::Formatters::Formatter do
|
|
28
29
|
let(:formatter) { described_class.new }
|
|
29
30
|
|
|
30
31
|
describe "#format_transcript" do
|
|
@@ -40,7 +41,7 @@ RSpec.describe Youtube::Transcript::Rb::Formatters do
|
|
|
40
41
|
end
|
|
41
42
|
end
|
|
42
43
|
|
|
43
|
-
describe
|
|
44
|
+
describe YoutubeRb::Formatters::JSONFormatter do
|
|
44
45
|
let(:formatter) { described_class.new }
|
|
45
46
|
|
|
46
47
|
describe "#format_transcript" do
|
|
@@ -88,7 +89,7 @@ RSpec.describe Youtube::Transcript::Rb::Formatters do
|
|
|
88
89
|
end
|
|
89
90
|
end
|
|
90
91
|
|
|
91
|
-
describe
|
|
92
|
+
describe YoutubeRb::Formatters::TextFormatter do
|
|
92
93
|
let(:formatter) { described_class.new }
|
|
93
94
|
|
|
94
95
|
describe "#format_transcript" do
|
|
@@ -118,7 +119,7 @@ RSpec.describe Youtube::Transcript::Rb::Formatters do
|
|
|
118
119
|
end
|
|
119
120
|
end
|
|
120
121
|
|
|
121
|
-
describe
|
|
122
|
+
describe YoutubeRb::Formatters::PrettyPrintFormatter do
|
|
122
123
|
let(:formatter) { described_class.new }
|
|
123
124
|
|
|
124
125
|
describe "#format_transcript" do
|
|
@@ -156,7 +157,7 @@ RSpec.describe Youtube::Transcript::Rb::Formatters do
|
|
|
156
157
|
end
|
|
157
158
|
end
|
|
158
159
|
|
|
159
|
-
describe
|
|
160
|
+
describe YoutubeRb::Formatters::SRTFormatter do
|
|
160
161
|
let(:formatter) { described_class.new }
|
|
161
162
|
|
|
162
163
|
describe "#format_transcript" do
|
|
@@ -205,7 +206,7 @@ RSpec.describe Youtube::Transcript::Rb::Formatters do
|
|
|
205
206
|
describe "timestamp edge cases" do
|
|
206
207
|
it "handles hours correctly" do
|
|
207
208
|
snippets = [
|
|
208
|
-
|
|
209
|
+
YoutubeRb::Transcript::TranscriptSnippet.new(text: "Long video", start: 3661.5, duration: 2.0)
|
|
209
210
|
]
|
|
210
211
|
transcript = create_transcript(snippets: snippets)
|
|
211
212
|
result = formatter.format_transcript(transcript)
|
|
@@ -215,8 +216,8 @@ RSpec.describe Youtube::Transcript::Rb::Formatters do
|
|
|
215
216
|
|
|
216
217
|
it "handles overlapping timestamps" do
|
|
217
218
|
snippets = [
|
|
218
|
-
|
|
219
|
-
|
|
219
|
+
YoutubeRb::Transcript::TranscriptSnippet.new(text: "First", start: 0.0, duration: 5.0),
|
|
220
|
+
YoutubeRb::Transcript::TranscriptSnippet.new(text: "Second", start: 2.0, duration: 3.0)
|
|
220
221
|
]
|
|
221
222
|
transcript = create_transcript(snippets: snippets)
|
|
222
223
|
result = formatter.format_transcript(transcript)
|
|
@@ -227,7 +228,7 @@ RSpec.describe Youtube::Transcript::Rb::Formatters do
|
|
|
227
228
|
end
|
|
228
229
|
end
|
|
229
230
|
|
|
230
|
-
describe
|
|
231
|
+
describe YoutubeRb::Formatters::WebVTTFormatter do
|
|
231
232
|
let(:formatter) { described_class.new }
|
|
232
233
|
|
|
233
234
|
describe "#format_transcript" do
|
|
@@ -251,7 +252,7 @@ RSpec.describe Youtube::Transcript::Rb::Formatters do
|
|
|
251
252
|
lines = result.split("\n")
|
|
252
253
|
# Skip WEBVTT header
|
|
253
254
|
timestamp_lines = lines.select { |l| l.include?("-->") }
|
|
254
|
-
timestamp_lines.each_with_index do |line,
|
|
255
|
+
timestamp_lines.each_with_index do |line, _i|
|
|
255
256
|
prev_line = lines[lines.index(line) - 1]
|
|
256
257
|
# Previous line should be empty or WEBVTT, not a number
|
|
257
258
|
expect(prev_line).not_to match(/^\d+$/)
|
|
@@ -272,7 +273,7 @@ RSpec.describe Youtube::Transcript::Rb::Formatters do
|
|
|
272
273
|
describe "timestamp edge cases" do
|
|
273
274
|
it "handles hours correctly" do
|
|
274
275
|
snippets = [
|
|
275
|
-
|
|
276
|
+
YoutubeRb::Transcript::TranscriptSnippet.new(text: "Long video", start: 3661.5, duration: 2.0)
|
|
276
277
|
]
|
|
277
278
|
transcript = create_transcript(snippets: snippets)
|
|
278
279
|
result = formatter.format_transcript(transcript)
|
|
@@ -282,61 +283,59 @@ RSpec.describe Youtube::Transcript::Rb::Formatters do
|
|
|
282
283
|
end
|
|
283
284
|
end
|
|
284
285
|
|
|
285
|
-
describe
|
|
286
|
+
describe YoutubeRb::Formatters::FormatterLoader do
|
|
286
287
|
let(:loader) { described_class.new }
|
|
287
288
|
|
|
288
289
|
describe "#load" do
|
|
289
290
|
it "loads JSONFormatter for 'json'" do
|
|
290
291
|
formatter = loader.load("json")
|
|
291
|
-
expect(formatter).to be_a(
|
|
292
|
+
expect(formatter).to be_a(YoutubeRb::Formatters::JSONFormatter)
|
|
292
293
|
end
|
|
293
294
|
|
|
294
295
|
it "loads TextFormatter for 'text'" do
|
|
295
296
|
formatter = loader.load("text")
|
|
296
|
-
expect(formatter).to be_a(
|
|
297
|
+
expect(formatter).to be_a(YoutubeRb::Formatters::TextFormatter)
|
|
297
298
|
end
|
|
298
299
|
|
|
299
300
|
it "loads PrettyPrintFormatter for 'pretty'" do
|
|
300
301
|
formatter = loader.load("pretty")
|
|
301
|
-
expect(formatter).to be_a(
|
|
302
|
+
expect(formatter).to be_a(YoutubeRb::Formatters::PrettyPrintFormatter)
|
|
302
303
|
end
|
|
303
304
|
|
|
304
305
|
it "loads SRTFormatter for 'srt'" do
|
|
305
306
|
formatter = loader.load("srt")
|
|
306
|
-
expect(formatter).to be_a(
|
|
307
|
+
expect(formatter).to be_a(YoutubeRb::Formatters::SRTFormatter)
|
|
307
308
|
end
|
|
308
309
|
|
|
309
310
|
it "loads WebVTTFormatter for 'webvtt'" do
|
|
310
311
|
formatter = loader.load("webvtt")
|
|
311
|
-
expect(formatter).to be_a(
|
|
312
|
+
expect(formatter).to be_a(YoutubeRb::Formatters::WebVTTFormatter)
|
|
312
313
|
end
|
|
313
314
|
|
|
314
315
|
it "defaults to PrettyPrintFormatter" do
|
|
315
316
|
formatter = loader.load
|
|
316
|
-
expect(formatter).to be_a(
|
|
317
|
+
expect(formatter).to be_a(YoutubeRb::Formatters::PrettyPrintFormatter)
|
|
317
318
|
end
|
|
318
319
|
|
|
319
320
|
it "accepts symbol as formatter type" do
|
|
320
321
|
formatter = loader.load(:json)
|
|
321
|
-
expect(formatter).to be_a(
|
|
322
|
+
expect(formatter).to be_a(YoutubeRb::Formatters::JSONFormatter)
|
|
322
323
|
end
|
|
323
324
|
|
|
324
325
|
it "raises UnknownFormatterType for invalid type" do
|
|
325
326
|
expect { loader.load("invalid") }.to raise_error(
|
|
326
|
-
|
|
327
|
+
YoutubeRb::Formatters::FormatterLoader::UnknownFormatterType
|
|
327
328
|
)
|
|
328
329
|
end
|
|
329
330
|
|
|
330
331
|
it "includes available formats in error message" do
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
expect(e.message).to include("pretty")
|
|
339
|
-
end
|
|
332
|
+
loader.load("invalid")
|
|
333
|
+
rescue YoutubeRb::Formatters::FormatterLoader::UnknownFormatterType => e
|
|
334
|
+
expect(e.message).to include("json")
|
|
335
|
+
expect(e.message).to include("text")
|
|
336
|
+
expect(e.message).to include("srt")
|
|
337
|
+
expect(e.message).to include("webvtt")
|
|
338
|
+
expect(e.message).to include("pretty")
|
|
340
339
|
end
|
|
341
340
|
end
|
|
342
341
|
|
|
@@ -352,7 +351,7 @@ RSpec.describe Youtube::Transcript::Rb::Formatters do
|
|
|
352
351
|
end
|
|
353
352
|
|
|
354
353
|
describe "integration tests" do
|
|
355
|
-
let(:loader) {
|
|
354
|
+
let(:loader) { YoutubeRb::Formatters::FormatterLoader.new }
|
|
356
355
|
|
|
357
356
|
it "can format transcript with each formatter type" do
|
|
358
357
|
%w[json text pretty srt webvtt].each do |type|
|
|
@@ -378,25 +377,25 @@ RSpec.describe Youtube::Transcript::Rb::Formatters do
|
|
|
378
377
|
let(:empty_transcript) { create_transcript(snippets: empty_snippets) }
|
|
379
378
|
|
|
380
379
|
it "JSONFormatter handles empty transcript" do
|
|
381
|
-
formatter =
|
|
380
|
+
formatter = YoutubeRb::Formatters::JSONFormatter.new
|
|
382
381
|
result = formatter.format_transcript(empty_transcript)
|
|
383
382
|
expect(JSON.parse(result)).to eq([])
|
|
384
383
|
end
|
|
385
384
|
|
|
386
385
|
it "TextFormatter handles empty transcript" do
|
|
387
|
-
formatter =
|
|
386
|
+
formatter = YoutubeRb::Formatters::TextFormatter.new
|
|
388
387
|
result = formatter.format_transcript(empty_transcript)
|
|
389
388
|
expect(result).to eq("")
|
|
390
389
|
end
|
|
391
390
|
|
|
392
391
|
it "SRTFormatter handles empty transcript" do
|
|
393
|
-
formatter =
|
|
392
|
+
formatter = YoutubeRb::Formatters::SRTFormatter.new
|
|
394
393
|
result = formatter.format_transcript(empty_transcript)
|
|
395
394
|
expect(result).to eq("\n")
|
|
396
395
|
end
|
|
397
396
|
|
|
398
397
|
it "WebVTTFormatter handles empty transcript" do
|
|
399
|
-
formatter =
|
|
398
|
+
formatter = YoutubeRb::Formatters::WebVTTFormatter.new
|
|
400
399
|
result = formatter.format_transcript(empty_transcript)
|
|
401
400
|
expect(result).to eq("WEBVTT\n\n\n")
|
|
402
401
|
end
|
|
@@ -405,15 +404,15 @@ RSpec.describe Youtube::Transcript::Rb::Formatters do
|
|
|
405
404
|
describe "special character handling" do
|
|
406
405
|
let(:special_snippets) do
|
|
407
406
|
[
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
407
|
+
YoutubeRb::Transcript::TranscriptSnippet.new(text: "Hello <b>world</b>", start: 0.0, duration: 2.0),
|
|
408
|
+
YoutubeRb::Transcript::TranscriptSnippet.new(text: 'Quote: "test"', start: 2.0, duration: 2.0),
|
|
409
|
+
YoutubeRb::Transcript::TranscriptSnippet.new(text: "Line1\nLine2", start: 4.0, duration: 2.0)
|
|
411
410
|
]
|
|
412
411
|
end
|
|
413
412
|
let(:special_transcript) { create_transcript(snippets: special_snippets) }
|
|
414
413
|
|
|
415
414
|
it "JSONFormatter escapes special characters" do
|
|
416
|
-
formatter =
|
|
415
|
+
formatter = YoutubeRb::Formatters::JSONFormatter.new
|
|
417
416
|
result = formatter.format_transcript(special_transcript)
|
|
418
417
|
parsed = JSON.parse(result)
|
|
419
418
|
expect(parsed[0]["text"]).to eq("Hello <b>world</b>")
|
|
@@ -421,14 +420,14 @@ RSpec.describe Youtube::Transcript::Rb::Formatters do
|
|
|
421
420
|
end
|
|
422
421
|
|
|
423
422
|
it "TextFormatter preserves special characters" do
|
|
424
|
-
formatter =
|
|
423
|
+
formatter = YoutubeRb::Formatters::TextFormatter.new
|
|
425
424
|
result = formatter.format_transcript(special_transcript)
|
|
426
425
|
expect(result).to include("<b>world</b>")
|
|
427
426
|
expect(result).to include('"test"')
|
|
428
427
|
end
|
|
429
428
|
|
|
430
429
|
it "SRTFormatter preserves HTML tags in text" do
|
|
431
|
-
formatter =
|
|
430
|
+
formatter = YoutubeRb::Formatters::SRTFormatter.new
|
|
432
431
|
result = formatter.format_transcript(special_transcript)
|
|
433
432
|
expect(result).to include("<b>world</b>")
|
|
434
433
|
end
|