m3u8 0.7.1 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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