m3u8 0.7.1 → 0.8.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.
@@ -8,233 +8,254 @@ describe M3u8::Playlist do
8
8
  it 'initializes with defaults' do
9
9
  expect(playlist.version).to be_nil
10
10
  expect(playlist.cache).to be_nil
11
- expect(playlist.target).to be 10
12
- expect(playlist.sequence).to be 0
11
+ expect(playlist.target).to eq(10)
12
+ expect(playlist.sequence).to eq(0)
13
+ expect(playlist.discontinuity_sequence).to be_nil
13
14
  expect(playlist.type).to be_nil
14
15
  expect(playlist.iframes_only).to be false
15
16
  expect(playlist.independent_segments).to be false
16
17
  end
17
18
 
18
- it 'initializes from hash' do
19
+ it 'initializes from options' do
19
20
  options = { version: 7, cache: false, target: 12, sequence: 1,
20
- type: 'VOD', independent_segments: true }
21
- playlist = M3u8::Playlist.new(options)
22
- expect(playlist.version).to be 7
21
+ discontinuity_sequence: 2, type: 'VOD',
22
+ independent_segments: true }
23
+ playlist = described_class.new(options)
24
+ expect(playlist.version).to eq(7)
23
25
  expect(playlist.cache).to be false
24
- expect(playlist.target).to be 12
25
- expect(playlist.sequence).to be 1
26
+ expect(playlist.target).to eq(12)
27
+ expect(playlist.sequence).to eq(1)
28
+ expect(playlist.discontinuity_sequence).to eq(2)
26
29
  expect(playlist.type).to eq('VOD')
27
30
  expect(playlist.iframes_only).to be false
28
31
  expect(playlist.independent_segments).to be true
29
32
  end
33
+
34
+ it 'initializes as master playlist' do
35
+ playlist = described_class.new(master: true)
36
+ expect(playlist.master?).to be true
37
+ end
30
38
  end
31
39
 
32
- it 'should generate codecs string' do
33
- options = { profile: 'baseline', level: 3.0, audio_codec: 'aac-lc' }
34
- codecs = M3u8::Playlist.codecs options
35
- expect(codecs).to eq 'avc1.66.30,mp4a.40.2'
40
+ describe '.codecs' do
41
+ it 'generates codecs string' do
42
+ options = { profile: 'baseline', level: 3.0, audio_codec: 'aac-lc' }
43
+ codecs = described_class.codecs(options)
44
+ expect(codecs).to eq('avc1.66.30,mp4a.40.2')
45
+ end
36
46
  end
37
47
 
