diff --git a/.jshintrc b/.jshintrc index c209d91b91..007cd48f4d 100644 --- a/.jshintrc +++ b/.jshintrc @@ -39,6 +39,7 @@ "start", "stop", "strictEqual", - "test" + "test", + "sinon" ] } diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f92facd4d..008d1adc86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,16 @@ CHANGELOG * Fixed extra mousemove events on Windows caused by certain apps, not users [[view](https://github.com/videojs/video.js/pull/1068)] * Fixed error due to undefined tech when no source is supported [[view](https://github.com/videojs/video.js/pull/1172)] * Fixed the progress bar not finishing when manual timeupdate events are used [[view](https://github.com/videojs/video.js/pull/1173)] +* Added a more informative and styled fallback message for non-html5 browsers [[view](https://github.com/videojs/video.js/pull/1181)] +* Added the option to provide an array of child components instead of an object [[view](https://github.com/videojs/video.js/pull/1093)] +* Fixed casing on webkitRequestFullscreen [[view](https://github.com/videojs/video.js/pull/1101)] +* Made tap events on mobile less sensitive to touch moves [[view](https://github.com/videojs/video.js/pull/1111)] +* Fixed the default flag for captions/subtitles tracks [[view](https://github.com/videojs/video.js/pull/1153)] +* Fixed compilation failures with LESS v1.7.0 and GRUNT v0.4.4 [[view](https://github.com/videojs/video.js/pull/1180)] +* Added better error handling across the library [[view](https://github.com/videojs/video.js/pull/1197)] +* Updated captions/subtiles file fetching to support cross-origin requests in older IE browsers [[view](https://github.com/videojs/video.js/pull/1095)] +* Added support for playback rate switching [[view](https://github.com/videojs/video.js/pull/1132)] +* Fixed an issue with the loadstart event order that caused the big play button to not hide [[view](https://github.com/videojs/video.js/pull/1209)] -------------------- diff --git a/Gruntfile.js b/Gruntfile.js index 00d046ed1c..31c91eb2a2 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -57,7 +57,7 @@ module.exports = function(grunt) { }, tests: { src: ['build/files/combined.video.js', 'build/compiler/goog.base.js', 'src/js/exports.js', 'test/unit/*.js'], - externs: ['src/js/player.externs.js', 'src/js/media/flash.externs.js', 'test/qunit-externs.js'], + externs: ['src/js/player.externs.js', 'src/js/media/flash.externs.js', 'test/qunit-externs.js', 'test/sinon-externs.js'], dest: 'build/files/test.minified.video.js' } }, diff --git a/build/demo-files/demo.html b/build/demo-files/demo.html index b2b3fa44d6..8093718565 100644 --- a/build/demo-files/demo.html +++ b/build/demo-files/demo.html @@ -25,6 +25,7 @@ +

To view this video please enable JavaScript, and consider upgrading to a web browser that supports HTML5 video

diff --git a/build/source-loader.js b/build/source-loader.js index 2dfa497666..84ee8cdff5 100644 --- a/build/source-loader.js +++ b/build/source-loader.js @@ -24,6 +24,7 @@ var sourceFiles = [ "src/js/button.js", "src/js/slider.js", "src/js/menu.js", + "src/js/media-error.js", "src/js/player.js", "src/js/control-bar/control-bar.js", "src/js/control-bar/live-display.js", @@ -34,9 +35,11 @@ var sourceFiles = [ "src/js/control-bar/volume-control.js", "src/js/control-bar/mute-toggle.js", "src/js/control-bar/volume-menu-button.js", + "src/js/control-bar/playback-rate-menu-button.js", "src/js/poster.js", "src/js/loading-spinner.js", "src/js/big-play-button.js", + "src/js/error-display.js", "src/js/media/media.js", "src/js/media/html5.js", "src/js/media/flash.js", diff --git a/contrib.json b/contrib.json index 2464cfbc00..5104490614 100644 --- a/contrib.json +++ b/contrib.json @@ -84,6 +84,7 @@ "contributions": { "feature": { + "desc": "Create a new feature or general enhancement", "start": { "desc": "Start a new feature", "steps": [ @@ -132,7 +133,7 @@ }, { "desc": "Are you sure <%= branch %> is the branch you want to submit", - "prompt": "confirm" + "confirm": "confirm" }, { "id": "user", @@ -151,7 +152,7 @@ }, "patch": { - "desc": "Urgent fixes for the latest stable version", + "desc": "Create an urgent fix for the latest stable version", "new": { "desc": "Start a new patch", "steps": [ @@ -200,7 +201,7 @@ }, { "desc": "Are you sure <%= branch %> is the branch you want to submit", - "prompt": "confirm" + "confirm": "confirm" }, { "id": "user", @@ -227,7 +228,7 @@ }, { "desc": "Confirm you are deleting the correct branch", - "prompt": "Delete branch '<%= name %>'?" + "confirm": "Delete branch '<%= name %>'?" }, { "desc": "Delete the local copy of the branch", @@ -241,6 +242,79 @@ } }, + "bug": { + "desc": "Submit a bug report", + "steps": [ + { + "id": "title", + "prompt": "Title your bug report" + }, + { + "id": "reproduce", + "prompt": "What did you do? (steps to reproduce)" + }, + { + "id": "expected", + "prompt": "What did you expect to happen?" + }, + { + "id": "actual", + "prompt": "What actually happened?" + }, + { + "id": "version", + "prompt": "What version of video.js are you using?" + }, + { + "id": "plugins", + "prompt": "Are you using any video.js plugins?" + }, + { + "id": "browsers", + "prompt": "What browsers/platforms did you experience this in (e.g. Win 7, IE10; Android 4, Chrome;)?" + }, + { + "id": "example", + "prompt": "Is there a URL to a live example, or a jsbin (e.g. http://jsbin.com/axedog/9999/edit)?" + }, + { + "id": "details", + "prompt": "Are there any other details you'd like to provide?" + }, + { + "open": "https://github.com/videojs/video.js/issues/new?title=<%= title %>&body=**Steps to reproduce:**\n> <%= reproduce %>\n\n**What was expected:**\n> <%= expected %>\n\n**What Happened:**\n> <%= actual %>\n\n**Video.js Version:**\n> <%= version %>\n\n**Plugins:**\n> <%= plugins %>\n\n**Browsers experienced on:**\n> <%= browsers %>\n\n**Example:**\n> <%= example %>\n\n**Other details:**\n> <%= details %>" + } + ] + }, + + "request": { + "desc": "Submit a feature/enhancement request", + "steps": [ + { + "id": "title", + "prompt": "Title your request" + }, + { + "id": "describe", + "prompt": "Describe the feature/enhancement (be as detailed as possible so it's clear who, why, and how it would be used)" + }, + { + "id": "docs", + "prompt": "Is there any existing documentation or related specifications?" + }, + { + "id": "examples", + "prompt": "Are there any existing examples?" + }, + { + "confirm": "You will be redirected to Github where you can submit this issue, OK?" + }, + { + "open": "https://github.com/videojs/video.js/issues/new?title=<%= title %>&body=**Describe the feature/enhancement:**\n> <%= describe %>\n\n**Existing docs/specs:**\n> <%= docs %>\n\n**Existing examples:**\n> <%= examples %>" + } + ] + }, + "release": { "desc": "Create and publish a release", "steps": [ @@ -254,7 +328,7 @@ }, { "desc": "Have the changes been merged into the release branch (stable)?", - "prompt": "confirm" + "confirm": "confirm" }, { "id": "type", diff --git a/docs/guides/setup.md b/docs/guides/setup.md index 9ef82749a3..706c6f4bd9 100644 --- a/docs/guides/setup.md +++ b/docs/guides/setup.md @@ -47,8 +47,7 @@ With Video.js you just use an HTML5 video tag to embed a video. Video.js will th - `video-js` applies styles that are required for Video.js functionality, like fullscreen and subtitles. - `vjs-default-skin` applies the default skin to the HTML controls, and can be removed or overridden to create your own controls design. -Otherwise include/exclude attributes, settings, sources, and tracks exactly as you would for HTML5 video. - +Otherwise include/exclude attributes, settings, sources, and tracks exactly as you would for HTML5 video.* ```html ``` @@ -100,3 +100,5 @@ videojs(document.getElementsByClassName('awesome_video_class')[0], {}, function( // if it's an array that you pick one (here we chose the first). }); ``` + +\* If you have trouble playing back content you know is in the [correct format](http://blog.zencoder.com/2013/09/13/what-formats-do-i-need-for-html5-video/), your HTTP server might not be delivering the content with the correct [MIME type](http://en.wikipedia.org/wiki/Internet_media_type#Type_video). Please double check your content's headers before opening an [issue](https://github.com/videojs/video.js/blob/master/CONTRIBUTING.md). diff --git a/package.json b/package.json index 6366ddf05b..141df5955c 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "qunitjs": "~1.12.0", "semver": "~1.1.4", "uglify-js": "~2.3.6", - "videojs-doc-generator": "0.0.1" + "videojs-doc-generator": "0.0.1", + "sinon": "~1.9.1" } } diff --git a/sandbox/index.html.example b/sandbox/index.html.example index b058ff4f9c..25d2e7c72c 100644 --- a/sandbox/index.html.example +++ b/sandbox/index.html.example @@ -25,7 +25,7 @@ -

Video Playback Not Supported

+

To view this video please enable JavaScript, and consider upgrading to a web browser that supports HTML5 video

+ diff --git a/test/karma.conf.js b/test/karma.conf.js index 8b10a53589..c994a1df35 100644 --- a/test/karma.conf.js +++ b/test/karma.conf.js @@ -51,6 +51,7 @@ module.exports = function(config) { files: [ '../test/karma-qunit-shim.js', + '../node_modules/sinon/pkg/sinon.js', "../src/js/core.js", "../src/js/core-object.js", "../src/js/events.js", @@ -60,6 +61,7 @@ module.exports = function(config) { "../src/js/button.js", "../src/js/slider.js", "../src/js/menu.js", + "../src/js/media-error.js", "../src/js/player.js", "../src/js/control-bar/control-bar.js", "../src/js/control-bar/live-display.js", @@ -70,9 +72,11 @@ module.exports = function(config) { "../src/js/control-bar/volume-control.js", "../src/js/control-bar/mute-toggle.js", "../src/js/control-bar/volume-menu-button.js", + "../src/js/control-bar/playback-rate-menu-button.js", "../src/js/poster.js", "../src/js/loading-spinner.js", "../src/js/big-play-button.js", + "../src/js/error-display.js", "../src/js/media/media.js", "../src/js/media/html5.js", "../src/js/media/flash.js", diff --git a/test/karma.minified.api.conf.js b/test/karma.minified.api.conf.js index 4ecf7515da..8825eadbf4 100644 --- a/test/karma.minified.api.conf.js +++ b/test/karma.minified.api.conf.js @@ -8,6 +8,7 @@ module.exports = function(config) { files: [ '../test/karma-qunit-shim.js', + '../node_modules/sinon/pkg/sinon.js', '../build/files/minified.video.js', '../test/unit/test-helpers.js', '../test/unit/api.js' diff --git a/test/karma.minified.conf.js b/test/karma.minified.conf.js index f8126a79fc..dbaa7e569d 100644 --- a/test/karma.minified.conf.js +++ b/test/karma.minified.conf.js @@ -8,6 +8,7 @@ module.exports = function(config) { files: [ '../test/karma-qunit-shim.js', + '../node_modules/sinon/pkg/sinon.js', '../build/files/test.minified.video.js' ], diff --git a/test/minified-api.html b/test/minified-api.html index 377b576fea..3246f62023 100644 --- a/test/minified-api.html +++ b/test/minified-api.html @@ -3,6 +3,10 @@ Video.js Test Suite + + + + diff --git a/test/minified.html b/test/minified.html index 65aee2de06..fdc18be008 100644 --- a/test/minified.html +++ b/test/minified.html @@ -3,6 +3,10 @@ Video.js Test Suite + + + + diff --git a/test/qunit-externs.js b/test/qunit-externs.js index a8209449e8..8a5544219d 100644 --- a/test/qunit-externs.js +++ b/test/qunit-externs.js @@ -81,4 +81,4 @@ function start(increment){} /** * @param {number=} increment */ -function stop(increment){} \ No newline at end of file +function stop(increment){} diff --git a/test/sinon-externs.js b/test/sinon-externs.js new file mode 100644 index 0000000000..d7130953a1 --- /dev/null +++ b/test/sinon-externs.js @@ -0,0 +1,99 @@ +/** + * Sinon externs + */ +function sinon(){} + +sinon.stub = function(){}; +sinon.spy = function(){}; +sinon.mock = function(){}; + +Function.prototype.alwaysCalledOn = function(){}; +Function.prototype.alwaysCalledWith = function(){}; +Function.prototype.alwaysCalledWithExactly = function(){}; +Function.prototype.alwaysCalledWithMatch = function(){}; +Function.prototype.alwaysCalledWithNew = function(){}; +Function.prototype.alwaysReturned = function(){}; +Function.prototype.alwaysThrew = function(){}; +Function.prototype.args; +Function.prototype.arguments; +Function.prototype.behaviors; +Function.prototype.callArg = function(){}; +Function.prototype.callArgOn = function(){}; +Function.prototype.callArgOnWith = function(){}; +Function.prototype.callArgWith = function(){}; +Function.prototype.callCount; +Function.prototype.callIds; +Function.prototype.called; +Function.prototype.calledAfter = function(){}; +Function.prototype.calledBefore = function(){}; +Function.prototype.calledOn = function(){}; +Function.prototype.calledOnce; +Function.prototype.calledThrice; +Function.prototype.calledTwice; +Function.prototype.calledWith = function(){}; +Function.prototype.calledWithExactly = function(){}; +Function.prototype.calledWithMatch = function(){}; +Function.prototype.calledWithNew = function(){}; +Function.prototype.caller; +Function.prototype.callsArg = function(){}; +Function.prototype.callsArgAsync = function(){}; +Function.prototype.callsArgOn = function(){}; +Function.prototype.callsArgOnAsync = function(){}; +Function.prototype.callsArgOnWith = function(){}; +Function.prototype.callsArgOnWithAsync = function(){}; +Function.prototype.callsArgWith = function(){}; +Function.prototype.callsArgWithAsync = function(){}; +Function.prototype.create = function(){}; +Function.prototype.defaultBehavior; +Function.prototype.displayName; +Function.prototype.exceptions; +Function.prototype.firstCall; +Function.prototype.formatters; +Function.prototype.func; +Function.prototype.getCall = function(){}; +Function.prototype.getCalls = function(){}; +Function.prototype.id; +Function.prototype.invoke = function(){}; +Function.prototype.invokeCallback = function(){}; +Function.prototype.isPresent = function(){}; +Function.prototype.lastCall; +Function.prototype.length; +Function.prototype.matches = function(){}; +Function.prototype.name; +Function.prototype.neverCalledWith = function(){}; +Function.prototype.neverCalledWithMatch = function(){}; +Function.prototype.notCalled; +Function.prototype.onCall = function(){}; +Function.prototype.onFirstCall = function(){}; +Function.prototype.onSecondCall = function(){}; +Function.prototype.onThirdCall = function(){}; +Function.prototype.printf = function(){}; +Function.prototype.reset = function(){}; +Function.prototype.resetBehavior = function(){}; +Function.prototype.restore = function(){}; +Function.prototype.returnValues; +Function.prototype.returned = function(){}; +Function.prototype.returns = function(){}; +Function.prototype.returnsArg = function(){}; +Function.prototype.returnsThis = function(){}; +Function.prototype.secondCall; +Function.prototype.spyCall; +Function.prototype.thirdCall; +Function.prototype.thisValues; +Function.prototype.threw = function(){}; +Function.prototype['throws'] = function(){}; +Function.prototype.throwsException = function(){}; +Function.prototype.toString = function(){}; +Function.prototype.withArgs = function(){}; +Function.prototype.yield = function(){}; +Function.prototype.yieldOn = function(){}; +Function.prototype.yieldTo = function(){}; +Function.prototype.yieldToOn = function(){}; +Function.prototype.yields = function(){}; +Function.prototype.yieldsAsync = function(){}; +Function.prototype.yieldsOn = function(){}; +Function.prototype.yieldsOnAsync = function(){}; +Function.prototype.yieldsTo = function(){}; +Function.prototype.yieldsToAsync = function(){}; +Function.prototype.yieldsToOn = function(){}; +Function.prototype.yieldsToOnAsync = function(){}; diff --git a/test/unit/api.js b/test/unit/api.js index 6e4a7b5d8c..309a0b1f0f 100644 --- a/test/unit/api.js +++ b/test/unit/api.js @@ -27,6 +27,7 @@ test('should be able to access expected player API methods', function() { ok(player.textTracks, 'textTracks exists'); ok(player.requestFullScreen, 'requestFullScreen exists'); ok(player.cancelFullScreen, 'cancelFullScreen exists'); + ok(player.playbackRate, 'playbackRate exists'); // Unsupported Native HTML5 Methods // ok(player.canPlayType, 'canPlayType exists'); @@ -138,6 +139,7 @@ test('should export useful components to the public', function () { ok(videojs.Menu, 'Menu should be public'); ok(videojs.MenuItem, 'MenuItem should be public'); ok(videojs.MenuButton, 'MenuButton should be public'); + ok(videojs.PlaybackRateMenuButton, 'PlaybackRateMenuButton should be public'); ok(videojs.util, 'util namespace should be public'); ok(videojs.util.mergeOptions, 'mergeOptions should be public'); diff --git a/test/unit/component.js b/test/unit/component.js index fd31df56e4..c8c0a7f783 100644 --- a/test/unit/component.js +++ b/test/unit/component.js @@ -26,7 +26,7 @@ test('should add a child component', function(){ ok(comp.getChildById(child.id()) === child); }); -test('should init child coponents from options', function(){ +test('should init child components from options', function(){ var comp = new vjs.Component(getFakePlayer(), { children: { 'component': true @@ -37,6 +37,32 @@ test('should init child coponents from options', function(){ ok(comp.el().childNodes.length === 1); }); +test('should init child components from simple children array', function(){ + var comp = new vjs.Component(getFakePlayer(), { + children: [ + 'component', + 'component', + 'component' + ] + }); + + ok(comp.children().length === 3); + ok(comp.el().childNodes.length === 3); +}); + +test('should init child components from children array of objects', function(){ + var comp = new vjs.Component(getFakePlayer(), { + children: [ + { 'name': 'component' }, + { 'name': 'component' }, + { 'name': 'component' } + ] + }); + + ok(comp.children().length === 3); + ok(comp.el().childNodes.length === 3); +}); + test('should do a deep merge of child options', function(){ // Create a default option for component vjs.Component.prototype.options_ = { @@ -229,7 +255,7 @@ test('should use a defined content el for appending children', function(){ }); test('should emit a tap event', function(){ - expect(1); + expect(2); // Fake touch support. Real touch support isn't needed for this test. var origTouch = vjs.TOUCH_ENABLED; @@ -241,13 +267,27 @@ test('should emit a tap event', function(){ comp.on('tap', function(){ ok(true, 'Tap event emitted'); }); - comp.trigger('touchstart'); + + // A touchstart followed by touchend should trigger a tap + vjs.trigger(comp.el(), {type: 'touchstart', touches: [{}]}); + comp.trigger('touchend'); + + // A touchmove with a lot of movement should not trigger a tap + vjs.trigger(comp.el(), {type: 'touchstart', touches: [ + { pageX: 0, pageY: 0 } + ]}); + vjs.trigger(comp.el(), {type: 'touchmove', touches: [ + { pageX: 100, pageY: 100 } + ]}); comp.trigger('touchend'); - // This second test should not trigger another tap event because - // a touchmove is happening - comp.trigger('touchstart'); - comp.trigger('touchmove'); + // A touchmove with not much movement should still allow a tap + vjs.trigger(comp.el(), {type: 'touchstart', touches: [ + { pageX: 0, pageY: 0 } + ]}); + vjs.trigger(comp.el(), {type: 'touchmove', touches: [ + { pageX: 10, pageY: 10 } + ]}); comp.trigger('touchend'); // Reset to orignial value diff --git a/test/unit/controls.js b/test/unit/controls.js index be690e9948..7a144b8926 100644 --- a/test/unit/controls.js +++ b/test/unit/controls.js @@ -103,3 +103,12 @@ test('calculateDistance should use changedTouches, if available', function() { equal(slider.calculateDistance(event), 0.5, 'we should have touched exactly in the center, so, the ratio should be half'); }); + +test('should hide playback rate control if it\'s not supported', function(){ + expect(1); + + var player = PlayerTest.makePlayer(); + var playbackRate = new vjs.PlaybackRateMenuButton(player); + + ok(playbackRate.el().className.indexOf('vjs-hidden') >= 0, 'playbackRate is not hidden'); +}); diff --git a/test/unit/lib.js b/test/unit/lib.js index 3862efeb41..d754338285 100644 --- a/test/unit/lib.js +++ b/test/unit/lib.js @@ -243,6 +243,16 @@ test('should get an absolute URL', function(){ ok(vjs.getAbsoluteURL('https://asdf.com/index.html') === 'https://asdf.com/index.html'); }); +test('should parse the details of a url correctly', function(){ + equal(vjs.parseUrl('#').protocol, window.location.protocol, 'parsed relative url protocol'); + equal(vjs.parseUrl('#').host, window.location.host, 'parsed relative url host'); + + equal(vjs.parseUrl('http://example.com').protocol, 'http:', 'parsed example url protocol'); + equal(vjs.parseUrl('http://example.com').hostname, 'example.com', 'parsed example url hostname'); + + equal(vjs.parseUrl('http://example.com:1234').port, '1234', 'parsed example url port'); +}); + test('vjs.findPosition should find top and left position', function() { var d = document.createElement('div'), position = vjs.findPosition(d); @@ -260,3 +270,57 @@ test('vjs.findPosition should find top and left position', function() { position = vjs.findPosition(d); deepEqual(position, {left: 0, top: 0}, 'If there is no gBCR, we should get zeros'); }); + +// LOG TESTS +test('should confirm logging functions work', function() { + var console = window['console']; + var origLog = console.log; + var origWarn = console.warn; + var origError = console.error; + + // in ie8 console.log is apparently not a 'function' so sinon chokes on it + // https://github.com/cjohansen/Sinon.JS/issues/386 + // instead we'll temporarily replace them with functions + if (typeof origLog === 'object') { + console.log = function(){}; + console.warn = function(){}; + console.error = function(){}; + } + + // stub the global log functions + var log = sinon.stub(console, 'log'); + var error = sinon.stub(console, 'error'); + var warn = sinon.stub(console, 'warn'); + + vjs.log('asdf', 'fdsa'); + ok(log.called, 'log was called'); + equal(log.firstCall.args[0], 'VIDEOJS:'); + equal(log.firstCall.args[1], 'asdf'); + equal(log.firstCall.args[2], 'fdsa'); + + vjs.log.warn('asdf', 'fdsa'); + ok(warn.called, 'warn was called'); + equal(warn.firstCall.args[0], 'VIDEOJS:'); + equal(warn.firstCall.args[1], 'WARN:'); + equal(warn.firstCall.args[2], 'asdf'); + equal(warn.firstCall.args[3], 'fdsa'); + + vjs.log.error('asdf', 'fdsa'); + ok(error.called, 'error was called'); + equal(error.firstCall.args[0], 'VIDEOJS:'); + equal(error.firstCall.args[1], 'ERROR:'); + equal(error.firstCall.args[2], 'asdf'); + equal(error.firstCall.args[3], 'fdsa'); + + // tear down sinon + log.restore(); + error.restore(); + warn.restore(); + + // restore ie8 + if (typeof origLog === 'object') { + console.log = origLog; + console.warn = origWarn; + console.error = origError; + } +}); diff --git a/test/unit/media.html5.js b/test/unit/media.html5.js index 6982115296..a8e3780ebc 100644 --- a/test/unit/media.html5.js +++ b/test/unit/media.html5.js @@ -92,3 +92,30 @@ test('should return a maybe for mp4 on OLD ANDROID', function() { vjs.IS_OLD_ANDROID = isOldAndroid; vjs.Html5.unpatchCanPlayType(); }); + +test('test playbackRate', function() { + var el, player, playbackRate, tech; + + el = document.createElement('div'); + el.innerHTML = '
'; + + player = { + id: function(){ return 'id'; }, + el: function(){ return el; }, + options_: {}, + options: function(){ return {}; }, + controls: function(){ return false; }, + usingNativeControls: function(){ return false; }, + on: function(){ return this; }, + ready: function(){} + }; + + tech = new vjs.Html5(player, {}); + tech.createEl(); + + tech.el_.playbackRate = 1.25; + strictEqual(tech.playbackRate(), 1.25); + + tech['setPlaybackRate'](0.75); + strictEqual(tech.playbackRate(), 0.75); +}); diff --git a/test/unit/player.js b/test/unit/player.js index 584df7f55e..70831b45d2 100644 --- a/test/unit/player.js +++ b/test/unit/player.js @@ -77,19 +77,19 @@ test('should get tag, source, and track settings', function(){ var fixture = document.getElementById('qunit-fixture'); - var html = '