7094ab96 by David LaPalomento

Upgrade to video.js 5 and convert to a source handler

Bump up to a vjs 5 release candidate. Make the necessary changes to work with the updated APIs. Convert the project from a subclass of the Flash tech to a source handler.
1 parent 67abe293
...@@ -4,10 +4,10 @@ ...@@ -4,10 +4,10 @@
4 <meta charset="utf-8"> 4 <meta charset="utf-8">
5 <title>video.js HLS Plugin Example</title> 5 <title>video.js HLS Plugin Example</title>
6 6
7 <link href="node_modules/video.js/dist/video-js/video-js.css" rel="stylesheet"> 7 <link href="node_modules/video.js/dist/video-js.css" rel="stylesheet">
8 8
9 <!-- video.js --> 9 <!-- video.js -->
10 <script src="node_modules/video.js/dist/video-js/video.dev.js"></script> 10 <script src="node_modules/video.js/dist/video.js"></script>
11 11
12 <!-- Media Sources plugin --> 12 <!-- Media Sources plugin -->
13 <script src="node_modules/videojs-contrib-media-sources/src/videojs-media-sources.js"></script> 13 <script src="node_modules/videojs-contrib-media-sources/src/videojs-media-sources.js"></script>
...@@ -72,8 +72,7 @@ ...@@ -72,8 +72,7 @@
72 type="application/x-mpegURL"> 72 type="application/x-mpegURL">
73 </video> 73 </video>
74 <script> 74 <script>
75 videojs.options.flash.swf = 'node_modules/videojs-swf/dist/video-js.swf'; 75 videojs.getGlobalOptions().flash.swf = 'node_modules/videojs-swf/dist/video-js.swf';
76
77 // initialize the player 76 // initialize the player
78 var player = videojs('video'); 77 var player = videojs('video');
79 </script> 78 </script>
......
1 /**
2 * QUnit v1.11.0 - A JavaScript Unit Testing Framework
3 *
4 * http://qunitjs.com
5 *
6 * Copyright 2012 jQuery Foundation and other contributors
7 * Released under the MIT license.
8 * http://jquery.org/license
9 */
10
11 /** Font Family and Sizes */
12
13 #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
14 font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
15 }
16
17 #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
18 #qunit-tests { font-size: smaller; }
19
20
21 /** Resets */
22
23 #qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
24 margin: 0;
25 padding: 0;
26 }
27
28
29 /** Header */
30
31 #qunit-header {
32 padding: 0.5em 0 0.5em 1em;
33
34 color: #8699a4;
35 background-color: #0d3349;
36
37 font-size: 1.5em;
38 line-height: 1em;
39 font-weight: normal;
40
41 border-radius: 5px 5px 0 0;
42 -moz-border-radius: 5px 5px 0 0;
43 -webkit-border-top-right-radius: 5px;
44 -webkit-border-top-left-radius: 5px;
45 }
46
47 #qunit-header a {
48 text-decoration: none;
49 color: #c2ccd1;
50 }
51
52 #qunit-header a:hover,
53 #qunit-header a:focus {
54 color: #fff;
55 }
56
57 #qunit-testrunner-toolbar label {
58 display: inline-block;
59 padding: 0 .5em 0 .1em;
60 }
61
62 #qunit-banner {
63 height: 5px;
64 }
65
66 #qunit-testrunner-toolbar {
67 padding: 0.5em 0 0.5em 2em;
68 color: #5E740B;
69 background-color: #eee;
70 overflow: hidden;
71 }
72
73 #qunit-userAgent {
74 padding: 0.5em 0 0.5em 2.5em;
75 background-color: #2b81af;
76 color: #fff;
77 text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
78 }
79
80 #qunit-modulefilter-container {
81 float: right;
82 }
83
84 /** Tests: Pass/Fail */
85
86 #qunit-tests {
87 list-style-position: inside;
88 }
89
90 #qunit-tests li {
91 padding: 0.4em 0.5em 0.4em 2.5em;
92 border-bottom: 1px solid #fff;
93 list-style-position: inside;
94 }
95
96 #qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running {
97 display: none;
98 }
99
100 #qunit-tests li strong {
101 cursor: pointer;
102 }
103
104 #qunit-tests li a {
105 padding: 0.5em;
106 color: #c2ccd1;
107 text-decoration: none;
108 }
109 #qunit-tests li a:hover,
110 #qunit-tests li a:focus {
111 color: #000;
112 }
113
114 #qunit-tests li .runtime {
115 float: right;
116 font-size: smaller;
117 }
118
119 .qunit-assert-list {
120 margin-top: 0.5em;
121 padding: 0.5em;
122
123 background-color: #fff;
124
125 border-radius: 5px;
126 -moz-border-radius: 5px;
127 -webkit-border-radius: 5px;
128 }
129
130 .qunit-collapsed {
131 display: none;
132 }
133
134 #qunit-tests table {
135 border-collapse: collapse;
136 margin-top: .2em;
137 }
138
139 #qunit-tests th {
140 text-align: right;
141 vertical-align: top;
142 padding: 0 .5em 0 0;
143 }
144
145 #qunit-tests td {
146 vertical-align: top;
147 }
148
149 #qunit-tests pre {
150 margin: 0;
151 white-space: pre-wrap;
152 word-wrap: break-word;
153 }
154
155 #qunit-tests del {
156 background-color: #e0f2be;
157 color: #374e0c;
158 text-decoration: none;
159 }
160
161 #qunit-tests ins {
162 background-color: #ffcaca;
163 color: #500;
164 text-decoration: none;
165 }
166
167 /*** Test Counts */
168
169 #qunit-tests b.counts { color: black; }
170 #qunit-tests b.passed { color: #5E740B; }
171 #qunit-tests b.failed { color: #710909; }
172
173 #qunit-tests li li {
174 padding: 5px;
175 background-color: #fff;
176 border-bottom: none;
177 list-style-position: inside;
178 }
179
180 /*** Passing Styles */
181
182 #qunit-tests li li.pass {
183 color: #3c510c;
184 background-color: #fff;
185 border-left: 10px solid #C6E746;
186 }
187
188 #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
189 #qunit-tests .pass .test-name { color: #366097; }
190
191 #qunit-tests .pass .test-actual,
192 #qunit-tests .pass .test-expected { color: #999999; }
193
194 #qunit-banner.qunit-pass { background-color: #C6E746; }
195
196 /*** Failing Styles */
197
198 #qunit-tests li li.fail {
199 color: #710909;
200 background-color: #fff;
201 border-left: 10px solid #EE5757;
202 white-space: pre;
203 }
204
205 #qunit-tests > li:last-child {
206 border-radius: 0 0 5px 5px;
207 -moz-border-radius: 0 0 5px 5px;
208 -webkit-border-bottom-right-radius: 5px;
209 -webkit-border-bottom-left-radius: 5px;
210 }
211
212 #qunit-tests .fail { color: #000000; background-color: #EE5757; }
213 #qunit-tests .fail .test-name,
214 #qunit-tests .fail .module-name { color: #000000; }
215
216 #qunit-tests .fail .test-actual { color: #EE5757; }
217 #qunit-tests .fail .test-expected { color: green; }
218
219 #qunit-banner.qunit-fail { background-color: #EE5757; }
220
221
222 /** Result */
223
224 #qunit-testresult {
225 padding: 0.5em 0.5em 0.5em 2.5em;
226
227 color: #2b81af;
228 background-color: #D2E0E6;
229
230 border-bottom: 1px solid white;
231 }
232 #qunit-testresult .module-name {
233 font-weight: bold;
234 }
235
236 /** Fixture */
237
238 #qunit-fixture {
239 position: absolute;
240 top: -10000px;
241 left: -10000px;
242 width: 1000px;
243 height: 1000px;
244 }
...@@ -42,13 +42,13 @@ ...@@ -42,13 +42,13 @@
42 "karma-qunit": "~0.1.1", 42 "karma-qunit": "~0.1.1",
43 "karma-safari-launcher": "~0.1.1", 43 "karma-safari-launcher": "~0.1.1",
44 "karma-sauce-launcher": "~0.1.8", 44 "karma-sauce-launcher": "~0.1.8",
45 "qunitjs": "^1.15.0", 45 "qunitjs": "^1.18.0",
46 "sinon": "1.10.2", 46 "sinon": "1.10.2",
47 "video.js": "^4.12.0" 47 "video.js": "^5.0.0-rc.4"
48 }, 48 },
49 "dependencies": { 49 "dependencies": {
50 "pkcs7": "^0.2.2", 50 "pkcs7": "^0.2.2",
51 "videojs-contrib-media-sources": "^1.0.0", 51 "videojs-contrib-media-sources": "^1.0.0",
52 "videojs-swf": "^4.7.0" 52 "videojs-swf": "5.0.0-rc0"
53 } 53 }
54 } 54 }
......
...@@ -299,7 +299,7 @@ AsyncStream.prototype = new videojs.Hls.Stream(); ...@@ -299,7 +299,7 @@ AsyncStream.prototype = new videojs.Hls.Stream();
299 AsyncStream.prototype.processJob_ = function() { 299 AsyncStream.prototype.processJob_ = function() {
300 this.jobs.shift()(); 300 this.jobs.shift()();
301 if (this.jobs.length) { 301 if (this.jobs.length) {
302 this.timeout_ = setTimeout(videojs.bind(this, this.processJob_), 302 this.timeout_ = setTimeout(this.processJob_.bind(this),
303 this.delay); 303 this.delay);
304 } else { 304 } else {
305 this.timeout_ = null; 305 this.timeout_ = null;
...@@ -308,7 +308,7 @@ AsyncStream.prototype.processJob_ = function() { ...@@ -308,7 +308,7 @@ AsyncStream.prototype.processJob_ = function() {
308 AsyncStream.prototype.push = function(job) { 308 AsyncStream.prototype.push = function(job) {
309 this.jobs.push(job); 309 this.jobs.push(job);
310 if (!this.timeout_) { 310 if (!this.timeout_) {
311 this.timeout_ = setTimeout(videojs.bind(this, this.processJob_), 311 this.timeout_ = setTimeout(this.processJob_.bind(this),
312 this.delay); 312 this.delay);
313 } 313 }
314 }; 314 };
......
...@@ -585,4 +585,4 @@ ...@@ -585,4 +585,4 @@
585 ParseStream: ParseStream, 585 ParseStream: ParseStream,
586 Parser: Parser 586 Parser: Parser
587 }; 587 };
588 })(window.videojs, window.parseInt, window.isFinite, window.videojs.util.mergeOptions); 588 })(window.videojs, window.parseInt, window.isFinite, window.videojs.mergeOptions);
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
18 resolveUrl = videojs.Hls.resolveUrl, 18 resolveUrl = videojs.Hls.resolveUrl,
19 xhr = videojs.Hls.xhr, 19 xhr = videojs.Hls.xhr,
20 Playlist = videojs.Hls.Playlist, 20 Playlist = videojs.Hls.Playlist,
21 mergeOptions = videojs.util.mergeOptions, 21 mergeOptions = videojs.mergeOptions,
22 22
23 /** 23 /**
24 * Returns a new master playlist that is the result of merging an 24 * Returns a new master playlist that is the result of merging an
...@@ -262,10 +262,10 @@ ...@@ -262,10 +262,10 @@
262 262
263 // request the new playlist 263 // request the new playlist
264 request = xhr({ 264 request = xhr({
265 url: resolveUrl(loader.master.uri, playlist.uri), 265 uri: resolveUrl(loader.master.uri, playlist.uri),
266 withCredentials: withCredentials 266 withCredentials: withCredentials
267 }, function(error) { 267 }, function(error, request) {
268 haveMetadata(error, this, playlist.uri); 268 haveMetadata(error, request, playlist.uri);
269 loader.trigger('mediachange'); 269 loader.trigger('mediachange');
270 }); 270 });
271 }; 271 };
...@@ -283,32 +283,35 @@ ...@@ -283,32 +283,35 @@
283 283
284 loader.state = 'HAVE_CURRENT_METADATA'; 284 loader.state = 'HAVE_CURRENT_METADATA';
285 request = xhr({ 285 request = xhr({
286 url: resolveUrl(loader.master.uri, loader.media().uri), 286 uri: resolveUrl(loader.master.uri, loader.media().uri),
287 withCredentials: withCredentials 287 withCredentials: withCredentials
288 }, function(error) { 288 }, function(error, request) {
289 haveMetadata(error, this, loader.media().uri); 289 haveMetadata(error, request, loader.media().uri);
290 }); 290 });
291 }); 291 });
292 292
293 // request the specified URL 293 // request the specified URL
294 xhr({ 294 request = xhr({
295 url: srcUrl, 295 uri: srcUrl,
296 withCredentials: withCredentials 296 withCredentials: withCredentials
297 }, function(error) { 297 }, function(error, req) {
298 var parser, i; 298 var parser, i;
299 299
300 // clear the loader's request reference
301 request = null;
302
300 if (error) { 303 if (error) {
301 loader.error = { 304 loader.error = {
302 status: this.status, 305 status: req.status,
303 message: 'HLS playlist request error at URL: ' + srcUrl, 306 message: 'HLS playlist request error at URL: ' + srcUrl,
304 responseText: this.responseText, 307 responseText: req.responseText,
305 code: 2 // MEDIA_ERR_NETWORK 308 code: 2 // MEDIA_ERR_NETWORK
306 }; 309 };
307 return loader.trigger('error'); 310 return loader.trigger('error');
308 } 311 }
309 312
310 parser = new videojs.m3u8.Parser(); 313 parser = new videojs.m3u8.Parser();
311 parser.push(this.responseText); 314 parser.push(req.responseText);
312 parser.end(); 315 parser.end();
313 316
314 loader.state = 'HAVE_MASTER'; 317 loader.state = 'HAVE_MASTER';
...@@ -326,12 +329,12 @@ ...@@ -326,12 +329,12 @@
326 } 329 }
327 330
328 request = xhr({ 331 request = xhr({
329 url: resolveUrl(srcUrl, parser.manifest.playlists[0].uri), 332 uri: resolveUrl(srcUrl, parser.manifest.playlists[0].uri),
330 withCredentials: withCredentials 333 withCredentials: withCredentials
331 }, function(error) { 334 }, function(error, request) {
332 // pass along the URL specified in the master playlist 335 // pass along the URL specified in the master playlist
333 haveMetadata(error, 336 haveMetadata(error,
334 this, 337 request,
335 parser.manifest.playlists[0].uri); 338 parser.manifest.playlists[0].uri);
336 if (!error) { 339 if (!error) {
337 loader.trigger('loadedmetadata'); 340 loader.trigger('loadedmetadata');
...@@ -349,7 +352,7 @@ ...@@ -349,7 +352,7 @@
349 }] 352 }]
350 }; 353 };
351 loader.master.playlists[srcUrl] = loader.master.playlists[0]; 354 loader.master.playlists[srcUrl] = loader.master.playlists[0];
352 haveMetadata(null, this, srcUrl); 355 haveMetadata(null, req, srcUrl);
353 return loader.trigger('loadedmetadata'); 356 return loader.trigger('loadedmetadata');
354 }); 357 });
355 }; 358 };
......
1 (function(videojs){ 1 (function(videojs) {
2 'use strict';
3
2 /** 4 /**
3 * Creates and sends an XMLHttpRequest. 5 * A wrapper for videojs.xhr that tracks bandwidth.
4 * TODO - expose video.js core's XHR and use that instead
5 *
6 * @param options {string | object} if this argument is a string, it
7 * is intrepreted as a URL and a simple GET request is
8 * inititated. If it is an object, it should contain a `url`
9 * property that indicates the URL to request and optionally a
10 * `method` which is the type of HTTP request to send.
11 * @param callback (optional) {function} a function to call when the
12 * request completes. If the request was not successful, the first
13 * argument will be falsey.
14 * @return {object} the XMLHttpRequest that was initiated.
15 */ 6 */
16 videojs.Hls.xhr = function(url, callback) { 7 videojs.Hls.xhr = function(options, callback) {
17 var 8 var request = videojs.xhr(options, function(error, request) {
18 options = { 9 if (request.response) {
19 method: 'GET', 10 request.responseTime = (new Date()).getTime();
20 timeout: 45 * 1000 11 request.roundTripTime = request.responseTime - request.requestTime;
21 }, 12 request.bytesReceived = request.response.byteLength || request.response.length;
22 request, 13 request.bandwidth = Math.floor((request.bytesReceived / request.roundTripTime) * 8 * 1000);
23 abortTimeout;
24
25 if (typeof callback !== 'function') {
26 callback = function() {};
27 }
28
29 if (typeof url === 'object') {
30 options = videojs.util.mergeOptions(options, url);
31 url = options.url;
32 }
33
34 request = new window.XMLHttpRequest();
35 request.open(options.method, url);
36 request.url = url;
37 request.requestTime = new Date().getTime();
38
39 if (options.responseType) {
40 request.responseType = options.responseType;
41 }
42 if (options.withCredentials) {
43 request.withCredentials = true;
44 }
45 if (options.timeout) {
46 abortTimeout = window.setTimeout(function() {
47 if (request.readyState !== 4) {
48 request.timedout = true;
49 request.abort();
50 }
51 }, options.timeout);
52 }
53
54 request.onreadystatechange = function() {
55 // wait until the request completes
56 if (this.readyState !== 4) {
57 return;
58 } 14 }
59 15
60 // clear outstanding timeouts 16 callback(error, request);
61 window.clearTimeout(abortTimeout); 17 });
62 18
63 // request timeout 19 request.requestTime = (new Date()).getTime();
64 if (request.timedout) {
65 return callback.call(this, 'timeout', url);
66 }
67
68 // request aborted or errored
69 if (this.status >= 400 || this.status === 0) {
70 return callback.call(this, true, url);
71 }
72
73 if (this.response) {
74 this.responseTime = new Date().getTime();
75 this.roundTripTime = this.responseTime - this.requestTime;
76 this.bytesReceived = this.response.byteLength || this.response.length;
77 this.bandwidth = Math.floor((this.bytesReceived / this.roundTripTime) * 8 * 1000);
78 }
79
80 return callback.call(this, false, url);
81 };
82 request.send(null);
83 return request; 20 return request;
84 }; 21 };
85
86 })(window.videojs); 22 })(window.videojs);
......
...@@ -69,12 +69,9 @@ module.exports = function(config) { ...@@ -69,12 +69,9 @@ module.exports = function(config) {
69 // add their paths to this list. 69 // add their paths to this list.
70 70
71 files: [ 71 files: [
72 '../node_modules/sinon/lib/sinon.js', 72 '../node_modules/sinon/pkg/sinon.js',
73 '../node_modules/sinon/lib/sinon/util/event.js', 73 '../node_modules/video.js/dist/video-js.css',
74 '../node_modules/sinon/lib/sinon/util/fake_xml_http_request.js', 74 '../node_modules/video.js/dist/video.js',
75 '../node_modules/sinon/lib/sinon/util/xhr_ie.js',
76 '../node_modules/sinon/lib/sinon/util/fake_timers.js',
77 '../node_modules/video.js/dist/video-js/video.dev.js',
78 '../node_modules/videojs-contrib-media-sources/src/videojs-media-sources.js', 75 '../node_modules/videojs-contrib-media-sources/src/videojs-media-sources.js',
79 '../node_modules/pkcs7/dist/pkcs7.unpad.js', 76 '../node_modules/pkcs7/dist/pkcs7.unpad.js',
80 '../test/karma-qunit-shim.js', 77 '../test/karma-qunit-shim.js',
......
...@@ -34,12 +34,9 @@ module.exports = function(config) { ...@@ -34,12 +34,9 @@ module.exports = function(config) {
34 // add their paths to this list. 34 // add their paths to this list.
35 35
36 files: [ 36 files: [
37 '../node_modules/sinon/lib/sinon.js', 37 '../node_modules/sinon/pkg/sinon.js',
38 '../node_modules/sinon/lib/sinon/util/event.js', 38 '../node_modules/video.js/dist/video-js.css',
39 '../node_modules/sinon/lib/sinon/util/fake_xml_http_request.js', 39 '../node_modules/video.js/dist/video.js',
40 '../node_modules/sinon/lib/sinon/util/xhr_ie.js',
41 '../node_modules/sinon/lib/sinon/util/fake_timers.js',
42 '../node_modules/video.js/dist/video-js/video.dev.js',
43 '../node_modules/videojs-contrib-media-sources/src/videojs-media-sources.js', 40 '../node_modules/videojs-contrib-media-sources/src/videojs-media-sources.js',
44 '../node_modules/pkcs7/dist/pkcs7.unpad.js', 41 '../node_modules/pkcs7/dist/pkcs7.unpad.js',
45 '../test/karma-qunit-shim.js', 42 '../test/karma-qunit-shim.js',
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
27 0x09, 0x00, 0x00, 0x00, 0x00 27 0x09, 0x00, 0x00, 0x00, 0x00
28 ], 28 ],
29 29
30 extend = window.videojs.util.mergeOptions, 30 mergeOptions = window.videojs.mergeOptions,
31 31
32 makePat, 32 makePat,
33 makePsi, 33 makePsi,
...@@ -178,7 +178,7 @@ ...@@ -178,7 +178,7 @@
178 makePacket = function(options) { 178 makePacket = function(options) {
179 var 179 var
180 result = [], 180 result = [],
181 settings = extend({ 181 settings = mergeOptions({
182 payloadUnitStartIndicator: true, 182 payloadUnitStartIndicator: true,
183 pid: 0x00 183 pid: 0x00
184 }, options); 184 }, options);
......
...@@ -4,18 +4,15 @@ ...@@ -4,18 +4,15 @@
4 <meta charset="utf-8"> 4 <meta charset="utf-8">
5 <title>video.js HLS Plugin Test Suite</title> 5 <title>video.js HLS Plugin Test Suite</title>
6 <!-- Load sinon server for fakeXHR --> 6 <!-- Load sinon server for fakeXHR -->
7 <script src="../node_modules/sinon/lib/sinon.js"></script> 7 <script src="../node_modules/sinon/pkg/sinon.js"></script>
8 <script src="../node_modules/sinon/lib/sinon/util/event.js"></script>
9 <script src="../node_modules/sinon/lib/sinon/util/fake_xml_http_request.js"></script>
10 <script src="../node_modules/sinon/lib/sinon/util/xhr_ie.js"></script>
11 <script src="../node_modules/sinon/lib/sinon/util/fake_timers.js"></script>
12 8
13 <!-- Load local QUnit. --> 9 <!-- Load local QUnit. -->
14 <link rel="stylesheet" href="../libs/qunit/qunit.css" media="screen"> 10 <link rel="stylesheet" href="../node_modules/qunitjs/qunit/qunit.css" media="screen">
15 <script src="../libs/qunit/qunit.js"></script> 11 <script src="../node_modules/qunitjs/qunit/qunit.js"></script>
16 12
17 <!-- video.js --> 13 <!-- video.js -->
18 <script src="../node_modules/video.js/dist/video-js/video.dev.js"></script> 14 <script src="../node_modules/video.js/dist/video.js"></script>
15 <link rel="stylesheet" href="../node_modules/video.js/dist/video-js.css" media="screen">
19 <script src="../node_modules/videojs-contrib-media-sources/src/videojs-media-sources.js"></script> 16 <script src="../node_modules/videojs-contrib-media-sources/src/videojs-media-sources.js"></script>
20 17
21 <!-- HLS plugin --> 18 <!-- HLS plugin -->
...@@ -63,7 +60,6 @@ ...@@ -63,7 +60,6 @@
63 <script src="playlist_test.js"></script> 60 <script src="playlist_test.js"></script>
64 <script src="playlist-loader_test.js"></script> 61 <script src="playlist-loader_test.js"></script>
65 <script src="decrypter_test.js"></script> 62 <script src="decrypter_test.js"></script>
66 <script src="xhr_test.js"></script>
67 </head> 63 </head>
68 <body> 64 <body>
69 <div id="qunit"></div> 65 <div id="qunit"></div>
......
1 (function(window, videojs, undefined) {
2 'use strict';
3
4 /*
5 XHR test suite
6 */
7
8 var xhr;
9
10 module('XHR', {
11 setup: function() {
12 xhr = sinon.useFakeXMLHttpRequest();
13 },
14
15 teardown: function() {
16 xhr.restore();
17 }
18 });
19
20 test('handles xhr timeouts correctly', function () {
21 var error;
22 var clock = sinon.useFakeTimers();
23 videojs.Hls.xhr({
24 url: 'http://example.com',
25 timeout: 1
26 }, function(innerError) {
27 error = innerError;
28 });
29 clock.tick(1);
30 strictEqual(error, 'timeout', 'called with timeout error');
31 clock.restore();
32 });
33
34 })(window, window.videojs);