38
- it 'should render master playlist' do
39
- options = { uri: 'playlist_url', bandwidth: 6400,
40
- audio_codec: 'mp3' }
41
- item = M3u8::PlaylistItem.new options
42
- playlist = M3u8::Playlist.new(independent_segments: true)
43
- playlist.items << item
44
-
45
- output = "#EXTM3U\n" \
46
- "#EXT-X-INDEPENDENT-SEGMENTS\n" +
47
- %(#EXT-X-STREAM-INF:CODECS="mp4a.40.34") +
48
- ",BANDWIDTH=6400\nplaylist_url\n"
49
- expect(playlist.to_s).to eq output
50
-
51
- options = { program_id: '1', uri: 'playlist_url', bandwidth: 6400,
52
- audio_codec: 'mp3' }
53
- item = M3u8::PlaylistItem.new options
54
- playlist = M3u8::Playlist.new
55
- playlist.items << item
56
-
57
- output = "#EXTM3U\n" +
58
- %(#EXT-X-STREAM-INF:PROGRAM-ID=1,CODECS="mp4a.40.34") +
59
- ",BANDWIDTH=6400\nplaylist_url\n"
60
- expect(playlist.to_s).to eq output
61
-
62
- options = { program_id: '2', uri: 'playlist_url', bandwidth: 50_000,
63
- width: 1920, height: 1080, profile: 'high', level: 4.1,
64
- audio_codec: 'aac-lc' }
65
- item = M3u8::PlaylistItem.new options
66
- playlist = M3u8::Playlist.new
67
- playlist.items << item
68
-
69
- output = "#EXTM3U\n" \
70
- '#EXT-X-STREAM-INF:PROGRAM-ID=2,RESOLUTION=1920x1080,' +
71
- %(CODECS="avc1.640029,mp4a.40.2",BANDWIDTH=50000\n) +
72
- "playlist_url\n"
73
-
74
- expect(playlist.to_s).to eq output
75
-
76
- playlist = M3u8::Playlist.new
77
- options = { program_id: '1', uri: 'playlist_url', bandwidth: 6400,
78
- audio_codec: 'mp3' }
79
- item = M3u8::PlaylistItem.new options
80
- playlist.items << item
81
- options = { program_id: '2', uri: 'playlist_url', bandwidth: 50_000,
82
- width: 1920, height: 1080, profile: 'high', level: 4.1,
83
- audio_codec: 'aac-lc' }
84
- item = M3u8::PlaylistItem.new options
85
- playlist.items << item
86
-
87
- output = "#EXTM3U\n" +
88
- %(#EXT-X-STREAM-INF:PROGRAM-ID=1,CODECS="mp4a.40.34") +
89
- ",BANDWIDTH=6400\nplaylist_url\n#EXT-X-STREAM-INF:PROGRAM-ID=2," +
90
- %(RESOLUTION=1920x1080,CODECS="avc1.640029,mp4a.40.2") +
91
- ",BANDWIDTH=50000\nplaylist_url\n"
92
- expect(playlist.to_s).to eq output
48
+ describe '.read' do
49
+ it 'returns new playlist from content' do
50
+ file = File.open('spec/fixtures/master.m3u8')
51
+ playlist = described_class.read(file)
52
+ expect(playlist.master?).to be true
53
+ expect(playlist.items.size).to eq(8)
54
+ end
93
55
  end
94
56
 
95
- it 'should render playlist' do
96
- options = { duration: 11.344644, segment: '1080-7mbps00000.ts' }
97
- item = M3u8::SegmentItem.new(options)
98
- playlist = M3u8::Playlist.new
99
- playlist.items << item
100
-
101
- output = "#EXTM3U\n" \
102
- "#EXT-X-MEDIA-SEQUENCE:0\n" \
103
- "#EXT-X-TARGETDURATION:10\n" \
104
- "#EXTINF:11.344644,\n" \
105
- "1080-7mbps00000.ts\n" \
106
- "#EXT-X-ENDLIST\n"
107
- expect(playlist.to_s).to eq output
108
-
109
- options = { duration: 11.261233, segment: '1080-7mbps00001.ts' }
110
- item = M3u8::SegmentItem.new(options)
111
- playlist.items << item
112
-
113
- output = "#EXTM3U\n" \
114
- "#EXT-X-MEDIA-SEQUENCE:0\n" \
115
- "#EXT-X-TARGETDURATION:10\n" \
116
- "#EXTINF:11.344644,\n" \
117
- "1080-7mbps00000.ts\n" \
118
- "#EXTINF:11.261233,\n" \
119
- "1080-7mbps00001.ts\n" \
120
- "#EXT-X-ENDLIST\n"
121
- expect(playlist.to_s).to eq output
122
-
123
- options = { version: 7, cache: false, target: 12, sequence: 1,
124
- type: 'VOD' }
125
- playlist = M3u8::Playlist.new options
126
- options = { duration: 11.344644, segment: '1080-7mbps00000.ts' }
127
- item = M3u8::SegmentItem.new options
128
- playlist.items << item
129
-
130
- output = "#EXTM3U\n" \
131
- "#EXT-X-PLAYLIST-TYPE:VOD\n" \
132
- "#EXT-X-VERSION:7\n" \
133
- "#EXT-X-MEDIA-SEQUENCE:1\n" \
134
- "#EXT-X-ALLOW-CACHE:NO\n" \
135
- "#EXT-X-TARGETDURATION:12\n" \
136
- "#EXTINF:11.344644,\n" \
137
- "1080-7mbps00000.ts\n" \
138
- "#EXT-X-ENDLIST\n"
139
-
140
- expect(playlist.to_s).to eq output
57
+ describe '#duration' do
58
+ it 'should return the total duration of a playlist' do
59
+ item = M3u8::SegmentItem.new(duration: 10.991, segment: 'test_01.ts')
60
+ playlist.items << item
61
+ item = M3u8::SegmentItem.new(duration: 9.891, segment: 'test_02.ts')
62
+ playlist.items << item
63
+ item = M3u8::SegmentItem.new(duration: 10.556, segment: 'test_03.ts')
64
+ playlist.items << item
65
+ item = M3u8::SegmentItem.new(duration: 8.790, segment: 'test_04.ts')
66
+ playlist.items << item
67
+
68
+ expect(playlist.duration.round(3)).to eq(40.228)
69
+ end
141
70
  end
142
71
 
143
- it 'should write playlist to io' do
144
- test_io = StringIO.new
145
- playlist = M3u8::Playlist.new
146
- options = { program_id: '1', uri: 'playlist_url', bandwidth: 6400,
147
- audio_codec: 'mp3' }
148
- item = M3u8::PlaylistItem.new options
149
- playlist.items << item
150
- playlist.write test_io
72
+ describe '#master?' do
73
+ context 'when playlist is a master playlist' do
74
+ it 'returns true' do
75
+ options = { program_id: '1', uri: 'playlist_url', bandwidth: 6400,
76
+ audio_codec: 'mp3' }
77
+ item = M3u8::PlaylistItem.new(options)
78
+ playlist.items << item
151
79
 
152
- output = "#EXTM3U\n" +
153
- %(#EXT-X-STREAM-INF:PROGRAM-ID=1,CODECS="mp4a.40.34",) +
154
- "BANDWIDTH=6400\nplaylist_url\n"
80
+ expect(playlist.master?).to be true
81
+ end
82
+ end
155
83
 
156
- expect(test_io.string).to eq output
84
+ context 'when playlist is a media playlist' do
85
+ it 'returns false' do
86
+ item = M3u8::SegmentItem.new(duration: 10.991, segment: 'test_01.ts')
87
+ playlist.items << item
88
+ expect(playlist.master?).to be false
89
+ end
90
+ end
157
91
 
158
- test_io = StringIO.new
159
- playlist.write test_io
92
+ context 'when playlist is a new playlist' do
93
+ it 'returns false' do
94
+ expect(playlist.master?).to be false
95
+ end
96
+ end
160
97
 
161
- output = "#EXTM3U\n" +
162
- %(#EXT-X-STREAM-INF:PROGRAM-ID=1,CODECS="mp4a.40.34",) +
163
- "BANDWIDTH=6400\nplaylist_url\n"
98
+ context 'when a new playlist is set as master' do
99
+ it 'returns true' do
100
+ playlist = described_class.new(master: true)
101
+ expect(playlist.master?).to be true
102
+ end
103
+ end
164
104
 
165
- expect(test_io.string).to eq output
105
+ context 'when a new playlist is set as not master' do
106
+ it 'returns false' do
107
+ playlist = described_class.new(master: false)
108
+ expect(playlist.master?).to be false
109
+ end
110
+ end
166
111
  end
167
112
 
168
- it 'should report if it is a master playlist' do
169
- playlist = M3u8::Playlist.new
170
- expect(playlist.master?).to be false
171
- options = { program_id: '1', uri: 'playlist_url', bandwidth: 6400,
172
- audio_codec: 'mp3' }
173
- item = M3u8::PlaylistItem.new options
174
- playlist.items << item
113
+ describe '#live?' do
114
+ context 'when playlist is a master playlist' do
115
+ it 'returns false' do
116
+ options = { program_id: '1', uri: 'playlist_url', bandwidth: 6400,
117
+ audio_codec: 'mp3' }
118
+ item = M3u8::PlaylistItem.new(options)
119
+ playlist.items << item
175
120
 
176
- expect(playlist.master?).to be true
177
- end
178
-
179
- it 'should raise error on write if item types are mixed' do
180
- playlist = M3u8::Playlist.new
121
+ expect(playlist.live).to be false
122
+ end
123
+ end
181
124
 
182
- hash = { program_id: 1, width: 1920, height: 1080, codecs: 'avc',
183
- bandwidth: 540, uri: 'test.url' }
184
- item = M3u8::PlaylistItem.new(hash)
185
- playlist.items << item
125
+ context 'when playlist is a media playlist and set as live' do
126
+ it 'returns true' do
127
+ playlist = described_class.new(live: true)
128
+ item = M3u8::SegmentItem.new(duration: 10.991, segment: 'test_01.ts')
129
+ playlist.items << item
130
+ expect(playlist.live?).to be true
131
+ end
132
+ end
186
133
 
187
- hash = { duration: 10.991, segment: 'test.ts' }
188
- item = M3u8::SegmentItem.new(hash)
189
- playlist.items << item
134
+ context 'when a new playlist is set as not live' do
135
+ it 'returns false' do
136
+ playlist = described_class.new(live: false)
137
+ expect(playlist.live).to be false
138
+ end
139
+ end
190
140
 
191
- message = 'Playlist is invalid.'
192
- io = StringIO.new
193
- expect { playlist.write io }
194
- .to raise_error(M3u8::PlaylistTypeError, message)
141
+ context 'when playlist is a new playlist' do
142
+ it 'returns false' do
143
+ expect(playlist.live?).to be false
144
+ end
145
+ end
195
146
  end
196
147
 
197
- it 'should return valid status' do
198
- playlist = M3u8::Playlist.new
199
- expect(playlist.valid?).to be true
200
-
201
- hash = { program_id: 1, width: 1920, height: 1080, codecs: 'avc',
202
- bandwidth: 540, uri: 'test.url' }
203
- item = M3u8::PlaylistItem.new(hash)
204
- playlist.items << item
205
- expect(playlist.valid?).to be true
148
+ describe '#to_s' do
149
+ it 'returns master playlist text' do
150
+ options = { program_id: '1', uri: 'playlist_url', bandwidth: 6400,
151
+ audio_codec: 'mp3' }
152
+ item = M3u8::PlaylistItem.new(options)
153
+ playlist.items << item
154
+
155
+ options = { program_id: '2', uri: 'playlist_url', bandwidth: 50_000,
156
+ width: 1920, height: 1080, profile: 'high', level: 4.1,
157
+ audio_codec: 'aac-lc' }
158
+ item = M3u8::PlaylistItem.new(options)
159
+ playlist.items << item
160
+
161
+ expected = "#EXTM3U\n" +
162
+ %(#EXT-X-STREAM-INF:PROGRAM-ID=1,CODECS="mp4a.40.34") +
163
+ ",BANDWIDTH=6400\nplaylist_url\n" \
164
+ '#EXT-X-STREAM-INF:PROGRAM-ID=2,' +
165
+ %(RESOLUTION=1920x1080,CODECS="avc1.640029,mp4a.40.2") +
166
+ ",BANDWIDTH=50000\nplaylist_url\n"
167
+ expect(playlist.to_s).to eq(expected)
168
+ end
206
169
 
207
- hash = { program_id: 1, width: 1920, height: 1080, codecs: 'avc',
208
- bandwidth: 540, uri: 'test.url' }
209
- item = M3u8::PlaylistItem.new(hash)
210
- playlist.items << item
211
- expect(playlist.valid?).to be true
170
+ it 'returns media playlist text' do
171
+ options = { duration: 11.344644, segment: '1080-7mbps00000.ts' }
172
+ item = M3u8::SegmentItem.new(options)
173
+ playlist.items << item
174
+
175
+ options = { duration: 11.261233, segment: '1080-7mbps00001.ts' }
176
+ item = M3u8::SegmentItem.new(options)
177
+ playlist.items << item
178
+
179
+ expected = "#EXTM3U\n" \
180
+ "#EXT-X-MEDIA-SEQUENCE:0\n" \
181
+ "#EXT-X-TARGETDURATION:10\n" \
182
+ "#EXTINF:11.344644,\n" \
183
+ "1080-7mbps00000.ts\n" \
184
+ "#EXTINF:11.261233,\n" \
185
+ "1080-7mbps00001.ts\n" \
186
+ "#EXT-X-ENDLIST\n"
187
+ expect(playlist.to_s).to eq(expected)
188
+ end
189
+ end
212
190
 
213
- hash = { duration: 10.991, segment: 'test.ts' }
214
- item = M3u8::SegmentItem.new(hash)
215
- playlist.items << item
191
+ describe '#valid?' do
192
+ context 'when playlist is valid' do
193
+ it 'returns true' do
194
+ expect(playlist.valid?).to be true
195
+
196
+ options = { program_id: 1, width: 1920, height: 1080, codecs: 'avc',
197
+ bandwidth: 540, uri: 'test.url' }
198
+ item = M3u8::PlaylistItem.new(options)
199
+ playlist.items << item
200
+ expect(playlist.valid?).to be true
201
+
202
+ options = { program_id: 1, width: 1920, height: 1080, codecs: 'avc',
203
+ bandwidth: 540, uri: 'test.url' }
204
+ item = M3u8::PlaylistItem.new(options)
205
+ playlist.items << item
206
+ expect(playlist.valid?).to be true
207
+ end
208
+ end
216
209
 
217
- expect(playlist.valid?).to be false
210
+ context 'when playlist is invalid' do
211
+ it 'returns false' do
212
+ options = { program_id: 1, width: 1920, height: 1080, codecs: 'avc',
213
+ bandwidth: 540, uri: 'test.url' }
214
+ item = M3u8::PlaylistItem.new(options)
215
+ playlist.items << item
216
+ expect(playlist.valid?).to be true
217
+
218
+ options = { duration: 10.991, segment: 'test.ts' }
219
+ item = M3u8::SegmentItem.new(options)
220
+ playlist.items << item
221
+ expect(playlist.valid?).to be false
222
+ end
223
+ end
218
224
  end
219
225
 
220
- it 'should allow reading of playlists' do
221
- file = File.open 'spec/fixtures/master.m3u8'
222
- playlist = M3u8::Playlist.read file
223
- expect(playlist.master?).to be true
224
- expect(playlist.items.size).to eq(8)
225
- end
226
+ describe '#write' do
227
+ context 'when playlist is valid' do
228
+ it 'returns playlist text' do
229
+ options = { program_id: '1', uri: 'playlist_url', bandwidth: 6400,
230
+ audio_codec: 'mp3' }
231
+ item = M3u8::PlaylistItem.new(options)
232
+ playlist.items << item
233
+
234
+ io = StringIO.new
235
+ playlist.write(io)
236
+ expected = "#EXTM3U\n" +
237
+ %(#EXT-X-STREAM-INF:PROGRAM-ID=1,CODECS="mp4a.40.34",) +
238
+ "BANDWIDTH=6400\nplaylist_url\n"
239
+ expect(io.string).to eq(expected)
240
+ end
241
+ end
226
242
 
227
- it 'should return the total duration of a playlist' do
228
- playlist = M3u8::Playlist.new
229
- item = M3u8::SegmentItem.new(duration: 10.991, segment: 'test_01.ts')
230
- playlist.items << item
231
- item = M3u8::SegmentItem.new(duration: 9.891, segment: 'test_02.ts')
232
- playlist.items << item
233
- item = M3u8::SegmentItem.new(duration: 10.556, segment: 'test_03.ts')
234
- playlist.items << item
235
- item = M3u8::SegmentItem.new(duration: 8.790, segment: 'test_04.ts')
236
- playlist.items << item
237
-
238
- expect(playlist.duration.round(3)).to eq(40.228)
243
+ context 'when item types are invalid' do
244
+ it 'raises error' do
245
+ options = { program_id: 1, width: 1920, height: 1080, codecs: 'avc',
246
+ bandwidth: 540, uri: 'test.url' }
247
+ item = M3u8::PlaylistItem.new(options)
248
+ playlist.items << item
249
+
250
+ options = { duration: 10.991, segment: 'test.ts' }
251
+ item = M3u8::SegmentItem.new(options)
252
+ playlist.items << item
253
+
254
+ message = 'Playlist is invalid.'
255
+ io = StringIO.new
256
+ expect { playlist.write(io) }
257
+ .to raise_error(M3u8::PlaylistTypeError, message)
258
+ end
259
+ end
239
260
  end
240
261
  end
@@ -2,13 +2,15 @@
2
2
  require 'spec_helper'
3
3
 
4
4
  describe M3u8::Reader do
5
+ let(:reader) { described_class.new }
6
+
5
7
  describe '#read' do
6
- it 'should parse master playlist' do
8
+ it 'parses master playlist' do
7
9
  file = File.open('spec/fixtures/master.m3u8')
8
10
  reader = M3u8::Reader.new
9
11
  playlist = reader.read(file)
10
12
  expect(playlist.master?).to be true
11
-
13
+ expect(playlist.discontinuity_sequence).to be_nil
12
14
  expect(playlist.independent_segments).to be true
13
15
 
14
16
  item = playlist.items[0]
@@ -50,7 +52,7 @@ describe M3u8::Reader do
50
52
  expect(item.resolution).to be_nil
51
53
  end
52
54
 
53
- it 'should parse master playlist with I-Frames' do
55
+ it 'parses master playlist with I-Frames' do
54
56
  file = File.open('spec/fixtures/master_iframes.m3u8')
55
57
  reader = M3u8::Reader.new
56
58
  playlist = reader.read(file)
@@ -65,13 +67,14 @@ describe M3u8::Reader do
65
67
  expect(item.uri).to eq('low/iframe.m3u8')
66
68
  end
67
69
 
68
- it 'should parse segment playlist' do
70
+ it 'parses media playlist' do
69
71
  file = File.open('spec/fixtures/playlist.m3u8')
70
72
  reader = M3u8::Reader.new
71
73
  playlist = reader.read(file)
72
74
  expect(playlist.master?).to be false
73
75
  expect(playlist.version).to eq(4)
74
76
  expect(playlist.sequence).to eq(1)
77
+ expect(playlist.discontinuity_sequence).to eq(8)
75
78
  expect(playlist.cache).to be false
76
79
  expect(playlist.target).to eq(12)
77
80
  expect(playlist.type).to eq('VOD')
@@ -88,7 +91,7 @@ describe M3u8::Reader do
88
91
  expect(playlist.items.size).to eq(140)
89
92
  end
90
93
 
91
- it 'should parse I-Frame playlist' do
94
+ it 'parses I-Frame playlist' do
92
95
  file = File.open('spec/fixtures/iframes.m3u8')
93
96
  reader = M3u8::Reader.new
94
97
  playlist = reader.read(file)
@@ -108,7 +111,7 @@ describe M3u8::Reader do
108
111
  expect(item.byterange.start).to be_nil
109
112
  end
110
113
 
111
- it 'should parse segment playlist with comments' do
114
+ it 'parses segment playlist with comments' do
112
115
  file = File.open('spec/fixtures/playlist_with_comments.m3u8')
113
116
  reader = M3u8::Reader.new
114
117
  playlist = reader.read(file)
@@ -130,7 +133,7 @@ describe M3u8::Reader do
130
133
  expect(playlist.items.size).to eq(139)
131
134
  end
132
135
 
133
- it 'should parse variant playlist with audio options and groups' do
136
+ it 'parses variant playlist with audio options and groups' do
134
137
  file = File.open('spec/fixtures/variant_audio.m3u8')
135
138
  reader = M3u8::Reader.new
136
139
  playlist = reader.read(file)
@@ -151,7 +154,7 @@ describe M3u8::Reader do
151
154
  expect(item.forced).to be true
152
155
  end
153
156
 
154
- it 'should parse variant playlist with camera angles' do
157
+ it 'parses variant playlist with camera angles' do
155
158
  file = File.open('spec/fixtures/variant_angles.m3u8')
156
159
  reader = M3u8::Reader.new
157
160
  playlist = reader.read(file)
@@ -177,7 +180,7 @@ describe M3u8::Reader do
177
180
  expect(item.subtitles).to eq('subs')
178
181
  end
179
182
 
180
- it 'should process multiple reads as separate playlists' do
183
+ it 'processes multiple reads as separate playlists' do
181
184
  file = File.open('spec/fixtures/master.m3u8')
182
185
  reader = M3u8::Reader.new
183
186
  playlist = reader.read(file)
@@ -190,7 +193,7 @@ describe M3u8::Reader do
190
193
  expect(playlist.items.size).to eq(8)
191
194
  end
192
195
 
193
- it 'should parse playlist with session data' do
196
+ it 'parses playlist with session data' do
194
197
  file = File.open('spec/fixtures/session_data.m3u8')
195
198
  reader = M3u8::Reader.new
196
199
  playlist = reader.read(file)
@@ -203,7 +206,7 @@ describe M3u8::Reader do
203
206
  expect(item.uri).to eq('lyrics.json')
204
207
  end
205
208
 
206
- it 'should parse encrypted playlist' do
209
+ it 'parses encrypted playlist' do
207
210
  file = File.open('spec/fixtures/encrypted.m3u8')
208
211
  reader = M3u8::Reader.new
209
212
  playlist = reader.read(file)
@@ -216,7 +219,7 @@ describe M3u8::Reader do
216
219
  expect(item.uri).to eq('https://priv.example.com/key.php?r=52')
217
220
  end
218
221
 
219
- it 'should parse map (media intialization section) playlists' do
222
+ it 'parses map (media intialization section) playlists' do
220
223
  file = File.open('spec/fixtures/map_playlist.m3u8')
221
224
  reader = M3u8::Reader.new
222
225
  playlist = reader.read(file)
@@ -230,7 +233,7 @@ describe M3u8::Reader do
230
233
  expect(item.byterange.start).to eq(600)
231
234
  end
232
235
 
233
- it 'should read segment with timestamp' do
236
+ it 'reads segment with timestamp' do
234
237
  file = File.open('spec/fixtures/timestamp_playlist.m3u8')
235
238
  reader = M3u8::Reader.new
236
239
  playlist = reader.read(file)
@@ -241,18 +244,25 @@ describe M3u8::Reader do
241
244
  expect(item_date_time.time).to eq(Time.iso8601('2016-04-11T15:24:31Z'))
242
245
  end
243
246
 
244
- context 'playlist with daterange' do
245
- it 'parses playlist' do
246
- file = File.open('spec/fixtures/date_range_scte35.m3u8')
247
- reader = M3u8::Reader.new
248
- playlist = reader.read(file)
249
- expect(playlist.items.count).to eq(5)
247
+ it 'parses playlist with daterange' do
248
+ file = File.open('spec/fixtures/date_range_scte35.m3u8')
249
+ reader = M3u8::Reader.new
250
+ playlist = reader.read(file)
251
+ expect(playlist.items.count).to eq(5)
252
+
253
+ item = playlist.items[0]
254
+ expect(item).to be_a(M3u8::DateRangeItem)
250
255
 
251
- item = playlist.items[0]
252
- expect(item).to be_a(M3u8::DateRangeItem)
256
+ item = playlist.items[4]
257
+ expect(item).to be_a(M3u8::DateRangeItem)
258
+ end
253
259
 
254
- item = playlist.items[4]
255
- expect(item).to be_a(M3u8::DateRangeItem)
260
+ context 'when playlist source is invalid' do
261
+ it 'raises error with message' do
262
+ message = 'Playlist must start with a #EXTM3U tag, line read ' \
263
+ 'contained the value: /path/to/file'
264
+ expect { reader.read('/path/to/file') }
265
+ .to raise_error(M3u8::InvalidPlaylistError, message)
256
266
  end
257
267
  end
258
268
  end