UNPKG

shaka-player

Version:
282 lines (246 loc) 9.62 kB
/** * @license * Copyright 2016 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ describe('CastUtils', function() { /** @const */ var CastUtils = shaka.cast.CastUtils; /** @const */ var FakeEvent = shaka.util.FakeEvent; it('includes every Player member', function() { var ignoredMembers = [ 'constructor', // JavaScript added field 'getNetworkingEngine', // Handled specially 'getMediaElement', // Handled specially 'setMaxHardwareResolution', 'destroy', // Should use CastProxy.destroy instead 'getManifest', // Too large to proxy // Test helper methods (not @export'd) 'createDrmEngine', 'createNetworkingEngine', 'createPlayhead', 'createPlayheadObserver', 'createMediaSource', 'createMediaSourceEngine', 'createStreamingEngine' ]; var CastUtils = shaka.cast.CastUtils; var castMembers = CastUtils.PlayerVoidMethods .concat(CastUtils.PlayerPromiseMethods); for (var name in CastUtils.PlayerGetterMethods) castMembers.push(name); for (var name in CastUtils.PlayerGetterMethodsThatRequireLive) castMembers.push(name); var playerMembers = Object.keys(shaka.Player.prototype).filter( function(name) { // Private members end with _. return ignoredMembers.indexOf(name) < 0 && name.substr(name.length - 1) != '_'; }); // To make debugging easier, don't check that they are equal; instead check // that neither has any extra entries. var extraCastMembers = castMembers.filter(function(name) { return playerMembers.indexOf(name) < 0; }); var extraPlayerMembers = playerMembers.filter(function(name) { return castMembers.indexOf(name) < 0; }); expect(extraCastMembers).toEqual([]); expect(extraPlayerMembers).toEqual([]); }); describe('serialize/deserialize', function() { it('transfers infinite values and NaN', function() { var orig = { 'nan': NaN, 'positive_infinity': Infinity, 'negative_infinity': -Infinity, 'null': null, 'true': true, 'false': false, 'one': 1, 'string': 'a string' }; var serialized = CastUtils.serialize(orig); // The object is turned into a string. expect(typeof serialized).toBe('string'); // The deserialized object matches the original. var deserialized = CastUtils.deserialize(serialized); for (var k in orig) { expect(deserialized[k]).toEqual(orig[k]); } }); it('transfers real Events', function() { // new Event() is not usable on IE11: var event = /** @type {!CustomEvent} */ (document.createEvent('CustomEvent')); event.initCustomEvent('myEventType', false, false, null); // Properties that can definitely be transferred. var nativeProperties = [ 'bubbles', 'type', 'cancelable', 'defaultPrevented' ]; var extraProperties = { 'key': 'value', 'true': true, 'one': 1 }; for (var k in extraProperties) { event[k] = extraProperties[k]; } // The event is turned into a string. var serialized = CastUtils.serialize(event); expect(typeof serialized).toBe('string'); // The string is turned back into an object. var deserialized = CastUtils.deserialize(serialized); expect(typeof deserialized).toBe('object'); // The object can be used to construct a FakeEvent. var fakeEvent = new FakeEvent(deserialized['type'], deserialized); // The fake event has the same type and properties as the original. nativeProperties.forEach(function(k) { expect(fakeEvent[k]).toEqual(event[k]); }); for (var k in extraProperties) { expect(fakeEvent[k]).toEqual(event[k]); } }); it('transfers dispatched FakeEvents', function(done) { var event = new FakeEvent('custom'); // Properties that can definitely be transferred. var nativeProperties = [ 'bubbles', 'type', 'cancelable', 'defaultPrevented' ]; var extraProperties = { 'key': 'value', 'true': true, 'one': 1 }; for (var k in extraProperties) { event[k] = extraProperties[k]; } var target = new shaka.util.FakeEventTarget(); target.addEventListener(event.type, function() { try { // The event is turned into a string. var serialized = CastUtils.serialize(event); expect(typeof serialized).toBe('string'); // The string is turned back into an object. var deserialized = CastUtils.deserialize(serialized); expect(typeof deserialized).toBe('object'); // The deserialized event has the same type and properties as the // original. nativeProperties.forEach(function(k) { expect(deserialized[k]).toEqual(event[k]); }); for (var k in extraProperties) { expect(deserialized[k]).toEqual(event[k]); } } catch (exception) { fail(exception); } done(); }); target.dispatchEvent(event); }); describe('TimeRanges', function() { /** @type {!HTMLVideoElement} */ var video; /** @type {!shaka.util.EventManager} */ var eventManager; /** @type {!shaka.media.MediaSourceEngine} */ var mediaSourceEngine; beforeAll(function() { video = /** @type {!HTMLVideoElement} */ (document.createElement('video')); document.body.appendChild(video); }); beforeEach(function(done) { // The TimeRanges constructor cannot be used directly, so we load a clip // to get ranges to use. var mediaSource = new MediaSource(); var fakeVideoStream = { mimeType: 'video/mp4', codecs: 'avc1.42c01e' }; var initSegmentUrl = '/base/test/test/assets/sintel-video-init.mp4'; var videoSegmentUrl = '/base/test/test/assets/sintel-video-segment.mp4'; // Wait for the media source to be open. eventManager = new shaka.util.EventManager(); video.src = window.URL.createObjectURL(mediaSource); eventManager.listen(video, 'error', onError); eventManager.listen(mediaSource, 'sourceopen', onSourceOpen); function onError() { fail('Error code ' + (video.error ? video.error.code : 0)); } function onSourceOpen() { var ContentType = shaka.util.ManifestParserUtils.ContentType; eventManager.unlisten(mediaSource, 'sourceopen'); mediaSourceEngine = new shaka.media.MediaSourceEngine( video, mediaSource, /* TextTrack */ null); // Create empty object first and initialize the fields through // [] to allow field names to be expressions. var initObject = {}; initObject[ContentType.VIDEO] = fakeVideoStream; mediaSourceEngine.init(initObject); shaka.test.Util.fetch(initSegmentUrl).then(function(data) { return mediaSourceEngine.appendBuffer(ContentType.VIDEO, data, null, null); }).then(function() { return shaka.test.Util.fetch(videoSegmentUrl); }).then(function(data) { return mediaSourceEngine.appendBuffer(ContentType.VIDEO, data, null, null); }).catch(fail).then(done); } }); afterEach(function(done) { eventManager.destroy().then(function() { if (mediaSourceEngine) { return mediaSourceEngine.destroy(); } }).then(function() { video.removeAttribute('src'); video.load(); done(); }); }); afterAll(function() { document.body.removeChild(video); }); it('deserialize into equivalent objects', function() { var buffered = video.buffered; // The test is less interesting if the ranges are empty. expect(buffered.length).toBeGreaterThan(0); // The TimeRanges object is turned into a string. var serialized = CastUtils.serialize(buffered); expect(typeof serialized).toBe('string'); // Expect the deserialized version to look like the original. var deserialized = CastUtils.deserialize(serialized); expect(deserialized.length).toEqual(buffered.length); expect(deserialized.start).toEqual(jasmine.any(Function)); expect(deserialized.end).toEqual(jasmine.any(Function)); for (var i = 0; i < deserialized.length; ++i) { // Not exact because of the possibility of rounding errors. expect(deserialized.start(i)).toBeCloseTo(buffered.start(i)); expect(deserialized.end(i)).toBeCloseTo(buffered.end(i)); } }); }); }); });